Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

464 lines
18 KiB

  1. /*****************************************************************************
  2. *
  3. * DIHid.c
  4. *
  5. * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
  6. *
  7. * Abstract:
  8. *
  9. * WINNT implementation of JOYHID.
  10. *
  11. * Contents:
  12. *
  13. * DIWdm_JoyHidMapping
  14. * JoyReg_JoyIdToDeviceInterface
  15. *
  16. *****************************************************************************/
  17. #include "dinputpr.h"
  18. #undef sqfl
  19. #define sqfl sqflWDM
  20. #include "dijoyhid.h"
  21. /*****************************************************************************
  22. *
  23. * @doc INTERNAL
  24. *
  25. * @func HRESULT EXTERNAL | DIWdm_JoyHidMapping |
  26. *
  27. * Does the work done by JoyHid on Win9x. This function
  28. * maps the Joystick ID to a HID device and talks to the
  29. * HID device to obtain its capabilities.
  30. *
  31. * @parm IN int | idJoy |
  32. *
  33. * The Id of the joystick to be located.
  34. *
  35. * @parm OUT PVXDINITPARAMS | pvip | OPTIONAL
  36. * Address of a VXDINITPARAMS structure that is filled out
  37. * by this function. This is an optional parameter
  38. * and can be NULL
  39. *
  40. * @parm OUT LPDIJOYCONFIG | pcfg |
  41. * Address of a DIJOYCONFIG structure that is filled out
  42. * by this function. This is an optional parameter.
  43. *
  44. * @parm IN OUT LPDIJOYTYPEINFO | pdijti |
  45. * Address of a DIJOYTYPEINFO structure that is filled out
  46. * by this function. This is an optional parameter.
  47. * If passed in, the hws.dwFlags is used to initialize the
  48. * same flags in the DIJOYCONFIG structure.
  49. *
  50. * @returns HRESULT
  51. * Returns a COM error code
  52. *
  53. *****************************************************************************/
  54. /*
  55. * ISSUE-2001/03/29-timgill function uses too much stack space
  56. * This function uses over 4K of stack space!
  57. * This causes the Win9x build to choke looking for _chkstk.
  58. * Hack by forcing caller to pass pcfg and pdijti
  59. */
  60. HRESULT EXTERNAL
  61. DIWdm_JoyHidMapping
  62. (
  63. IN int idJoy,
  64. OUT PVXDINITPARMS pvip, OPTIONAL
  65. OUT LPDIJOYCONFIG pcfg, OPTIONAL
  66. IN OUT LPDIJOYTYPEINFO pdijti
  67. )
  68. {
  69. HRESULT hres;
  70. PHIDDEVICEINFO phdi;
  71. VXDINITPARMS vip;
  72. DWORD wCaps = 0;
  73. DIPROPINFO propi;
  74. DIPROPSTRING dips;
  75. DIPROPDWORD dipd;
  76. BOOL fBadCalData = FALSE;
  77. EnterProc(DIWdm_JoyHidMapping, (_ "uxx", idJoy, pvip, pcfg));
  78. // AssertF(InCrit());
  79. if( pvip == NULL )
  80. {
  81. ZeroX(vip);
  82. vip.dwSize = cbX(vip);
  83. pvip = &vip;
  84. }
  85. AssertF(pdijti != NULL );
  86. /*
  87. * Copy the type info because JOY_HWS_ISYOKE, JOY_HWS_ISCARCTRL and
  88. * JOY_HWS_ISHEADTRACKER have no simple equivalents in HID so would
  89. * otherwise get lost. No harm done if it's zero.
  90. * Note, the dwFlags is built in pvip then copied elsewhere.
  91. */
  92. pvip->dwFlags = pdijti->hws.dwFlags;
  93. phdi = phdiFindJoyId(idJoy);
  94. if( phdi != NULL )
  95. {
  96. IDirectInputDeviceCallback *pdcb;
  97. hres = CHid_New(0, &phdi->guid,
  98. &IID_IDirectInputDeviceCallback,
  99. (PPV)&pdcb);
  100. if( SUCCEEDED(hres) )
  101. {
  102. DIDEVCAPS dc;
  103. hres = pdcb->lpVtbl->GetCapabilities(pdcb, &dc );
  104. if( SUCCEEDED(hres) )
  105. {
  106. DIDEVICEINSTANCEW didi;
  107. didi.dwSize = cbX(didi);
  108. hres = pdcb->lpVtbl->GetDeviceInfo(pdcb, &didi);
  109. if( SUCCEEDED(hres) )
  110. {
  111. LPDIDATAFORMAT pdf;
  112. hres = pdcb->lpVtbl->GetDataFormat(pdcb, &pdf);
  113. if( SUCCEEDED(hres) )
  114. {
  115. DIPROPCAL dipc;
  116. DWORD axis, pov = 0;
  117. ZeroBuf(pvip->Usages, 6 * cbX(pvip->Usages[0]));
  118. hres = pdcb->lpVtbl->MapUsage(pdcb, CheckHatswitch->dwUsage, &propi.iobj);
  119. if(SUCCEEDED(hres) )
  120. {
  121. pvip->dwPOV1usage = CheckHatswitch->dwUsage;
  122. pvip->dwFlags |= CheckHatswitch->dwFlags;
  123. wCaps |= CheckHatswitch->dwCaps;
  124. propi.pguid = DIPROP_GRANULARITY;
  125. propi.dwDevType = pdf->rgodf[propi.iobj].dwType;
  126. hres = pdcb->lpVtbl->GetProperty(pdcb, &propi, &dipd.diph);
  127. if( SUCCEEDED( hres ) )
  128. {
  129. if( dipd.dwData >= 9000 ) // 4 directional POV
  130. {
  131. wCaps |= JOYCAPS_POV4DIR;
  132. if( pcfg != NULL ) {
  133. pcfg->hwc.hwv.dwPOVValues[JOY_POVVAL_FORWARD] = JOY_POVFORWARD;
  134. pcfg->hwc.hwv.dwPOVValues[JOY_POVVAL_BACKWARD] = JOY_POVBACKWARD;
  135. pcfg->hwc.hwv.dwPOVValues[JOY_POVVAL_LEFT] = JOY_POVLEFT;
  136. pcfg->hwc.hwv.dwPOVValues[JOY_POVVAL_RIGHT] = JOY_POVRIGHT;
  137. }
  138. } else // Continuous POV
  139. {
  140. wCaps |= JOYCAPS_POVCTS;
  141. }
  142. }
  143. }
  144. for( axis = 0; axis < cA(AxesUsages)-1; axis++ )
  145. {
  146. USAGES *pUse = &AxesUsages[axis];
  147. DWORD dwCurAxisPos = pUse->dwAxisPos;
  148. if( pvip->Usages[dwCurAxisPos] != 0) {
  149. continue;
  150. } else {
  151. int i;
  152. BOOL bHasUsed = FALSE;
  153. for( i = 0; i < (int)dwCurAxisPos; i++ ) {
  154. if( pvip->Usages[i] == pUse->dwUsage ) {
  155. bHasUsed = TRUE;
  156. break;
  157. }
  158. }
  159. if( bHasUsed ) {
  160. continue;
  161. }
  162. }
  163. hres = pdcb->lpVtbl->MapUsage(pdcb, pUse->dwUsage, &propi.iobj);
  164. if(SUCCEEDED(hres) )
  165. {
  166. pvip->Usages[dwCurAxisPos] = pUse->dwUsage;
  167. pvip->dwFlags |= pUse->dwFlags;
  168. wCaps |= pUse->dwCaps;
  169. propi.pguid = DIPROP_CALIBRATION;
  170. propi.dwDevType = pdf->rgodf[propi.iobj].dwType;
  171. hres = pdcb->lpVtbl->GetProperty(pdcb, &propi, &dipc.diph);
  172. if( SUCCEEDED(hres) && pcfg != NULL )
  173. {
  174. #ifdef WINNT
  175. (&pcfg->hwc.hwv.jrvHardware.jpMin.dwX)[dwCurAxisPos]
  176. = dipc.lMin;
  177. (&pcfg->hwc.hwv.jrvHardware.jpMax.dwX)[dwCurAxisPos]
  178. = dipc.lMax;
  179. (&pcfg->hwc.hwv.jrvHardware.jpCenter.dwX)[dwCurAxisPos]
  180. = CCal_Midpoint(dipc.lMin, dipc.lMax);
  181. #else
  182. DIPROPRANGE diprp;
  183. DIPROPRANGE diprl;
  184. propi.pguid = DIPROP_PHYSICALRANGE;
  185. propi.dwDevType = pdf->rgodf[propi.iobj].dwType;
  186. hres = pdcb->lpVtbl->GetProperty(pdcb, &propi, &diprp.diph);
  187. if( SUCCEEDED( hres ) )
  188. {
  189. propi.pguid = DIPROP_LOGICALRANGE;
  190. propi.dwDevType = pdf->rgodf[propi.iobj].dwType;
  191. hres = pdcb->lpVtbl->GetProperty(pdcb, &propi, &diprl.diph);
  192. if( SUCCEEDED( hres ) )
  193. {
  194. LONG lMin, lMax;
  195. lMin = (&pcfg->hwc.hwv.jrvHardware.jpMin.dwX)[dwCurAxisPos]
  196. = CHid_CoordinateTransform( (PLMINMAX)&diprp.lMin, (PLMINMAX)&diprl.lMin, dipc.lMin );
  197. lMax = (&pcfg->hwc.hwv.jrvHardware.jpMax.dwX)[dwCurAxisPos]
  198. = CHid_CoordinateTransform( (PLMINMAX)&diprp.lMin, (PLMINMAX)&diprl.lMin, dipc.lMax );
  199. (&pcfg->hwc.hwv.jrvHardware.jpCenter.dwX)[dwCurAxisPos]
  200. = CCal_Midpoint(lMin, lMax);
  201. if( lMin >= lMax ) {
  202. fBadCalData = TRUE;
  203. break;
  204. }
  205. }
  206. }
  207. #endif
  208. }
  209. }
  210. } //for (axis=0...
  211. } //GetDataFormat
  212. pvip->hres = S_OK;
  213. pvip->dwSize = cbX(*pvip); /* Which version of VJOYD are we? */
  214. pvip->dwFlags |= JOY_HWS_AUTOLOAD; /* Describes the device */
  215. if(didi.wUsage == HID_USAGE_GENERIC_GAMEPAD) {
  216. pvip->dwFlags |= JOY_HWS_ISGAMEPAD;
  217. }
  218. pvip->dwId = idJoy; /* Internal joystick ID */
  219. pvip->dwFirmwareRevision = dc.dwFirmwareRevision;
  220. pvip->dwHardwareRevision = dc.dwHardwareRevision;
  221. pvip->dwFFDriverVersion = dc.dwFFDriverVersion;
  222. pvip->dwFilenameLengths = lstrlen(phdi->pdidd->DevicePath);
  223. pvip->pFilenameBuffer = phdi->pdidd->DevicePath;
  224. //pvip->Usages[6];
  225. //pvip->dwPOV1usage = 0x0;
  226. pvip->dwPOV2usage = 0x0;
  227. pvip->dwPOV3usage = 0x0;
  228. /* Fill all fields of cfg */
  229. if( pcfg != NULL ) {
  230. AssertF( pcfg->dwSize == sizeof(DIJOYCONFIG_DX5)
  231. || pcfg->dwSize == sizeof(DIJOYCONFIG_DX6) );
  232. pcfg->guidInstance = phdi->guid;
  233. pcfg->hwc.hws.dwNumButtons = dc.dwButtons;
  234. pcfg->hwc.hws.dwFlags = pvip->dwFlags;
  235. //pcfg.hwc.hwv.jrvHardware
  236. //pcfg.hwc.hwv.dwPOVValues
  237. pcfg->hwc.hwv.dwCalFlags = 0x0;
  238. if( ( LOWORD(phdi->guidProduct.Data1) == MSFT_SYSTEM_VID )
  239. &&( ( HIWORD(phdi->guidProduct.Data1) >= MSFT_SYSTEM_PID + JOY_HW_PREDEFMIN)
  240. &&( HIWORD(phdi->guidProduct.Data1) < MSFT_SYSTEM_PID + JOY_HW_PREDEFMAX ) ) )
  241. {
  242. pcfg->hwc.dwType = HIWORD(phdi->guidProduct.Data1) - MSFT_SYSTEM_PID;
  243. pcfg->hwc.dwUsageSettings = JOY_US_PRESENT | JOY_US_VOLATILE;
  244. }
  245. else
  246. {
  247. /*
  248. * This value really does not matter much but ideally
  249. * should be greater than or equal to JOY_HW_PREDEFMAX
  250. * Add idJoy for best compatiblity with the old CPLs.
  251. */
  252. pcfg->hwc.dwType = idJoy + JOY_HW_PREDEFMAX;
  253. pcfg->hwc.dwUsageSettings = JOY_US_PRESENT | JOY_US_VOLATILE | JOY_US_ISOEM;
  254. }
  255. if(pcfg && pvip->Usages[ecRz]) {
  256. pcfg->hwc.dwUsageSettings |= JOY_US_HASRUDDER;
  257. }
  258. pcfg->hwc.dwReserved = 0x0;
  259. /*
  260. * Default gain to nominal max so it does not get written
  261. * to the registry unless it has some other value.
  262. */
  263. pcfg->dwGain = DI_FFNOMINALMAX;
  264. propi.pguid = DIPROP_FFGAIN;
  265. propi.dwDevType = DIPH_DEVICE;
  266. propi.iobj = 0xFFFFFFFF;
  267. hres = pdcb->lpVtbl->GetProperty(pdcb, &propi, &dipd.diph);
  268. if( SUCCEEDED(hres) )
  269. {
  270. pcfg->dwGain = dipd.dwData;
  271. } else
  272. {
  273. // Failure to get gain is not crutial
  274. hres = S_OK;
  275. }
  276. if( pcfg->hwc.dwType >= JOY_HW_PREDEFMAX )
  277. {
  278. #ifndef UNICODE
  279. char szType[20];
  280. #endif
  281. /*
  282. * This should work, but it doesn't in Win98, bug!
  283. *
  284. * wsprintfW(pcfg->wszType, L"VID_%04X&PID_%04X",
  285. * LOWORD(didi.guidProduct.Data1), HIWORD(didi.guidProduct.Data1));
  286. */
  287. #ifdef UNICODE
  288. wsprintf(pcfg->wszType, VID_PID_TEMPLATE,
  289. LOWORD(phdi->guidProduct.Data1), HIWORD(phdi->guidProduct.Data1));
  290. #else
  291. wsprintf(szType, VID_PID_TEMPLATE,
  292. LOWORD(phdi->guidProduct.Data1), HIWORD(phdi->guidProduct.Data1));
  293. AToU(pcfg->wszType, cA(pcfg->wszType), szType);
  294. #endif
  295. }
  296. else
  297. {
  298. /*
  299. * Predefined types do not have type strings for the
  300. * uses the callers of this function need.
  301. */
  302. ZeroX(pcfg->wszType);
  303. }
  304. #ifdef WINNT
  305. // No callout on NT
  306. ZeroX(pcfg->wszCallout);
  307. #else
  308. lstrcpyW( pcfg->wszCallout, L"joyhid.vxd" );
  309. #endif
  310. } // end of filling pcfg's fields
  311. pdijti->dwSize = cbX(*pdijti);
  312. pdijti->hws.dwNumButtons = dc.dwButtons;
  313. pdijti->hws.dwFlags = pvip->dwFlags;
  314. ZeroX(pdijti->clsidConfig);
  315. propi.pguid = DIPROP_INSTANCENAME;
  316. propi.dwDevType = DIPH_DEVICE;
  317. propi.iobj = 0xFFFFFFFF;
  318. hres = pdcb->lpVtbl->GetProperty(pdcb, &propi, &dips.diph);
  319. if( hres != S_OK && lstrlenW(pdijti->wszDisplayName) != 0x0 )
  320. {
  321. // Failure to get friendly name
  322. // We will try and use the OEM name from the registry
  323. lstrcpyW(dips.wsz, pdijti->wszDisplayName);
  324. //pdcb->lpVtbl->SetProperty(pdcb, &propi, &dips.diph);
  325. }else if( SUCCEEDED(hres) )
  326. {
  327. // Use friendly name in the registry
  328. lstrcpyW(pdijti->wszDisplayName, dips.wsz);
  329. hres = S_OK;
  330. }
  331. } // GetDeviceInfo FAILED
  332. } // GetCapabilities FAILED
  333. Invoke_Release(&pdcb);
  334. }
  335. } else // No HID device for JoyID
  336. {
  337. hres = E_FAIL;
  338. }
  339. if( fBadCalData ) {
  340. hres = E_FAIL;
  341. }
  342. ExitProcX(hres);
  343. return hres;
  344. }
  345. /*****************************************************************************
  346. *
  347. * @doc INTERNAL
  348. *
  349. * @func HRESULT | JoyReg_JoyIdToDeviceInterface |
  350. *
  351. * Given a joystick ID number, obtain the device interface
  352. * corresponding to it.
  353. *
  354. * @parm UINT | idJoy |
  355. *
  356. * Joystick ID number, zero-based.
  357. *
  358. * @parm PVXDINITPARMS | pvip |
  359. *
  360. * Receives init parameters from the driver.
  361. *
  362. * @parm LPTSTR | ptszBuf |
  363. *
  364. * A buffer of size <c MAX_PATH> in which the device interface
  365. * path is built.
  366. *
  367. * @returns
  368. * A pointer to the part of the <p ptszBuf> buffer that
  369. * contains the actual device interface path.
  370. *
  371. *****************************************************************************/
  372. LPTSTR EXTERNAL
  373. JoyReg_JoyIdToDeviceInterface_NT
  374. (
  375. IN UINT idJoy,
  376. OUT PVXDINITPARMS pvip,
  377. OUT LPTSTR ptszBuf
  378. )
  379. {
  380. HRESULT hres;
  381. DIJOYCONFIG cfg;
  382. DIJOYTYPEINFO dijti;
  383. DllEnterCrit();
  384. ZeroX(cfg);
  385. ZeroX(dijti);
  386. cfg.dwSize = cbX(cfg);
  387. dijti.dwSize = cbX(dijti);
  388. hres = DIWdm_JoyHidMapping(idJoy, pvip, &cfg, &dijti );
  389. if( SUCCEEDED(hres ) )
  390. {
  391. AssertF( lstrlen(pvip->pFilenameBuffer) < MAX_PATH );
  392. lstrcpy(ptszBuf, pvip->pFilenameBuffer);
  393. }
  394. DllLeaveCrit();
  395. return ptszBuf;
  396. }