Source code of Windows XP (NT5)
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.

445 lines
12 KiB

  1. /*****************************************************************************
  2. *
  3. * PidOp.c
  4. *
  5. * Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
  6. *
  7. * Abstract:
  8. *
  9. * PID device Operation .
  10. *
  11. *****************************************************************************/
  12. #include "pidpr.h"
  13. #define sqfl ( sqflOp )
  14. #pragma BEGIN_CONST_DATA
  15. static PIDUSAGE c_rgUsgGain[] =
  16. {
  17. MAKE_PIDUSAGE(DEVICE_GAIN, 0x0 )
  18. };
  19. static PIDREPORT DeviceGain =
  20. {
  21. HidP_Output,
  22. HID_USAGE_PAGE_PID,
  23. HID_USAGE_PID_DEVICE_GAIN_REPORT,
  24. cbX(DWORD),
  25. cA(c_rgUsgGain),
  26. c_rgUsgGain
  27. };
  28. PIDUSAGE c_rgUsgOperationReport[] =
  29. {
  30. MAKE_PIDUSAGE(LOOP_COUNT, 0x0),
  31. };
  32. static PIDREPORT OperationReport =
  33. {
  34. HidP_Output,
  35. HID_USAGE_PAGE_PID,
  36. HID_USAGE_PID_EFFECT_OPERATION_REPORT,
  37. cbX(DWORD),
  38. cA(c_rgUsgOperationReport),
  39. c_rgUsgOperationReport
  40. };
  41. static PIDREPORT DeviceControlReport =
  42. {
  43. HidP_Output,
  44. HID_USAGE_PAGE_PID,
  45. HID_USAGE_PID_DEVICE_CONTROL,
  46. 0x0,
  47. 0x0,
  48. NULL
  49. };
  50. #pragma END_CONST_DATA
  51. STDMETHODIMP
  52. PID_EffectOperation
  53. (
  54. IDirectInputEffectDriver *ped,
  55. DWORD dwId,
  56. DWORD dwEffect,
  57. DWORD dwMode,
  58. DWORD dwCount,
  59. BOOL bBlocking,
  60. UINT blockNr,
  61. UINT totalBlocks
  62. )
  63. {
  64. CPidDrv *this = (CPidDrv *)ped;
  65. HRESULT hres = S_OK;
  66. EnterProcI( PID_EffectOperation, (_"xxxxx", ped, dwId, dwEffect, dwMode, dwCount ));
  67. hres = PID_ValidateEffectIndex(ped, dwEffect);
  68. // Allocate Memory for the report
  69. if( SUCCEEDED(hres) )
  70. {
  71. USHORT cbReport;
  72. PUCHAR pReport;
  73. USHORT LinkCollection;
  74. AssertF(OperationReport.HidP_Type == HidP_Output);
  75. cbReport = this->cbReport[OperationReport.HidP_Type];
  76. pReport = this->pReport[OperationReport.HidP_Type];
  77. PID_GetLinkCollectionIndex(ped, OperationReport.UsagePage, OperationReport.Collection, 0x0, &LinkCollection );
  78. // Set the Effect Structure
  79. if( SUCCEEDED(hres) )
  80. {
  81. ZeroBuf(pReport, cbReport);
  82. // Set Effect Operation
  83. if( SUCCEEDED(hres) )
  84. {
  85. USAGE Usage;
  86. USAGE UsagePage;
  87. NTSTATUS ntStat;
  88. UINT nUsages = 0x1;
  89. USAGE LinkCollection0;
  90. PEFFECTSTATE pEffectState = PeffectStateFromBlockIndex(this,dwEffect);
  91. UsagePage = OperationReport.UsagePage;
  92. PID_GetLinkCollectionIndex(ped, OperationReport.UsagePage, HID_USAGE_PID_EFFECT_OPERATION, 0x0, &LinkCollection0);
  93. if( dwMode & DIES_SOLO )
  94. {
  95. Usage = HID_USAGE_PID_OP_EFFECT_START_SOLO;
  96. pEffectState->lEfState |= PID_EFFECT_STARTED_SOLO;
  97. } else if( dwMode & PID_DIES_START )
  98. {
  99. Usage = HID_USAGE_PID_OP_EFFECT_START;
  100. pEffectState->lEfState |= PID_EFFECT_STARTED;
  101. } else if(dwMode & PID_DIES_STOP )
  102. {
  103. Usage = HID_USAGE_PID_OP_EFFECT_STOP;
  104. pEffectState->lEfState &= ~(PID_EFFECT_STARTED | PID_EFFECT_STARTED_SOLO);
  105. } else
  106. {
  107. SquirtSqflPtszV(sqfl | sqflError,
  108. TEXT("%s: FAIL Could not understand dwMode=0x%x"),
  109. s_tszProc, dwMode );
  110. hres = E_NOTIMPL;
  111. }
  112. ntStat = HidP_SetUsages
  113. (
  114. OperationReport.HidP_Type,
  115. UsagePage,
  116. LinkCollection0,
  117. &Usage,
  118. &nUsages,
  119. this->ppd,
  120. pReport,
  121. cbReport);
  122. if( FAILED(hres) )
  123. {
  124. SquirtSqflPtszV(sqfl | sqflBenign,
  125. TEXT("%s: FAIL HidP_SetUsages:0x%x for(%x,%x,%x:%s)"),
  126. s_tszProc, ntStat,
  127. LinkCollection0, UsagePage, Usage,
  128. PIDUSAGETXT(UsagePage,Usage) );
  129. } else
  130. {
  131. SquirtSqflPtszV(sqfl | sqflVerbose,
  132. TEXT("%s: HidP_SetUsages:0x%x for(%x,%x,%x:%s)"),
  133. s_tszProc, ntStat,
  134. LinkCollection0, UsagePage, Usage,
  135. PIDUSAGETXT(UsagePage,Usage) );
  136. }
  137. }
  138. // Set the Loop Count
  139. if( SUCCEEDED(hres) )
  140. {
  141. PID_PackValue
  142. (
  143. ped,
  144. &OperationReport,
  145. LinkCollection,
  146. &dwCount,
  147. cbX(dwCount),
  148. pReport,
  149. cbReport
  150. );
  151. // Set the Block Index
  152. PID_PackValue
  153. (
  154. ped,
  155. &g_BlockIndex,
  156. LinkCollection,
  157. &dwEffect,
  158. cbX(dwEffect),
  159. pReport,
  160. cbReport
  161. );
  162. }
  163. if( SUCCEEDED(hres) )
  164. {
  165. hres = PID_SendReport(ped, pReport, cbReport, OperationReport.HidP_Type, bBlocking, blockNr, totalBlocks);
  166. }
  167. }
  168. }
  169. ExitOleProc();
  170. return hres;
  171. }
  172. /*****************************************************************************
  173. *
  174. * PID_SetGain
  175. *
  176. * Set the overall device gain.
  177. *
  178. * dwId
  179. *
  180. * The joystick ID number being used.
  181. *
  182. * dwGain
  183. *
  184. * The new gain value.
  185. *
  186. * If the value is out of range for the device, the device
  187. * should use the nearest supported value and return
  188. * DI_TRUNCATED.
  189. *
  190. * Returns:
  191. *
  192. *
  193. * S_OK if the operation completed successfully.
  194. *
  195. * DI_TRUNCATED if the value was out of range and was
  196. * changed to the nearest supported value.
  197. *
  198. * Any DIERR_* error code may be returned.
  199. *
  200. * Private driver-specific error codes in the range
  201. * DIERR_DRIVERFIRST through DIERR_DRIVERLAST
  202. * may be returned.
  203. *
  204. *****************************************************************************/
  205. STDMETHODIMP
  206. PID_SetGain
  207. (
  208. IDirectInputEffectDriver *ped,
  209. DWORD dwId,
  210. DWORD dwGain
  211. )
  212. {
  213. CPidDrv *this = (CPidDrv *)ped;
  214. HRESULT hres = S_OK;
  215. EnterProc( PID_SetGain, (_"xxx", ped, dwId, dwGain));
  216. DllEnterCrit();
  217. // Allocate Memory for the report
  218. if( SUCCEEDED(hres) )
  219. {
  220. USHORT cbReport;
  221. PUCHAR pReport;
  222. USHORT LinkCollection;
  223. AssertF(DeviceGain.HidP_Type == HidP_Output);
  224. cbReport = this->cbReport[DeviceGain.HidP_Type];
  225. pReport = this->pReport[DeviceGain.HidP_Type];
  226. PID_GetLinkCollectionIndex(ped, DeviceGain.UsagePage, DeviceGain.Collection, 0x0, &LinkCollection );
  227. // Set the Effect Structure
  228. if( SUCCEEDED(hres) )
  229. {
  230. ZeroBuf(pReport, cbReport);
  231. // Set the Loop Count
  232. if( SUCCEEDED(hres) )
  233. {
  234. hres = PID_PackValue
  235. (
  236. ped,
  237. &DeviceGain,
  238. LinkCollection,
  239. &dwGain,
  240. cbX(dwGain),
  241. pReport,
  242. cbReport
  243. );
  244. }
  245. if( SUCCEEDED(hres) )
  246. {
  247. hres = PID_SendReport(ped, pReport, cbReport, DeviceGain.HidP_Type, FALSE, 0, 1);
  248. }
  249. }
  250. }
  251. DllLeaveCrit();
  252. ExitOleProc();
  253. return hres;
  254. }
  255. /*****************************************************************************
  256. *
  257. * PID_SendForceFeedbackCommand
  258. *
  259. * Send a command to the device.
  260. *
  261. * dwId
  262. *
  263. * The external joystick number being addressed.
  264. *
  265. * dwCommand
  266. *
  267. * A DISFFC_* value specifying the command to send.
  268. *
  269. * Returns:
  270. *
  271. * S_OK on success.
  272. *
  273. * Any DIERR_* error code may be returned.
  274. *
  275. * Private driver-specific error codes in the range
  276. * DIERR_DRIVERFIRST through DIERR_DRIVERLAST
  277. * may be returned.
  278. *
  279. *****************************************************************************/
  280. STDMETHODIMP
  281. PID_SendForceFeedbackCommand
  282. (
  283. IDirectInputEffectDriver *ped,
  284. DWORD dwId,
  285. DWORD dwCommand
  286. )
  287. {
  288. CPidDrv *this = (CPidDrv *)ped;
  289. HRESULT hres = S_OK;
  290. USAGE Usages[6];
  291. PUSAGE pUsages = &Usages[0];
  292. UINT nUsages;
  293. EnterProcI( PID_SendForceFeedbackCommand, (_"xxx", ped, dwId, dwCommand));
  294. DllEnterCrit();
  295. if( dwCommand & DISFFC_RESET )
  296. {
  297. DWORD indx;
  298. *pUsages++ = HID_USAGE_PID_DC_DEVICE_RESET;
  299. for(indx = 1 ;
  300. (indx <= this->cMaxEffects) && (((PUNITSTATE)(g_pshmem + this->iUnitStateOffset))->cEfDownloaded != 0x0 );
  301. indx++ )
  302. {
  303. PID_DestroyEffect(ped, dwId, indx);
  304. }
  305. this->dwState = DIGFFS_STOPPED;
  306. }
  307. if( dwCommand & DISFFC_STOPALL )
  308. {
  309. *pUsages++ = HID_USAGE_PID_DC_STOP_ALL_EFFECTS;
  310. this->dwState = DIGFFS_STOPPED;
  311. }
  312. if( dwCommand & DISFFC_PAUSE )
  313. {
  314. *pUsages++ = HID_USAGE_PID_DC_DEVICE_PAUSE;
  315. }
  316. if( dwCommand & DISFFC_CONTINUE )
  317. {
  318. *pUsages++ = HID_USAGE_PID_DC_DEVICE_CONTINUE;
  319. }
  320. if( dwCommand & DISFFC_SETACTUATORSON)
  321. {
  322. *pUsages++ = HID_USAGE_PID_DC_ENABLE_ACTUATORS;
  323. }
  324. if(dwCommand & DISFFC_SETACTUATORSOFF)
  325. {
  326. *pUsages++ = HID_USAGE_PID_DC_DISABLE_ACTUATORS;
  327. }
  328. nUsages = (UINT)(pUsages - &Usages[0]);
  329. if(nUsages == 0x0 )
  330. {
  331. hres = E_NOTIMPL;
  332. SquirtSqflPtszV(sqfl | sqflError,
  333. TEXT("%s: FAIL Do not understand dwCommand(0x%x) "),
  334. s_tszProc, dwCommand);
  335. }
  336. if( SUCCEEDED(hres) )
  337. {
  338. USHORT cbReport;
  339. PUCHAR pReport;
  340. USHORT LinkCollection;
  341. AssertF(DeviceControlReport.HidP_Type == HidP_Output);
  342. cbReport = this->cbReport[DeviceControlReport.HidP_Type];
  343. pReport = this->pReport[DeviceControlReport.HidP_Type];
  344. PID_GetLinkCollectionIndex(ped, DeviceControlReport.UsagePage, DeviceControlReport.Collection, 0x0, &LinkCollection );
  345. // Set the Effect Structure
  346. if( SUCCEEDED(hres) )
  347. {
  348. USHORT UsagePage;
  349. NTSTATUS ntStat;
  350. ZeroBuf(pReport, cbReport);
  351. UsagePage = OperationReport.UsagePage;
  352. ntStat = HidP_SetUsages
  353. (
  354. OperationReport.HidP_Type,
  355. UsagePage,
  356. LinkCollection,
  357. &Usages[0],
  358. &nUsages,
  359. this->ppd,
  360. pReport,
  361. cbReport);
  362. if( FAILED(ntStat) )
  363. {
  364. SquirtSqflPtszV(sqfl | sqflError,
  365. TEXT("%s: FAIL HidP_SetUsages:0x%x for(%x,%x,%x:%s)"),
  366. s_tszProc, ntStat,
  367. LinkCollection, UsagePage, Usages[0],
  368. PIDUSAGETXT(UsagePage,Usages[0]) );
  369. hres = ntStat;
  370. } else
  371. {
  372. SquirtSqflPtszV(sqfl | sqflVerbose,
  373. TEXT("%s: HidP_SetUsages:0x%x for(%x,%x,%x:%s)"),
  374. s_tszProc, ntStat,
  375. LinkCollection,UsagePage, Usages[0],
  376. PIDUSAGETXT(UsagePage,Usages[0]) );
  377. }
  378. if( SUCCEEDED(hres) )
  379. {
  380. hres = PID_SendReport(ped, pReport, cbReport, OperationReport.HidP_Type, TRUE, 0, 1); //we block on this call
  381. }
  382. }
  383. }
  384. DllLeaveCrit();
  385. ExitOleProc();
  386. return hres;
  387. }