2 * PROJECT: ReactOS HID Parser Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/hidparser/api.c
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
14 static ULONG KeyboardScanCodes
[256] =
16 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
17 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
18 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
19 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
20 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
21 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
22 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
23 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
24 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0,
25 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
26 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
27 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
28 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
31 150,158,159,128,136,177,178,176,142,152,173,140
35 HidParser_GetCollectionUsagePage(
36 IN PVOID CollectionContext
,
38 OUT PUSHORT UsagePage
)
40 PHID_COLLECTION Collection
;
45 Collection
= HidParser_GetCollectionFromContext(CollectionContext
);
49 // collection not found
51 return HIDPARSER_STATUS_COLLECTION_NOT_FOUND
;
57 *UsagePage
= (Collection
->Usage
>> 16);
58 *Usage
= (Collection
->Usage
& 0xFFFF);
59 return HIDPARSER_STATUS_SUCCESS
;
63 HidParser_GetReportLength(
64 IN PVOID CollectionContext
,
73 Report
= HidParser_GetReportInCollection(CollectionContext
, ReportType
);
85 ReportLength
= Report
->ReportSize
;
93 // byte aligned length
95 ASSERT(ReportLength
% 8 == 0);
96 return ReportLength
/ 8;
102 HidParser_GetReportItemCountFromReportType(
103 IN PVOID CollectionContext
,
111 Report
= HidParser_GetReportInCollection(CollectionContext
, ReportType
);
121 // return report item count
123 return Report
->ItemCount
;
128 HidParser_GetReportItemTypeCountFromReportType(
129 IN PVOID CollectionContext
,
140 Report
= HidParser_GetReportInCollection(CollectionContext
, ReportType
);
150 // enumerate all items
152 for(Index
= 0; Index
< Report
->ItemCount
; Index
++)
157 if (Report
->Items
[Index
].HasData
&& bData
== TRUE
)
164 else if (Report
->Items
[Index
].HasData
== FALSE
&& bData
== FALSE
)
181 HidParser_InitParser(
182 IN PHIDPARSER_ALLOC_FUNCTION AllocFunction
,
183 IN PHIDPARSER_FREE_FUNCTION FreeFunction
,
184 IN PHIDPARSER_ZERO_FUNCTION ZeroFunction
,
185 IN PHIDPARSER_COPY_FUNCTION CopyFunction
,
186 IN PHIDPARSER_DEBUG_FUNCTION DebugFunction
,
187 OUT PHID_PARSER Parser
)
189 Parser
->Alloc
= AllocFunction
;
190 Parser
->Free
= FreeFunction
;
191 Parser
->Zero
= ZeroFunction
;
192 Parser
->Copy
= CopyFunction
;
193 Parser
->Debug
= DebugFunction
;
197 HidParser_GetMaxUsageListLengthWithReportAndPage(
198 IN PVOID CollectionContext
,
200 IN USAGE UsagePage OPTIONAL
)
205 USHORT CurrentUsagePage
;
210 Report
= HidParser_GetReportInCollection(CollectionContext
, ReportType
);
219 for(Index
= 0; Index
< Report
->ItemCount
; Index
++)
224 CurrentUsagePage
= (Report
->Items
[Index
].UsageMinimum
>> 16);
225 if (CurrentUsagePage
== UsagePage
&& Report
->Items
[Index
].HasData
)
241 HidParser_GetSpecificValueCapsWithReport(
242 IN PHID_PARSER Parser
,
243 IN PVOID CollectionContext
,
247 OUT PHIDP_VALUE_CAPS ValueCaps
,
248 IN OUT PULONG ValueCapsLength
)
253 USHORT CurrentUsagePage
;
259 Report
= HidParser_GetReportInCollection(CollectionContext
, ReportType
);
265 return HIDPARSER_STATUS_REPORT_NOT_FOUND
;
268 for(Index
= 0; Index
< Report
->ItemCount
; Index
++)
273 CurrentUsagePage
= (Report
->Items
[Index
].UsageMinimum
>> 16);
274 CurrentUsage
= (Report
->Items
[Index
].UsageMinimum
& 0xFFFF);
276 if ((Usage
== CurrentUsage
&& UsagePage
== CurrentUsagePage
) || (Usage
== 0 && UsagePage
== CurrentUsagePage
) || (Usage
== CurrentUsage
&& UsagePage
== 0) || (Usage
== 0 && UsagePage
== 0))
279 // check if there is enough place for the caps
281 if (ItemCount
< *ValueCapsLength
)
286 Parser
->Zero(&ValueCaps
[ItemCount
], sizeof(HIDP_VALUE_CAPS
));
291 ValueCaps
[ItemCount
].UsagePage
= CurrentUsagePage
;
292 ValueCaps
[ItemCount
].ReportID
= Report
->ReportID
;
293 ValueCaps
[ItemCount
].LogicalMin
= Report
->Items
[Index
].Minimum
;
294 ValueCaps
[ItemCount
].LogicalMax
= Report
->Items
[Index
].Maximum
;
295 ValueCaps
[ItemCount
].IsAbsolute
= !Report
->Items
[Index
].Relative
;
296 ValueCaps
[ItemCount
].BitSize
= Report
->Items
[Index
].BitCount
;
314 *ValueCapsLength
= ItemCount
;
321 return HIDPARSER_STATUS_SUCCESS
;
327 return HIDPARSER_STATUS_USAGE_NOT_FOUND
;
331 HidParser_GetUsagesWithReport(
332 IN PHID_PARSER Parser
,
333 IN PVOID CollectionContext
,
336 OUT USAGE
*UsageList
,
337 IN OUT PULONG UsageLength
,
338 IN PCHAR ReportDescriptor
,
339 IN ULONG ReportDescriptorLength
)
344 USHORT CurrentUsagePage
;
345 PHID_REPORT_ITEM ReportItem
;
352 Report
= HidParser_GetReportInCollection(CollectionContext
, ReportType
);
358 return HIDPARSER_STATUS_REPORT_NOT_FOUND
;
361 if (Report
->ReportSize
/ 8 != (ReportDescriptorLength
- 1))
364 // invalid report descriptor length
366 return HIDPARSER_STATUS_INVALID_REPORT_LENGTH
;
369 for(Index
= 0; Index
< Report
->ItemCount
; Index
++)
374 ReportItem
= &Report
->Items
[Index
];
379 if (!ReportItem
->HasData
)
385 CurrentUsagePage
= (ReportItem
->UsageMinimum
>> 16);
390 if (UsagePage
!= CurrentUsagePage
)
394 // check if the specified usage is activated
396 ASSERT(ReportItem
->ByteOffset
< ReportDescriptorLength
);
397 ASSERT(ReportItem
->BitCount
< 8);
400 // one extra shift for skipping the prepended report id
402 Data
= ReportDescriptor
[ReportItem
->ByteOffset
+ 1];
407 Data
>>= ReportItem
->Shift
;
410 // clear unwanted bits
412 Data
&= ReportItem
->Mask
;
417 Activated
= (Data
!= 0);
423 // is there enough space for the usage
425 if (ItemCount
>= *UsageLength
)
434 UsageList
[ItemCount
] = (ReportItem
->UsageMinimum
& 0xFFFF);
438 if (ItemCount
> *UsageLength
)
443 return HIDPARSER_STATUS_BUFFER_TOO_SMALL
;
447 // success, clear rest of array
449 Parser
->Zero(&UsageList
[ItemCount
], (*UsageLength
- ItemCount
) * sizeof(USAGE
));
454 *UsageLength
= ItemCount
;
459 return HIDPARSER_STATUS_SUCCESS
;
463 HidParser_GetScaledUsageValueWithReport(
464 IN PHID_PARSER Parser
,
465 IN PVOID CollectionContext
,
469 OUT PLONG UsageValue
,
470 IN PCHAR ReportDescriptor
,
471 IN ULONG ReportDescriptorLength
)
475 USHORT CurrentUsagePage
;
476 PHID_REPORT_ITEM ReportItem
;
482 Report
= HidParser_GetReportInCollection(CollectionContext
, ReportType
);
488 return HIDPARSER_STATUS_REPORT_NOT_FOUND
;
491 if (Report
->ReportSize
/ 8 != (ReportDescriptorLength
- 1))
494 // invalid report descriptor length
496 return HIDPARSER_STATUS_INVALID_REPORT_LENGTH
;
499 for(Index
= 0; Index
< Report
->ItemCount
; Index
++)
504 ReportItem
= &Report
->Items
[Index
];
509 CurrentUsagePage
= (ReportItem
->UsageMinimum
>> 16);
512 // does usage page match
514 if (UsagePage
!= CurrentUsagePage
)
518 // does the usage match
520 if (Usage
!= (ReportItem
->UsageMinimum
& 0xFFFF))
524 // check if the specified usage is activated
526 ASSERT(ReportItem
->ByteOffset
< ReportDescriptorLength
);
529 // one extra shift for skipping the prepended report id
532 Parser
->Copy(&Data
, &ReportDescriptor
[ReportItem
->ByteOffset
+1], min(sizeof(ULONG
), ReportDescriptorLength
- (ReportItem
->ByteOffset
+ 1)));
533 Data
= ReportDescriptor
[ReportItem
->ByteOffset
+ 1];
538 Data
>>= ReportItem
->Shift
;
541 // clear unwanted bits
543 Data
&= ReportItem
->Mask
;
545 if (ReportItem
->Minimum
> ReportItem
->Maximum
)
548 // logical boundaries are signed values
550 if ((Data
& ~(ReportItem
->Mask
>> 1)) != 0)
552 Data
|= ~ReportItem
->Mask
;
560 return HIDPARSER_STATUS_SUCCESS
;
566 return HIDPARSER_STATUS_USAGE_NOT_FOUND
;
570 HidParser_GetScanCode(
573 if (Usage
< sizeof(KeyboardScanCodes
) / sizeof(KeyboardScanCodes
[0]))
578 return KeyboardScanCodes
[Usage
];
588 HidParser_DispatchKey(
590 IN HIDP_KEYBOARD_DIRECTION KeyAction
,
591 IN PHIDP_INSERT_SCANCODES InsertCodesProcedure
,
592 IN PVOID InsertCodesContext
)
600 for(Index
= 0; Index
< sizeof(ULONG
); Index
++)
602 if (ScanCodes
[Index
] == 0)
611 // is this a key break
613 if (KeyAction
== HidP_Keyboard_Break
)
618 ScanCodes
[Index
] |= KEY_BREAK
;
630 // dispatch scan codes
632 InsertCodesProcedure(InsertCodesContext
, ScanCodes
, Length
);
638 HidParser_TranslateUsage(
639 IN PHID_PARSER Parser
,
641 IN HIDP_KEYBOARD_DIRECTION KeyAction
,
642 IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState
,
643 IN PHIDP_INSERT_SCANCODES InsertCodesProcedure
,
644 IN PVOID InsertCodesContext
)
651 ScanCode
= HidParser_GetScanCode(Usage
);
655 // invalid lookup or no scan code available
657 return HIDPARSER_STATUS_I8042_TRANS_UNKNOWN
;
661 // FIXME: translate modifier states
664 HidParser_DispatchKey((PCHAR
)&ScanCode
, KeyAction
, InsertCodesProcedure
, InsertCodesContext
);
669 return HIDPARSER_STATUS_SUCCESS
;