[USB-BRINGUP]
[reactos.git] / lib / drivers / hidparser / api.c
1 /*
2 * PROJECT: ReactOS HID Parser Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/hidparser/api.c
5 * PURPOSE: HID Parser
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10
11
12 #include "parser.h"
13
14 static ULONG KeyboardScanCodes[256] =
15 {
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
32 };
33
34
35
36 ULONG
37 HidParser_NumberOfTopCollections(
38 IN PHID_PARSER Parser)
39 {
40 PHID_PARSER_CONTEXT ParserContext;
41
42 //
43 // get parser context
44 //
45 ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
46
47 //
48 // sanity checks
49 //
50 ASSERT(ParserContext);
51 ASSERT(ParserContext->RootCollection);
52 ASSERT(ParserContext->RootCollection->NodeCount);
53
54 //
55 // number of top collections
56 //
57 return ParserContext->RootCollection->NodeCount;
58 }
59
60 PHID_COLLECTION
61 HidParser_GetCollection(
62 IN PHID_PARSER Parser,
63 IN ULONG CollectionNumber)
64 {
65 PHID_PARSER_CONTEXT ParserContext;
66
67 //
68 // get parser context
69 //
70 ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
71
72 //
73 // sanity checks
74 //
75 ASSERT(ParserContext);
76 ASSERT(ParserContext->RootCollection);
77 ASSERT(ParserContext->RootCollection->NodeCount);
78
79 //
80 // is collection index out of bounds
81 //
82 if (CollectionNumber < ParserContext->RootCollection->NodeCount)
83 {
84 //
85 // valid collection
86 //
87 return ParserContext->RootCollection->Nodes[CollectionNumber];
88 }
89
90 //
91 // no such collection
92 //
93 Parser->Debug("HIDPARSE] No such collection %lu\n", CollectionNumber);
94 return NULL;
95 }
96
97 PHID_REPORT
98 HidParser_GetReportByType(
99 IN PHID_PARSER Parser,
100 IN ULONG ReportType)
101 {
102 PHID_PARSER_CONTEXT ParserContext;
103 ULONG Index;
104
105 //
106 // get parser context
107 //
108 ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
109
110 //
111 // sanity checks
112 //
113 ASSERT(ParserContext);
114
115 //
116 // FIXME support multiple top collecions
117 //
118 ASSERT(ParserContext->RootCollection->NodeCount == 1);
119 for(Index = 0; Index < ParserContext->ReportCount; Index++)
120 {
121 //
122 // check if the report type match
123 //
124 if (ParserContext->Reports[Index]->Type == ReportType)
125 {
126 //
127 // found report
128 //
129 return ParserContext->Reports[Index];
130 }
131 }
132
133 //
134 // report not found
135 //
136 return NULL;
137 }
138
139
140 ULONG
141 HidParser_NumberOfReports(
142 IN PHID_PARSER Parser,
143 IN ULONG ReportType)
144 {
145 PHID_PARSER_CONTEXT ParserContext;
146 ULONG Index;
147 ULONG ReportCount = 0;
148
149 //
150 // get parser context
151 //
152 ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
153
154 //
155 // sanity checks
156 //
157 ASSERT(ParserContext);
158
159 //
160 // FIXME support multiple top collecions
161 //
162 ASSERT(ParserContext->RootCollection->NodeCount == 1);
163 for(Index = 0; Index < ParserContext->ReportCount; Index++)
164 {
165 //
166 // check if the report type match
167 //
168 if (ParserContext->Reports[Index]->Type == ReportType)
169 {
170 //
171 // found report
172 //
173 ReportCount++;
174 }
175 }
176
177 //
178 // done
179 //
180 return ReportCount;
181 }
182
183 HIDPARSER_STATUS
184 HidParser_GetCollectionUsagePage(
185 IN PHID_PARSER Parser,
186 IN ULONG CollectionIndex,
187 OUT PUSHORT Usage,
188 OUT PUSHORT UsagePage)
189 {
190 PHID_COLLECTION Collection;
191
192 //
193 // find collection
194 //
195 Collection = HidParser_GetCollection(Parser, CollectionIndex);
196 if (!Collection)
197 {
198 //
199 // collection not found
200 //
201 return HIDPARSER_STATUS_COLLECTION_NOT_FOUND;
202 }
203
204 //
205 // store result
206 //
207 *UsagePage = (Collection->Usage >> 16);
208 *Usage = (Collection->Usage & 0xFFFF);
209 return HIDPARSER_STATUS_SUCCESS;
210 }
211
212 ULONG
213 HidParser_GetReportLength(
214 IN PHID_PARSER Parser,
215 IN ULONG ReportType)
216 {
217 PHID_PARSER_CONTEXT ParserContext;
218 PHID_REPORT Report;
219 ULONG ReportLength;
220
221 //
222 // get parser context
223 //
224 ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
225
226 //
227 // sanity checks
228 //
229 ASSERT(ParserContext);
230
231 //
232 // FIXME support multiple top collecions
233 //
234 ASSERT(ParserContext->RootCollection->NodeCount == 1);
235
236 //
237 // get first report
238 //
239 Report = HidParser_GetReportByType(Parser, ReportType);
240 if (!Report)
241 {
242 //
243 // no report found
244 //
245 return 0;
246 }
247
248 //
249 // get report length
250 //
251 ReportLength = Report->ReportSize;
252
253 //
254 // done
255 //
256 if (ReportLength)
257 {
258 //
259 // byte aligned length
260 //
261 ASSERT(ReportLength % 8 == 0);
262 return ReportLength / 8;
263 }
264 return ReportLength;
265 }
266
267 UCHAR
268 HidParser_IsReportIDUsed(
269 IN PHID_PARSER Parser)
270 {
271 PHID_PARSER_CONTEXT ParserContext;
272
273 //
274 // get parser context
275 //
276 ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
277
278 //
279 // sanity checks
280 //
281 ASSERT(ParserContext);
282
283 //
284 // return flag
285 //
286 return ParserContext->UseReportIDs;
287 }
288
289 ULONG
290 HidParser_GetReportItemCountFromReportType(
291 IN PHID_PARSER Parser,
292 IN ULONG ReportType)
293 {
294 PHID_PARSER_CONTEXT ParserContext;
295 PHID_REPORT Report;
296
297 //
298 // get parser context
299 //
300 ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
301
302 //
303 // sanity checks
304 //
305 ASSERT(ParserContext);
306
307 //
308 // FIXME support multiple top collecions
309 //
310 ASSERT(ParserContext->RootCollection->NodeCount == 1);
311
312 //
313 // get report
314 //
315 Report = HidParser_GetReportByType(Parser, ReportType);
316 if (!Report)
317 {
318 //
319 // no such report
320 //
321 return 0;
322 }
323
324 //
325 // return report item count
326 //
327 return Report->ItemCount;
328 }
329
330
331 ULONG
332 HidParser_GetReportItemTypeCountFromReportType(
333 IN PHID_PARSER Parser,
334 IN ULONG ReportType,
335 IN ULONG bData)
336 {
337 PHID_PARSER_CONTEXT ParserContext;
338 ULONG Index;
339 PHID_REPORT Report;
340 ULONG ItemCount = 0;
341
342 //
343 // get parser context
344 //
345 ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
346
347 //
348 // sanity checks
349 //
350 ASSERT(ParserContext);
351
352 //
353 // FIXME support multiple top collecions
354 //
355 ASSERT(ParserContext->RootCollection->NodeCount == 1);
356
357 //
358 // get report
359 //
360 Report = HidParser_GetReportByType(Parser, ReportType);
361 if (!Report)
362 {
363 //
364 // no such report
365 //
366 return 0;
367 }
368
369 //
370 // enumerate all items
371 //
372 for(Index = 0; Index < Report->ItemCount; Index++)
373 {
374 //
375 // check item type
376 //
377 if (Report->Items[Index]->HasData && bData == TRUE)
378 {
379 //
380 // found data item
381 //
382 ItemCount++;
383 }
384 else if (Report->Items[Index]->HasData == FALSE && bData == FALSE)
385 {
386 //
387 // found value item
388 //
389 ItemCount++;
390 }
391 }
392
393 //
394 // no report items
395 //
396 return ItemCount;
397 }
398
399 ULONG
400 HidParser_GetContextSize(
401 IN PHID_PARSER Parser)
402 {
403 //
404 // FIXME the context must contain all parsed info
405 //
406 return sizeof(HID_PARSER_CONTEXT);
407 }
408
409 VOID
410 HidParser_FreeContext(
411 IN PHID_PARSER Parser,
412 IN PUCHAR Context,
413 IN ULONG ContextLength)
414 {
415 //
416 // FIXME implement freeing of parsed info
417 //
418 }
419
420 HIDPARSER_STATUS
421 HidParser_AllocateParser(
422 IN PHIDPARSER_ALLOC_FUNCTION AllocFunction,
423 IN PHIDPARSER_FREE_FUNCTION FreeFunction,
424 IN PHIDPARSER_ZERO_FUNCTION ZeroFunction,
425 IN PHIDPARSER_COPY_FUNCTION CopyFunction,
426 IN PHIDPARSER_DEBUG_FUNCTION DebugFunction,
427 OUT PHID_PARSER *OutParser)
428 {
429 PHID_PARSER Parser;
430 PHID_PARSER_CONTEXT ParserContext;
431
432 //
433 // allocate
434 //
435 Parser = (PHID_PARSER)AllocFunction(sizeof(HID_PARSER));
436 if (!Parser)
437 {
438 //
439 // no memory
440 //
441 return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
442 }
443
444 //
445 // allocate parser context
446 //
447 ParserContext = (PHID_PARSER_CONTEXT)AllocFunction(sizeof(HID_PARSER_CONTEXT));
448 if (!ParserContext)
449 {
450 //
451 // no memory
452 //
453 FreeFunction(Parser);
454 return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
455 }
456
457
458 //
459 // init parser
460 //
461 Parser->Alloc = AllocFunction;
462 Parser->Free = FreeFunction;
463 Parser->Zero = ZeroFunction;
464 Parser->Copy = CopyFunction;
465 Parser->Debug = DebugFunction;
466 Parser->ParserContext = ParserContext;
467
468 //
469 // store result
470 //
471 *OutParser = Parser;
472 //
473 // success
474 //
475 return HIDPARSER_STATUS_SUCCESS;
476 }
477
478 VOID
479 HidParser_InitParser(
480 IN PHIDPARSER_ALLOC_FUNCTION AllocFunction,
481 IN PHIDPARSER_FREE_FUNCTION FreeFunction,
482 IN PHIDPARSER_ZERO_FUNCTION ZeroFunction,
483 IN PHIDPARSER_COPY_FUNCTION CopyFunction,
484 IN PHIDPARSER_DEBUG_FUNCTION DebugFunction,
485 IN PVOID ParserContext,
486 OUT PHID_PARSER Parser)
487 {
488 Parser->Alloc = AllocFunction;
489 Parser->Free = FreeFunction;
490 Parser->Zero = ZeroFunction;
491 Parser->Copy = CopyFunction;
492 Parser->Debug = DebugFunction;
493 Parser->ParserContext = ParserContext;
494 }
495
496 ULONG
497 HidParser_GetCollectionCount(
498 IN PHID_COLLECTION Collection)
499 {
500 ULONG Index;
501 ULONG Count = Collection->NodeCount;
502
503 for(Index = 0; Index < Collection->NodeCount; Index++)
504 {
505 //
506 // count collection for sub nodes
507 //
508 Count += HidParser_GetCollectionCount(Collection->Nodes[Index]);
509 }
510
511 //
512 // done
513 //
514 return Count;
515 }
516
517 ULONG
518 HidParser_GetTotalCollectionCount(
519 IN PHID_PARSER Parser)
520 {
521 PHID_PARSER_CONTEXT ParserContext;
522
523 //
524 // get parser context
525 //
526 ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
527
528 //
529 // sanity check
530 //
531 ASSERT(ParserContext);
532 ASSERT(ParserContext->RootCollection);
533
534 //
535 // count collections
536 //
537 return HidParser_GetCollectionCount(ParserContext->RootCollection);
538 }
539
540 ULONG
541 HidParser_GetMaxUsageListLengthWithReportAndPage(
542 IN PHID_PARSER Parser,
543 IN ULONG ReportType,
544 IN USAGE UsagePage OPTIONAL)
545 {
546 PHID_PARSER_CONTEXT ParserContext;
547 ULONG Index;
548 PHID_REPORT Report;
549 ULONG ItemCount = 0;
550 USHORT CurrentUsagePage;
551
552 //
553 // get parser context
554 //
555 ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
556
557 //
558 // sanity checks
559 //
560 ASSERT(ParserContext);
561
562 //
563 // FIXME support multiple top collecions
564 //
565 ASSERT(ParserContext->RootCollection->NodeCount == 1);
566
567 //
568 // get report
569 //
570 Report = HidParser_GetReportByType(Parser, ReportType);
571 if (!Report)
572 {
573 //
574 // no such report
575 //
576 return 0;
577 }
578
579 for(Index = 0; Index < Report->ItemCount; Index++)
580 {
581 //
582 // check usage page
583 //
584 CurrentUsagePage = (Report->Items[Index]->UsageMinimum >> 16);
585 if (CurrentUsagePage == UsagePage && Report->Items[Index]->HasData)
586 {
587 //
588 // found item
589 //
590 ItemCount++;
591 }
592 }
593
594 //
595 // done
596 //
597 return ItemCount;
598 }
599
600 HIDPARSER_STATUS
601 HidParser_GetSpecificValueCapsWithReport(
602 IN PHID_PARSER Parser,
603 IN ULONG ReportType,
604 IN USHORT UsagePage,
605 IN USHORT Usage,
606 OUT PHIDP_VALUE_CAPS ValueCaps,
607 IN OUT PULONG ValueCapsLength)
608 {
609 PHID_PARSER_CONTEXT ParserContext;
610 ULONG Index;
611 PHID_REPORT Report;
612 ULONG ItemCount = 0;
613 USHORT CurrentUsagePage;
614 USHORT CurrentUsage;
615
616 //
617 // get parser context
618 //
619 ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
620
621 //
622 // sanity checks
623 //
624 ASSERT(ParserContext);
625
626 //
627 // FIXME support multiple top collecions
628 //
629 ASSERT(ParserContext->RootCollection->NodeCount == 1);
630
631 //
632 // get report
633 //
634 Report = HidParser_GetReportByType(Parser, ReportType);
635 if (!Report)
636 {
637 //
638 // no such report
639 //
640 return HIDPARSER_STATUS_REPORT_NOT_FOUND;
641 }
642
643 for(Index = 0; Index < Report->ItemCount; Index++)
644 {
645 //
646 // check usage page
647 //
648 CurrentUsagePage = (Report->Items[Index]->UsageMinimum >> 16);
649 CurrentUsage = (Report->Items[Index]->UsageMinimum & 0xFFFF);
650
651 if ((Usage == CurrentUsage && UsagePage == CurrentUsagePage) || (Usage == 0 && UsagePage == CurrentUsagePage) || (Usage == CurrentUsage && UsagePage == 0) || (Usage == 0 && UsagePage == 0))
652 {
653 //
654 // check if there is enough place for the caps
655 //
656 if (ItemCount < *ValueCapsLength)
657 {
658 //
659 // zero caps
660 //
661 Parser->Zero(&ValueCaps[ItemCount], sizeof(HIDP_VALUE_CAPS));
662
663 //
664 // init caps
665 //
666 ValueCaps[ItemCount].UsagePage = CurrentUsagePage;
667 ValueCaps[ItemCount].ReportID = Report->ReportID;
668 ValueCaps[ItemCount].LogicalMin = Report->Items[Index]->Minimum;
669 ValueCaps[ItemCount].LogicalMax = Report->Items[Index]->Maximum;
670 ValueCaps[ItemCount].IsAbsolute = !Report->Items[Index]->Relative;
671 ValueCaps[ItemCount].BitSize = Report->Items[Index]->BitCount;
672
673 //
674 // FIXME: FILLMEIN
675 //
676 }
677
678
679 //
680 // found item
681 //
682 ItemCount++;
683 }
684 }
685
686 //
687 // store result
688 //
689 *ValueCapsLength = ItemCount;
690
691 if (ItemCount)
692 {
693 //
694 // success
695 //
696 return HIDPARSER_STATUS_SUCCESS;
697 }
698
699 //
700 // item not found
701 //
702 return HIDPARSER_STATUS_USAGE_NOT_FOUND;
703 }
704
705 HIDPARSER_STATUS
706 HidParser_GetUsagesWithReport(
707 IN PHID_PARSER Parser,
708 IN ULONG ReportType,
709 IN USAGE UsagePage,
710 OUT USAGE *UsageList,
711 IN OUT PULONG UsageLength,
712 IN PCHAR ReportDescriptor,
713 IN ULONG ReportDescriptorLength)
714 {
715 PHID_PARSER_CONTEXT ParserContext;
716 ULONG Index;
717 PHID_REPORT Report;
718 ULONG ItemCount = 0;
719 USHORT CurrentUsagePage;
720 PHID_REPORT_ITEM ReportItem;
721 UCHAR Activated;
722 ULONG Data;
723
724 //
725 // get parser context
726 //
727 ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
728
729 //
730 // sanity checks
731 //
732 ASSERT(ParserContext);
733
734 //
735 // FIXME support multiple top collecions
736 //
737 ASSERT(ParserContext->RootCollection->NodeCount == 1);
738
739 //
740 // get report
741 //
742 Report = HidParser_GetReportByType(Parser, ReportType);
743 if (!Report)
744 {
745 //
746 // no such report
747 //
748 return HIDPARSER_STATUS_REPORT_NOT_FOUND;
749 }
750
751 if (Report->ReportSize / 8 != (ReportDescriptorLength - 1))
752 {
753 //
754 // invalid report descriptor length
755 //
756 return HIDPARSER_STATUS_INVALID_REPORT_LENGTH;
757 }
758
759 for(Index = 0; Index < Report->ItemCount; Index++)
760 {
761 //
762 // get report item
763 //
764 ReportItem = Report->Items[Index];
765
766 //
767 // does it have data
768 //
769 if (!ReportItem->HasData)
770 continue;
771
772 //
773 // check usage page
774 //
775 CurrentUsagePage = (ReportItem->UsageMinimum >> 16);
776
777 //
778 // does usage match
779 //
780 if (UsagePage != CurrentUsagePage)
781 continue;
782
783 //
784 // check if the specified usage is activated
785 //
786 ASSERT(ReportItem->ByteOffset < ReportDescriptorLength);
787 ASSERT(ReportItem->BitCount < 8);
788
789 //
790 // one extra shift for skipping the prepended report id
791 //
792 Data = ReportDescriptor[ReportItem->ByteOffset + 1];
793
794 //
795 // shift data
796 //
797 Data >>= ReportItem->Shift;
798
799 //
800 // clear unwanted bits
801 //
802 Data &= ReportItem->Mask;
803
804 //
805 // is it activated
806 //
807 Activated = (Data != 0);
808
809 if (!Activated)
810 continue;
811
812 //
813 // is there enough space for the usage
814 //
815 if (ItemCount >= *UsageLength)
816 {
817 ItemCount++;
818 continue;
819 }
820
821 //
822 // store item
823 //
824 UsageList[ItemCount] = (ReportItem->UsageMinimum & 0xFFFF);
825 ItemCount++;
826 }
827
828 if (ItemCount > *UsageLength)
829 {
830 //
831 // list too small
832 //
833 return HIDPARSER_STATUS_BUFFER_TOO_SMALL;
834 }
835
836 //
837 // success, clear rest of array
838 //
839 Parser->Zero(&UsageList[ItemCount], (*UsageLength - ItemCount) * sizeof(USAGE));
840
841 //
842 // store result size
843 //
844 *UsageLength = ItemCount;
845
846 //
847 // done
848 //
849 return HIDPARSER_STATUS_SUCCESS;
850 }
851
852 HIDPARSER_STATUS
853 HidParser_GetScaledUsageValueWithReport(
854 IN PHID_PARSER Parser,
855 IN ULONG ReportType,
856 IN USAGE UsagePage,
857 IN USAGE Usage,
858 OUT PLONG UsageValue,
859 IN PCHAR ReportDescriptor,
860 IN ULONG ReportDescriptorLength)
861 {
862 PHID_PARSER_CONTEXT ParserContext;
863 ULONG Index;
864 PHID_REPORT Report;
865 USHORT CurrentUsagePage;
866 PHID_REPORT_ITEM ReportItem;
867 ULONG Data;
868
869 //
870 // get parser context
871 //
872 ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
873
874 //
875 // sanity checks
876 //
877 ASSERT(ParserContext);
878
879 //
880 // FIXME support multiple top collecions
881 //
882 ASSERT(ParserContext->RootCollection->NodeCount == 1);
883
884 //
885 // get report
886 //
887 Report = HidParser_GetReportByType(Parser, ReportType);
888 if (!Report)
889 {
890 //
891 // no such report
892 //
893 return HIDPARSER_STATUS_REPORT_NOT_FOUND;
894 }
895
896 if (Report->ReportSize / 8 != (ReportDescriptorLength - 1))
897 {
898 //
899 // invalid report descriptor length
900 //
901 return HIDPARSER_STATUS_INVALID_REPORT_LENGTH;
902 }
903
904 for(Index = 0; Index < Report->ItemCount; Index++)
905 {
906 //
907 // get report item
908 //
909 ReportItem = Report->Items[Index];
910
911 //
912 // check usage page
913 //
914 CurrentUsagePage = (ReportItem->UsageMinimum >> 16);
915
916 //
917 // does usage page match
918 //
919 if (UsagePage != CurrentUsagePage)
920 continue;
921
922 //
923 // does the usage match
924 //
925 if (Usage != (ReportItem->UsageMinimum & 0xFFFF))
926 continue;
927
928 //
929 // check if the specified usage is activated
930 //
931 ASSERT(ReportItem->ByteOffset < ReportDescriptorLength);
932
933 //
934 // one extra shift for skipping the prepended report id
935 //
936 Data = 0;
937 Parser->Copy(&Data, &ReportDescriptor[ReportItem->ByteOffset +1], min(sizeof(ULONG), ReportDescriptorLength - (ReportItem->ByteOffset + 1)));
938 Data = ReportDescriptor[ReportItem->ByteOffset + 1];
939
940 //
941 // shift data
942 //
943 Data >>= ReportItem->Shift;
944
945 //
946 // clear unwanted bits
947 //
948 Data &= ReportItem->Mask;
949
950 if (ReportItem->Minimum > ReportItem->Maximum)
951 {
952 //
953 // logical boundaries are signed values
954 //
955 if ((Data & ~(ReportItem->Mask >> 1)) != 0)
956 {
957 Data |= ~ReportItem->Mask;
958 }
959 }
960
961 //
962 // store result
963 //
964 *UsageValue = Data;
965 return HIDPARSER_STATUS_SUCCESS;
966 }
967
968 //
969 // usage not found
970 //
971 return HIDPARSER_STATUS_USAGE_NOT_FOUND;
972 }
973
974 ULONG
975 HidParser_GetScanCode(
976 IN USAGE Usage)
977 {
978 if (Usage < sizeof(KeyboardScanCodes) / sizeof(KeyboardScanCodes[0]))
979 {
980 //
981 // valid usage
982 //
983 return KeyboardScanCodes[Usage];
984 }
985
986 //
987 // invalid usage
988 //
989 return 0;
990 }
991
992 VOID
993 HidParser_DispatchKey(
994 IN PCHAR ScanCodes,
995 IN HIDP_KEYBOARD_DIRECTION KeyAction,
996 IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,
997 IN PVOID InsertCodesContext)
998 {
999 ULONG Index;
1000 ULONG Length = 0;
1001
1002 //
1003 // count code length
1004 //
1005 for(Index = 0; Index < sizeof(ULONG); Index++)
1006 {
1007 if (ScanCodes[Index] == 0)
1008 {
1009 //
1010 // last scan code
1011 //
1012 break;
1013 }
1014
1015 //
1016 // is this a key break
1017 //
1018 if (KeyAction == HidP_Keyboard_Break)
1019 {
1020 //
1021 // add break
1022 //
1023 ScanCodes[Index] |= KEY_BREAK;
1024 }
1025
1026 //
1027 // more scan counts
1028 //
1029 Length++;
1030 }
1031
1032 if (Length > 0)
1033 {
1034 //
1035 // dispatch scan codes
1036 //
1037 InsertCodesProcedure(InsertCodesContext, ScanCodes, Length);
1038 }
1039 }
1040
1041
1042 HIDPARSER_STATUS
1043 HidParser_TranslateUsage(
1044 IN PHID_PARSER Parser,
1045 IN USAGE Usage,
1046 IN HIDP_KEYBOARD_DIRECTION KeyAction,
1047 IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,
1048 IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,
1049 IN PVOID InsertCodesContext)
1050 {
1051 ULONG ScanCode;
1052
1053 //
1054 // get scan code
1055 //
1056 ScanCode = HidParser_GetScanCode(Usage);
1057 if (!ScanCode)
1058 {
1059 //
1060 // invalid lookup or no scan code available
1061 //
1062 return HIDPARSER_STATUS_I8042_TRANS_UNKNOWN;
1063 }
1064
1065 //
1066 // FIXME: translate modifier states
1067 //
1068
1069 HidParser_DispatchKey((PCHAR)&ScanCode, KeyAction, InsertCodesProcedure, InsertCodesContext);
1070
1071 //
1072 // done
1073 //
1074 return HIDPARSER_STATUS_SUCCESS;
1075 }