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.

3042 lines
94 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. query.c
  5. Abstract:
  6. This module contains the code for querying HID report packets.
  7. Environment:
  8. Kernel & user mode
  9. Revision History:
  10. Aug-96 : created by Kenneth Ray
  11. --*/
  12. #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
  13. #include <wtypes.h>
  14. #include "hidsdi.h"
  15. #include "hidparse.h"
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(PAGE, HidP_GetCaps)
  18. #pragma alloc_text(PAGE, HidP_GetLinkCollectionNodes)
  19. #pragma alloc_text(PAGE, HidP_GetButtonCaps)
  20. #pragma alloc_text(PAGE, HidP_GetSpecificButtonCaps)
  21. #pragma alloc_text(PAGE, HidP_GetValueCaps)
  22. #pragma alloc_text(PAGE, HidP_GetSpecificValueCaps)
  23. #pragma alloc_text(PAGE, HidP_MaxUsageListLength)
  24. #pragma alloc_text(PAGE, HidP_InitializeReportForID)
  25. #pragma alloc_text(PAGE, HidP_GetExtendedAttributes)
  26. #endif
  27. #define PAGED_CODE()
  28. #ifndef HIDPARSE_USERMODE
  29. #if DBG
  30. typedef UCHAR KIRQL;
  31. KIRQL KeGetCurrentIrql();
  32. #define APC_LEVEL 0x1
  33. ULONG _cdecl DbgPrint (PCH Format, ...);
  34. NTSYSAPI VOID NTAPI RtlAssert(PVOID, PVOID, ULONG, PCHAR);
  35. #define ASSERT( exp ) \
  36. if (!(exp)) RtlAssert( #exp, __FILE__, __LINE__, NULL )
  37. #undef PAGED_CODE
  38. #define PAGED_CODE() \
  39. if (KeGetCurrentIrql() > APC_LEVEL) { \
  40. HidP_KdPrint(2, ( "EX: Pageable code called at IRQL %d\n", KeGetCurrentIrql() )); \
  41. ASSERT(FALSE); \
  42. }
  43. #else // DBG
  44. #define ASSERT(x)
  45. #endif // DBG
  46. #else // HIDPARSE_USERMODE
  47. #define ASSERT(x)
  48. #endif // HIDPARSE_USERMODE
  49. #define CHECK_PPD(_x_) \
  50. if ((HIDP_PREPARSED_DATA_SIGNATURE1 != (_x_)->Signature1) ||\
  51. (HIDP_PREPARSED_DATA_SIGNATURE2 != (_x_)->Signature2)) \
  52. { return HIDP_STATUS_INVALID_PREPARSED_DATA; }
  53. ULONG
  54. HidP_ExtractData (
  55. IN USHORT ByteOffset,
  56. IN USHORT BitOffset,
  57. IN USHORT BitLength,
  58. IN PUCHAR Report
  59. )
  60. /*++
  61. Routine Description:
  62. Given a HID report a byte offset, bit offset and bitlength extract the
  63. bits from the report in little endian BIT order.
  64. --*/
  65. {
  66. ULONG inspect = 0;
  67. USHORT tmpByte = 0;
  68. USHORT tmpBit = 0;
  69. // Start with the high bits and work our way down.
  70. //
  71. // Little endian (by bit)
  72. // Byte 2 |Byte 1 |Byte 0
  73. // 765432107654321076543210 (bits)
  74. //
  75. // Get low byte first. (need the higher bits)
  76. // Offset is from bit zero.
  77. //
  78. tmpByte = (ByteOffset << 3) + BitOffset + BitLength;
  79. tmpBit = tmpByte & 7;
  80. tmpByte >>= 3;
  81. if (BitLength < tmpBit) {
  82. inspect = (UCHAR) Report [tmpByte] & ((1 << tmpBit) - 1);
  83. inspect >>= BitOffset;
  84. return inspect;
  85. }
  86. if (tmpBit)
  87. { // Not Byte alligned!
  88. inspect = (UCHAR) Report [tmpByte] & ((1 << tmpBit) - 1);
  89. BitLength -= tmpBit;
  90. }
  91. tmpByte--;
  92. while (BitLength >= 8)
  93. {
  94. inspect <<= 8;
  95. inspect |= (UCHAR) Report[tmpByte];
  96. BitLength -= 8;
  97. tmpByte--;
  98. }
  99. if (BitLength)
  100. {
  101. inspect <<= BitLength;
  102. inspect |= (UCHAR) ( (Report [tmpByte] >> (8 - BitLength))
  103. & ((1 << BitLength) - 1));
  104. }
  105. return inspect;
  106. }
  107. void
  108. HidP_InsertData (
  109. IN USHORT ByteOffset,
  110. IN USHORT BitOffset,
  111. IN USHORT BitLength, // Length of the value set in bits.
  112. IN OUT PUCHAR Report,
  113. IN ULONG Value
  114. )
  115. /*++
  116. Routine Description:
  117. Given a HID report a byte offset, bit offset and bitlength set those bits
  118. in little endian BIT order to the value provided.
  119. --*/
  120. {
  121. ULONG mask;
  122. ULONG tmpBit;
  123. //
  124. // Little endian (by bit)
  125. // Byte 2 |Byte 1 |Byte 0
  126. // 765432107654321076543210 (bits)
  127. //
  128. // Get low byte first. (need the higher bits)
  129. // Offset is from bit zero.
  130. //
  131. tmpBit = BitLength + BitOffset;
  132. if (tmpBit < 8) {
  133. mask = (1 << tmpBit) - (1 << BitOffset);
  134. Report [ByteOffset] &= ~mask;
  135. Report [ByteOffset] |= (UCHAR) ((Value << BitOffset) & mask);
  136. return;
  137. }
  138. if (BitOffset)
  139. { // Not byte aligned, deal with the last partial byte.
  140. Report [ByteOffset] &= ((1 << BitOffset) - 1); // Zap upper bits
  141. Report [ByteOffset] |= (UCHAR) (Value << BitOffset);
  142. BitLength -= (8 - BitOffset);
  143. Value >>= (8 - BitOffset);
  144. ByteOffset++;
  145. }
  146. while (BitLength >= 8)
  147. {
  148. Report [ByteOffset] = (UCHAR) Value;
  149. Value >>= 8;
  150. BitLength -= 8;
  151. ByteOffset++;
  152. }
  153. if (BitLength)
  154. {
  155. Report [ByteOffset] &= ((UCHAR) 0 - (UCHAR) (1 << BitLength));
  156. // Zap lower bits.
  157. Report [ByteOffset] |= (Value & ((1 << BitLength) - 1));
  158. }
  159. }
  160. HidP_DeleteArrayEntry (
  161. IN ULONG BitPos,
  162. IN USHORT BitLength, // Length of the value set in bits.
  163. IN USHORT ReportCount,
  164. IN ULONG Value, // Value to delete.
  165. IN OUT PUCHAR Report
  166. )
  167. /*++
  168. Routine Description:
  169. Given a HID report a byte offset, bit offset and bitlength
  170. remove that data item from the report, by shifting all data items
  171. left until the last item finally setting that one to zero.
  172. In otherwards clear the given entry from the hid array.
  173. NOTE: If there are two such values set we only eliminate the first one.
  174. --*/
  175. {
  176. ULONG tmpValue;
  177. ULONG localBitPos; // for debugging only. Compiler should kill this line.
  178. ULONG localRemaining;
  179. ULONG nextBitPos;
  180. localBitPos = BitPos;
  181. tmpValue = 0;
  182. localRemaining = ReportCount;
  183. ASSERT (0 < ReportCount);
  184. ASSERT (0 != Value);
  185. //
  186. // Find the data.
  187. //
  188. while (0 < localRemaining) {
  189. tmpValue = HidP_ExtractData ((USHORT) (localBitPos >> 3),
  190. (USHORT) (localBitPos & 7),
  191. BitLength,
  192. Report);
  193. if (Value == tmpValue) {
  194. break;
  195. }
  196. localBitPos += BitLength;
  197. localRemaining--;
  198. }
  199. if (Value != tmpValue) {
  200. return HIDP_STATUS_BUTTON_NOT_PRESSED;
  201. }
  202. while (1 < localRemaining) {
  203. nextBitPos = localBitPos + BitLength;
  204. tmpValue = HidP_ExtractData ((USHORT) (nextBitPos >> 3),
  205. (USHORT) (nextBitPos & 7),
  206. BitLength,
  207. Report);
  208. HidP_InsertData ((USHORT) (localBitPos >> 3),
  209. (USHORT) (localBitPos & 7),
  210. BitLength,
  211. Report,
  212. tmpValue);
  213. localBitPos = nextBitPos;
  214. localRemaining--;
  215. }
  216. HidP_InsertData ((USHORT) (localBitPos >> 3),
  217. (USHORT) (localBitPos & 7),
  218. BitLength,
  219. Report,
  220. 0);
  221. return HIDP_STATUS_SUCCESS;
  222. }
  223. NTSTATUS __stdcall
  224. HidP_GetCaps (
  225. IN PHIDP_PREPARSED_DATA PreparsedData,
  226. OUT PHIDP_CAPS Capabilities
  227. )
  228. /*++
  229. Routine Description:
  230. Please see Hidpi.h for routine description
  231. Notes:
  232. --*/
  233. {
  234. ULONG i;
  235. HIDP_CHANNEL_DESC * data;
  236. PAGED_CODE();
  237. CHECK_PPD (PreparsedData);
  238. RtlZeroMemory (Capabilities, sizeof(HIDP_CAPS));
  239. Capabilities->UsagePage = PreparsedData->UsagePage;
  240. Capabilities->Usage = PreparsedData->Usage;
  241. Capabilities->InputReportByteLength = PreparsedData->Input.ByteLen;
  242. Capabilities->OutputReportByteLength = PreparsedData->Output.ByteLen;
  243. Capabilities->FeatureReportByteLength = PreparsedData->Feature.ByteLen;
  244. // Reserved fields go here
  245. Capabilities->NumberLinkCollectionNodes =
  246. PreparsedData->LinkCollectionArrayLength;
  247. Capabilities->NumberInputButtonCaps = 0;
  248. Capabilities->NumberInputValueCaps = 0;
  249. Capabilities->NumberOutputButtonCaps = 0;
  250. Capabilities->NumberOutputValueCaps = 0;
  251. Capabilities->NumberFeatureButtonCaps = 0;
  252. Capabilities->NumberFeatureValueCaps = 0;
  253. i=PreparsedData->Input.Offset;
  254. data = &PreparsedData->Data[i];
  255. Capabilities->NumberInputDataIndices = 0;
  256. for (; i < PreparsedData->Input.Index; i++, data++)
  257. {
  258. if (data->IsButton)
  259. {
  260. Capabilities->NumberInputButtonCaps++;
  261. } else
  262. {
  263. Capabilities->NumberInputValueCaps++;
  264. }
  265. Capabilities->NumberInputDataIndices += data->Range.DataIndexMax
  266. - data->Range.DataIndexMin
  267. + 1;
  268. }
  269. i=PreparsedData->Output.Offset;
  270. data = &PreparsedData->Data[i];
  271. Capabilities->NumberOutputDataIndices = 0;
  272. for (; i < PreparsedData->Output.Index; i++, data++)
  273. {
  274. if (data->IsButton)
  275. {
  276. Capabilities->NumberOutputButtonCaps++;
  277. } else
  278. {
  279. Capabilities->NumberOutputValueCaps++;
  280. }
  281. Capabilities->NumberOutputDataIndices += data->Range.DataIndexMax
  282. - data->Range.DataIndexMin
  283. + 1;
  284. }
  285. i=PreparsedData->Feature.Offset;
  286. data = &PreparsedData->Data[i];
  287. Capabilities->NumberFeatureDataIndices = 0;
  288. for (; i < PreparsedData->Feature.Index; i++, data++)
  289. {
  290. if (data->IsButton)
  291. {
  292. Capabilities->NumberFeatureButtonCaps++;
  293. } else
  294. {
  295. Capabilities->NumberFeatureValueCaps++;
  296. }
  297. Capabilities->NumberFeatureDataIndices += data->Range.DataIndexMax
  298. - data->Range.DataIndexMin
  299. + 1;
  300. }
  301. return HIDP_STATUS_SUCCESS;
  302. }
  303. NTSTATUS __stdcall
  304. HidP_GetLinkCollectionNodes (
  305. OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes,
  306. IN OUT PULONG LinkCollectionNodesLength,
  307. IN PHIDP_PREPARSED_DATA PreparsedData
  308. )
  309. /*++
  310. Routine Description:
  311. Please see Hidpi.h for routine description
  312. --*/
  313. {
  314. PHIDP_PRIVATE_LINK_COLLECTION_NODE nodeArray;
  315. ULONG length;
  316. ULONG i;
  317. NTSTATUS status = HIDP_STATUS_SUCCESS;
  318. PAGED_CODE();
  319. CHECK_PPD (PreparsedData);
  320. if (*LinkCollectionNodesLength < PreparsedData->LinkCollectionArrayLength) {
  321. length = *LinkCollectionNodesLength;
  322. status = HIDP_STATUS_BUFFER_TOO_SMALL;
  323. } else {
  324. length = PreparsedData->LinkCollectionArrayLength;
  325. }
  326. *LinkCollectionNodesLength = PreparsedData->LinkCollectionArrayLength;
  327. nodeArray = (PHIDP_PRIVATE_LINK_COLLECTION_NODE)
  328. (PreparsedData->RawBytes +
  329. PreparsedData->LinkCollectionArrayOffset);
  330. for (i = 0;
  331. i < length;
  332. i++, LinkCollectionNodes++, nodeArray++ ) {
  333. // *LinkCollectionNodes = *nodeArray;
  334. LinkCollectionNodes->LinkUsage = nodeArray->LinkUsage;
  335. LinkCollectionNodes->LinkUsagePage = nodeArray->LinkUsagePage;
  336. LinkCollectionNodes->Parent = nodeArray->Parent;
  337. LinkCollectionNodes->NumberOfChildren = nodeArray->NumberOfChildren;
  338. LinkCollectionNodes->NextSibling = nodeArray->NextSibling;
  339. LinkCollectionNodes->FirstChild = nodeArray->FirstChild;
  340. LinkCollectionNodes->CollectionType = nodeArray->CollectionType;
  341. LinkCollectionNodes->IsAlias = nodeArray->IsAlias;
  342. }
  343. return status;
  344. }
  345. #undef HidP_GetButtonCaps
  346. NTSTATUS __stdcall
  347. HidP_GetButtonCaps (
  348. IN HIDP_REPORT_TYPE ReportType,
  349. OUT PHIDP_BUTTON_CAPS ButtonCaps,
  350. IN OUT PUSHORT ButtonCapsLength,
  351. IN PHIDP_PREPARSED_DATA PreparsedData
  352. )
  353. /*++
  354. Routine Description:
  355. Please see Hidpi.h for routine description
  356. Notes:
  357. --*/
  358. {
  359. return HidP_GetSpecificButtonCaps (ReportType,
  360. 0,
  361. 0,
  362. 0,
  363. ButtonCaps,
  364. ButtonCapsLength,
  365. PreparsedData);
  366. }
  367. NTSTATUS __stdcall
  368. HidP_GetSpecificButtonCaps (
  369. IN HIDP_REPORT_TYPE ReportType,
  370. IN USAGE UsagePage, // Optional (0 => ignore)
  371. IN USHORT LinkCollection, // Optional (0 => ignore)
  372. IN USAGE Usage, // Optional (0 => ignore)
  373. OUT PHIDP_BUTTON_CAPS ButtonCaps,
  374. IN OUT PUSHORT ButtonCapsLength,
  375. IN PHIDP_PREPARSED_DATA PreparsedData
  376. )
  377. /*++
  378. Routine Description:
  379. Please see Hidpi.h for routine description
  380. Notes:
  381. --*/
  382. {
  383. struct _CHANNEL_REPORT_HEADER * iof;
  384. PHIDP_CHANNEL_DESC channel;
  385. NTSTATUS status = HIDP_STATUS_USAGE_NOT_FOUND;
  386. USHORT i, j;
  387. PAGED_CODE();
  388. CHECK_PPD (PreparsedData);
  389. switch (ReportType) {
  390. case HidP_Input:
  391. iof = &PreparsedData->Input;
  392. break;
  393. case HidP_Output:
  394. iof = &PreparsedData->Output;
  395. break;
  396. case HidP_Feature:
  397. iof = &PreparsedData->Feature;
  398. break;
  399. default:
  400. return HIDP_STATUS_INVALID_REPORT_TYPE;
  401. }
  402. for (i = iof->Offset, j = 0; i < iof->Index ; i++)
  403. {
  404. channel = &PreparsedData->Data[i];
  405. if ((channel->IsButton) &&
  406. ((!UsagePage || (UsagePage == channel->UsagePage)) &&
  407. (!LinkCollection || (LinkCollection == channel->LinkCollection)
  408. || ((HIDP_LINK_COLLECTION_ROOT == LinkCollection) &&
  409. (0 == channel->LinkCollection))) &&
  410. (!Usage || ((channel->Range.UsageMin <= Usage) &&
  411. (Usage <= channel->Range.UsageMax)))))
  412. {
  413. status = HIDP_STATUS_SUCCESS;
  414. if (j < *ButtonCapsLength)
  415. {
  416. ButtonCaps[j].UsagePage = channel->UsagePage;
  417. ButtonCaps[j].LinkCollection = channel->LinkCollection;
  418. ButtonCaps[j].LinkUsagePage = channel->LinkUsagePage;
  419. ButtonCaps[j].LinkUsage = channel->LinkUsage;
  420. ButtonCaps[j].IsRange = (BOOLEAN) channel->IsRange;
  421. ButtonCaps[j].IsStringRange = (BOOLEAN) channel->IsStringRange;
  422. ButtonCaps[j].IsDesignatorRange=(BOOLEAN)channel->IsDesignatorRange;
  423. ButtonCaps[j].ReportID = channel->ReportID;
  424. ButtonCaps[j].BitField = (USHORT) channel->BitField;
  425. ButtonCaps[j].IsAbsolute = (BOOLEAN) channel->IsAbsolute;
  426. ButtonCaps[j].IsAlias = (BOOLEAN) channel->IsAlias;
  427. // if (channel->IsRange)
  428. // {
  429. ButtonCaps[j].Range.UsageMin = channel->Range.UsageMin;
  430. ButtonCaps[j].Range.UsageMax = channel->Range.UsageMax;
  431. ButtonCaps[j].Range.DataIndexMin = channel->Range.DataIndexMin;
  432. ButtonCaps[j].Range.DataIndexMax = channel->Range.DataIndexMax;
  433. // } else
  434. // {
  435. // ButtonCaps[j].NotRange.Usage = channel->NotRange.Usage;
  436. // }
  437. // if (channel->IsStringRange)
  438. // {
  439. ButtonCaps[j].Range.StringMin = channel->Range.StringMin;
  440. ButtonCaps[j].Range.StringMax = channel->Range.StringMax;
  441. // } else
  442. // {
  443. // ButtonCaps[j].NotRange.StringIndex
  444. // = channel->NotRange.StringIndex;
  445. // }
  446. // if (channel->IsDesignatorRange)
  447. // {
  448. ButtonCaps[j].Range.DesignatorMin = channel->Range.DesignatorMin;
  449. ButtonCaps[j].Range.DesignatorMax = channel->Range.DesignatorMax;
  450. // } else
  451. // {
  452. // ButtonCaps[j].NotRange.DesignatorIndex
  453. // = channel->NotRange.DesignatorIndex;
  454. // }
  455. } else {
  456. status = HIDP_STATUS_BUFFER_TOO_SMALL;
  457. }
  458. j++;
  459. }
  460. }
  461. *ButtonCapsLength = j;
  462. return status;
  463. }
  464. #undef HidP_GetValueCaps
  465. NTSTATUS __stdcall
  466. HidP_GetValueCaps (
  467. IN HIDP_REPORT_TYPE ReportType,
  468. OUT PHIDP_VALUE_CAPS ValueCaps,
  469. IN OUT PUSHORT ValueCapsLength,
  470. IN PHIDP_PREPARSED_DATA PreparsedData
  471. )
  472. /*++
  473. Routine Description:
  474. Please see Hidpi.h for routine description
  475. Notes:
  476. --*/
  477. {
  478. return HidP_GetSpecificValueCaps (ReportType,
  479. 0,
  480. 0,
  481. 0,
  482. ValueCaps,
  483. ValueCapsLength,
  484. PreparsedData);
  485. }
  486. NTSTATUS __stdcall
  487. HidP_GetSpecificValueCaps (
  488. IN HIDP_REPORT_TYPE ReportType,
  489. IN USAGE UsagePage, // Optional (0 => ignore)
  490. IN USHORT LinkCollection, // Optional (0 => ignore)
  491. IN USAGE Usage, // Optional (0 => ignore)
  492. OUT PHIDP_VALUE_CAPS ValueCaps,
  493. IN OUT PUSHORT ValueCapsLength,
  494. IN PHIDP_PREPARSED_DATA PreparsedData
  495. )
  496. /*++
  497. Routine Description:
  498. Please see Hidpi.h for routine description
  499. Notes:
  500. --*/
  501. {
  502. struct _CHANNEL_REPORT_HEADER * iof;
  503. PHIDP_CHANNEL_DESC channel;
  504. NTSTATUS status = HIDP_STATUS_USAGE_NOT_FOUND;
  505. USHORT i, j;
  506. CHECK_PPD (PreparsedData);
  507. PAGED_CODE ();
  508. switch (ReportType) {
  509. case HidP_Input:
  510. iof = &PreparsedData->Input;
  511. break;
  512. case HidP_Output:
  513. iof = &PreparsedData->Output;
  514. break;
  515. case HidP_Feature:
  516. iof = &PreparsedData->Feature;
  517. break;
  518. default:
  519. return HIDP_STATUS_INVALID_REPORT_TYPE;
  520. }
  521. for (i = iof->Offset, j = 0; i < iof->Index ; i++)
  522. {
  523. channel = &PreparsedData->Data[i];
  524. if ((!channel->IsButton) &&
  525. ((!UsagePage || (UsagePage == channel->UsagePage)) &&
  526. (!LinkCollection || (LinkCollection == channel->LinkCollection)
  527. || ((HIDP_LINK_COLLECTION_ROOT == LinkCollection) &&
  528. (0 == channel->LinkCollection))) &&
  529. (!Usage || ((channel->Range.UsageMin <= Usage) &&
  530. (Usage <= channel->Range.UsageMax)))))
  531. {
  532. status = HIDP_STATUS_SUCCESS;
  533. if (j < *ValueCapsLength)
  534. {
  535. ValueCaps[j].UsagePage = channel->UsagePage;
  536. ValueCaps[j].LinkCollection = channel->LinkCollection;
  537. ValueCaps[j].LinkUsagePage = channel->LinkUsagePage;
  538. ValueCaps[j].LinkUsage = channel->LinkUsage;
  539. ValueCaps[j].IsRange = (BOOLEAN) channel->IsRange;
  540. ValueCaps[j].IsStringRange = (BOOLEAN) channel->IsStringRange;
  541. ValueCaps[j].IsDesignatorRange =(BOOLEAN)channel->IsDesignatorRange;
  542. ValueCaps[j].ReportID = channel->ReportID;
  543. ValueCaps[j].BitField = (USHORT) channel->BitField;
  544. ValueCaps[j].BitSize = channel->ReportSize;
  545. ValueCaps[j].IsAbsolute = (BOOLEAN) channel->IsAbsolute;
  546. ValueCaps[j].HasNull = channel->Data.HasNull;
  547. ValueCaps[j].Units = channel->Units;
  548. ValueCaps[j].UnitsExp = channel->UnitExp;
  549. ValueCaps[j].LogicalMin = channel->Data.LogicalMin;
  550. ValueCaps[j].LogicalMax = channel->Data.LogicalMax;
  551. ValueCaps[j].PhysicalMin = channel->Data.PhysicalMin;
  552. ValueCaps[j].PhysicalMax = channel->Data.PhysicalMax;
  553. ValueCaps[j].IsAlias = (BOOLEAN) channel->IsAlias;
  554. // if (channel->IsRange)
  555. // {
  556. ValueCaps[j].Range.UsageMin = channel->Range.UsageMin;
  557. ValueCaps[j].Range.UsageMax = channel->Range.UsageMax;
  558. ValueCaps[j].Range.DataIndexMin = channel->Range.DataIndexMin;
  559. ValueCaps[j].Range.DataIndexMax = channel->Range.DataIndexMax;
  560. // } else
  561. // {
  562. // ValueCaps[j].NotRange.Usage = channel->NotRange.Usage;
  563. // }
  564. // if (channel->IsStringRange)
  565. // {
  566. ValueCaps[j].Range.StringMin = channel->Range.StringMin;
  567. ValueCaps[j].Range.StringMax = channel->Range.StringMax;
  568. // } else
  569. // {
  570. // ValueCaps[j].NotRange.StringIndex
  571. // = channel->NotRange.StringIndex;
  572. // }
  573. // if (channel->IsDesignatorRange)
  574. // {
  575. ValueCaps[j].Range.DesignatorMin = channel->Range.DesignatorMin;
  576. ValueCaps[j].Range.DesignatorMax = channel->Range.DesignatorMax;
  577. // } else
  578. // {
  579. // ValueCaps[j].NotRange.DesignatorIndex
  580. // = channel->NotRange.DesignatorIndex;
  581. // }
  582. ValueCaps[j].ReportCount = (channel->IsRange)
  583. ? 1
  584. : channel->ReportCount;
  585. } else {
  586. status = HIDP_STATUS_BUFFER_TOO_SMALL;
  587. }
  588. j++;
  589. }
  590. }
  591. *ValueCapsLength = j;
  592. return status;
  593. }
  594. NTSTATUS __stdcall
  595. HidP_GetExtendedAttributes (
  596. IN HIDP_REPORT_TYPE ReportType,
  597. IN USHORT DataIndex,
  598. IN PHIDP_PREPARSED_DATA PreparsedData,
  599. OUT PHIDP_EXTENDED_ATTRIBUTES Attributes,
  600. IN OUT PULONG LengthAttributes
  601. )
  602. /*++
  603. Routine Description:
  604. Please See hidpi.h for description.
  605. --*/
  606. {
  607. struct _CHANNEL_REPORT_HEADER * iof;
  608. PHIDP_CHANNEL_DESC channel;
  609. HIDP_EXTENDED_ATTRIBUTES buffer;
  610. ULONG channelIndex = 0;
  611. NTSTATUS status = HIDP_STATUS_DATA_INDEX_NOT_FOUND;
  612. ULONG i;
  613. ULONG actualLen, copyLen = 0;
  614. CHECK_PPD (PreparsedData);
  615. PAGED_CODE ();
  616. switch (ReportType) {
  617. case HidP_Input:
  618. iof = &PreparsedData->Input;
  619. break;
  620. case HidP_Output:
  621. iof = &PreparsedData->Output;
  622. break;
  623. case HidP_Feature:
  624. iof = &PreparsedData->Feature;
  625. break;
  626. default:
  627. return HIDP_STATUS_INVALID_REPORT_TYPE;
  628. }
  629. for (channelIndex = iof->Offset, channel = PreparsedData->Data;
  630. channelIndex < iof->Index;
  631. channelIndex++, channel++) {
  632. if ((channel->Range.DataIndexMin <= DataIndex) &&
  633. (DataIndex <= channel->Range.DataIndexMax)) {
  634. RtlZeroMemory (Attributes, *LengthAttributes);
  635. RtlZeroMemory (&buffer, sizeof (buffer));
  636. //
  637. // Set the fixed parameters
  638. //
  639. buffer.NumGlobalUnknowns = (UCHAR) channel->NumGlobalUnknowns;
  640. // buffer.GlobalUnknowns = channel->GlobalUnknowns;
  641. //
  642. // Set the length
  643. //
  644. actualLen = FIELD_OFFSET (HIDP_EXTENDED_ATTRIBUTES, Data)
  645. + (buffer.NumGlobalUnknowns * sizeof(HIDP_UNKNOWN_TOKEN));
  646. //
  647. // Copy over the fixed paramters
  648. //
  649. copyLen = MIN (*LengthAttributes, sizeof (buffer));
  650. RtlCopyMemory (Attributes, &buffer, copyLen);
  651. //
  652. // Copy over the data.
  653. //
  654. copyLen = MIN (*LengthAttributes, actualLen)
  655. - FIELD_OFFSET (HIDP_EXTENDED_ATTRIBUTES, Data);
  656. if (copyLen && copyLen <= (MIN(*LengthAttributes, actualLen))) {
  657. RtlCopyMemory ((PVOID) Attributes->Data,
  658. (PVOID) channel->GlobalUnknowns,
  659. copyLen);
  660. }
  661. if (*LengthAttributes < actualLen) {
  662. status = HIDP_STATUS_BUFFER_TOO_SMALL;
  663. } else {
  664. status = HIDP_STATUS_SUCCESS;
  665. }
  666. break;
  667. }
  668. }
  669. return status;
  670. }
  671. NTSTATUS __stdcall
  672. HidP_InitializeReportForID (
  673. IN HIDP_REPORT_TYPE ReportType,
  674. IN UCHAR ReportID,
  675. IN PHIDP_PREPARSED_DATA PreparsedData,
  676. IN OUT PCHAR Report,
  677. IN ULONG ReportLength
  678. )
  679. /*++
  680. Routine Description:
  681. Please See hidpi.h for description.
  682. --*/
  683. {
  684. struct _CHANNEL_REPORT_HEADER * iof;
  685. PHIDP_CHANNEL_DESC channel;
  686. NTSTATUS status = HIDP_STATUS_REPORT_DOES_NOT_EXIST;
  687. ULONG channelIndex = 0;
  688. ULONG reportBitIndex = 0;
  689. ULONG nullMask = 0;
  690. LONG nullValue = 0;
  691. ULONG i;
  692. CHECK_PPD (PreparsedData);
  693. PAGED_CODE ();
  694. switch (ReportType) {
  695. case HidP_Input:
  696. iof = &PreparsedData->Input;
  697. break;
  698. case HidP_Output:
  699. iof = &PreparsedData->Output;
  700. break;
  701. case HidP_Feature:
  702. iof = &PreparsedData->Feature;
  703. break;
  704. default:
  705. return HIDP_STATUS_INVALID_REPORT_TYPE;
  706. }
  707. if ((USHORT) ReportLength != iof->ByteLen) {
  708. return HIDP_STATUS_INVALID_REPORT_LENGTH;
  709. }
  710. if (0 == iof->ByteLen) {
  711. return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
  712. }
  713. RtlZeroMemory (Report, ReportLength);
  714. // Set the report ID for this report
  715. Report[0] = ReportID;
  716. for (channelIndex = iof->Offset, channel = PreparsedData->Data;
  717. channelIndex < iof->Index;
  718. channelIndex++, channel++) {
  719. //
  720. // Walk the list of channels looking for fields that need initialization
  721. //
  722. if (channel->ReportID != ReportID) {
  723. continue;
  724. }
  725. status = HIDP_STATUS_SUCCESS;
  726. if ((channel->IsButton) || (channel->IsConst) || (channel->IsAlias)) {
  727. //
  728. // Buttons are initialized to zero
  729. // Constants cannot be set
  730. // Aliases are referenced by their first entries
  731. //
  732. continue;
  733. }
  734. if (channel->Data.HasNull) {
  735. if (32 == channel->ReportSize) {
  736. nullMask = -1;
  737. } else {
  738. nullMask = (1 << channel->ReportSize) - 1;
  739. }
  740. //
  741. // Note logical values are always unsigned.
  742. // (Not to be confused with physical values which are signed.)
  743. //
  744. if (channel->Data.LogicalMax < channel->Data.LogicalMin) {
  745. //
  746. // This is really an error. I'm not sure what I should do here.
  747. //
  748. nullValue = 0;
  749. } else {
  750. nullValue = (channel->Data.LogicalMin - 1) & nullMask;
  751. }
  752. if ((channel->Data.LogicalMin <= nullValue) &&
  753. (nullValue <= channel->Data.LogicalMax)) {
  754. //
  755. //
  756. //
  757. // Now what?
  758. //
  759. nullValue = 0;
  760. }
  761. } else {
  762. //
  763. // I don't know what I should do in this case: the device has no
  764. // reported nul state.
  765. //
  766. // For now let's just leave it zero
  767. //
  768. nullValue = 0;
  769. }
  770. if (0 == nullValue) {
  771. //
  772. // Nothing to do on this pass
  773. //
  774. continue;
  775. }
  776. if (channel->IsRange) {
  777. for (i = 0, reportBitIndex = (channel->ByteOffset << 3)
  778. + (channel->BitOffset);
  779. i < channel->ReportCount;
  780. i++, reportBitIndex += channel->ReportSize) {
  781. //
  782. // Set all the fields in the range
  783. //
  784. HidP_InsertData ((USHORT) (reportBitIndex >> 3),
  785. (USHORT) (reportBitIndex & 7),
  786. channel->ReportSize,
  787. Report,
  788. nullValue);
  789. }
  790. } else {
  791. HidP_InsertData (channel->ByteOffset,
  792. channel->BitOffset,
  793. channel->ReportSize,
  794. Report,
  795. nullValue);
  796. }
  797. }
  798. return status;
  799. }
  800. USAGE
  801. HidP_Index2Usage (
  802. PHIDP_CHANNEL_DESC Channels,
  803. ULONG Index
  804. )
  805. /*++
  806. Routine Description:
  807. Given an array of channels convert an index (the likes of which you might
  808. find in an array field of a HID report) into a usage value.
  809. --*/
  810. {
  811. USHORT len;
  812. PHIDP_CHANNEL_DESC startChannel = Channels;
  813. USAGE usageMin;
  814. USAGE usageMax;
  815. if (!Index) {
  816. return 0;
  817. }
  818. while (Channels->MoreChannels) {
  819. // The channels are listed in reverse order.
  820. Channels++;
  821. }
  822. while (Index) {
  823. if (Channels->IsRange) {
  824. usageMin = Channels->Range.UsageMin;
  825. usageMin = (usageMin ? usageMin : 1);
  826. // Index is 1 based (an index of zero is no usage at all)
  827. // But a UsageMin of zero means that UsageMin is exclusive.
  828. // That means that if the index is 1 and UsageMin is non-zero,
  829. // than this function should return UsageMin
  830. usageMax = Channels->Range.UsageMax;
  831. len = (usageMax + 1) - usageMin;
  832. // ^^^ Usage Max is inclusive.
  833. if (Index <= len) {
  834. return ((USAGE) Index) + usageMin - 1;
  835. } else {
  836. Index -= len;
  837. }
  838. } else if (1 == Index) {
  839. return Channels->NotRange.Usage;
  840. } else {
  841. Index--;
  842. }
  843. if (startChannel != Channels) {
  844. Channels--;
  845. continue;
  846. }
  847. return 0;
  848. }
  849. return 0;
  850. }
  851. ULONG
  852. HidP_Usage2Index (
  853. PHIDP_CHANNEL_DESC Channels,
  854. USAGE Usage
  855. )
  856. /*++
  857. Routine Description:
  858. Given an usage convert it into an index suitable for placement into an
  859. array main item.
  860. --*/
  861. {
  862. PHIDP_CHANNEL_DESC startChannel;
  863. ULONG index = 0;
  864. USAGE UsageMin;
  865. USAGE UsageMax;
  866. startChannel = Channels;
  867. while (Channels->MoreChannels) {
  868. Channels++;
  869. }
  870. for (; startChannel <= Channels; Channels--) {
  871. if (Channels->IsRange) {
  872. UsageMin = Channels->Range.UsageMin;
  873. UsageMin = (UsageMin ? UsageMin : 1);
  874. // Index is 1 based (an index of zero is no usage at all)
  875. // But a UsageMin of zero means that UsageMin is exclusive.
  876. // That means that if the index is 1 and UsageMin is non-zero,
  877. // than this function should return UsageMin
  878. UsageMax = Channels->Range.UsageMax;
  879. if ((UsageMin <= Usage) && (Usage <= UsageMax)) {
  880. return (index + 1 + Usage - UsageMin);
  881. }
  882. index += 1 + (UsageMax - UsageMin);
  883. } else {
  884. index++;
  885. if (Usage == Channels->NotRange.Usage) {
  886. return index;
  887. }
  888. }
  889. }
  890. return 0;
  891. }
  892. NTSTATUS __stdcall
  893. HidP_SetUnsetOneUsage (
  894. struct _CHANNEL_REPORT_HEADER *,
  895. USAGE,
  896. USHORT,
  897. USAGE,
  898. PHIDP_PREPARSED_DATA,
  899. PCHAR,
  900. BOOLEAN);
  901. NTSTATUS __stdcall
  902. HidP_SetUsages (
  903. IN HIDP_REPORT_TYPE ReportType,
  904. IN USAGE UsagePage,
  905. IN USHORT LinkCollection,
  906. IN PUSAGE UsageList,
  907. IN OUT PULONG UsageLength,
  908. IN PHIDP_PREPARSED_DATA PreparsedData,
  909. IN OUT PCHAR Report,
  910. IN ULONG ReportLength
  911. )
  912. /*++
  913. Routine Description:
  914. Please See hidpi.h for description.
  915. Notes:
  916. --*/
  917. {
  918. struct _CHANNEL_REPORT_HEADER * iof;
  919. NTSTATUS status = HIDP_STATUS_SUCCESS;
  920. ULONG usageIndex = 0;
  921. CHECK_PPD (PreparsedData);
  922. switch (ReportType) {
  923. case HidP_Input:
  924. iof = &PreparsedData->Input;
  925. break;
  926. case HidP_Output:
  927. iof = &PreparsedData->Output;
  928. break;
  929. case HidP_Feature:
  930. iof = &PreparsedData->Feature;
  931. break;
  932. default:
  933. return HIDP_STATUS_INVALID_REPORT_TYPE;
  934. }
  935. if ((USHORT) ReportLength != iof->ByteLen) {
  936. return HIDP_STATUS_INVALID_REPORT_LENGTH;
  937. }
  938. if (0 == iof->ByteLen) {
  939. return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
  940. }
  941. for (usageIndex = 0; usageIndex < *UsageLength; usageIndex++) {
  942. if (0 == UsageList [usageIndex]) {
  943. continue;
  944. }
  945. status = HidP_SetUnsetOneUsage (iof,
  946. UsagePage,
  947. LinkCollection,
  948. UsageList [usageIndex],
  949. PreparsedData,
  950. Report,
  951. TRUE);
  952. if (!NT_SUCCESS(status)) {
  953. break;
  954. }
  955. }
  956. *UsageLength = usageIndex;
  957. return status;
  958. }
  959. NTSTATUS __stdcall
  960. HidP_UnsetUsages (
  961. IN HIDP_REPORT_TYPE ReportType,
  962. IN USAGE UsagePage,
  963. IN USHORT LinkCollection,
  964. IN PUSAGE UsageList,
  965. IN OUT PULONG UsageLength,
  966. IN PHIDP_PREPARSED_DATA PreparsedData,
  967. IN OUT PCHAR Report,
  968. IN ULONG ReportLength
  969. )
  970. /*++
  971. Routine Description:
  972. Please See hidpi.h for description.
  973. Notes:
  974. --*/
  975. {
  976. struct _CHANNEL_REPORT_HEADER * iof;
  977. NTSTATUS status = HIDP_STATUS_SUCCESS;
  978. ULONG usageIndex = 0;
  979. CHECK_PPD (PreparsedData);
  980. switch (ReportType) {
  981. case HidP_Input:
  982. iof = &PreparsedData->Input;
  983. break;
  984. case HidP_Output:
  985. iof = &PreparsedData->Output;
  986. break;
  987. case HidP_Feature:
  988. iof = &PreparsedData->Feature;
  989. break;
  990. default:
  991. return HIDP_STATUS_INVALID_REPORT_TYPE;
  992. }
  993. if ((USHORT) ReportLength != iof->ByteLen) {
  994. return HIDP_STATUS_INVALID_REPORT_LENGTH;
  995. }
  996. if (0 == iof->ByteLen) {
  997. return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
  998. }
  999. for (usageIndex = 0; usageIndex < *UsageLength; usageIndex++) {
  1000. if (0 == UsageList [usageIndex]) {
  1001. continue;
  1002. }
  1003. status = HidP_SetUnsetOneUsage (iof,
  1004. UsagePage,
  1005. LinkCollection,
  1006. UsageList [usageIndex],
  1007. PreparsedData,
  1008. Report,
  1009. FALSE);
  1010. if (!NT_SUCCESS(status)) {
  1011. break;
  1012. }
  1013. }
  1014. *UsageLength = usageIndex;
  1015. return status;
  1016. }
  1017. NTSTATUS __stdcall
  1018. HidP_SetUnsetOneUsage (
  1019. struct _CHANNEL_REPORT_HEADER * IOF,
  1020. USAGE UsagePage,
  1021. USHORT LinkCollection,
  1022. USAGE Usage,
  1023. PHIDP_PREPARSED_DATA PreparsedData,
  1024. PCHAR Report,
  1025. BOOLEAN Set
  1026. )
  1027. /*++
  1028. Routine Description:
  1029. Perform the work of SetUsage one usage at a time.
  1030. Yes this is slow but it works.
  1031. Notes:
  1032. This function assumes the report length has already been verified.
  1033. --*/
  1034. {
  1035. PHIDP_CHANNEL_DESC channel = 0;
  1036. PHIDP_CHANNEL_DESC priChannel = 0;
  1037. PHIDP_CHANNEL_DESC firstChannel = 0;
  1038. // the channel where the array starts
  1039. ULONG channelIndex = 0;
  1040. ULONG reportByteIndex = 0;
  1041. ULONG inspect = 0;
  1042. USHORT reportBitIndex = 0;
  1043. BOOLEAN wrongReportID = FALSE;
  1044. BOOLEAN noArraySpace = FALSE;
  1045. BOOLEAN notPressed = FALSE;
  1046. NTSTATUS status = HIDP_STATUS_SUCCESS;
  1047. for (channelIndex = IOF->Offset; channelIndex < IOF->Index; channelIndex++) {
  1048. channel = (PreparsedData->Data + channelIndex);
  1049. if (priChannel) {
  1050. if (!priChannel->MoreChannels) {
  1051. firstChannel = channel;
  1052. }
  1053. } else {
  1054. firstChannel = channel;
  1055. }
  1056. priChannel = channel;
  1057. if ((!channel->IsButton) ||
  1058. (channel->UsagePage != UsagePage)) {
  1059. continue;
  1060. }
  1061. //
  1062. // If LinkCollection is zero we will not filter by link collections
  1063. // If channel->LinkCollection is zero this is the root collection.
  1064. // Therefore if LinkCollection == channel->LinkCollection then this is OK
  1065. //
  1066. if ((!LinkCollection) ||
  1067. (LinkCollection == channel->LinkCollection) ||
  1068. ((HIDP_LINK_COLLECTION_ROOT == LinkCollection) &&
  1069. (0 == channel->LinkCollection))) {
  1070. ;
  1071. } else {
  1072. continue;
  1073. }
  1074. if ( ((channel->IsRange) && (channel->Range.UsageMin <= Usage)
  1075. && (Usage <= channel->Range.UsageMax))
  1076. || ((!channel->IsRange) && (channel->NotRange.Usage == Usage))) {
  1077. //
  1078. // Test the report ID to see if it is compatible.
  1079. //
  1080. if ((0 != Report[0]) && (channel->ReportID != (UCHAR) Report[0])) {
  1081. //
  1082. // Distinguish between the errors HIDP_USAGE_NOT_FOUND and
  1083. // HIDP_INCOMPATIBLE_REPORT_ID.
  1084. wrongReportID = TRUE;
  1085. continue;
  1086. }
  1087. Report[0] = (CHAR) channel->ReportID;
  1088. //
  1089. // Set the report ID for this report
  1090. //
  1091. if (1 == channel->ReportSize) {
  1092. reportBitIndex = (channel->ByteOffset << 3)
  1093. + channel->BitOffset
  1094. + (USHORT) (Usage - channel->Range.UsageMin);
  1095. if (Set) {
  1096. Report [reportBitIndex >> 3] |= (1 << (reportBitIndex & 7));
  1097. } else if (Report [reportBitIndex >> 3] & (1 << (reportBitIndex & 7))) {
  1098. Report [reportBitIndex >> 3] &= ~(1 << (reportBitIndex & 7));
  1099. } else {
  1100. return HIDP_STATUS_BUTTON_NOT_PRESSED;
  1101. }
  1102. return HIDP_STATUS_SUCCESS;
  1103. } else if (Set) { // usage array
  1104. for (reportBitIndex = channel->BitOffset;
  1105. reportBitIndex < (channel->BitOffset + channel->BitLength);
  1106. reportBitIndex += channel->ReportSize) {
  1107. inspect = HidP_ExtractData (
  1108. (USHORT) ((reportBitIndex >> 3) + channel->ByteOffset),
  1109. (USHORT) (reportBitIndex & 7),
  1110. channel->ReportSize,
  1111. Report);
  1112. if (inspect) {
  1113. //
  1114. // Distinguish between errors HIDP_USAGE_NOT_FOUND and
  1115. // HIDP_BUFFER_TOO_SMALL
  1116. //
  1117. noArraySpace = TRUE;
  1118. continue;
  1119. }
  1120. inspect = HidP_Usage2Index (firstChannel, Usage);
  1121. if (!inspect) {
  1122. //
  1123. // Gads! We should NEVER get here!
  1124. // We already know that the given usage falls into the
  1125. // current channel, so it should translate into an index.
  1126. //
  1127. return HIDP_STATUS_INTERNAL_ERROR;
  1128. }
  1129. HidP_InsertData (
  1130. (USHORT) ((reportBitIndex >> 3) + channel->ByteOffset),
  1131. (USHORT) (reportBitIndex & 7),
  1132. channel->ReportSize,
  1133. Report,
  1134. inspect);
  1135. return HIDP_STATUS_SUCCESS;
  1136. }
  1137. // If we got to this point then there was no room to add this
  1138. // usage into the given array. However there might be another
  1139. // array later into which the given usage might fit. Let's continue
  1140. // looking.
  1141. while (channel->MoreChannels) {
  1142. // Skip by all the additional channels that describe this
  1143. // same data field.
  1144. channelIndex++;
  1145. channel = (PreparsedData->Data + channelIndex);
  1146. }
  1147. priChannel = channel;
  1148. } else { // Set a Usage Array
  1149. inspect = HidP_Usage2Index (firstChannel, Usage);
  1150. reportBitIndex += channel->ByteOffset << 3;
  1151. status = HidP_DeleteArrayEntry (reportBitIndex,
  1152. channel->ReportSize,
  1153. channel->ReportCount,
  1154. inspect,
  1155. Report);
  1156. if (HIDP_STATUS_BUTTON_NOT_PRESSED == status) {
  1157. notPressed = TRUE;
  1158. continue;
  1159. }
  1160. if (NT_SUCCESS (status)) {
  1161. return status;
  1162. } else {
  1163. ASSERT (0 == status);
  1164. }
  1165. } // end byte aray
  1166. }
  1167. }
  1168. if (wrongReportID) {
  1169. return HIDP_STATUS_INCOMPATIBLE_REPORT_ID;
  1170. }
  1171. if (notPressed) {
  1172. return HIDP_STATUS_BUTTON_NOT_PRESSED;
  1173. }
  1174. if (noArraySpace) {
  1175. return HIDP_STATUS_BUFFER_TOO_SMALL;
  1176. }
  1177. return HIDP_STATUS_USAGE_NOT_FOUND;
  1178. }
  1179. NTSTATUS __stdcall
  1180. HidP_GetUsagesEx (
  1181. IN HIDP_REPORT_TYPE ReportType,
  1182. IN USHORT LinkCollection, // Optional
  1183. OUT PUSAGE_AND_PAGE ButtonList,
  1184. IN OUT ULONG * UsageLength,
  1185. IN PHIDP_PREPARSED_DATA PreparsedData,
  1186. IN PCHAR Report,
  1187. IN ULONG ReportLength
  1188. )
  1189. /*++
  1190. Routine Description:
  1191. Please see hidpi.h for description.
  1192. --*/
  1193. {
  1194. return HidP_GetUsages (ReportType,
  1195. 0,
  1196. LinkCollection,
  1197. (PUSAGE) ButtonList,
  1198. UsageLength,
  1199. PreparsedData,
  1200. Report,
  1201. ReportLength);
  1202. }
  1203. NTSTATUS __stdcall
  1204. HidP_GetUsages (
  1205. IN HIDP_REPORT_TYPE ReportType,
  1206. IN USAGE UsagePage,
  1207. IN USHORT LinkCollection,
  1208. OUT USAGE * UsageList,
  1209. IN OUT ULONG * UsageLength,
  1210. IN PHIDP_PREPARSED_DATA PreparsedData,
  1211. IN PCHAR Report,
  1212. IN ULONG ReportLength
  1213. )
  1214. /*++
  1215. Routine Description:
  1216. Please see hidpi.h for description.
  1217. Notes:
  1218. --*/
  1219. {
  1220. struct _CHANNEL_REPORT_HEADER * iof;
  1221. PHIDP_CHANNEL_DESC channel;
  1222. USHORT channelIndex = 0;
  1223. USHORT usageListIndex = 0;
  1224. USHORT reportBitIndex = 0;
  1225. USHORT tmpBitIndex;
  1226. NTSTATUS status = HIDP_STATUS_SUCCESS;
  1227. ULONG data = 0;
  1228. USHORT inspect = 0;
  1229. BOOLEAN wrongReportID = FALSE;
  1230. BOOLEAN found = FALSE;
  1231. PUSAGE_AND_PAGE usageAndPage = (PUSAGE_AND_PAGE) UsageList;
  1232. CHECK_PPD (PreparsedData);
  1233. memset (UsageList, '\0', *UsageLength * sizeof (USAGE));
  1234. switch (ReportType) {
  1235. case HidP_Input:
  1236. iof = &PreparsedData->Input;
  1237. break;
  1238. case HidP_Output:
  1239. iof = &PreparsedData->Output;
  1240. break;
  1241. case HidP_Feature:
  1242. iof = &PreparsedData->Feature;
  1243. break;
  1244. default:
  1245. return HIDP_STATUS_INVALID_REPORT_TYPE;
  1246. }
  1247. if ((USHORT) ReportLength != iof->ByteLen) {
  1248. return HIDP_STATUS_INVALID_REPORT_LENGTH;
  1249. }
  1250. if (0 == iof->ByteLen) {
  1251. return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
  1252. }
  1253. for (channelIndex = iof->Offset; channelIndex < iof->Index; channelIndex++){
  1254. channel = (PreparsedData->Data + channelIndex);
  1255. if ((!channel->IsButton) ||
  1256. ((UsagePage) && (channel->UsagePage != UsagePage))) {
  1257. continue;
  1258. }
  1259. //
  1260. // If LinkCollection is zero we will not filter by link collections
  1261. // If channel->LinkCollection is zero this is the root collection.
  1262. // Therefore if LinkCollection == channel->LinkCollection then this is OK
  1263. //
  1264. if ((!LinkCollection) ||
  1265. (LinkCollection == channel->LinkCollection) ||
  1266. ((HIDP_LINK_COLLECTION_ROOT == LinkCollection) &&
  1267. (0 == channel->LinkCollection))) {
  1268. ;
  1269. } else {
  1270. continue;
  1271. }
  1272. // Test the report ID to see if it is compatible.
  1273. if ((0 != Report[0]) && (channel->ReportID != (UCHAR) Report[0])) {
  1274. // Distinguish between the errors HIDP_USAGE_NOT_FOUND and
  1275. // HIDP_INCOMPATIBLE_REPORT_ID.
  1276. wrongReportID = TRUE;
  1277. continue;
  1278. }
  1279. found = TRUE;
  1280. if (1 == channel->ReportSize) {
  1281. // A bitfield
  1282. //
  1283. // Little endian (by bit)
  1284. // Byte 2 |Byte 1 |Byte 0
  1285. // 765432107654321076543210 (bits)
  1286. //
  1287. // Get low byte first. (need the higher bits)
  1288. // Offset is from bit zero.
  1289. //
  1290. for (reportBitIndex = channel->BitOffset;
  1291. reportBitIndex < (channel->BitLength + channel->BitOffset);
  1292. reportBitIndex++) {
  1293. // Check it one bit at a time.
  1294. tmpBitIndex = reportBitIndex + (channel->ByteOffset << 3);
  1295. inspect = Report [tmpBitIndex >> 3] & (1 << (tmpBitIndex & 7));
  1296. tmpBitIndex = reportBitIndex - channel->BitOffset;
  1297. if (inspect) {
  1298. if (channel->IsRange) {
  1299. inspect = channel->Range.UsageMin + tmpBitIndex;
  1300. } else {
  1301. inspect = channel->NotRange.Usage;
  1302. }
  1303. if (usageListIndex < *UsageLength) {
  1304. if (0 == UsagePage) {
  1305. usageAndPage[usageListIndex].UsagePage
  1306. = channel->UsagePage;
  1307. usageAndPage[usageListIndex].Usage = inspect;
  1308. } else {
  1309. UsageList[usageListIndex] = inspect;
  1310. }
  1311. }
  1312. usageListIndex++;
  1313. }
  1314. }
  1315. continue;
  1316. }
  1317. for (reportBitIndex = channel->BitOffset;
  1318. reportBitIndex < (channel->BitOffset + channel->BitLength);
  1319. reportBitIndex += channel->ReportSize) {
  1320. // an array of usages.
  1321. data = HidP_ExtractData (
  1322. (USHORT) ((reportBitIndex >> 3) + channel->ByteOffset),
  1323. (USHORT) (reportBitIndex & 7),
  1324. channel->ReportSize,
  1325. Report);
  1326. if (data) {
  1327. inspect = HidP_Index2Usage (channel, data);
  1328. if (!inspect) {
  1329. // We found an invalid index. I'm not quite sure what
  1330. // we should do with it. But lets just ignore it since
  1331. // we cannot convert it into a real usage.
  1332. continue;
  1333. }
  1334. if (usageListIndex < *UsageLength) {
  1335. if (0 == UsagePage) {
  1336. usageAndPage[usageListIndex].UsagePage
  1337. = channel->UsagePage;
  1338. usageAndPage[usageListIndex].Usage = inspect;
  1339. } else {
  1340. UsageList[usageListIndex] = inspect;
  1341. }
  1342. }
  1343. usageListIndex++;
  1344. }
  1345. }
  1346. while (channel->MoreChannels) {
  1347. // Skip by all the additional channels that describe this
  1348. // same data field.
  1349. channelIndex++;
  1350. channel = (PreparsedData->Data + channelIndex);
  1351. }
  1352. } // end for channel
  1353. if (*UsageLength < usageListIndex) {
  1354. status = HIDP_STATUS_BUFFER_TOO_SMALL;
  1355. }
  1356. *UsageLength = usageListIndex;
  1357. if (!found) {
  1358. if (wrongReportID) {
  1359. status = HIDP_STATUS_INCOMPATIBLE_REPORT_ID;
  1360. } else {
  1361. status = HIDP_STATUS_USAGE_NOT_FOUND;
  1362. }
  1363. }
  1364. return status;
  1365. }
  1366. ULONG __stdcall
  1367. HidP_MaxUsageListLength (
  1368. IN HIDP_REPORT_TYPE ReportType,
  1369. IN USAGE UsagePage,
  1370. IN PHIDP_PREPARSED_DATA PreparsedData
  1371. )
  1372. /*++
  1373. Routine Description:
  1374. Please see hidpi.h for description.
  1375. Notes:
  1376. --*/
  1377. {
  1378. struct _CHANNEL_REPORT_HEADER * iof;
  1379. PHIDP_CHANNEL_DESC channel;
  1380. USHORT channelIndex = 0;
  1381. ULONG len = 0;
  1382. PAGED_CODE ();
  1383. if ((HIDP_PREPARSED_DATA_SIGNATURE1 != PreparsedData->Signature1) &&
  1384. (HIDP_PREPARSED_DATA_SIGNATURE2 != PreparsedData->Signature2)) {
  1385. return 0;
  1386. }
  1387. switch (ReportType) {
  1388. case HidP_Input:
  1389. iof = &PreparsedData->Input;
  1390. break;
  1391. case HidP_Output:
  1392. iof = &PreparsedData->Output;
  1393. break;
  1394. case HidP_Feature:
  1395. iof = &PreparsedData->Feature;
  1396. break;
  1397. default:
  1398. return 0;
  1399. }
  1400. for (channelIndex = iof->Offset; channelIndex < iof->Index; channelIndex++){
  1401. channel = (PreparsedData->Data + channelIndex);
  1402. if (channel->IsButton &&
  1403. ((!UsagePage) || (channel->UsagePage == UsagePage))) {
  1404. // How many buttons can show up in this device?
  1405. // If this is a bitmap then the max number of buttons is the length
  1406. // aka the count, if this is an array then the max number of buttons
  1407. // is the number of array positions aka the count.
  1408. len += channel->ReportCount;
  1409. }
  1410. }
  1411. return len;
  1412. }
  1413. ULONG __stdcall
  1414. HidP_MaxDataListLength (
  1415. IN HIDP_REPORT_TYPE ReportType,
  1416. IN PHIDP_PREPARSED_DATA PreparsedData
  1417. )
  1418. /*++
  1419. Routine Description:
  1420. Please see hidpi.h for description.
  1421. Notes:
  1422. --*/
  1423. {
  1424. struct _CHANNEL_REPORT_HEADER * iof;
  1425. PHIDP_CHANNEL_DESC channel;
  1426. USHORT channelIndex = 0;
  1427. ULONG len = 0;
  1428. PAGED_CODE ();
  1429. if ((HIDP_PREPARSED_DATA_SIGNATURE1 != PreparsedData->Signature1) &&
  1430. (HIDP_PREPARSED_DATA_SIGNATURE2 != PreparsedData->Signature2)) {
  1431. return 0;
  1432. }
  1433. switch (ReportType) {
  1434. case HidP_Input:
  1435. iof = &PreparsedData->Input;
  1436. break;
  1437. case HidP_Output:
  1438. iof = &PreparsedData->Output;
  1439. break;
  1440. case HidP_Feature:
  1441. iof = &PreparsedData->Feature;
  1442. break;
  1443. default:
  1444. return 0;
  1445. }
  1446. for (channelIndex = iof->Offset; channelIndex < iof->Index; channelIndex++){
  1447. channel = (PreparsedData->Data + channelIndex);
  1448. if (channel->IsButton) {
  1449. // How many buttons can show up in this device?
  1450. // If this is a bitmap then the max number of buttons is the length
  1451. // aka the count, if this is an array then the max number of buttons
  1452. // is the number of array positions aka the count.
  1453. len += channel->ReportCount;
  1454. } else if (channel->IsRange) {
  1455. len += channel->ReportCount;
  1456. } else {
  1457. len += 1;
  1458. }
  1459. }
  1460. return len;
  1461. }
  1462. NTSTATUS __stdcall
  1463. HidP_SetUsageValue (
  1464. IN HIDP_REPORT_TYPE ReportType,
  1465. IN USAGE UsagePage,
  1466. IN USHORT LinkCollection, // Optional
  1467. IN USAGE Usage,
  1468. IN ULONG UsageValue,
  1469. IN PHIDP_PREPARSED_DATA PreparsedData,
  1470. IN OUT PCHAR Report,
  1471. IN ULONG ReportLength
  1472. )
  1473. /*++
  1474. Routine Description:
  1475. Please see hidpi.h for description
  1476. Notes:
  1477. --*/
  1478. {
  1479. struct _CHANNEL_REPORT_HEADER * iof;
  1480. PHIDP_CHANNEL_DESC channel;
  1481. ULONG channelIndex = 0;
  1482. ULONG reportBitIndex = 0;
  1483. NTSTATUS status = HIDP_STATUS_SUCCESS;
  1484. BOOLEAN wrongReportID = FALSE;
  1485. CHECK_PPD (PreparsedData);
  1486. switch (ReportType) {
  1487. case HidP_Input:
  1488. iof = &PreparsedData->Input;
  1489. break;
  1490. case HidP_Output:
  1491. iof = &PreparsedData->Output;
  1492. break;
  1493. case HidP_Feature:
  1494. iof = &PreparsedData->Feature;
  1495. break;
  1496. default:
  1497. return HIDP_STATUS_INVALID_REPORT_TYPE;
  1498. }
  1499. if ((USHORT) ReportLength != iof->ByteLen) {
  1500. return HIDP_STATUS_INVALID_REPORT_LENGTH;
  1501. }
  1502. if (0 == iof->ByteLen) {
  1503. return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
  1504. }
  1505. for (channelIndex = iof->Offset; channelIndex < iof->Index; channelIndex++) {
  1506. channel = (PreparsedData->Data + channelIndex);
  1507. if ((channel->IsButton) ||
  1508. (channel->UsagePage != UsagePage)) {
  1509. continue;
  1510. }
  1511. //
  1512. // If LinkCollection is zero we will not filter by link collections
  1513. // If channel->LinkCollection is zero this is the root collection.
  1514. // Therefore if LinkCollection == channel->LinkCollection then this is OK
  1515. //
  1516. if ((!LinkCollection) ||
  1517. (LinkCollection == channel->LinkCollection) ||
  1518. ((HIDP_LINK_COLLECTION_ROOT == LinkCollection) &&
  1519. (0 == channel->LinkCollection))) {
  1520. ;
  1521. } else {
  1522. continue;
  1523. }
  1524. if (channel->IsRange) {
  1525. if ((channel->Range.UsageMin <= Usage) &&
  1526. (Usage <= channel->Range.UsageMax)) {
  1527. reportBitIndex = (channel->ByteOffset << 3)
  1528. + channel->BitOffset
  1529. + ( (Usage - channel->Range.UsageMin)
  1530. * channel->ReportSize);
  1531. } else {
  1532. continue;
  1533. }
  1534. } else {
  1535. if (channel->NotRange.Usage == Usage) {
  1536. reportBitIndex = (channel->ByteOffset << 3)
  1537. + channel->BitOffset;
  1538. } else {
  1539. continue;
  1540. }
  1541. }
  1542. // Test the report ID to see if it is compatible.
  1543. if ((0 != Report[0]) && (channel->ReportID != (UCHAR) Report[0])) {
  1544. // Distinguish between the errors HIDP_USAGE_NOT_FOUND and
  1545. // HIDP_INCOMPATIBLE_REPORT_ID.
  1546. wrongReportID = TRUE;
  1547. continue;
  1548. }
  1549. Report[0] = (CHAR) channel->ReportID;
  1550. // Set the report ID for this report
  1551. HidP_InsertData ((USHORT) (reportBitIndex >> 3),
  1552. (USHORT) (reportBitIndex & 7),
  1553. channel->ReportSize,
  1554. Report,
  1555. UsageValue);
  1556. return HIDP_STATUS_SUCCESS;
  1557. }
  1558. if (wrongReportID) {
  1559. return HIDP_STATUS_INCOMPATIBLE_REPORT_ID;
  1560. }
  1561. return HIDP_STATUS_USAGE_NOT_FOUND;
  1562. }
  1563. NTSTATUS __stdcall
  1564. HidP_SetUsageValueArray (
  1565. IN HIDP_REPORT_TYPE ReportType,
  1566. IN USAGE UsagePage,
  1567. IN USHORT LinkCollection, // Optional
  1568. IN USAGE Usage,
  1569. OUT PCHAR UsageValue,
  1570. IN USHORT UsageValueByteLength,
  1571. IN PHIDP_PREPARSED_DATA PreparsedData,
  1572. IN PCHAR Report,
  1573. IN ULONG ReportLength
  1574. )
  1575. /*++
  1576. Routine Description:
  1577. Please see hidpi.h for description
  1578. Notes:
  1579. --*/
  1580. {
  1581. struct _CHANNEL_REPORT_HEADER * iof;
  1582. PHIDP_CHANNEL_DESC channel;
  1583. ULONG channelIndex = 0;
  1584. ULONG reportBitIndex;
  1585. ULONG i,j;
  1586. NTSTATUS status = HIDP_STATUS_SUCCESS;
  1587. BOOLEAN wrongReportID = FALSE;
  1588. CHECK_PPD (PreparsedData);
  1589. switch (ReportType) {
  1590. case HidP_Input:
  1591. iof = &PreparsedData->Input;
  1592. break;
  1593. case HidP_Output:
  1594. iof = &PreparsedData->Output;
  1595. break;
  1596. case HidP_Feature:
  1597. iof = &PreparsedData->Feature;
  1598. break;
  1599. default:
  1600. return HIDP_STATUS_INVALID_REPORT_TYPE;
  1601. }
  1602. if ((USHORT) ReportLength != iof->ByteLen) {
  1603. return HIDP_STATUS_INVALID_REPORT_LENGTH;
  1604. }
  1605. if (0 == iof->ByteLen) {
  1606. return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
  1607. }
  1608. for (channelIndex = iof->Offset; channelIndex < iof->Index; channelIndex++){
  1609. channel = (PreparsedData->Data + channelIndex);
  1610. if ((channel->IsButton) ||
  1611. (channel->UsagePage != UsagePage)) {
  1612. continue;
  1613. }
  1614. //
  1615. // If LinkCollection is zero we will not filter by link collections
  1616. // If channel->LinkCollection is zero this is the root collection.
  1617. // Therefore if LinkCollection == channel->LinkCollection then this is OK
  1618. //
  1619. if ((!LinkCollection) ||
  1620. (LinkCollection == channel->LinkCollection) ||
  1621. ((HIDP_LINK_COLLECTION_ROOT == LinkCollection) &&
  1622. (0 == channel->LinkCollection))) {
  1623. ;
  1624. } else {
  1625. continue;
  1626. }
  1627. if (channel->IsRange) {
  1628. if ((channel->Range.UsageMin <= Usage) &&
  1629. (Usage <= channel->Range.UsageMax)) {
  1630. return HIDP_STATUS_NOT_VALUE_ARRAY;
  1631. } else {
  1632. continue;
  1633. }
  1634. } else {
  1635. if (channel->NotRange.Usage == Usage) {
  1636. if (1 == channel->ReportCount) {
  1637. return HIDP_STATUS_NOT_VALUE_ARRAY;
  1638. }
  1639. reportBitIndex =(channel->ByteOffset << 3) + channel->BitOffset;
  1640. } else {
  1641. continue;
  1642. }
  1643. }
  1644. // Test the report ID to see if it is compatible.
  1645. if ((0 != Report[0]) && (channel->ReportID != (UCHAR) Report[0])) {
  1646. // Distinguish between the errors HIDP_USAGE_NOT_FOUND and
  1647. // HIDP_INCOMPATIBLE_REPORT_ID.
  1648. wrongReportID = TRUE;
  1649. continue;
  1650. }
  1651. Report[0] = (CHAR) channel->ReportID;
  1652. // Set the report ID for this report
  1653. if ((UsageValueByteLength * 8) <
  1654. (channel->ReportCount * channel->ReportSize)) {
  1655. return HIDP_STATUS_BUFFER_TOO_SMALL;
  1656. }
  1657. if (0 == (channel->ReportSize % 8)) {
  1658. //
  1659. // set the data the easy way: one byte at a time.
  1660. //
  1661. for (i = 0; i < channel->ReportCount; i++) {
  1662. for (j = 0; j < (UCHAR) (channel->ReportSize / 8); j++) {
  1663. HidP_InsertData ((USHORT) (reportBitIndex >> 3),
  1664. (USHORT) (reportBitIndex & 7),
  1665. 8,
  1666. Report,
  1667. *UsageValue);
  1668. reportBitIndex += 8;
  1669. UsageValue++;
  1670. }
  1671. }
  1672. } else {
  1673. //
  1674. // Do it the hard way: one bit at a time.
  1675. //
  1676. return HIDP_STATUS_NOT_IMPLEMENTED;
  1677. }
  1678. return HIDP_STATUS_SUCCESS;
  1679. }
  1680. if (wrongReportID) {
  1681. return HIDP_STATUS_INCOMPATIBLE_REPORT_ID;
  1682. }
  1683. return HIDP_STATUS_USAGE_NOT_FOUND;
  1684. }
  1685. NTSTATUS __stdcall
  1686. HidP_SetScaledUsageValue (
  1687. IN HIDP_REPORT_TYPE ReportType,
  1688. IN USAGE UsagePage,
  1689. IN USHORT LinkCollection, // Optional
  1690. IN USAGE Usage,
  1691. IN LONG UsageValue,
  1692. IN PHIDP_PREPARSED_DATA PreparsedData,
  1693. IN OUT PCHAR Report,
  1694. IN ULONG ReportLength
  1695. )
  1696. /*++
  1697. Routine Description:
  1698. Please see hidpi.h for description
  1699. Notes:
  1700. --*/
  1701. {
  1702. struct _CHANNEL_REPORT_HEADER * iof;
  1703. PHIDP_CHANNEL_DESC channel;
  1704. ULONG channelIndex = 0;
  1705. ULONG reportBitIndex = 0;
  1706. NTSTATUS status = HIDP_STATUS_USAGE_NOT_FOUND;
  1707. LONG logicalMin, logicalMax;
  1708. LONG physicalMin, physicalMax;
  1709. LONG value;
  1710. BOOLEAN wrongReportID = FALSE;
  1711. CHECK_PPD (PreparsedData);
  1712. switch (ReportType) {
  1713. case HidP_Input:
  1714. iof = &PreparsedData->Input;
  1715. break;
  1716. case HidP_Output:
  1717. iof = &PreparsedData->Output;
  1718. break;
  1719. case HidP_Feature:
  1720. iof = &PreparsedData->Feature;
  1721. break;
  1722. default:
  1723. return HIDP_STATUS_INVALID_REPORT_TYPE;
  1724. }
  1725. if ((USHORT) ReportLength != iof->ByteLen) {
  1726. return HIDP_STATUS_INVALID_REPORT_LENGTH;
  1727. }
  1728. if (0 == iof->ByteLen) {
  1729. return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
  1730. }
  1731. for (channelIndex = iof->Offset; channelIndex < iof->Index; channelIndex++) {
  1732. channel = (PreparsedData->Data + channelIndex);
  1733. if ((channel->IsButton) ||
  1734. (channel->UsagePage != UsagePage)) {
  1735. continue;
  1736. }
  1737. //
  1738. // If LinkCollection is zero we will not filter by link collections
  1739. // If channel->LinkCollection is zero this is the root collection.
  1740. // Therefore if LinkCollection == channel->LinkCollection then this is OK
  1741. //
  1742. if ((!LinkCollection) ||
  1743. (LinkCollection == channel->LinkCollection) ||
  1744. ((HIDP_LINK_COLLECTION_ROOT == LinkCollection) &&
  1745. (0 == channel->LinkCollection))) {
  1746. ;
  1747. } else {
  1748. continue;
  1749. }
  1750. if (channel->IsRange) {
  1751. if ((channel->Range.UsageMin <= Usage) &&
  1752. (Usage <= channel->Range.UsageMax)) {
  1753. reportBitIndex = (channel->ByteOffset << 3)
  1754. + channel->BitOffset
  1755. + ( (Usage - channel->Range.UsageMin)
  1756. * channel->ReportSize);
  1757. } else {
  1758. continue;
  1759. }
  1760. } else {
  1761. if (channel->NotRange.Usage == Usage) {
  1762. reportBitIndex = (channel->ByteOffset << 3)
  1763. + channel->BitOffset;
  1764. } else {
  1765. continue;
  1766. }
  1767. }
  1768. // Test the report ID to see if it is compatible.
  1769. if ((0 != Report[0]) && (channel->ReportID != (UCHAR) Report[0])) {
  1770. // Distinguish between the errors HIDP_USAGE_NOT_FOUND and
  1771. // HIDP_INCOMPATIBLE_REPORT_ID.
  1772. wrongReportID = TRUE;
  1773. continue;
  1774. }
  1775. Report[0] = (CHAR) channel->ReportID;
  1776. // Set the report ID for this report
  1777. logicalMin = channel->Data.LogicalMin;
  1778. logicalMax = channel->Data.LogicalMax;
  1779. physicalMin = channel->Data.PhysicalMin;
  1780. physicalMax = channel->Data.PhysicalMax;
  1781. //
  1782. // The code path here is ALWAYS the same, we should test it once
  1783. // and then use some sort of switch statement to do the calculation.
  1784. //
  1785. if ((0 == physicalMin) &&
  1786. (0 == physicalMax) &&
  1787. (logicalMin != logicalMax)) {
  1788. //
  1789. // The device did not set the physical min and max values
  1790. //
  1791. if ((logicalMin <= UsageValue) && (UsageValue <= logicalMax)) {
  1792. value = UsageValue;
  1793. //
  1794. // fix the sign bit
  1795. // I should store away the sign bit somewhere so I don't
  1796. // have to calculate it all the time.
  1797. //
  1798. if (value & 0x80000000) {
  1799. value |= (1 << (channel->ReportSize - 1));
  1800. } else {
  1801. value &= ((1 << (channel->ReportSize - 1)) - 1);
  1802. }
  1803. } else {
  1804. if (channel->Data.HasNull) {
  1805. value = (1 << (channel->ReportSize - 1));// Most negitive value
  1806. status = HIDP_STATUS_NULL;
  1807. } else {
  1808. return HIDP_STATUS_VALUE_OUT_OF_RANGE;
  1809. }
  1810. }
  1811. } else {
  1812. //
  1813. // The device has physical descriptors.
  1814. //
  1815. if ((logicalMax <= logicalMin) || (physicalMax <= physicalMin)) {
  1816. return HIDP_STATUS_BAD_LOG_PHY_VALUES;
  1817. }
  1818. if ((physicalMin <= UsageValue) && (UsageValue <= physicalMax)) {
  1819. value = logicalMin + ((UsageValue - physicalMin) *
  1820. (logicalMax - logicalMin + 1) /
  1821. (physicalMax - physicalMin + 1));
  1822. } else {
  1823. if (channel->Data.HasNull) {
  1824. value = (1 << (channel->ReportSize - 1));// Most negitive value
  1825. status = HIDP_STATUS_NULL;
  1826. } else {
  1827. return HIDP_STATUS_VALUE_OUT_OF_RANGE;
  1828. }
  1829. }
  1830. }
  1831. HidP_InsertData ((USHORT) (reportBitIndex >> 3),
  1832. (USHORT) (reportBitIndex & 7),
  1833. channel->ReportSize,
  1834. Report,
  1835. (ULONG) value);
  1836. return HIDP_STATUS_SUCCESS;
  1837. }
  1838. if (wrongReportID) {
  1839. return HIDP_STATUS_INCOMPATIBLE_REPORT_ID;
  1840. }
  1841. return status;
  1842. }
  1843. NTSTATUS __stdcall
  1844. HidP_GetUsageValue (
  1845. IN HIDP_REPORT_TYPE ReportType,
  1846. IN USAGE UsagePage,
  1847. IN USHORT LinkCollection, // Optional
  1848. IN USAGE Usage,
  1849. OUT PULONG UsageValue,
  1850. IN PHIDP_PREPARSED_DATA PreparsedData,
  1851. IN PCHAR Report,
  1852. IN ULONG ReportLength
  1853. )
  1854. /*++
  1855. Routine Description:
  1856. Please see hidpi.h for description
  1857. Notes:
  1858. --*/
  1859. {
  1860. struct _CHANNEL_REPORT_HEADER * iof;
  1861. PHIDP_CHANNEL_DESC channel;
  1862. ULONG channelIndex = 0;
  1863. ULONG reportBitIndex = 0;
  1864. ULONG reportByteIndex = 0;
  1865. NTSTATUS status = HIDP_STATUS_SUCCESS;
  1866. ULONG inspect = 0;
  1867. BOOLEAN wrongReportID = FALSE;
  1868. CHECK_PPD (PreparsedData);
  1869. switch (ReportType)
  1870. {
  1871. case HidP_Input:
  1872. iof = &PreparsedData->Input;
  1873. break;
  1874. case HidP_Output:
  1875. iof = &PreparsedData->Output;
  1876. break;
  1877. case HidP_Feature:
  1878. iof = &PreparsedData->Feature;
  1879. break;
  1880. default:
  1881. return HIDP_STATUS_INVALID_REPORT_TYPE;
  1882. }
  1883. if ((USHORT) ReportLength != iof->ByteLen) {
  1884. return HIDP_STATUS_INVALID_REPORT_LENGTH;
  1885. }
  1886. if (0 == iof->ByteLen) {
  1887. return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
  1888. }
  1889. for (channelIndex = iof->Offset; channelIndex < iof->Index; channelIndex++)
  1890. {
  1891. channel = (PreparsedData->Data + channelIndex);
  1892. if ((channel->IsButton) ||
  1893. (channel->UsagePage != UsagePage)) {
  1894. continue;
  1895. }
  1896. //
  1897. // If LinkCollection is zero we will not filter by link collections
  1898. // If channel->LinkCollection is zero this is the root collection.
  1899. // Therefore if LinkCollection == channel->LinkCollection then this is OK
  1900. //
  1901. if ((!LinkCollection) ||
  1902. (LinkCollection == channel->LinkCollection) ||
  1903. ((HIDP_LINK_COLLECTION_ROOT == LinkCollection) &&
  1904. (0 == channel->LinkCollection))) {
  1905. ;
  1906. } else {
  1907. continue;
  1908. }
  1909. if (channel->IsRange) {
  1910. if ((channel->Range.UsageMin <= Usage) &&
  1911. (Usage <= channel->Range.UsageMax))
  1912. {
  1913. reportBitIndex = (channel->ByteOffset << 3)
  1914. + channel->BitOffset
  1915. + ( (Usage - channel->Range.UsageMin)
  1916. * channel->ReportSize);
  1917. } else
  1918. {
  1919. continue;
  1920. }
  1921. } else
  1922. {
  1923. if (channel->NotRange.Usage == Usage)
  1924. {
  1925. reportBitIndex = (channel->ByteOffset << 3)
  1926. + channel->BitOffset;
  1927. } else
  1928. {
  1929. continue;
  1930. }
  1931. }
  1932. // Test the report ID to see if it is compatible.
  1933. if ((0 != Report[0]) && (channel->ReportID != (UCHAR) Report[0])) {
  1934. // Distinguish between the errors HIDP_USAGE_NOT_FOUND and
  1935. // HIDP_INCOMPATIBLE_REPORT_ID.
  1936. wrongReportID = TRUE;
  1937. continue;
  1938. }
  1939. inspect = HidP_ExtractData ((USHORT) (reportBitIndex >> 3),
  1940. (USHORT) (reportBitIndex & 7),
  1941. channel->ReportSize,
  1942. Report);
  1943. *UsageValue = inspect;
  1944. return HIDP_STATUS_SUCCESS;
  1945. }
  1946. if (wrongReportID) {
  1947. return HIDP_STATUS_INCOMPATIBLE_REPORT_ID;
  1948. }
  1949. return HIDP_STATUS_USAGE_NOT_FOUND;
  1950. }
  1951. NTSTATUS __stdcall
  1952. HidP_GetUsageValueArray (
  1953. IN HIDP_REPORT_TYPE ReportType,
  1954. IN USAGE UsagePage,
  1955. IN USHORT LinkCollection, // Optional
  1956. IN USAGE Usage,
  1957. OUT PCHAR UsageValue,
  1958. IN USHORT UsageValueByteLength,
  1959. IN PHIDP_PREPARSED_DATA PreparsedData,
  1960. IN PCHAR Report,
  1961. IN ULONG ReportLength
  1962. )
  1963. /*++
  1964. Routine Description:
  1965. Please see hidpi.h for description
  1966. Notes:
  1967. --*/
  1968. {
  1969. struct _CHANNEL_REPORT_HEADER * iof;
  1970. PHIDP_CHANNEL_DESC channel;
  1971. ULONG channelIndex = 0;
  1972. ULONG reportBitIndex;
  1973. ULONG i,j;
  1974. NTSTATUS status = HIDP_STATUS_SUCCESS;
  1975. ULONG inspect = 0;
  1976. BOOLEAN wrongReportID = FALSE;
  1977. CHECK_PPD (PreparsedData);
  1978. switch (ReportType) {
  1979. case HidP_Input:
  1980. iof = &PreparsedData->Input;
  1981. break;
  1982. case HidP_Output:
  1983. iof = &PreparsedData->Output;
  1984. break;
  1985. case HidP_Feature:
  1986. iof = &PreparsedData->Feature;
  1987. break;
  1988. default:
  1989. return HIDP_STATUS_INVALID_REPORT_TYPE;
  1990. }
  1991. if ((USHORT) ReportLength != iof->ByteLen) {
  1992. return HIDP_STATUS_INVALID_REPORT_LENGTH;
  1993. }
  1994. if (0 == iof->ByteLen) {
  1995. return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
  1996. }
  1997. for (channelIndex = iof->Offset; channelIndex < iof->Index; channelIndex++){
  1998. channel = (PreparsedData->Data + channelIndex);
  1999. if ((channel->IsButton) ||
  2000. (channel->UsagePage != UsagePage)) {
  2001. continue;
  2002. }
  2003. //
  2004. // If LinkCollection is zero we will not filter by link collections
  2005. // If channel->LinkCollection is zero this is the root collection.
  2006. // Therefore if LinkCollection == channel->LinkCollection then this is OK
  2007. //
  2008. if ((!LinkCollection) ||
  2009. (LinkCollection == channel->LinkCollection) ||
  2010. ((HIDP_LINK_COLLECTION_ROOT == LinkCollection) &&
  2011. (0 == channel->LinkCollection))) {
  2012. ;
  2013. } else {
  2014. continue;
  2015. }
  2016. if (channel->IsRange) {
  2017. if ((channel->Range.UsageMin <= Usage) &&
  2018. (Usage <= channel->Range.UsageMax)) {
  2019. return HIDP_STATUS_NOT_VALUE_ARRAY;
  2020. } else {
  2021. continue;
  2022. }
  2023. } else {
  2024. if (channel->NotRange.Usage == Usage) {
  2025. if (1 == channel->ReportCount) {
  2026. return HIDP_STATUS_NOT_VALUE_ARRAY;
  2027. }
  2028. reportBitIndex =(channel->ByteOffset << 3) + channel->BitOffset;
  2029. } else {
  2030. continue;
  2031. }
  2032. }
  2033. // Test the report ID to see if it is compatible.
  2034. if ((0 != Report[0]) && (channel->ReportID != (UCHAR) Report[0])) {
  2035. // Distinguish between the errors HIDP_USAGE_NOT_FOUND and
  2036. // HIDP_INCOMPATIBLE_REPORT_ID.
  2037. wrongReportID = TRUE;
  2038. continue;
  2039. }
  2040. if ((UsageValueByteLength * 8) <
  2041. (channel->ReportCount * channel->ReportSize)) {
  2042. return HIDP_STATUS_BUFFER_TOO_SMALL;
  2043. }
  2044. if (0 == (channel->ReportSize % 8)) {
  2045. //
  2046. // Retrieve the data the easy way
  2047. //
  2048. for (i = 0; i < channel->ReportCount; i++) {
  2049. for (j = 0; j < (USHORT) (channel->ReportSize / 8); j++) {
  2050. *UsageValue = (CHAR) HidP_ExtractData (
  2051. (USHORT) (reportBitIndex >> 3),
  2052. (USHORT) (reportBitIndex & 7),
  2053. 8,
  2054. Report);
  2055. reportBitIndex += 8;
  2056. UsageValue++;
  2057. }
  2058. }
  2059. } else {
  2060. //
  2061. // Do it the hard way
  2062. //
  2063. return HIDP_STATUS_NOT_IMPLEMENTED;
  2064. }
  2065. return HIDP_STATUS_SUCCESS;
  2066. }
  2067. if (wrongReportID) {
  2068. return HIDP_STATUS_INCOMPATIBLE_REPORT_ID;
  2069. }
  2070. return HIDP_STATUS_USAGE_NOT_FOUND;
  2071. }
  2072. NTSTATUS __stdcall
  2073. HidP_GetScaledUsageValue (
  2074. IN HIDP_REPORT_TYPE ReportType,
  2075. IN USAGE UsagePage,
  2076. IN USHORT LinkCollection, // Optional
  2077. IN USAGE Usage,
  2078. OUT PLONG UsageValue,
  2079. IN PHIDP_PREPARSED_DATA PreparsedData,
  2080. IN PCHAR Report,
  2081. IN ULONG ReportLength
  2082. )
  2083. /*++
  2084. Routine Description:
  2085. Please see hidpi.h for description
  2086. Notes:
  2087. --*/
  2088. {
  2089. struct _CHANNEL_REPORT_HEADER * iof;
  2090. PHIDP_CHANNEL_DESC channel;
  2091. ULONG channelIndex = 0;
  2092. ULONG reportBitIndex = 0;
  2093. ULONG reportByteIndex = 0;
  2094. NTSTATUS status = HIDP_STATUS_SUCCESS;
  2095. ULONG inspect = 0;
  2096. LONG logicalMin, logicalMax;
  2097. LONG physicalMin, physicalMax;
  2098. LONG value;
  2099. BOOLEAN wrongReportID = FALSE;
  2100. CHECK_PPD (PreparsedData);
  2101. switch (ReportType) {
  2102. case HidP_Input:
  2103. iof = &PreparsedData->Input;
  2104. break;
  2105. case HidP_Output:
  2106. iof = &PreparsedData->Output;
  2107. break;
  2108. case HidP_Feature:
  2109. iof = &PreparsedData->Feature;
  2110. break;
  2111. default:
  2112. return HIDP_STATUS_INVALID_REPORT_TYPE;
  2113. }
  2114. if ((USHORT) ReportLength != iof->ByteLen) {
  2115. return HIDP_STATUS_INVALID_REPORT_LENGTH;
  2116. }
  2117. if (0 == iof->ByteLen) {
  2118. return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
  2119. }
  2120. for (channelIndex = iof->Offset; channelIndex < iof->Index; channelIndex++) {
  2121. channel = (PreparsedData->Data + channelIndex);
  2122. if ((channel->IsButton) ||
  2123. (channel->UsagePage != UsagePage)) {
  2124. continue;
  2125. }
  2126. //
  2127. // If LinkCollection is zero we will not filter by link collections
  2128. // If channel->LinkCollection is zero this is the root collection.
  2129. // Therefore if LinkCollection == channel->LinkCollection then this is OK
  2130. //
  2131. if ((!LinkCollection) ||
  2132. (LinkCollection == channel->LinkCollection) ||
  2133. ((HIDP_LINK_COLLECTION_ROOT == LinkCollection) &&
  2134. (0 == channel->LinkCollection))) {
  2135. ;
  2136. } else {
  2137. continue;
  2138. }
  2139. if (channel->IsRange) {
  2140. if ((channel->Range.UsageMin <= Usage) &&
  2141. (Usage <= channel->Range.UsageMax)) {
  2142. reportBitIndex = (channel->ByteOffset << 3)
  2143. + channel->BitOffset
  2144. + ( (Usage - channel->Range.UsageMin)
  2145. * channel->ReportSize);
  2146. } else {
  2147. continue;
  2148. }
  2149. } else {
  2150. if (channel->NotRange.Usage == Usage) {
  2151. reportBitIndex = (channel->ByteOffset << 3)
  2152. + channel->BitOffset;
  2153. } else {
  2154. continue;
  2155. }
  2156. }
  2157. // Test the report ID to see if it is compatible.
  2158. if ((0 != Report[0]) && (channel->ReportID != (UCHAR) Report[0])) {
  2159. // Distinguish between the errors HIDP_USAGE_NOT_FOUND and
  2160. // HIDP_INCOMPATIBLE_REPORT_ID.
  2161. wrongReportID = TRUE;
  2162. continue;
  2163. }
  2164. logicalMin = channel->Data.LogicalMin;
  2165. logicalMax = channel->Data.LogicalMax;
  2166. physicalMin = channel->Data.PhysicalMin;
  2167. physicalMax = channel->Data.PhysicalMax;
  2168. inspect = HidP_ExtractData ((USHORT) (reportBitIndex >> 3),
  2169. (USHORT) (reportBitIndex & 7),
  2170. channel->ReportSize,
  2171. Report);
  2172. //
  2173. // Sign extend the value;
  2174. // Find the top most bit of the field.
  2175. // (logical and with 1 shifted by bit length minus one)
  2176. // based on that, set the upper most bits.
  2177. //
  2178. value = (LONG) (inspect | ((inspect & (1 << (channel->ReportSize - 1))) ?
  2179. ((~(1 << (channel->ReportSize - 1))) + 1) :
  2180. 0));
  2181. //
  2182. // the code path here is ALWAYS the same, we should test it once
  2183. // and then use some sort of switch statement to do the calculation.
  2184. //
  2185. if ((0 == physicalMin) &&
  2186. (0 == physicalMax) &&
  2187. (logicalMin != logicalMax)) {
  2188. //
  2189. // The Device did not set the physical Min and Max Values
  2190. //
  2191. *UsageValue = value;
  2192. } else if ((logicalMax <= logicalMin) || (physicalMax <= physicalMin)) {
  2193. *UsageValue = 0;
  2194. return HIDP_STATUS_BAD_LOG_PHY_VALUES;
  2195. } else {
  2196. // the Min and Max are both inclusive.
  2197. // The value is in range
  2198. // *UsageValue = physicalMin + (((value - logicalMin) *
  2199. // (physicalMax - physicalMin)) /
  2200. // (logicalMax - logicalMin));
  2201. // not enough accuracy.
  2202. //
  2203. *UsageValue = physicalMin
  2204. + (LONG)(((LONGLONG)(value - logicalMin) *
  2205. (LONGLONG)(physicalMax - physicalMin)) /
  2206. (LONGLONG)(logicalMax - logicalMin));
  2207. }
  2208. if ((logicalMin <= value) && (value <= logicalMax)) {
  2209. return HIDP_STATUS_SUCCESS;
  2210. } else {
  2211. // The value is not in range
  2212. *UsageValue = 0;
  2213. if (channel->Data.HasNull) {
  2214. return HIDP_STATUS_NULL;
  2215. } else {
  2216. return HIDP_STATUS_VALUE_OUT_OF_RANGE;
  2217. }
  2218. }
  2219. }
  2220. if (wrongReportID) {
  2221. return HIDP_STATUS_INCOMPATIBLE_REPORT_ID;
  2222. }
  2223. return HIDP_STATUS_USAGE_NOT_FOUND;
  2224. }
  2225. NTSTATUS __stdcall
  2226. HidP_SetOneData (
  2227. struct _CHANNEL_REPORT_HEADER * Iof,
  2228. IN PHIDP_DATA Data,
  2229. IN PHIDP_PREPARSED_DATA PreparsedData,
  2230. IN OUT PCHAR Report
  2231. )
  2232. /*++
  2233. Routine Description:
  2234. Please see hidpi.h for description
  2235. Notes:
  2236. --*/
  2237. {
  2238. PHIDP_CHANNEL_DESC channel;
  2239. ULONG inspect;
  2240. NTSTATUS status = HIDP_STATUS_SUCCESS;
  2241. USHORT channelIndex = 0;
  2242. USHORT dataListIndex = 0;
  2243. USHORT reportBitIndex;
  2244. BOOLEAN wrongReportID = FALSE;
  2245. BOOLEAN noArraySpace = FALSE;
  2246. BOOLEAN notPressed = FALSE;
  2247. for (channelIndex = Iof->Offset; channelIndex < Iof->Index; channelIndex++){
  2248. channel = (PreparsedData->Data + channelIndex);
  2249. if ((channel->Range.DataIndexMin <= Data->DataIndex) &&
  2250. (Data->DataIndex <= channel->Range.DataIndexMax)) {
  2251. if ((!channel->IsRange) && (1 != channel->ReportCount)) {
  2252. //
  2253. // This value array. We cannot access this here.
  2254. //
  2255. return HIDP_STATUS_IS_VALUE_ARRAY;
  2256. }
  2257. // Test the report ID to see if it is compatible.
  2258. if (0 != Report[0]) {
  2259. if (channel->ReportID != (UCHAR) Report[0]) {
  2260. wrongReportID = TRUE;
  2261. continue;
  2262. }
  2263. } else {
  2264. Report[0] = (CHAR) channel->ReportID;
  2265. }
  2266. if (channel->IsButton) {
  2267. if (1 == channel->ReportSize) {
  2268. // A bitfield
  2269. //
  2270. // Little endian (by bit)
  2271. // Byte 2 |Byte 1 |Byte 0
  2272. // 765432107654321076543210 (bits)
  2273. //
  2274. // Get low byte first. (need the higher bits)
  2275. // Offset is from bit zero.
  2276. //
  2277. reportBitIndex = (channel->ByteOffset << 3)
  2278. + channel->BitOffset
  2279. + (USHORT) (Data->DataIndex -
  2280. channel->Range.DataIndexMin);
  2281. if (Data->On) {
  2282. Report [reportBitIndex >> 3] |= (1 << (reportBitIndex & 7));
  2283. } else if (Report [reportBitIndex >> 3] &
  2284. (1 << (reportBitIndex & 7))) {
  2285. Report [reportBitIndex >> 3] &= ~(1 << (reportBitIndex & 7));
  2286. } else {
  2287. return HIDP_STATUS_BUTTON_NOT_PRESSED;
  2288. }
  2289. return HIDP_STATUS_SUCCESS;
  2290. }
  2291. //
  2292. // Not a bit field
  2293. // an array of usages then.
  2294. //
  2295. //
  2296. // Are we clearing a usage from this array?
  2297. //
  2298. if (FALSE == Data->On) {
  2299. //
  2300. // NB Wizard Time (tm)
  2301. //
  2302. // We know that data indices are assigned consecutively
  2303. // for every control, and that the array channels
  2304. // are reversed in the channel array.
  2305. //
  2306. // inspect is the index (1 based not zero based) into the
  2307. // channel array.
  2308. //
  2309. // Skip to the last channel that describes this same data
  2310. // fild;
  2311. //
  2312. while (channel->MoreChannels) {
  2313. channelIndex++;
  2314. channel++;
  2315. }
  2316. inspect = Data->DataIndex - channel->Range.DataIndexMin + 1;
  2317. if (0 == channel->Range.UsageMin) {
  2318. inspect--;
  2319. }
  2320. // Clear the value of inspect which is the usage translated
  2321. // to the index in the array.
  2322. reportBitIndex = channel->BitOffset
  2323. + (channel->ByteOffset << 3);
  2324. status = HidP_DeleteArrayEntry (reportBitIndex,
  2325. channel->ReportSize,
  2326. channel->ReportCount,
  2327. inspect,
  2328. Report);
  2329. if (HIDP_STATUS_BUTTON_NOT_PRESSED == status) {
  2330. notPressed = TRUE;
  2331. continue;
  2332. }
  2333. if (NT_SUCCESS (status)) {
  2334. return status;
  2335. } else {
  2336. ASSERT (0 == status);
  2337. }
  2338. }
  2339. //
  2340. // We are clearly setting a usage into an array.
  2341. //
  2342. for (reportBitIndex = channel->BitOffset;
  2343. reportBitIndex < (channel->BitOffset + channel->BitLength);
  2344. reportBitIndex += channel->ReportSize) {
  2345. // Search for an empty entry in this array
  2346. inspect = (USHORT) HidP_ExtractData (
  2347. (USHORT) ((reportBitIndex >> 3) + channel->ByteOffset),
  2348. (USHORT) (reportBitIndex & 7),
  2349. channel->ReportSize,
  2350. Report);
  2351. if (inspect) {
  2352. //
  2353. // Distinguish between errors HIDP_INDEX_NOT_FOUND and
  2354. // HIDP_BUFFER_TOO_SMALL
  2355. //
  2356. noArraySpace = TRUE;
  2357. continue;
  2358. }
  2359. //
  2360. // NB Wizard Time (tm)
  2361. //
  2362. // We know that data indices are assigned consecutively
  2363. // for every control, and that the array channels
  2364. // are reversed in the channel array.
  2365. //
  2366. // inspect is the index (1 based not zero based) into the
  2367. // channel array.
  2368. //
  2369. // Skip to the last channel that describes this same data
  2370. // fild;
  2371. //
  2372. while (channel->MoreChannels) {
  2373. channelIndex++;
  2374. channel++;
  2375. }
  2376. inspect = Data->DataIndex - channel->Range.DataIndexMin + 1;
  2377. if (0 == channel->Range.UsageMin) {
  2378. inspect--;
  2379. }
  2380. HidP_InsertData (
  2381. (USHORT) ((reportBitIndex >> 3) + channel->ByteOffset),
  2382. (USHORT) (reportBitIndex & 7),
  2383. channel->ReportSize,
  2384. Report,
  2385. inspect);
  2386. return HIDP_STATUS_SUCCESS;
  2387. } // end of search for entry
  2388. continue;
  2389. }
  2390. //
  2391. // Not a button therefore a value.
  2392. //
  2393. reportBitIndex = (channel->ByteOffset << 3)
  2394. + channel->BitOffset
  2395. + ( (Data->DataIndex - channel->Range.DataIndexMin)
  2396. * channel->ReportSize);
  2397. HidP_InsertData ((USHORT) (reportBitIndex >> 3),
  2398. (USHORT) (reportBitIndex & 7),
  2399. channel->ReportSize,
  2400. Report,
  2401. Data->RawValue);
  2402. return HIDP_STATUS_SUCCESS;
  2403. } // end matched data index
  2404. } // end for loop
  2405. if (wrongReportID) {
  2406. return HIDP_STATUS_INCOMPATIBLE_REPORT_ID;
  2407. }
  2408. if (notPressed) {
  2409. return HIDP_STATUS_BUTTON_NOT_PRESSED;
  2410. }
  2411. if (noArraySpace) {
  2412. return HIDP_STATUS_BUFFER_TOO_SMALL;
  2413. }
  2414. return HIDP_STATUS_DATA_INDEX_NOT_FOUND;
  2415. }
  2416. NTSTATUS
  2417. HidP_SetData (
  2418. IN HIDP_REPORT_TYPE ReportType,
  2419. IN PHIDP_DATA DataList,
  2420. IN OUT PULONG DataLength,
  2421. IN PHIDP_PREPARSED_DATA PreparsedData,
  2422. IN OUT PCHAR Report,
  2423. IN ULONG ReportLength
  2424. )
  2425. {
  2426. ULONG dataIndex;
  2427. NTSTATUS status;
  2428. struct _CHANNEL_REPORT_HEADER * iof;
  2429. CHECK_PPD (PreparsedData);
  2430. switch (ReportType) {
  2431. case HidP_Input:
  2432. iof = &PreparsedData->Input;
  2433. break;
  2434. case HidP_Output:
  2435. iof = &PreparsedData->Output;
  2436. break;
  2437. case HidP_Feature:
  2438. iof = &PreparsedData->Feature;
  2439. break;
  2440. default:
  2441. return HIDP_STATUS_INVALID_REPORT_TYPE;
  2442. }
  2443. if ((USHORT) ReportLength != iof->ByteLen) {
  2444. return HIDP_STATUS_INVALID_REPORT_LENGTH;
  2445. }
  2446. if (0 == iof->ByteLen) {
  2447. return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
  2448. }
  2449. for (dataIndex = 0; dataIndex < *DataLength; dataIndex++, DataList++) {
  2450. status = HidP_SetOneData (iof, DataList, PreparsedData, Report);
  2451. if (!NT_SUCCESS (status)) {
  2452. break;
  2453. }
  2454. }
  2455. *DataLength = dataIndex;
  2456. return status;
  2457. }
  2458. NTSTATUS __stdcall
  2459. HidP_GetData (
  2460. IN HIDP_REPORT_TYPE ReportType,
  2461. OUT PHIDP_DATA DataList,
  2462. IN OUT PULONG DataLength,
  2463. IN PHIDP_PREPARSED_DATA PreparsedData,
  2464. IN PCHAR Report,
  2465. IN ULONG ReportLength
  2466. )
  2467. {
  2468. struct _CHANNEL_REPORT_HEADER * iof;
  2469. PHIDP_CHANNEL_DESC channel;
  2470. ULONG inspect;
  2471. USHORT channelIndex = 0;
  2472. USHORT dataListIndex = 0;
  2473. USHORT reportBitIndex;
  2474. USHORT tmpBitIndex;
  2475. USHORT tmpDataIndex;
  2476. NTSTATUS status = HIDP_STATUS_SUCCESS;
  2477. CHECK_PPD (PreparsedData);
  2478. switch (ReportType) {
  2479. case HidP_Input:
  2480. iof = &PreparsedData->Input;
  2481. break;
  2482. case HidP_Output:
  2483. iof = &PreparsedData->Output;
  2484. break;
  2485. case HidP_Feature:
  2486. iof = &PreparsedData->Feature;
  2487. break;
  2488. default:
  2489. return HIDP_STATUS_INVALID_REPORT_TYPE;
  2490. }
  2491. if ((USHORT) ReportLength != iof->ByteLen) {
  2492. return HIDP_STATUS_INVALID_REPORT_LENGTH;
  2493. }
  2494. if (0 == iof->ByteLen) {
  2495. return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
  2496. }
  2497. for (channelIndex = iof->Offset; channelIndex < iof->Index; channelIndex++) {
  2498. channel = (PreparsedData->Data + channelIndex);
  2499. if ((!channel->IsRange) && (1 != channel->ReportCount)) {
  2500. //
  2501. // This value array. We cannot access this here.
  2502. //
  2503. continue;
  2504. }
  2505. // Test the report ID to see if it is compatible.
  2506. if ((0 != Report[0]) && (channel->ReportID != (UCHAR) Report[0])) {
  2507. continue;
  2508. }
  2509. if (channel->IsButton) {
  2510. if (1 == channel->ReportSize) {
  2511. // A bitfield
  2512. //
  2513. // Little endian (by bit)
  2514. // Byte 2 |Byte 1 |Byte 0
  2515. // 765432107654321076543210 (bits)
  2516. //
  2517. // Get low byte first. (need the higher bits)
  2518. // Offset is from bit zero.
  2519. //
  2520. for (reportBitIndex = channel->BitOffset;
  2521. reportBitIndex < (channel->BitLength + channel->BitOffset);
  2522. reportBitIndex++) {
  2523. // Check it one bit at a time.
  2524. tmpBitIndex = reportBitIndex + (channel->ByteOffset << 3);
  2525. inspect = Report [tmpBitIndex >> 3] & (1 << (tmpBitIndex & 7));
  2526. tmpBitIndex = reportBitIndex - channel->BitOffset;
  2527. if (inspect) {
  2528. if (channel->IsRange) {
  2529. inspect = channel->Range.DataIndexMin + tmpBitIndex;
  2530. } else {
  2531. inspect = channel->NotRange.DataIndex;
  2532. }
  2533. if (dataListIndex < *DataLength) {
  2534. DataList[dataListIndex].On = TRUE;
  2535. DataList[dataListIndex].DataIndex = (USHORT)inspect;
  2536. }
  2537. dataListIndex++;
  2538. }
  2539. }
  2540. continue;
  2541. }
  2542. //
  2543. // Not a bit field
  2544. // an array of usages.
  2545. //
  2546. for (reportBitIndex = channel->BitOffset;
  2547. reportBitIndex < (channel->BitOffset + channel->BitLength);
  2548. reportBitIndex += channel->ReportSize) {
  2549. inspect = (USHORT) HidP_ExtractData (
  2550. (USHORT) ((reportBitIndex >> 3) + channel->ByteOffset),
  2551. (USHORT) (reportBitIndex & 7),
  2552. channel->ReportSize,
  2553. Report);
  2554. if (inspect) {
  2555. //
  2556. // NB Wizard Time (tm)
  2557. //
  2558. // We know that data indices are assigned consecutively
  2559. // for every control, and that the array channels
  2560. // are reversed in the channel array.
  2561. //
  2562. // inspect is the index (1 based not zero based) into the
  2563. // channel array.
  2564. //
  2565. if (0 == inspect) {
  2566. continue;
  2567. }
  2568. //
  2569. // Skip to the last channel that describes this same data
  2570. // fild;
  2571. //
  2572. while (channel->MoreChannels) {
  2573. channelIndex++;
  2574. channel++;
  2575. }
  2576. inspect += channel->Range.DataIndexMin - 1;
  2577. if (0 == channel->Range.UsageMin) {
  2578. inspect++;
  2579. }
  2580. if (dataListIndex < *DataLength) {
  2581. DataList [dataListIndex].On = TRUE;
  2582. DataList [dataListIndex].DataIndex = (USHORT) inspect;
  2583. }
  2584. dataListIndex++;
  2585. }
  2586. }
  2587. continue;
  2588. }
  2589. //
  2590. // Not a button so therefore a value.
  2591. //
  2592. for (reportBitIndex = channel->BitOffset, tmpDataIndex = 0;
  2593. reportBitIndex < (channel->BitOffset + channel->BitLength);
  2594. reportBitIndex += channel->ReportSize, tmpDataIndex++) {
  2595. inspect = HidP_ExtractData (
  2596. (USHORT) ((reportBitIndex >> 3) + channel->ByteOffset),
  2597. (USHORT) (reportBitIndex & 7),
  2598. channel->ReportSize,
  2599. Report);
  2600. if (dataListIndex < *DataLength) {
  2601. ASSERT(tmpDataIndex + channel->Range.DataIndexMin <=
  2602. channel->Range.DataIndexMax);
  2603. DataList [dataListIndex].RawValue = inspect;
  2604. DataList [dataListIndex].DataIndex =
  2605. channel->Range.DataIndexMin + tmpDataIndex;
  2606. }
  2607. dataListIndex++;
  2608. }
  2609. }
  2610. if (*DataLength < dataListIndex) {
  2611. status = HIDP_STATUS_BUFFER_TOO_SMALL;
  2612. }
  2613. *DataLength = dataListIndex;
  2614. return status;
  2615. }