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