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.

1703 lines
46 KiB

  1. #define __DEBUG_MODULE_IN_USE__ CIC_CONTROLITEM_CPP
  2. #include "stdhdrs.h"
  3. // @doc
  4. /**********************************************************************
  5. *
  6. * @module ControlItems.cpp |
  7. *
  8. * Implementation of CControlItem and derivative member functions,
  9. * and non-member help functions.
  10. *
  11. * History
  12. * ----------------------------------------------------------
  13. * Mitchell S. Dernis Original
  14. *
  15. * (c) 1986-1998 Microsoft Corporation. All right reserved.
  16. *
  17. **********************************************************************/
  18. const LONG c_lM1X = 1;
  19. const LONG c_lM1Y = 2;
  20. const LONG c_lM2X = 2;
  21. const LONG c_lM2Y = 1;
  22. long SignExtend(long lVal, ULONG ulNumValidBits)
  23. {
  24. ULONG ulMask = 1 << (ulNumValidBits-1);
  25. if( ulMask & lVal )
  26. {
  27. return (~(ulMask-1))|lVal;
  28. }
  29. else
  30. {
  31. return (ulMask-1)&lVal;
  32. }
  33. }
  34. long ClearSignExtension(long lVal, ULONG ulNumValidBits)
  35. {
  36. ULONG ulMask = 1 << ulNumValidBits;
  37. return lVal&(ulMask-1);
  38. }
  39. void ControlItemsFuncs::Direction2XY(LONG& rlValX, LONG& rlValY, LONG lDirection, const CONTROL_ITEM_DESC& crControlItemDesc)
  40. {
  41. // Check East
  42. if( (lDirection >= ControlItemConst::lNorthEast) && (lDirection <= ControlItemConst::lSouthEast) )
  43. {
  44. rlValX = crControlItemDesc.DPAD.pRangeTable->lMaxX;
  45. }
  46. // Check West
  47. else if( (lDirection >= ControlItemConst::lSouthWest) && (lDirection <= ControlItemConst::lNorthWest) )
  48. {
  49. rlValX = crControlItemDesc.DPAD.pRangeTable->lMinX;
  50. }
  51. // Otherwise Centered w.r.t East-West
  52. else
  53. {
  54. //If max - min is an odd number we cheat the center to the high side(i.e. add back the remainder)
  55. rlValX = crControlItemDesc.DPAD.pRangeTable->lCenterX;
  56. }
  57. // Check North (North cannot do range, because NorthWest is not contiguous
  58. if(
  59. (lDirection == ControlItemConst::lNorthEast) ||
  60. (lDirection == ControlItemConst::lNorth) ||
  61. (lDirection == ControlItemConst::lNorthWest)
  62. )
  63. {
  64. rlValY = crControlItemDesc.DPAD.pRangeTable->lMinY;
  65. }
  66. // Check South
  67. else if( (lDirection >= ControlItemConst::lSouthEast) && (lDirection <= ControlItemConst::lSouthWest) )
  68. {
  69. rlValY = crControlItemDesc.DPAD.pRangeTable->lMaxY;
  70. }
  71. // Otherwsie Centered w.r.t North-South
  72. else
  73. {
  74. //If max - min is an odd number we cheat the center to the high side (i.e. add back the remainder)
  75. rlValY = crControlItemDesc.DPAD.pRangeTable->lCenterY;
  76. }
  77. }
  78. void ControlItemsFuncs::XY2Direction(LONG lValX, LONG lValY, LONG& rlDirection, const CONTROL_ITEM_DESC& crControlItemDesc)
  79. {
  80. const ULONG localNorth = 0x01;
  81. const ULONG localSouth = 0x02;
  82. const ULONG localEast = 0x04;
  83. const ULONG localWest = 0x08;
  84. // Check North - North equals minimum Y value
  85. rlDirection = 0;
  86. if( crControlItemDesc.DPAD.pRangeTable->lNorth >= lValY )
  87. {
  88. rlDirection += localNorth;
  89. }
  90. //Check South - South equals maximum Y value
  91. else if( crControlItemDesc.DPAD.pRangeTable->lSouth <= lValY )
  92. {
  93. rlDirection += localSouth;
  94. }
  95. // Check East - East equals maximum X value
  96. if( crControlItemDesc.DPAD.pRangeTable->lEast <= lValX )
  97. {
  98. rlDirection += localEast;
  99. }
  100. //Check West - West equals minimum X value
  101. else if( crControlItemDesc.DPAD.pRangeTable->lWest >= lValX )
  102. {
  103. rlDirection += localWest;
  104. }
  105. //We have built a uniue value for each direction, but it is not what we need
  106. //use lookup table to convert to what we need
  107. static LONG DirectionLookUp[] =
  108. {
  109. ControlItemConst::lCenter, // 0 = Nothing
  110. ControlItemConst::lNorth, // 1 = localNorth
  111. ControlItemConst::lSouth, // 2 = localSouth
  112. ControlItemConst::lCenter, // 3 = Not Possible with above code
  113. ControlItemConst::lEast, // 4 = localEast
  114. ControlItemConst::lNorthEast, // 5 = localNorth + localEast
  115. ControlItemConst::lSouthEast, // 6 = localSouth + localEast
  116. ControlItemConst::lCenter, // 7 = Not Possible with above code
  117. ControlItemConst::lWest, // 8 = localWest
  118. ControlItemConst::lNorthWest, // 9 = localNorth + localWest
  119. ControlItemConst::lSouthWest // 10 = localSouth + localWest
  120. };
  121. rlDirection = DirectionLookUp[rlDirection];
  122. }
  123. NTSTATUS CAxesItem::ReadFromReport
  124. (
  125. PHIDP_PREPARSED_DATA pHidPreparsedData,
  126. PCHAR pcReport,
  127. LONG lReportLength
  128. )
  129. {
  130. NTSTATUS NtStatus;
  131. //
  132. // Read X
  133. //
  134. NtStatus = HidP_GetUsageValue(
  135. HidP_Input,
  136. m_cpControlItemDesc->UsagePage,
  137. m_cpControlItemDesc->usLinkCollection,
  138. m_cpControlItemDesc->Axes.UsageX,
  139. reinterpret_cast<PULONG>(&m_ItemState.Axes.lValX),
  140. pHidPreparsedData,
  141. pcReport,
  142. lReportLength
  143. );
  144. #if 0
  145. //Should be okay without this check (Driver should handle it now)
  146. if (HIDP_STATUS_INCOMPATIBLE_REPORT_ID == NtStatus)
  147. {
  148. // according to the ddk documentation 2.6.3
  149. // HIDP_STATUS_INCOMPATIBLE_REPORT_ID is a 'valid' error
  150. // we try again with the next packet
  151. // keep the data unchanged
  152. return HIDP_STATUS_SUCCESS;
  153. }
  154. #endif
  155. if( FAILED(NtStatus) )
  156. {
  157. ASSERT( NT_SUCCESS(NtStatus) );
  158. return NtStatus;
  159. }
  160. // Sign extend it (only if there are negatives)
  161. if (m_cpControlItemDesc->Axes.pRangeTable->lMinX < 0)
  162. {
  163. m_ItemState.Axes.lValX = SignExtend(m_ItemState.Axes.lValX, m_cpControlItemDesc->usBitSize);
  164. }
  165. //
  166. // Read Y
  167. //
  168. NtStatus = HidP_GetUsageValue(
  169. HidP_Input,
  170. m_cpControlItemDesc->UsagePage,
  171. m_cpControlItemDesc->usLinkCollection,
  172. m_cpControlItemDesc->Axes.UsageY,
  173. reinterpret_cast<PULONG>(&m_ItemState.Axes.lValY),
  174. pHidPreparsedData,
  175. pcReport,
  176. lReportLength
  177. );
  178. // Sign extend it (only if there are negatives)
  179. if (m_cpControlItemDesc->Axes.pRangeTable->lMinY < 0)
  180. {
  181. m_ItemState.Axes.lValY = SignExtend(m_ItemState.Axes.lValY, m_cpControlItemDesc->usBitSize);
  182. }
  183. ASSERT( NT_SUCCESS(NtStatus) );
  184. return NtStatus;
  185. }
  186. NTSTATUS CAxesItem::WriteToReport
  187. (
  188. PHIDP_PREPARSED_DATA pHidPreparsedData,
  189. PCHAR pcReport,
  190. LONG lReportLength
  191. ) const
  192. {
  193. NTSTATUS NtStatus;
  194. // Clear the sign extension before writing
  195. ULONG ulX, ulY;
  196. // Sign extend it (only if there are negatives)
  197. if (m_cpControlItemDesc->Axes.pRangeTable->lMinX < 0)
  198. {
  199. ulX = static_cast<ULONG>(ClearSignExtension(m_ItemState.Axes.lValX, m_cpControlItemDesc->usBitSize));
  200. }
  201. else
  202. {
  203. ulX = static_cast<ULONG>(m_ItemState.Axes.lValX);
  204. }
  205. if (m_cpControlItemDesc->Axes.pRangeTable->lMinY < 0)
  206. {
  207. ulY = static_cast<ULONG>(ClearSignExtension(m_ItemState.Axes.lValY, m_cpControlItemDesc->usBitSize));
  208. }
  209. else
  210. {
  211. ulY = static_cast<ULONG>(m_ItemState.Axes.lValY);
  212. }
  213. //
  214. // Write X
  215. //
  216. NtStatus = HidP_SetUsageValue(
  217. HidP_Input,
  218. m_cpControlItemDesc->UsagePage,
  219. m_cpControlItemDesc->usLinkCollection,
  220. m_cpControlItemDesc->Axes.UsageX,
  221. ulX,
  222. pHidPreparsedData,
  223. pcReport,
  224. lReportLength
  225. );
  226. #if 0
  227. //Should be okay without this check (Driver should handle it now)
  228. if (HIDP_STATUS_INCOMPATIBLE_REPORT_ID == NtStatus)
  229. {
  230. // according to the ddk documentation 2.6.3
  231. // HIDP_STATUS_INCOMPATIBLE_REPORT_ID is a 'valid' error
  232. // we try again with the next packet
  233. // keep the data unchanged
  234. return HIDP_STATUS_SUCCESS;
  235. }
  236. #endif
  237. if( NT_ERROR(NtStatus) )
  238. {
  239. ASSERT( NT_SUCCESS(NtStatus) );
  240. return NtStatus;
  241. }
  242. //
  243. // Write Y
  244. //
  245. NtStatus = HidP_SetUsageValue(
  246. HidP_Input,
  247. m_cpControlItemDesc->UsagePage,
  248. m_cpControlItemDesc->usLinkCollection,
  249. m_cpControlItemDesc->Axes.UsageY,
  250. ulY,
  251. pHidPreparsedData,
  252. pcReport,
  253. lReportLength
  254. );
  255. ASSERT( NT_SUCCESS(NtStatus) );
  256. return NtStatus;
  257. }
  258. NTSTATUS CDPADItem::ReadFromReport
  259. (
  260. PHIDP_PREPARSED_DATA pHidPreparsedData,
  261. PCHAR pcReport,
  262. LONG lReportLength
  263. )
  264. {
  265. NTSTATUS NtStatus;
  266. //
  267. // Read X
  268. //
  269. NtStatus = HidP_GetUsageValue(
  270. HidP_Input,
  271. m_cpControlItemDesc->UsagePage,
  272. m_cpControlItemDesc->usLinkCollection,
  273. m_cpControlItemDesc->DPAD.UsageX,
  274. reinterpret_cast<PULONG>(&m_ItemState.DPAD.lValX),
  275. pHidPreparsedData,
  276. pcReport,
  277. lReportLength
  278. );
  279. #if 0
  280. //Should be okay without this check (Driver should handle it now)
  281. if (HIDP_STATUS_INCOMPATIBLE_REPORT_ID == NtStatus)
  282. {
  283. // according to the ddk documentation 2.6.3
  284. // HIDP_STATUS_INCOMPATIBLE_REPORT_ID is a 'valid' error
  285. // we try again with the next packet
  286. // keep the data unchanged
  287. return HIDP_STATUS_SUCCESS;
  288. }
  289. #endif
  290. if( NT_ERROR(NtStatus) )
  291. {
  292. ASSERT( NT_SUCCESS(NtStatus) );
  293. return NtStatus;
  294. }
  295. //Sign extend it
  296. m_ItemState.DPAD.lValX = SignExtend(m_ItemState.DPAD.lValX, m_cpControlItemDesc->usBitSize);
  297. //
  298. // Read Y
  299. //
  300. NtStatus = HidP_GetUsageValue(
  301. HidP_Input,
  302. m_cpControlItemDesc->UsagePage,
  303. m_cpControlItemDesc->usLinkCollection,
  304. m_cpControlItemDesc->DPAD.UsageY,
  305. reinterpret_cast<PULONG>(&m_ItemState.DPAD.lValY),
  306. pHidPreparsedData,
  307. pcReport,
  308. lReportLength
  309. );
  310. ASSERT( NT_SUCCESS(NtStatus) );
  311. //Sign extend it
  312. m_ItemState.DPAD.lValY = SignExtend(m_ItemState.DPAD.lValY, m_cpControlItemDesc->usBitSize);
  313. return NtStatus;
  314. }
  315. NTSTATUS CDPADItem::WriteToReport
  316. (
  317. PHIDP_PREPARSED_DATA pHidPreparsedData,
  318. PCHAR pcReport,
  319. LONG lReportLength
  320. ) const
  321. {
  322. NTSTATUS NtStatus;
  323. // Clear the sign extension before writing
  324. ULONG ulX, ulY;
  325. ulX = static_cast<ULONG>(ClearSignExtension(m_ItemState.DPAD.lValX, m_cpControlItemDesc->usBitSize));
  326. ulY = static_cast<ULONG>(ClearSignExtension(m_ItemState.DPAD.lValY, m_cpControlItemDesc->usBitSize));
  327. //
  328. // Write X
  329. //
  330. NtStatus = HidP_SetUsageValue(
  331. HidP_Input,
  332. m_cpControlItemDesc->UsagePage,
  333. m_cpControlItemDesc->usLinkCollection,
  334. m_cpControlItemDesc->DPAD.UsageX,
  335. ulX,
  336. pHidPreparsedData,
  337. pcReport,
  338. lReportLength
  339. );
  340. #if 0
  341. //Should be okay without this check (Driver should handle it now)
  342. if (HIDP_STATUS_INCOMPATIBLE_REPORT_ID == NtStatus)
  343. {
  344. // according to the ddk documentation 2.6.3
  345. // HIDP_STATUS_INCOMPATIBLE_REPORT_ID is a 'valid' error
  346. // we try again with the next packet
  347. // keep the data unchanged
  348. return HIDP_STATUS_SUCCESS;
  349. }
  350. #endif
  351. if( NT_ERROR(NtStatus) )
  352. {
  353. ASSERT( NT_SUCCESS(NtStatus) );
  354. return NtStatus;
  355. }
  356. //
  357. // Write Y
  358. //
  359. NtStatus = HidP_SetUsageValue(
  360. HidP_Input,
  361. m_cpControlItemDesc->UsagePage,
  362. m_cpControlItemDesc->usLinkCollection,
  363. m_cpControlItemDesc->DPAD.UsageY,
  364. ulY,
  365. pHidPreparsedData,
  366. pcReport,
  367. lReportLength
  368. );
  369. ASSERT( NT_SUCCESS(NtStatus) );
  370. return NtStatus;
  371. }
  372. NTSTATUS CPropDPADItem::ReadFromReport(
  373. PHIDP_PREPARSED_DATA pHidPreparsedData,
  374. PCHAR pcReport,
  375. LONG lReportLength
  376. )
  377. {
  378. NTSTATUS NtStatus;
  379. //
  380. // Read X
  381. //
  382. NtStatus = HidP_GetUsageValue(
  383. HidP_Input,
  384. m_cpControlItemDesc->UsagePage,
  385. m_cpControlItemDesc->usLinkCollection,
  386. m_cpControlItemDesc->PropDPAD.UsageX,
  387. reinterpret_cast<PULONG>(&m_ItemState.PropDPAD.lValX),
  388. pHidPreparsedData,
  389. pcReport,
  390. lReportLength
  391. );
  392. #if 0
  393. //Should be okay without this check (Driver should handle it now)
  394. if (HIDP_STATUS_INCOMPATIBLE_REPORT_ID == NtStatus)
  395. {
  396. // according to the ddk documentation 2.6.3
  397. // HIDP_STATUS_INCOMPATIBLE_REPORT_ID is a 'valid' error
  398. // we try again with the next packet
  399. // keep the data unchanged
  400. return HIDP_STATUS_SUCCESS;
  401. }
  402. #endif
  403. if( NT_ERROR(NtStatus) )
  404. {
  405. ASSERT( NT_SUCCESS(NtStatus) );
  406. return NtStatus;
  407. }
  408. //Sign extend it
  409. m_ItemState.PropDPAD.lValX = SignExtend(m_ItemState.PropDPAD.lValX, m_cpControlItemDesc->usBitSize);
  410. //
  411. // Read Y
  412. //
  413. NtStatus = HidP_GetUsageValue(
  414. HidP_Input,
  415. m_cpControlItemDesc->UsagePage,
  416. m_cpControlItemDesc->usLinkCollection,
  417. m_cpControlItemDesc->PropDPAD.UsageY,
  418. reinterpret_cast<PULONG>(&m_ItemState.PropDPAD.lValY),
  419. pHidPreparsedData,
  420. pcReport,
  421. lReportLength
  422. );
  423. //Sign extend it
  424. m_ItemState.PropDPAD.lValY = SignExtend(m_ItemState.PropDPAD.lValY, m_cpControlItemDesc->usBitSize);
  425. ASSERT( NT_SUCCESS(NtStatus) );
  426. return NtStatus;
  427. }
  428. NTSTATUS CPropDPADItem::WriteToReport(
  429. PHIDP_PREPARSED_DATA pHidPreparsedData,
  430. PCHAR pcReport,
  431. LONG lReportLength
  432. ) const
  433. {
  434. NTSTATUS NtStatus;
  435. //Clear sign extension before writing
  436. ULONG ulX, ulY;
  437. ulX = static_cast<ULONG>(ClearSignExtension(m_ItemState.PropDPAD.lValX, m_cpControlItemDesc->usBitSize));
  438. ulY = static_cast<ULONG>(ClearSignExtension(m_ItemState.PropDPAD.lValY, m_cpControlItemDesc->usBitSize));
  439. //
  440. // Write X
  441. //
  442. NtStatus = HidP_SetUsageValue(
  443. HidP_Input,
  444. m_cpControlItemDesc->UsagePage,
  445. m_cpControlItemDesc->usLinkCollection,
  446. m_cpControlItemDesc->PropDPAD.UsageX,
  447. ulX,
  448. pHidPreparsedData,
  449. pcReport,
  450. lReportLength
  451. );
  452. #if 0
  453. //Should be okay without this check (Driver should handle it now)
  454. if (HIDP_STATUS_INCOMPATIBLE_REPORT_ID == NtStatus)
  455. {
  456. // according to the ddk documentation 2.6.3
  457. // HIDP_STATUS_INCOMPATIBLE_REPORT_ID is a 'valid' error
  458. // we try again with the next packet
  459. // keep the data unchanged
  460. return HIDP_STATUS_SUCCESS;
  461. }
  462. #endif
  463. if( NT_ERROR(NtStatus) )
  464. {
  465. ASSERT( NT_SUCCESS(NtStatus) );
  466. return NtStatus;
  467. }
  468. //
  469. // Write Y
  470. //
  471. NtStatus = HidP_SetUsageValue(
  472. HidP_Input,
  473. m_cpControlItemDesc->UsagePage,
  474. m_cpControlItemDesc->usLinkCollection,
  475. m_cpControlItemDesc->PropDPAD.UsageY,
  476. ulY,
  477. pHidPreparsedData,
  478. pcReport,
  479. lReportLength
  480. );
  481. ASSERT( NT_SUCCESS(NtStatus) );
  482. return NtStatus;
  483. }
  484. BOOLEAN CPropDPADItem::GetModeSwitchFeaturePacket(BOOLEAN fDigital, UCHAR rguReport[2], PHIDP_PREPARSED_DATA pHidPreparsedData)
  485. {
  486. if(m_fProgrammable)
  487. {
  488. PMODIFIER_ITEM_DESC pModifierDesc;
  489. ASSERT(m_cpControlItemDesc->pModifierDescTable->ulModifierCount > m_ucProgramModifierIndex);
  490. pModifierDesc = &m_cpControlItemDesc->pModifierDescTable->pModifierArray[m_ucProgramModifierIndex];
  491. rguReport[0] = pModifierDesc->ucReportId;
  492. rguReport[1] = NULL;
  493. NTSTATUS NtStatus;
  494. ULONG ulNumButtons = 1;
  495. if(fDigital)
  496. {
  497. NtStatus = HidP_SetButtons(
  498. HidP_Feature,
  499. pModifierDesc->UsagePage,
  500. pModifierDesc->usLinkCollection,
  501. &pModifierDesc->Usage,
  502. &ulNumButtons,
  503. pHidPreparsedData,
  504. (char *)rguReport,
  505. 2);
  506. }
  507. else
  508. {
  509. NtStatus = HidP_UnsetButtons(
  510. HidP_Feature,
  511. pModifierDesc->UsagePage,
  512. pModifierDesc->usLinkCollection,
  513. &pModifierDesc->Usage,
  514. &ulNumButtons,
  515. pHidPreparsedData,
  516. (char *)rguReport,
  517. 2);
  518. if(HIDP_STATUS_BUTTON_NOT_PRESSED == NtStatus)
  519. {
  520. NtStatus = HIDP_STATUS_SUCCESS;
  521. }
  522. }
  523. ASSERT(NT_SUCCESS(NtStatus));
  524. if( NT_ERROR(NtStatus) )
  525. {
  526. return FALSE;
  527. }
  528. }
  529. return m_fProgrammable;
  530. }
  531. /***********************************************************************************
  532. **
  533. ** CControlItemCollectionImpl::InitDigitalModeInfo
  534. **
  535. ** @mfunc Initializes info regarding whether and how digital\proportional
  536. ** information can be manipulated.
  537. **
  538. *************************************************************************************/
  539. void CPropDPADItem::InitDigitalModeInfo()
  540. {
  541. //Walk modifiers table looking for a proportional\digital mode switch
  542. //The first in the table should always be a bit in the input report
  543. //that indicates the state. This is true of all proportional\digital
  544. //axes controls. After that we look for a feature request that should
  545. //be at least writable. If we find one, than we indicate that device programmable.
  546. PMODIFIER_DESC_TABLE pModifierDescTable = m_cpControlItemDesc->pModifierDescTable;
  547. PMODIFIER_ITEM_DESC pModifierItemDesc;
  548. ULONG ulModifierIndex;
  549. m_ucDigitalModifierBit = 0xff; //initialize to indicate none
  550. for(
  551. ulModifierIndex = pModifierDescTable->ulShiftButtonCount; //skip shift buttons
  552. ulModifierIndex < pModifierDescTable->ulModifierCount; //don't overun aray
  553. ulModifierIndex++
  554. )
  555. {
  556. //Get pointer to item desc for convienence
  557. pModifierItemDesc = &pModifierDescTable->pModifierArray[ulModifierIndex];
  558. if(
  559. (ControlItemConst::HID_VENDOR_PAGE == pModifierItemDesc->UsagePage) &&
  560. (ControlItemConst::ucReportTypeInput == pModifierItemDesc->ucReportType)
  561. )
  562. {
  563. if(ControlItemConst::HID_VENDOR_TILT_SENSOR == pModifierItemDesc->Usage)
  564. {
  565. m_ucDigitalModifierBit = static_cast<UCHAR>(ulModifierIndex);
  566. ulModifierIndex++;
  567. break;
  568. }
  569. if(ControlItemConst::HID_VENDOR_PROPDPAD_MODE == pModifierItemDesc->Usage)
  570. {
  571. m_ucDigitalModifierBit = static_cast<UCHAR>(ulModifierIndex);
  572. ulModifierIndex++;
  573. break;
  574. }
  575. }
  576. }
  577. m_fProgrammable = FALSE;
  578. m_ucProgramModifierIndex = 0xFF;
  579. //Now look for switching feature
  580. for(
  581. ulModifierIndex = 0; //start at 0 index
  582. ulModifierIndex < pModifierDescTable->ulModifierCount; //don't overun aray
  583. ulModifierIndex++
  584. )
  585. {
  586. //Get pointer to item desc for convienence
  587. pModifierItemDesc = &pModifierDescTable->pModifierArray[ulModifierIndex];
  588. if(
  589. (ControlItemConst::HID_VENDOR_PAGE == pModifierItemDesc->UsagePage) &&
  590. (ControlItemConst::ucReportTypeFeature & pModifierItemDesc->ucReportType) &&
  591. (ControlItemConst::ucReportTypeWriteable & pModifierItemDesc->ucReportType) &&
  592. (ControlItemConst::HID_VENDOR_PROPDPAD_SWITCH == pModifierItemDesc->Usage)
  593. )
  594. {
  595. m_fProgrammable = TRUE;
  596. m_ucProgramModifierIndex = static_cast<UCHAR>(ulModifierIndex);
  597. break;
  598. }
  599. }
  600. }
  601. NTSTATUS CButtonsItem::ReadFromReport(
  602. PHIDP_PREPARSED_DATA pHidPreparsedData,
  603. PCHAR pcReport,
  604. LONG lReportLength
  605. )
  606. {
  607. NTSTATUS NtStatus;
  608. /*
  609. ** IMPORTANT! the array pUsages was previously allocated dynamically and deleted at the end
  610. ** of this function. This function get called frequently! The value ten was big enough for
  611. ** all get originally, if this assertion is ever hit in the future, it is very important
  612. ** to increase the value in the next to lines of code from 15 to whatever it must be to avoid
  613. ** this assertion.
  614. **/
  615. ASSERT(15 >= m_cpControlItemDesc->usReportCount && "!!!!IF HIT, MUST READ NOTE IN CODE");
  616. USAGE pUsages[15];
  617. ULONG ulNumUsages = static_cast<ULONG>(m_cpControlItemDesc->usReportCount);
  618. NtStatus = HidP_GetButtons(
  619. HidP_Input,
  620. m_cpControlItemDesc->UsagePage,
  621. m_cpControlItemDesc->usLinkCollection,
  622. pUsages,
  623. &ulNumUsages,
  624. pHidPreparsedData,
  625. pcReport,
  626. lReportLength
  627. );
  628. #if 0
  629. //Should be okay without this check (Driver should handle it now)
  630. if (HIDP_STATUS_INCOMPATIBLE_REPORT_ID == NtStatus)
  631. {
  632. // according to the ddk documentation 2.6.3
  633. // HIDP_STATUS_INCOMPATIBLE_REPORT_ID is a 'valid' error
  634. // we try again with the next packet
  635. // keep the data unchanged
  636. return HIDP_STATUS_SUCCESS;
  637. }
  638. #endif
  639. ASSERT( NT_SUCCESS(NtStatus) );
  640. if( NT_SUCCESS(NtStatus) )
  641. {
  642. //
  643. // Start with all buttons up
  644. //
  645. m_ItemState.Button.ulButtonBitArray = 0x0;
  646. if(ulNumUsages)
  647. {
  648. m_ItemState.Button.usButtonNumber = pUsages[0];
  649. }
  650. else
  651. {
  652. m_ItemState.Button.usButtonNumber = 0;
  653. }
  654. //
  655. // Now that we have button info fill in the state information
  656. //
  657. for(ULONG ulIndex = 0; ulIndex < ulNumUsages; ulIndex++)
  658. {
  659. //
  660. // Check Range and set bit of down buttons in range
  661. //
  662. if(
  663. (pUsages[ulIndex] >= m_cpControlItemDesc->Buttons.UsageMin) &&
  664. (pUsages[ulIndex] <= m_cpControlItemDesc->Buttons.UsageMax)
  665. )
  666. {
  667. //
  668. // Set Bit in array
  669. //
  670. m_ItemState.Button.ulButtonBitArray |=
  671. (1 << (pUsages[ulIndex]-m_cpControlItemDesc->Buttons.UsageMin));
  672. //
  673. // Update lowest number
  674. //
  675. if( m_ItemState.Button.usButtonNumber > pUsages[ulIndex] )
  676. {
  677. m_ItemState.Button.usButtonNumber = pUsages[ulIndex];
  678. }
  679. } //end of check if in range
  680. } //end of loop over buttons
  681. } //end of check for success
  682. return NtStatus;
  683. }
  684. NTSTATUS CButtonsItem::WriteToReport(
  685. PHIDP_PREPARSED_DATA pHidPreparsedData,
  686. PCHAR pcReport,
  687. LONG lReportLength
  688. ) const
  689. {
  690. NTSTATUS NtStatus;
  691. ULONG ulMaxUsages =
  692. (m_cpControlItemDesc->Buttons.UsageMax -
  693. m_cpControlItemDesc->Buttons.UsageMin) + 1;
  694. /*
  695. ** IMPORTANT! the array pUsages was previously allocated dynamically and deleted at the end
  696. ** of this function. This function get called frequently! The value ten was big enough for
  697. ** all get originally, if this assertion is ever hit in the future, it is very important
  698. ** to increase the value in the next to lines of code from 10 to whatever it must be to avoid
  699. ** this assertion.
  700. **/
  701. ASSERT(10 >= ulMaxUsages && "!!!!IF HIT, MUST READ NOTE IN CODE");
  702. USAGE pUsages[10];
  703. //
  704. // Fill in array of usages
  705. //
  706. ULONG ulNextToFill=0;
  707. for(ULONG ulIndex = 0; ulIndex < ulMaxUsages; ulIndex++)
  708. {
  709. if( (1 << ulIndex) & m_ItemState.Button.ulButtonBitArray )
  710. {
  711. pUsages[ulNextToFill++] = static_cast<USAGE>(ulIndex +
  712. m_cpControlItemDesc->Buttons.UsageMin);
  713. }
  714. }
  715. NtStatus = HidP_SetButtons(
  716. HidP_Input,
  717. m_cpControlItemDesc->UsagePage,
  718. m_cpControlItemDesc->usLinkCollection,
  719. pUsages,
  720. &ulNextToFill,
  721. pHidPreparsedData,
  722. pcReport,
  723. lReportLength
  724. );
  725. #if 0
  726. //Should be okay without this check (Driver should handle it now)
  727. if (HIDP_STATUS_INCOMPATIBLE_REPORT_ID == NtStatus)
  728. {
  729. // according to the ddk documentation 2.6.3
  730. // HIDP_STATUS_INCOMPATIBLE_REPORT_ID is a 'valid' error
  731. // we try again with the next packet
  732. // keep the data unchanged
  733. return HIDP_STATUS_SUCCESS;
  734. }
  735. #endif
  736. ASSERT( NT_SUCCESS(NtStatus) );
  737. return NtStatus;
  738. }
  739. //------------------------------------------------------------------
  740. // Implementation of CZoneIndicatorItem
  741. //------------------------------------------------------------------
  742. const ULONG CZoneIndicatorItem::X_ZONE = 0x00000001;
  743. const ULONG CZoneIndicatorItem::Y_ZONE = 0x00000002;
  744. const ULONG CZoneIndicatorItem::Z_ZONE = 0x00000004;
  745. //
  746. // Read\Write to Report
  747. //
  748. NTSTATUS CZoneIndicatorItem::ReadFromReport(
  749. PHIDP_PREPARSED_DATA pHidPreparsedData,
  750. PCHAR pcReport,
  751. LONG lReportLength
  752. )
  753. {
  754. NTSTATUS NtStatus;
  755. /*
  756. ** IMPORTANT! the array pUsages was previously allocated dynamically and deleted at the end
  757. ** of this function. This function get called frequently! The value three was big enough for
  758. ** all get originally, if this assertion is ever hit in the future, it is very important
  759. ** to increase the value in the next to lines of code from three to whatever it must be to avoid
  760. ** this assertion.
  761. **/
  762. ASSERT(3 >= m_cpControlItemDesc->usReportCount && "!!!!IF HIT, MUST READ NOTE IN CODE");
  763. USAGE pUsages[3];
  764. ULONG ulNumUsages = static_cast<ULONG>(m_cpControlItemDesc->usReportCount);
  765. NtStatus = HidP_GetButtons(
  766. HidP_Input,
  767. m_cpControlItemDesc->UsagePage,
  768. m_cpControlItemDesc->usLinkCollection,
  769. pUsages,
  770. &ulNumUsages,
  771. pHidPreparsedData,
  772. pcReport,
  773. lReportLength
  774. );
  775. #if 0
  776. //Should be okay without this check (Driver should handle it now)
  777. if (HIDP_STATUS_INCOMPATIBLE_REPORT_ID == NtStatus)
  778. {
  779. // according to the ddk documentation 2.6.3
  780. // HIDP_STATUS_INCOMPATIBLE_REPORT_ID is a 'valid' error
  781. // we try again with the next packet
  782. // keep the data unchanged
  783. return HIDP_STATUS_SUCCESS;
  784. }
  785. #endif
  786. ASSERT( NT_SUCCESS(NtStatus) );
  787. if( NT_SUCCESS(NtStatus) )
  788. {
  789. //
  790. // Start with no indicators set
  791. //
  792. m_ItemState.ZoneIndicators.ulZoneIndicatorBits = 0x0;
  793. //
  794. // Now that we have button info fill in the state information
  795. //
  796. for(ULONG ulIndex = 0; ulIndex < ulNumUsages; ulIndex++)
  797. {
  798. //
  799. // Set Bit in array
  800. //
  801. m_ItemState.ZoneIndicators.ulZoneIndicatorBits |=
  802. (1 << (pUsages[ulIndex]-m_cpControlItemDesc->ZoneIndicators.BaseIndicatorUsage));
  803. } //end of loop over buttons
  804. } //end of check for success
  805. return NtStatus;
  806. }
  807. NTSTATUS CZoneIndicatorItem::WriteToReport(
  808. PHIDP_PREPARSED_DATA pHidPreparsedData,
  809. PCHAR pcReport,
  810. LONG lReportLength
  811. ) const
  812. {
  813. NTSTATUS NtStatus;
  814. ULONG ulMaxUsages = m_cpControlItemDesc->usReportCount;
  815. /*
  816. ** IMPORTANT! the array pUsages was previously allocated dynamically and deleted at the end
  817. ** of this function. This function get called frequently! The value three was big enough for
  818. ** all get originally, if this assertion is ever hit in the future, it is very important
  819. ** to increase the value in the next to lines of code from three to whatever it must be to avoid
  820. ** this assertion.
  821. **/
  822. ASSERT(3 >= m_cpControlItemDesc->usReportCount && "!!!!IF HIT, MUST READ NOTE IN CODE");
  823. USAGE pUsages[3];
  824. //
  825. // Fill in array of usages
  826. //
  827. ULONG ulNextToFill=0;
  828. for(ULONG ulIndex = 0; ulIndex < ulMaxUsages; ulIndex++)
  829. {
  830. if( (1 << ulIndex) & m_ItemState.ZoneIndicators.ulZoneIndicatorBits )
  831. {
  832. pUsages[ulNextToFill++] = static_cast<USAGE>(ulIndex +
  833. m_cpControlItemDesc->ZoneIndicators.BaseIndicatorUsage);
  834. }
  835. }
  836. NtStatus = HidP_SetButtons(
  837. HidP_Input,
  838. m_cpControlItemDesc->UsagePage,
  839. m_cpControlItemDesc->usLinkCollection,
  840. pUsages,
  841. &ulNextToFill,
  842. pHidPreparsedData,
  843. pcReport,
  844. lReportLength
  845. );
  846. #if 0
  847. //Should be okay without this check (Driver should handle it now)
  848. if (HIDP_STATUS_INCOMPATIBLE_REPORT_ID == NtStatus)
  849. {
  850. // according to the ddk documentation 2.6.3
  851. // HIDP_STATUS_INCOMPATIBLE_REPORT_ID is a 'valid' error
  852. // we try again with the next packet
  853. // keep the data unchanged
  854. return HIDP_STATUS_SUCCESS;
  855. }
  856. #endif
  857. ASSERT( NT_SUCCESS(NtStatus) );
  858. return NtStatus;
  859. }
  860. // **************** Implementation of DualZoneIndicator Item ******************* //
  861. void CDualZoneIndicatorItem::SetActiveZone(LONG lZone)
  862. {
  863. ASSERT((lZone >= 0) && (lZone <= m_cpControlItemDesc->DualZoneIndicators.lNumberOfZones));
  864. if (m_cpControlItemDesc->DualZoneIndicators.rgUsageAxis[1] == 0)
  865. {
  866. ASSERT(m_cpControlItemDesc->DualZoneIndicators.lNumberOfZones == 2);
  867. if (lZone == 1)
  868. {
  869. m_ItemState.DualZoneIndicators.rglVal[0] = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lMin[0];
  870. }
  871. else if (lZone == 2)
  872. {
  873. m_ItemState.DualZoneIndicators.rglVal[0] = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lMax[0];
  874. }
  875. else
  876. {
  877. m_ItemState.DualZoneIndicators.rglVal[0] = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lCenter[0];
  878. }
  879. return;
  880. }
  881. m_ItemState.DualZoneIndicators.rglVal[0] = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lCenter[0];
  882. m_ItemState.DualZoneIndicators.rglVal[1] = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lCenter[1];
  883. switch (lZone)
  884. {
  885. case 1:
  886. m_ItemState.DualZoneIndicators.rglVal[0] = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lMin[0];
  887. case 2:
  888. m_ItemState.DualZoneIndicators.rglVal[1] = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lMin[1];
  889. break;
  890. case 3:
  891. m_ItemState.DualZoneIndicators.rglVal[1] = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lMin[1];
  892. case 4:
  893. m_ItemState.DualZoneIndicators.rglVal[0] = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lMax[0];
  894. break;
  895. case 5:
  896. m_ItemState.DualZoneIndicators.rglVal[0] = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lMax[0];
  897. m_ItemState.DualZoneIndicators.rglVal[1] = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lMax[1];
  898. case 6:
  899. m_ItemState.DualZoneIndicators.rglVal[1] = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lMax[1];
  900. break;
  901. case 7:
  902. m_ItemState.DualZoneIndicators.rglVal[1] = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lMax[1];
  903. case 8:
  904. m_ItemState.DualZoneIndicators.rglVal[0] = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lMin[0];
  905. break;
  906. }
  907. }
  908. /*
  909. USHORT g_FourByFourTileMaps[7] =
  910. {
  911. 0x0000,
  912. 0x0011,
  913. 0xFFFF,
  914. 0x3377,
  915. 0xFFC0,
  916. 0xC000,
  917. 0x3348
  918. };
  919. USHORT g_EightByEightTiles[16] = // 4 Entries (4 bits each) - 4x4 array
  920. {
  921. 0x0000, 0x0103, 0x2222, 0x2222,
  922. 0x0000, 0x1232, 0x2222, 0x2222,
  923. 0x0103, 0x2222, 0x2245, 0x4500,
  924. 0x1265, 0x4500, 0x0000, 0x0000
  925. };
  926. // Currently Fixed for 8 zones
  927. LONG CDualZoneIndicatorItem::GetActiveZone()
  928. {
  929. LONG lxReading = 0 - m_cpControlItemDesc->DualZoneIndicators.pRangeTable->lCenterX;
  930. LONG lyReading = 0 - m_cpControlItemDesc->DualZoneIndicators.pRangeTable->lCenterY;
  931. LONG lxHalfRange = m_cpControlItemDesc->DualZoneIndicators.pRangeTable->lMaxX - m_cpControlItemDesc->DualZoneIndicators.pRangeTable->lCenterX;
  932. LONG lyHalfRange = m_cpControlItemDesc->DualZoneIndicators.pRangeTable->lMaxY - m_cpControlItemDesc->DualZoneIndicators.pRangeTable->lCenterY;
  933. for (int n = 0; n < 2; n++)
  934. {
  935. if (m_cpControlItemDesc->DualZoneIndicators.rgUsageAxis[n] == HID_USAGE_GENERIC_X)
  936. {
  937. lxReading += m_ItemState.DualZoneIndicators.rglVal[n];
  938. }
  939. else
  940. {
  941. lyReading += m_ItemState.DualZoneIndicators.rglVal[n];
  942. }
  943. }
  944. // Translate to +/+ quadrant
  945. LONG lxTranslation = lxReading - m_cpControlItemDesc->DualZoneIndicators.pRangeTable->lCenterX;
  946. if (lxTranslation < 0)
  947. {
  948. lxTranslation = 0 - lxTranslation;
  949. }
  950. LONG lyTranslation = lyReading - m_cpControlItemDesc->DualZoneIndicators.pRangeTable->lCenterY;
  951. if (lyTranslation < 0)
  952. {
  953. lyTranslation = 0 - lyTranslation;
  954. }
  955. // What 32nd of the Quadrant am I in (512 << 5 fits fine in a ULONG)
  956. USHORT us32QuadrantX = USHORT(ULONG((ULONG(lxTranslation << 5) + lxHalfRange - 1)/lxHalfRange));
  957. USHORT us32QuadrantY = USHORT(ULONG((ULONG(lyTranslation << 5) + lyHalfRange - 1)/lxHalfRange));
  958. // What Eight of the Quadrant am I in?
  959. USHORT us8QuadrantX = us32QuadrantX >> 2;
  960. USHORT us8QuadrantY = us32QuadrantY >> 2;
  961. // What Quarter of the Quadrant am I in
  962. USHORT us4QuadrantX = us8QuadrantX >> 1;
  963. USHORT us4QuadrantY = us8QuadrantX >> 1;
  964. // Use the magic from above to find the pixel value
  965. USHORT usOctantValue = g_EightByEightTiles[us4QuadrantX + us8QuadrantY]; // x + 4*y
  966. USHORT usOctantNibble = (us8QuadrantX % 2) + ((us8QuadrantY % 2) << 1) * 4;
  967. USHORT usOctantNibbleValue = (usOctantValue & (0x0F << usOctantNibble)) >> usOctantNibble;
  968. USHORT usBit = g_FourByFourTileMaps[usOctantNibbleValue] & (1 << ((us32QuadrantX % 4) + ((us32QuadrantX % 4) << 2)));
  969. return usBit;
  970. };
  971. */
  972. inline BOOLEAN FirstSlopeGreater(LONG x1, LONG y1, LONG x2, LONG y2)
  973. {
  974. return BOOLEAN((y1 * x2) > (y2 * x1));
  975. }
  976. inline BOOLEAN FirstSlopeLess(LONG x1, LONG y1, LONG x2, LONG y2)
  977. {
  978. return BOOLEAN((y1 * x2) < (y2 * x1));
  979. }
  980. // Dansan's method (much simplier)
  981. // Currently Fixed for 8 zones (or 2)
  982. LONG CDualZoneIndicatorItem::GetActiveZone(SHORT sXDeadZone, SHORT sYDeadZone)
  983. {
  984. // Get the two values (assume x/y or just x)
  985. LONG lxReading = m_ItemState.DualZoneIndicators.rglVal[0] - m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lCenter[0];
  986. LONG lyReading = 0;
  987. if (m_cpControlItemDesc->DualZoneIndicators.rgUsageAxis[1] != 0)
  988. { // Also flip Y about the axis
  989. lyReading = m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lCenter[1] - m_ItemState.DualZoneIndicators.rglVal[1];
  990. }
  991. else // Single axis
  992. {
  993. if (lxReading < -sXDeadZone)
  994. {
  995. return 1;
  996. }
  997. if (lxReading > sXDeadZone)
  998. {
  999. return 2;
  1000. }
  1001. return 0;
  1002. }
  1003. // Rule out the center
  1004. if (lxReading < sXDeadZone)
  1005. {
  1006. if (lxReading > -sXDeadZone)
  1007. {
  1008. if (lyReading < sYDeadZone)
  1009. {
  1010. if (lyReading > -sYDeadZone)
  1011. {
  1012. return 0;
  1013. }
  1014. }
  1015. }
  1016. }
  1017. // First find the quadrant (++0 +-1 --2 -+3)
  1018. UCHAR ucQuadrant = 0;
  1019. if (lxReading >= 0)
  1020. {
  1021. ucQuadrant = (lyReading >= 0) ? 0 : 1;
  1022. }
  1023. else
  1024. {
  1025. ucQuadrant = (lyReading < 0) ? 2 : 3;
  1026. }
  1027. // Determine the reading based on the quadrant
  1028. switch (ucQuadrant)
  1029. {
  1030. case 0: // Slope goes from infinity to 0 (sectors 2,3,4)
  1031. if (FirstSlopeGreater(lxReading, lyReading, c_lM1X, c_lM1Y))
  1032. {
  1033. return 2;
  1034. }
  1035. if (FirstSlopeLess(lxReading, lyReading, c_lM2X, c_lM2Y))
  1036. {
  1037. return 4;
  1038. }
  1039. return 3;
  1040. case 1: // Slope goes from 0 to -infinity (sectors 4,5,6)
  1041. if (FirstSlopeGreater(lxReading, lyReading, c_lM2X, -c_lM2Y))
  1042. {
  1043. return 4;
  1044. }
  1045. if (FirstSlopeLess(lxReading, lyReading, c_lM1X, -c_lM1Y))
  1046. {
  1047. return 6;
  1048. }
  1049. return 5;
  1050. case 2: // Slope goes from infinity to 0 (sectors 6,7,8)
  1051. if (FirstSlopeGreater(lxReading, lyReading, -c_lM1X, -c_lM1Y))
  1052. {
  1053. return 6;
  1054. }
  1055. if (FirstSlopeLess(lxReading, lyReading, -c_lM2X, -c_lM2Y))
  1056. {
  1057. return 8;
  1058. }
  1059. return 7;
  1060. case 3: // Slope goes from 0 to -infinity (sectors 8,1,2)
  1061. if (FirstSlopeGreater(lxReading, lyReading, -c_lM2X, c_lM2Y))
  1062. {
  1063. return 8;
  1064. }
  1065. if (FirstSlopeLess(lxReading, lyReading, -c_lM1X, c_lM1Y))
  1066. {
  1067. return 2;
  1068. }
  1069. return 1;
  1070. default:
  1071. ASSERT(FALSE);
  1072. return 0;
  1073. }
  1074. }
  1075. LONG CDualZoneIndicatorItem::GetActiveZone()
  1076. {
  1077. return GetActiveZone( SHORT(m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lDeadZone[0]),
  1078. SHORT(m_cpControlItemDesc->DualZoneIndicators.pZoneRangeTable->lDeadZone[1])
  1079. );
  1080. }
  1081. //
  1082. // Read\Write to Report
  1083. //
  1084. NTSTATUS CDualZoneIndicatorItem::ReadFromReport(
  1085. PHIDP_PREPARSED_DATA pHidPreparsedData,
  1086. PCHAR pcReport,
  1087. LONG lReportLength
  1088. )
  1089. {
  1090. NTSTATUS NtStatus;
  1091. //
  1092. // Read Data
  1093. //
  1094. for (int n = 0; n < 2; n++)
  1095. {
  1096. // Read if the item is valid
  1097. if (m_cpControlItemDesc->DualZoneIndicators.rgUsageAxis[n] != 0)
  1098. {
  1099. NtStatus = HidP_GetUsageValue(
  1100. HidP_Input,
  1101. m_cpControlItemDesc->UsagePage,
  1102. m_cpControlItemDesc->usLinkCollection,
  1103. m_cpControlItemDesc->DualZoneIndicators.rgUsageAxis[n],
  1104. reinterpret_cast<PULONG>(&m_ItemState.DualZoneIndicators.rglVal[n]),
  1105. pHidPreparsedData,
  1106. pcReport,
  1107. lReportLength
  1108. );
  1109. if( FAILED(NtStatus) )
  1110. {
  1111. ASSERT( NT_SUCCESS(NtStatus) );
  1112. return NtStatus;
  1113. }
  1114. //Sign extend it
  1115. m_ItemState.DualZoneIndicators.rglVal[n] = SignExtend(m_ItemState.DualZoneIndicators.rglVal[n], m_cpControlItemDesc->usBitSize);
  1116. }
  1117. else
  1118. {
  1119. m_ItemState.DualZoneIndicators.rglVal[n] = 0;
  1120. }
  1121. }
  1122. return NtStatus;
  1123. }
  1124. NTSTATUS CDualZoneIndicatorItem::WriteToReport(
  1125. PHIDP_PREPARSED_DATA pHidPreparsedData,
  1126. PCHAR pcReport,
  1127. LONG lReportLength
  1128. ) const
  1129. {
  1130. NTSTATUS NtStatus;
  1131. for (int n = 0; n < 2; n++)
  1132. {
  1133. // Clear the sign extension before writing
  1134. ULONG ulItem =
  1135. static_cast<ULONG>(ClearSignExtension(m_ItemState.DualZoneIndicators.rglVal[n], m_cpControlItemDesc->usBitSize));
  1136. // Write Item if it is valid
  1137. if (m_cpControlItemDesc->DualZoneIndicators.rgUsageAxis[n] != 0)
  1138. {
  1139. NtStatus = HidP_SetUsageValue(
  1140. HidP_Input,
  1141. m_cpControlItemDesc->UsagePage,
  1142. m_cpControlItemDesc->usLinkCollection,
  1143. m_cpControlItemDesc->DualZoneIndicators.rgUsageAxis[n],
  1144. ulItem,
  1145. pHidPreparsedData,
  1146. pcReport,
  1147. lReportLength
  1148. );
  1149. if( NT_ERROR(NtStatus) )
  1150. {
  1151. ASSERT( NT_SUCCESS(NtStatus) );
  1152. return NtStatus;
  1153. }
  1154. }
  1155. }
  1156. return NtStatus;
  1157. }
  1158. NTSTATUS CGenericItem::ReadFromReport(
  1159. PHIDP_PREPARSED_DATA pHidPreparsedData,
  1160. PCHAR pcReport,
  1161. LONG lReportLength
  1162. )
  1163. {
  1164. NTSTATUS NtStatus;
  1165. //
  1166. // Read Value
  1167. //
  1168. NtStatus = HidP_GetUsageValue(
  1169. HidP_Input,
  1170. m_cpControlItemDesc->UsagePage,
  1171. m_cpControlItemDesc->usLinkCollection,
  1172. m_cpControlItemDesc->Generic.Usage,
  1173. reinterpret_cast<PULONG>(&m_ItemState.Generic.lVal),
  1174. pHidPreparsedData,
  1175. pcReport,
  1176. lReportLength
  1177. );
  1178. #if 0
  1179. //Should be okay without this check (Driver should handle it now)
  1180. if (HIDP_STATUS_INCOMPATIBLE_REPORT_ID == NtStatus)
  1181. {
  1182. // according to the ddk documentation 2.6.3
  1183. // HIDP_STATUS_INCOMPATIBLE_REPORT_ID is a 'valid' error
  1184. // we try again with the next packet
  1185. // keep the data unchanged
  1186. return HIDP_STATUS_SUCCESS;
  1187. }
  1188. #endif
  1189. //Sign extend it
  1190. if(m_cpControlItemDesc->Generic.lMin < 0)
  1191. {
  1192. m_ItemState.Generic.lVal = SignExtend(m_ItemState.Generic.lVal, m_cpControlItemDesc->usBitSize);
  1193. }
  1194. ASSERT( NT_SUCCESS(NtStatus) );
  1195. return NtStatus;
  1196. }
  1197. /***********************************************************************************
  1198. **
  1199. ** CPedalItem::InitPedalPresentInfo
  1200. **
  1201. ** @mfunc Initializes info how to read if pedals are present.
  1202. **
  1203. *************************************************************************************/
  1204. void CPedalItem::InitPedalPresentInfo()
  1205. {
  1206. //Walk modifiers table looking for a Pedals present switch
  1207. //The first in the table should always be a bit in the input report
  1208. //that indicates the state. This is true of all proportional\digital
  1209. //axes controls. After that we look for a feature request that should
  1210. //be at least writable. If we find one, than we indicate that device programmable.
  1211. PMODIFIER_DESC_TABLE pModifierDescTable = m_cpControlItemDesc->pModifierDescTable;
  1212. PMODIFIER_ITEM_DESC pModifierItemDesc;
  1213. ULONG ulModifierIndex;
  1214. m_ucPedalsPresentModifierBit = 0xff; //initialize to indicate none
  1215. for(
  1216. ulModifierIndex = pModifierDescTable->ulShiftButtonCount; //skip shift buttons
  1217. ulModifierIndex < pModifierDescTable->ulModifierCount; //don't overun aray
  1218. ulModifierIndex++
  1219. )
  1220. {
  1221. //Get pointer to item desc for convienence
  1222. pModifierItemDesc = &pModifierDescTable->pModifierArray[ulModifierIndex];
  1223. if(
  1224. (ControlItemConst::HID_VENDOR_PAGE == pModifierItemDesc->UsagePage) &&
  1225. (ControlItemConst::ucReportTypeInput == pModifierItemDesc->ucReportType)
  1226. )
  1227. {
  1228. if(ControlItemConst::HID_VENDOR_PEDALS_PRESENT == pModifierItemDesc->Usage)
  1229. {
  1230. m_ucPedalsPresentModifierBit = static_cast<UCHAR>(ulModifierIndex);
  1231. ulModifierIndex++;
  1232. break;
  1233. }
  1234. }
  1235. }
  1236. }
  1237. NTSTATUS CGenericItem::WriteToReport(
  1238. PHIDP_PREPARSED_DATA pHidPreparsedData,
  1239. PCHAR pcReport,
  1240. LONG lReportLength
  1241. ) const
  1242. {
  1243. NTSTATUS NtStatus;
  1244. //Clear sign extension before writing
  1245. ULONG ulVal;
  1246. if(m_cpControlItemDesc->Generic.lMin < 0)
  1247. {
  1248. ulVal = static_cast<ULONG>(ClearSignExtension(m_ItemState.Generic.lVal, m_cpControlItemDesc->usBitSize));
  1249. }
  1250. else
  1251. {
  1252. ulVal = m_ItemState.Generic.lVal;
  1253. }
  1254. //
  1255. // Write Value
  1256. //
  1257. NtStatus = HidP_SetUsageValue(
  1258. HidP_Input,
  1259. m_cpControlItemDesc->UsagePage,
  1260. m_cpControlItemDesc->usLinkCollection,
  1261. m_cpControlItemDesc->Generic.Usage,
  1262. ulVal,
  1263. pHidPreparsedData,
  1264. pcReport,
  1265. lReportLength
  1266. );
  1267. #if 0
  1268. //Should be okay without this check (Driver should handle it now)
  1269. if (HIDP_STATUS_INCOMPATIBLE_REPORT_ID == NtStatus)
  1270. {
  1271. // according to the ddk documentation 2.6.3
  1272. // HIDP_STATUS_INCOMPATIBLE_REPORT_ID is a 'valid' error
  1273. // we try again with the next packet
  1274. // keep the data unchanged
  1275. return HIDP_STATUS_SUCCESS;
  1276. }
  1277. #endif
  1278. ASSERT( NT_SUCCESS(NtStatus) );
  1279. return NtStatus;
  1280. }
  1281. NTSTATUS ControlItemsFuncs::ReadModifiersFromReport
  1282. (
  1283. PMODIFIER_DESC_TABLE pModifierDescTable,
  1284. ULONG& rulModifiers,
  1285. PHIDP_PREPARSED_DATA pHidPPreparsedData,
  1286. PCHAR pcReport,
  1287. LONG lReportLength
  1288. )
  1289. {
  1290. if (NULL == pModifierDescTable)
  1291. return 42;
  1292. CIC_DBG_RT_ENTRY_PRINT(("ControlItemsFuncs::ReadModifiersFromReport ModTable = 0x%0.8x\n", pModifierDescTable));
  1293. NTSTATUS NtStatus = 0;
  1294. rulModifiers = 0;
  1295. // A caveat here is that each entry must have usReportCount as large as the largest
  1296. ULONG ulNumUsages = static_cast<ULONG>(pModifierDescTable->pModifierArray->usReportCount);
  1297. /*
  1298. ** IMPORTANT! the array pUsages was previously allocated dynamically and deleted at the end
  1299. ** of this function. This function get called frequently! The value ten was big enough for
  1300. ** all originally. If this assertion is ever hit in the future, it is very important
  1301. ** to increase the value in the next to lines of code from ten to whatever it must be to avoid
  1302. ** this assertion.
  1303. **/
  1304. ASSERT(15 >= pModifierDescTable->pModifierArray->usReportCount && "!!!!IF HIT, MUST READ NOTE IN CODE");
  1305. USAGE pUsages[15];
  1306. USAGE UsageToGet;
  1307. // Loop over all the modifiers
  1308. ULONG ulIndex=0;
  1309. for(ulIndex = 0; ulIndex < pModifierDescTable->ulModifierCount; ulIndex++)
  1310. {
  1311. //
  1312. // Only try to read inputs
  1313. //
  1314. if( ControlItemConst::ucReportTypeInput != pModifierDescTable->pModifierArray[ulIndex].ucReportType)
  1315. { continue; }
  1316. UsageToGet = pModifierDescTable->pModifierArray[ulIndex].Usage;
  1317. // The tilt sensor (legacy) is a special case, it has a digital value,
  1318. // but is actually a two bit value and therefore we transform it.
  1319. if( ControlItemConst::HID_VENDOR_TILT_SENSOR == UsageToGet)
  1320. {
  1321. ULONG ulValueToRead;
  1322. NtStatus = HidP_GetUsageValue(
  1323. HidP_Input,
  1324. pModifierDescTable->pModifierArray[ulIndex].UsagePage,
  1325. pModifierDescTable->pModifierArray[ulIndex].usLinkCollection,
  1326. UsageToGet,
  1327. &ulValueToRead,
  1328. pHidPPreparsedData,
  1329. pcReport,
  1330. lReportLength
  1331. );
  1332. if( NT_ERROR(NtStatus) )
  1333. {
  1334. break;
  1335. }
  1336. //Set the bit appropriately
  1337. if(ulValueToRead)
  1338. {
  1339. rulModifiers |= (1 << ulIndex);
  1340. }
  1341. else
  1342. {
  1343. rulModifiers &= ~(1 << ulIndex);
  1344. }
  1345. continue;
  1346. }
  1347. //Processing for all modifiers other than the Tilt Sensor continues here
  1348. ulNumUsages = static_cast<ULONG>(pModifierDescTable->pModifierArray->usReportCount);
  1349. NtStatus = HidP_GetButtons(
  1350. HidP_Input,
  1351. pModifierDescTable->pModifierArray[ulIndex].UsagePage,
  1352. pModifierDescTable->pModifierArray[ulIndex].usLinkCollection,
  1353. pUsages,
  1354. &ulNumUsages,
  1355. pHidPPreparsedData,
  1356. pcReport,
  1357. lReportLength
  1358. );
  1359. if( NT_ERROR(NtStatus) )
  1360. {
  1361. CIC_DBG_CRITICAL_PRINT(("HidP_GetButtons returned = 0x%0.8x\n", NtStatus));
  1362. break;
  1363. }
  1364. //
  1365. // Loop over usages returned
  1366. //
  1367. for(ULONG ulUsageIndex = 0; ulUsageIndex < ulNumUsages; ulUsageIndex++)
  1368. {
  1369. if( pUsages[ulUsageIndex] == UsageToGet )
  1370. {
  1371. rulModifiers |= (1 << ulIndex);
  1372. break;
  1373. }
  1374. }
  1375. }
  1376. return NtStatus;
  1377. }
  1378. NTSTATUS ControlItemsFuncs::WriteModifiersToReport
  1379. (
  1380. PMODIFIER_DESC_TABLE pModifierDescTable,
  1381. ULONG ulModifiers,
  1382. PHIDP_PREPARSED_DATA pHidPPreparsedData,
  1383. PCHAR pcReport,
  1384. LONG lReportLength
  1385. )
  1386. {
  1387. if (NULL == pModifierDescTable)
  1388. return 42;
  1389. NTSTATUS NtStatus = 0;
  1390. ULONG ulNumUsages=1;
  1391. USAGE UsageToSet;
  1392. //
  1393. // Loop over all the modifiers
  1394. //
  1395. ULONG ulIndex=0;
  1396. for(ulIndex = 0; ulIndex < pModifierDescTable->ulModifierCount; ulIndex++)
  1397. {
  1398. ulNumUsages = 1;
  1399. UsageToSet = pModifierDescTable->pModifierArray[ulIndex].Usage;
  1400. // The tilt sensor (legacy) is a special case, it has a digital value,
  1401. // but is actually a two bit value and therefore we transform it.
  1402. if( ControlItemConst::HID_VENDOR_TILT_SENSOR == UsageToSet)
  1403. {
  1404. ULONG ValueToWrite = (ulModifiers & (1 << ulIndex)) ? 2 : 0;
  1405. NtStatus = HidP_SetUsageValue(
  1406. HidP_Input,
  1407. pModifierDescTable->pModifierArray[ulIndex].UsagePage,
  1408. pModifierDescTable->pModifierArray[ulIndex].usLinkCollection,
  1409. UsageToSet,
  1410. ValueToWrite,
  1411. pHidPPreparsedData,
  1412. pcReport,
  1413. lReportLength
  1414. );
  1415. if( NT_ERROR(NtStatus) )
  1416. {
  1417. break;
  1418. }
  1419. continue;
  1420. }
  1421. // All modifiers beside the legacy tilt-sensor are one bit values
  1422. if( ulModifiers & (1 << ulIndex) )
  1423. {
  1424. // Now set the binary value
  1425. NtStatus = HidP_SetButtons(
  1426. HidP_Input,
  1427. pModifierDescTable->pModifierArray[ulIndex].UsagePage,
  1428. pModifierDescTable->pModifierArray[ulIndex].usLinkCollection,
  1429. &UsageToSet,
  1430. &ulNumUsages,
  1431. pHidPPreparsedData,
  1432. pcReport,
  1433. lReportLength
  1434. );
  1435. }
  1436. else
  1437. {
  1438. // Now set the binary value
  1439. NtStatus = HidP_UnsetButtons(
  1440. HidP_Input,
  1441. pModifierDescTable->pModifierArray[ulIndex].UsagePage,
  1442. pModifierDescTable->pModifierArray[ulIndex].usLinkCollection,
  1443. &UsageToSet,
  1444. &ulNumUsages,
  1445. pHidPPreparsedData,
  1446. pcReport,
  1447. lReportLength
  1448. );
  1449. }
  1450. if( NT_ERROR(NtStatus) )
  1451. {
  1452. break;
  1453. }
  1454. }
  1455. return NtStatus;
  1456. }
  1457. NTSTATUS CForceMapItem::ReadFromReport
  1458. (
  1459. PHIDP_PREPARSED_DATA pHidPreparsedData,
  1460. PCHAR pcReport,
  1461. LONG lReportLength
  1462. )
  1463. {
  1464. return HIDP_STATUS_SUCCESS;
  1465. }
  1466. NTSTATUS CForceMapItem::WriteToReport
  1467. (
  1468. PHIDP_PREPARSED_DATA pHidPreparsedData,
  1469. PCHAR pcReport,
  1470. LONG lReportLength
  1471. ) const
  1472. {
  1473. return HIDP_STATUS_SUCCESS;
  1474. }
  1475. NTSTATUS CProfileSelector::ReadFromReport
  1476. (
  1477. PHIDP_PREPARSED_DATA pHidPreparsedData,
  1478. PCHAR pcReport,
  1479. LONG lReportLength
  1480. )
  1481. {
  1482. NTSTATUS NtStatus;
  1483. /*
  1484. ** IMPORTANT! the array pUsages was previously allocated dynamically and deleted at the end
  1485. ** of this function. This function get called frequently! The value ten was big enough for
  1486. ** all get originally, if this assertion is ever hit in the future, it is very important
  1487. ** to increase the value in the next to lines of code from 15 to whatever it must be to avoid
  1488. ** this assertion.
  1489. **/
  1490. ASSERT(15 >= m_cpControlItemDesc->usReportCount && "!!!!IF HIT, MUST READ NOTE IN CODE");
  1491. USAGE pUsages[15];
  1492. ULONG ulNumUsages = static_cast<ULONG>(m_cpControlItemDesc->usReportCount);
  1493. NtStatus = HidP_GetButtons(
  1494. HidP_Input,
  1495. m_cpControlItemDesc->UsagePage,
  1496. m_cpControlItemDesc->usLinkCollection,
  1497. pUsages,
  1498. &ulNumUsages,
  1499. pHidPreparsedData,
  1500. pcReport,
  1501. lReportLength
  1502. );
  1503. ASSERT( NT_SUCCESS(NtStatus) );
  1504. if( NT_SUCCESS(NtStatus) )
  1505. {
  1506. for (int usageIndex = 0; usageIndex < (long)ulNumUsages; usageIndex++)
  1507. {
  1508. if (pUsages[usageIndex] >= m_cpControlItemDesc->ProfileSelectors.UsageButtonMin)
  1509. {
  1510. if (pUsages[usageIndex] <= m_cpControlItemDesc->ProfileSelectors.UsageButtonMax)
  1511. {
  1512. m_ItemState.ProfileSelector.lVal = pUsages[usageIndex] - m_cpControlItemDesc->ProfileSelectors.UsageButtonMin;
  1513. if (m_cpControlItemDesc->ProfileSelectors.ulFirstProfile < m_cpControlItemDesc->ProfileSelectors.ulLastProfile)
  1514. {
  1515. m_ItemState.ProfileSelector.lVal += m_cpControlItemDesc->ProfileSelectors.ulFirstProfile;
  1516. }
  1517. else
  1518. {
  1519. m_ItemState.ProfileSelector.lVal = m_cpControlItemDesc->ProfileSelectors.ulFirstProfile - m_ItemState.ProfileSelector.lVal;
  1520. }
  1521. return NtStatus;
  1522. }
  1523. }
  1524. }
  1525. }
  1526. return NtStatus;
  1527. }
  1528. NTSTATUS CProfileSelector::WriteToReport
  1529. (
  1530. PHIDP_PREPARSED_DATA pHidPreparsedData,
  1531. PCHAR pcReport,
  1532. LONG lReportLength
  1533. ) const
  1534. {
  1535. return HIDP_STATUS_SUCCESS;
  1536. }
  1537. NTSTATUS CButtonLED::ReadFromReport
  1538. (
  1539. PHIDP_PREPARSED_DATA pHidPreparsedData,
  1540. PCHAR pcReport,
  1541. LONG lReportLength
  1542. )
  1543. {
  1544. return HIDP_STATUS_SUCCESS; // We really don't care what they look like
  1545. }
  1546. NTSTATUS CButtonLED::WriteToReport
  1547. (
  1548. PHIDP_PREPARSED_DATA pHidPreparsedData,
  1549. PCHAR pcReport,
  1550. LONG lReportLength
  1551. ) const
  1552. {
  1553. return HIDP_STATUS_SUCCESS;
  1554. }