c84533ef56bd34d0e40e9abb527de19f11b82a1f
[reactos.git] / lib / drivers / hidparser / hidparser.c
1 /*
2 * PROJECT: ReactOS HID Parser Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/hidparser/hidparser.c
5 * PURPOSE: HID Parser
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10
11 #include "parser.h"
12
13 NTSTATUS
14 TranslateHidParserStatus(
15 IN HIDPARSER_STATUS Status)
16 {
17 switch(Status)
18 {
19 case HIDPARSER_STATUS_INSUFFICIENT_RESOURCES:
20 return HIDP_STATUS_INTERNAL_ERROR;
21 case HIDPARSER_STATUS_NOT_IMPLEMENTED:
22 return HIDP_STATUS_NOT_IMPLEMENTED;
23 case HIDPARSER_STATUS_REPORT_NOT_FOUND:
24 return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
25 case HIDPARSER_STATUS_INVALID_REPORT_LENGTH:
26 return HIDP_STATUS_INVALID_REPORT_LENGTH;
27 case HIDPARSER_STATUS_INVALID_REPORT_TYPE:
28 return HIDP_STATUS_INVALID_REPORT_TYPE;
29 case HIDPARSER_STATUS_BUFFER_TOO_SMALL:
30 return HIDP_STATUS_BUFFER_TOO_SMALL;
31 case HIDPARSER_STATUS_USAGE_NOT_FOUND:
32 return HIDP_STATUS_USAGE_NOT_FOUND;
33 case HIDPARSER_STATUS_I8042_TRANS_UNKNOWN:
34 return HIDP_STATUS_I8042_TRANS_UNKNOWN;
35 case HIDPARSER_STATUS_COLLECTION_NOT_FOUND:
36 return HIDP_STATUS_NOT_IMPLEMENTED; //FIXME
37 }
38 DPRINT1("TranslateHidParserStatus Status %ld not implemented\n", Status);
39 return HIDP_STATUS_NOT_IMPLEMENTED;
40 }
41
42 NTSTATUS
43 NTAPI
44 HidParser_GetCollectionDescription(
45 IN PHID_PARSER Parser,
46 IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
47 IN ULONG DescLength,
48 IN POOL_TYPE PoolType,
49 OUT PHIDP_DEVICE_DESC DeviceDescription)
50 {
51 HIDPARSER_STATUS ParserStatus;
52 ULONG CollectionCount;
53 ULONG Index;
54
55 //
56 // first parse the report descriptor
57 //
58 ParserStatus = HidParser_ParseReportDescriptor(Parser, ReportDesc, DescLength);
59 if (ParserStatus != HIDPARSER_STATUS_SUCCESS)
60 {
61 //
62 // failed to parse report descriptor
63 //
64 Parser->Debug("[HIDPARSER] Failed to parse report descriptor with %x\n", ParserStatus);
65 return TranslateHidParserStatus(ParserStatus);
66 }
67
68 //
69 // get collection count
70 //
71 CollectionCount = HidParser_NumberOfTopCollections(Parser);
72 if (CollectionCount == 0)
73 {
74 //
75 // no top level collections found
76 //
77 ASSERT(FALSE);
78 return STATUS_NO_DATA_DETECTED;
79 }
80
81 //
82 // zero description
83 //
84 Parser->Zero(DeviceDescription, sizeof(HIDP_DEVICE_DESC));
85
86 //
87 // allocate collection
88 //
89 DeviceDescription->CollectionDesc = (PHIDP_COLLECTION_DESC)Parser->Alloc(sizeof(HIDP_COLLECTION_DESC) * CollectionCount);
90 if (!DeviceDescription->CollectionDesc)
91 {
92 //
93 // no memory
94 //
95 return STATUS_INSUFFICIENT_RESOURCES;
96 }
97
98 //
99 // allocate report description
100 //
101 DeviceDescription->ReportIDs = (PHIDP_REPORT_IDS)Parser->Alloc(sizeof(HIDP_REPORT_IDS) * CollectionCount);
102 if (!DeviceDescription->ReportIDs)
103 {
104 //
105 // no memory
106 //
107 Parser->Free(DeviceDescription->CollectionDesc);
108 return STATUS_INSUFFICIENT_RESOURCES;
109 }
110
111 for(Index = 0; Index < CollectionCount; Index++)
112 {
113 //
114 // init report description
115 //
116 DeviceDescription->ReportIDs[Index].CollectionNumber = Index + 1;
117 DeviceDescription->ReportIDs[Index].ReportID = Index; //FIXME
118 DeviceDescription->ReportIDs[Index].InputLength = HidParser_GetReportLength(Parser, Index, HID_REPORT_TYPE_INPUT);
119 DeviceDescription->ReportIDs[Index].OutputLength = HidParser_GetReportLength(Parser, Index, HID_REPORT_TYPE_OUTPUT);
120 DeviceDescription->ReportIDs[Index].FeatureLength = HidParser_GetReportLength(Parser, Index, HID_REPORT_TYPE_FEATURE);
121
122 //
123 // init collection description
124 //
125 DeviceDescription->CollectionDesc[Index].CollectionNumber = Index + 1;
126
127 //
128 // get collection usage page
129 //
130 ParserStatus = HidParser_GetCollectionUsagePage(Parser, Index, &DeviceDescription->CollectionDesc[Index].Usage, &DeviceDescription->CollectionDesc[Index].UsagePage);
131
132 //
133 // windows seems to prepend the report id, regardless if it is required
134 //
135 DeviceDescription->CollectionDesc[Index].InputLength = (DeviceDescription->ReportIDs[Index].InputLength > 0 ? DeviceDescription->ReportIDs[Index].InputLength + 1 : 0);
136 DeviceDescription->CollectionDesc[Index].OutputLength = (DeviceDescription->ReportIDs[Index].OutputLength > 0 ? DeviceDescription->ReportIDs[Index].OutputLength + 1 : 0);
137 DeviceDescription->CollectionDesc[Index].FeatureLength = (DeviceDescription->ReportIDs[Index].FeatureLength > 0 ? DeviceDescription->ReportIDs[Index].FeatureLength + 1 : 0);
138
139 //
140 // set preparsed data length
141 //
142 DeviceDescription->CollectionDesc[Index].PreparsedDataLength = HidParser_GetContextSize(Parser, Index);
143 DeviceDescription->CollectionDesc[Index].PreparsedData = Parser->Alloc(DeviceDescription->CollectionDesc[Index].PreparsedDataLength);
144 if (!DeviceDescription->CollectionDesc[Index].PreparsedData)
145 {
146 //
147 // no memory
148 //
149 return STATUS_INSUFFICIENT_RESOURCES;
150 }
151
152 //
153 // copy context
154 //
155 Parser->Copy(DeviceDescription->CollectionDesc[Index].PreparsedData, Parser->ParserContext, DeviceDescription->CollectionDesc[Index].PreparsedDataLength);
156 }
157
158 //
159 // store collection & report count
160 //
161 DeviceDescription->CollectionDescLength = CollectionCount;
162 DeviceDescription->ReportIDsLength = CollectionCount;
163
164 //
165 // done
166 //
167 return STATUS_SUCCESS;
168 }
169
170 VOID
171 NTAPI
172 HidParser_FreeCollectionDescription(
173 IN PHID_PARSER Parser,
174 IN PHIDP_DEVICE_DESC DeviceDescription)
175 {
176 ULONG Index;
177
178 //
179 // first free all context
180 //
181 for(Index = 0; Index < DeviceDescription->CollectionDescLength; Index++)
182 {
183 //
184 // free parser context
185 //
186 HidParser_FreeContext(Parser, (PUCHAR)DeviceDescription->CollectionDesc[Index].PreparsedData, DeviceDescription->CollectionDesc[Index].PreparsedDataLength);
187 }
188
189 //
190 // now free collection description
191 //
192 Parser->Free(DeviceDescription->CollectionDesc);
193
194 //
195 // free report description
196 //
197 ExFreePool(DeviceDescription->ReportIDs);
198 }
199
200 HIDAPI
201 NTSTATUS
202 NTAPI
203 HidParser_GetCaps(
204 IN PHID_PARSER Parser,
205 OUT PHIDP_CAPS Capabilities)
206 {
207 ULONG CollectionNumber;
208
209 //
210 // get collection number from context
211 //
212 CollectionNumber = HidParser_GetCollectionNumberFromParserContext(Parser);
213
214 //
215 // zero capabilities
216 //
217 Parser->Zero(Capabilities, sizeof(HIDP_CAPS));
218
219 //
220 // init capabilities
221 //
222 HidParser_GetCollectionUsagePage(Parser, CollectionNumber, &Capabilities->Usage, &Capabilities->UsagePage);
223 Capabilities->InputReportByteLength = HidParser_GetReportLength(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT);
224 Capabilities->OutputReportByteLength = HidParser_GetReportLength(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT);
225 Capabilities->FeatureReportByteLength = HidParser_GetReportLength(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE);
226
227 //
228 // always pre-prend report id
229 //
230 Capabilities->InputReportByteLength = (Capabilities->InputReportByteLength > 0 ? Capabilities->InputReportByteLength + 1 : 0);
231 Capabilities->OutputReportByteLength = (Capabilities->OutputReportByteLength > 0 ? Capabilities->OutputReportByteLength + 1 : 0);
232 Capabilities->FeatureReportByteLength = (Capabilities->FeatureReportByteLength > 0 ? Capabilities->FeatureReportByteLength + 1 : 0);
233
234 //
235 // get number of link collection nodes
236 //
237 Capabilities->NumberLinkCollectionNodes = HidParser_GetTotalCollectionCount(Parser, CollectionNumber);
238
239 //
240 // get data indices
241 //
242 Capabilities->NumberInputDataIndices = HidParser_GetReportItemTypeCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT, TRUE);
243 Capabilities->NumberOutputDataIndices = HidParser_GetReportItemTypeCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT, TRUE);
244 Capabilities->NumberFeatureDataIndices = HidParser_GetReportItemTypeCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE, TRUE);
245
246 //
247 // get value caps
248 //
249 Capabilities->NumberInputValueCaps = HidParser_GetReportItemTypeCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT, FALSE);
250 Capabilities->NumberOutputValueCaps = HidParser_GetReportItemTypeCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT, FALSE);
251 Capabilities->NumberFeatureValueCaps = HidParser_GetReportItemTypeCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE, FALSE);
252
253
254 //
255 // get button caps
256 //
257 Capabilities->NumberInputButtonCaps = HidParser_GetReportItemCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT);
258 Capabilities->NumberOutputButtonCaps = HidParser_GetReportItemCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT);
259 Capabilities->NumberFeatureButtonCaps = HidParser_GetReportItemCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE);
260
261 //
262 // done
263 //
264 return HIDP_STATUS_SUCCESS;
265 }
266
267 HIDAPI
268 ULONG
269 NTAPI
270 HidParser_MaxUsageListLength(
271 IN PHID_PARSER Parser,
272 IN HIDP_REPORT_TYPE ReportType,
273 IN USAGE UsagePage OPTIONAL)
274 {
275 ULONG CollectionNumber;
276
277 //
278 // get collection number from context
279 //
280 CollectionNumber = HidParser_GetCollectionNumberFromParserContext(Parser);
281
282
283 //
284 // FIXME test what should be returned when usage page is not defined
285 //
286 if (UsagePage == HID_USAGE_PAGE_UNDEFINED)
287 {
288 //
289 // implement me
290 //
291 UNIMPLEMENTED
292
293 //
294 // invalid report
295 //
296 return 0;
297 }
298
299 if (ReportType == HidP_Input)
300 {
301 //
302 // input report
303 //
304 return HidParser_GetMaxUsageListLengthWithReportAndPage(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT, UsagePage);
305 }
306 else if (ReportType == HidP_Output)
307 {
308 //
309 // input report
310 //
311 return HidParser_GetMaxUsageListLengthWithReportAndPage(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT, UsagePage);
312 }
313 else if (ReportType == HidP_Feature)
314 {
315 //
316 // input report
317 //
318 return HidParser_GetMaxUsageListLengthWithReportAndPage(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE, UsagePage);
319 }
320 else
321 {
322 //
323 // invalid report type
324 //
325 return 0;
326 }
327 }
328
329 #undef HidParser_GetButtonCaps
330
331 HIDAPI
332 NTSTATUS
333 NTAPI
334 HidParser_GetButtonCaps(
335 IN PHID_PARSER Parser,
336 IN HIDP_REPORT_TYPE ReportType,
337 IN PHIDP_BUTTON_CAPS ButtonCaps,
338 IN PUSHORT ButtonCapsLength)
339 {
340 return HidParser_GetSpecificButtonCaps(Parser, ReportType, HID_USAGE_PAGE_UNDEFINED, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_PAGE_UNDEFINED, ButtonCaps, (PULONG)ButtonCapsLength);
341 }
342
343 HIDAPI
344 NTSTATUS
345 NTAPI
346 HidParser_GetSpecificValueCaps(
347 IN PHID_PARSER Parser,
348 IN HIDP_REPORT_TYPE ReportType,
349 IN USAGE UsagePage,
350 IN USHORT LinkCollection,
351 IN USAGE Usage,
352 OUT PHIDP_VALUE_CAPS ValueCaps,
353 IN OUT PULONG ValueCapsLength)
354 {
355 HIDPARSER_STATUS ParserStatus;
356 ULONG CollectionNumber;
357
358 //
359 // get collection number from context
360 //
361 CollectionNumber = HidParser_GetCollectionNumberFromParserContext(Parser);
362
363
364
365 //
366 // FIXME: implement searching in specific collection
367 //
368 ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED);
369
370 if (ReportType == HidP_Input)
371 {
372 //
373 // input report
374 //
375 ParserStatus = HidParser_GetSpecificValueCapsWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT, UsagePage, Usage, ValueCaps, ValueCapsLength);
376 }
377 else if (ReportType == HidP_Output)
378 {
379 //
380 // input report
381 //
382 ParserStatus = HidParser_GetSpecificValueCapsWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, ValueCaps, ValueCapsLength);
383 }
384 else if (ReportType == HidP_Feature)
385 {
386 //
387 // input report
388 //
389 ParserStatus = HidParser_GetSpecificValueCapsWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, ValueCaps, ValueCapsLength);
390 }
391 else
392 {
393 //
394 // invalid report type
395 //
396 return HIDP_STATUS_INVALID_REPORT_TYPE;
397 }
398
399
400 if (ParserStatus == HIDPARSER_STATUS_SUCCESS)
401 {
402 //
403 // success
404 //
405 return HIDP_STATUS_SUCCESS;
406 }
407
408 //
409 // translate error
410 //
411 return TranslateHidParserStatus(ParserStatus);
412 }
413
414 HIDAPI
415 NTSTATUS
416 NTAPI
417 HidParser_UsageListDifference(
418 IN PUSAGE PreviousUsageList,
419 IN PUSAGE CurrentUsageList,
420 OUT PUSAGE BreakUsageList,
421 OUT PUSAGE MakeUsageList,
422 IN ULONG UsageListLength)
423 {
424 ULONG Index, SubIndex, bFound, BreakUsageIndex = 0, MakeUsageIndex = 0;
425 USAGE CurrentUsage, Usage;
426
427 if (UsageListLength)
428 {
429 Index = 0;
430 do
431 {
432 /* get current usage */
433 CurrentUsage = PreviousUsageList[Index];
434
435 /* is the end of list reached? */
436 if (!CurrentUsage)
437 break;
438
439 /* start searching in current usage list */
440 SubIndex = 0;
441 bFound = FALSE;
442 do
443 {
444 /* get usage of current list */
445 Usage = CurrentUsageList[SubIndex];
446
447 /* end of list reached? */
448 if (!Usage)
449 break;
450
451 /* check if it matches the current one */
452 if (CurrentUsage == Usage)
453 {
454 /* it does */
455 bFound = TRUE;
456 break;
457 }
458
459 /* move to next usage */
460 SubIndex++;
461 }while(SubIndex < UsageListLength);
462
463 /* was the usage found ?*/
464 if (!bFound)
465 {
466 /* store it in the break usage list */
467 BreakUsageList[BreakUsageIndex] = CurrentUsage;
468 BreakUsageIndex++;
469 }
470
471 /* move to next usage */
472 Index++;
473
474 }while(Index < UsageListLength);
475
476 /* now process the new items */
477 Index = 0;
478 do
479 {
480 /* get current usage */
481 CurrentUsage = CurrentUsageList[Index];
482
483 /* is the end of list reached? */
484 if (!CurrentUsage)
485 break;
486
487 /* start searching in current usage list */
488 SubIndex = 0;
489 bFound = FALSE;
490 do
491 {
492 /* get usage of previous list */
493 Usage = PreviousUsageList[SubIndex];
494
495 /* end of list reached? */
496 if (!Usage)
497 break;
498
499 /* check if it matches the current one */
500 if (CurrentUsage == Usage)
501 {
502 /* it does */
503 bFound = TRUE;
504 break;
505 }
506
507 /* move to next usage */
508 SubIndex++;
509 }while(SubIndex < UsageListLength);
510
511 /* was the usage found ?*/
512 if (!bFound)
513 {
514 /* store it in the make usage list */
515 MakeUsageList[MakeUsageIndex] = CurrentUsage;
516 MakeUsageIndex++;
517 }
518
519 /* move to next usage */
520 Index++;
521
522 }while(Index < UsageListLength);
523 }
524
525 /* does the break list contain empty entries */
526 if (BreakUsageIndex < UsageListLength)
527 {
528 /* zeroize entries */
529 RtlZeroMemory(&BreakUsageList[BreakUsageIndex], sizeof(USAGE) * (UsageListLength - BreakUsageIndex));
530 }
531
532 /* does the make usage list contain empty entries */
533 if (MakeUsageIndex < UsageListLength)
534 {
535 /* zeroize entries */
536 RtlZeroMemory(&MakeUsageList[MakeUsageIndex], sizeof(USAGE) * (UsageListLength - MakeUsageIndex));
537 }
538
539 /* done */
540 return HIDP_STATUS_SUCCESS;
541 }
542
543 HIDAPI
544 NTSTATUS
545 NTAPI
546 HidParser_GetUsages(
547 IN PHID_PARSER Parser,
548 IN HIDP_REPORT_TYPE ReportType,
549 IN USAGE UsagePage,
550 IN USHORT LinkCollection OPTIONAL,
551 OUT USAGE *UsageList,
552 IN OUT PULONG UsageLength,
553 IN PCHAR Report,
554 IN ULONG ReportLength)
555 {
556 HIDPARSER_STATUS ParserStatus;
557 ULONG CollectionNumber;
558
559 //
560 // get collection number from context
561 //
562 CollectionNumber = HidParser_GetCollectionNumberFromParserContext(Parser);
563
564 //
565 // FIXME: implement searching in specific collection
566 //
567 ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED);
568
569 if (ReportType == HidP_Input)
570 {
571 //
572 // input report
573 //
574 ParserStatus = HidParser_GetUsagesWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT, UsagePage, UsageList, UsageLength, Report, ReportLength);
575 }
576 else if (ReportType == HidP_Output)
577 {
578 //
579 // input report
580 //
581 ParserStatus = HidParser_GetUsagesWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT, UsagePage, UsageList, UsageLength, Report, ReportLength);
582 }
583 else if (ReportType == HidP_Feature)
584 {
585 //
586 // input report
587 //
588 ParserStatus = HidParser_GetUsagesWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE, UsagePage, UsageList, UsageLength, Report, ReportLength);
589 }
590 else
591 {
592 //
593 // invalid report type
594 //
595 return HIDP_STATUS_INVALID_REPORT_TYPE;
596 }
597
598 if (ParserStatus == HIDPARSER_STATUS_SUCCESS)
599 {
600 //
601 // success
602 //
603 return HIDP_STATUS_SUCCESS;
604 }
605
606 //
607 // translate error
608 //
609 return TranslateHidParserStatus(ParserStatus);
610 }
611
612 HIDAPI
613 NTSTATUS
614 NTAPI
615 HidParser_GetScaledUsageValue(
616 IN PHID_PARSER Parser,
617 IN HIDP_REPORT_TYPE ReportType,
618 IN USAGE UsagePage,
619 IN USHORT LinkCollection OPTIONAL,
620 IN USAGE Usage,
621 OUT PLONG UsageValue,
622 IN PCHAR Report,
623 IN ULONG ReportLength)
624 {
625 HIDPARSER_STATUS ParserStatus;
626 ULONG CollectionNumber;
627
628 //
629 // get collection number from context
630 //
631 CollectionNumber = HidParser_GetCollectionNumberFromParserContext(Parser);
632
633 //
634 // FIXME: implement searching in specific collection
635 //
636 ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED);
637
638 if (ReportType == HidP_Input)
639 {
640 //
641 // input report
642 //
643 ParserStatus = HidParser_GetScaledUsageValueWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT, UsagePage, Usage, UsageValue, Report, ReportLength);
644 }
645 else if (ReportType == HidP_Output)
646 {
647 //
648 // input report
649 //
650 ParserStatus = HidParser_GetScaledUsageValueWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, UsageValue, Report, ReportLength);
651 }
652 else if (ReportType == HidP_Feature)
653 {
654 //
655 // input report
656 //
657 ParserStatus = HidParser_GetScaledUsageValueWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, UsageValue, Report, ReportLength);
658 }
659 else
660 {
661 //
662 // invalid report type
663 //
664 return HIDP_STATUS_INVALID_REPORT_TYPE;
665 }
666
667 if (ParserStatus == HIDPARSER_STATUS_SUCCESS)
668 {
669 //
670 // success
671 //
672 return HIDP_STATUS_SUCCESS;
673 }
674
675 //
676 // translate error
677 //
678 return TranslateHidParserStatus(ParserStatus);
679 }
680
681 HIDAPI
682 NTSTATUS
683 NTAPI
684 HidParser_TranslateUsageAndPagesToI8042ScanCodes(
685 IN PHID_PARSER Parser,
686 IN PUSAGE_AND_PAGE ChangedUsageList,
687 IN ULONG UsageListLength,
688 IN HIDP_KEYBOARD_DIRECTION KeyAction,
689 IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,
690 IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,
691 IN PVOID InsertCodesContext)
692 {
693 ULONG Index;
694 HIDPARSER_STATUS Status = HIDPARSER_STATUS_SUCCESS;
695 ULONG CollectionNumber;
696
697 //
698 // get collection number from context
699 //
700 CollectionNumber = HidParser_GetCollectionNumberFromParserContext(Parser);
701
702 for(Index = 0; Index < UsageListLength; Index++)
703 {
704 //
705 // check current usage
706 //
707 if (ChangedUsageList[Index].UsagePage == HID_USAGE_PAGE_KEYBOARD)
708 {
709 //
710 // process usage
711 //
712 Status = HidParser_TranslateUsage(Parser, CollectionNumber, ChangedUsageList[Index].Usage, KeyAction, ModifierState, InsertCodesProcedure, InsertCodesContext);
713 }
714 else if (ChangedUsageList[Index].UsagePage == HID_USAGE_PAGE_CONSUMER)
715 {
716 //
717 // FIXME: implement me
718 //
719 UNIMPLEMENTED
720 Status = HIDPARSER_STATUS_NOT_IMPLEMENTED;
721 }
722 else
723 {
724 //
725 // invalid page
726 //
727 DPRINT1("[HIDPARSE] Error unexpected usage page %x\n", ChangedUsageList[Index].UsagePage);
728 return HIDP_STATUS_I8042_TRANS_UNKNOWN;
729 }
730
731 //
732 // check status
733 //
734 if (Status != HIDPARSER_STATUS_SUCCESS)
735 {
736 //
737 // failed
738 //
739 return TranslateHidParserStatus(Status);
740 }
741 }
742
743 if (Status != HIDPARSER_STATUS_SUCCESS)
744 {
745 //
746 // failed
747 //
748 return TranslateHidParserStatus(Status);
749 }
750
751 //
752 // done
753 //
754 return HIDP_STATUS_SUCCESS;
755 }
756
757
758 HIDAPI
759 NTSTATUS
760 NTAPI
761 HidParser_GetUsagesEx(
762 IN PHID_PARSER Parser,
763 IN HIDP_REPORT_TYPE ReportType,
764 IN USHORT LinkCollection,
765 OUT PUSAGE_AND_PAGE ButtonList,
766 IN OUT ULONG *UsageLength,
767 IN PCHAR Report,
768 IN ULONG ReportLength)
769 {
770 return HidParser_GetUsages(Parser, ReportType, HID_USAGE_PAGE_UNDEFINED, LinkCollection, (PUSAGE)ButtonList, UsageLength, Report, ReportLength);
771 }
772
773 HIDAPI
774 NTSTATUS
775 NTAPI
776 HidParser_UsageAndPageListDifference(
777 IN PUSAGE_AND_PAGE PreviousUsageList,
778 IN PUSAGE_AND_PAGE CurrentUsageList,
779 OUT PUSAGE_AND_PAGE BreakUsageList,
780 OUT PUSAGE_AND_PAGE MakeUsageList,
781 IN ULONG UsageListLength)
782 {
783 ULONG Index, SubIndex, BreakUsageListIndex = 0, MakeUsageListIndex = 0, bFound;
784 PUSAGE_AND_PAGE CurrentUsage, Usage;
785
786 if (UsageListLength)
787 {
788 /* process removed usages */
789 Index = 0;
790 do
791 {
792 /* get usage from current index */
793 CurrentUsage = &PreviousUsageList[Index];
794
795 /* end of list reached? */
796 if (CurrentUsage->Usage == 0 && CurrentUsage->UsagePage == 0)
797 break;
798
799 /* search in current list */
800 SubIndex = 0;
801 bFound = FALSE;
802 do
803 {
804 /* get usage */
805 Usage = &CurrentUsageList[SubIndex];
806
807 /* end of list reached? */
808 if (Usage->Usage == 0 && Usage->UsagePage == 0)
809 break;
810
811 /* does it match */
812 if (Usage->Usage == CurrentUsage->Usage && Usage->UsagePage == CurrentUsage->UsagePage)
813 {
814 /* found match */
815 bFound = TRUE;
816 }
817
818 /* move to next index */
819 SubIndex++;
820
821 }while(SubIndex < UsageListLength);
822
823 if (!bFound)
824 {
825 /* store it in break usage list */
826 BreakUsageList[BreakUsageListIndex].Usage = CurrentUsage->Usage;
827 BreakUsageList[BreakUsageListIndex].UsagePage = CurrentUsage->UsagePage;
828 BreakUsageListIndex++;
829 }
830
831 /* move to next index */
832 Index++;
833
834 }while(Index < UsageListLength);
835
836 /* process new usages */
837 Index = 0;
838 do
839 {
840 /* get usage from current index */
841 CurrentUsage = &CurrentUsageList[Index];
842
843 /* end of list reached? */
844 if (CurrentUsage->Usage == 0 && CurrentUsage->UsagePage == 0)
845 break;
846
847 /* search in current list */
848 SubIndex = 0;
849 bFound = FALSE;
850 do
851 {
852 /* get usage */
853 Usage = &PreviousUsageList[SubIndex];
854
855 /* end of list reached? */
856 if (Usage->Usage == 0 && Usage->UsagePage == 0)
857 break;
858
859 /* does it match */
860 if (Usage->Usage == CurrentUsage->Usage && Usage->UsagePage == CurrentUsage->UsagePage)
861 {
862 /* found match */
863 bFound = TRUE;
864 }
865
866 /* move to next index */
867 SubIndex++;
868
869 }while(SubIndex < UsageListLength);
870
871 if (!bFound)
872 {
873 /* store it in break usage list */
874 MakeUsageList[MakeUsageListIndex].Usage = CurrentUsage->Usage;
875 MakeUsageList[MakeUsageListIndex].UsagePage = CurrentUsage->UsagePage;
876 MakeUsageListIndex++;
877 }
878
879 /* move to next index */
880 Index++;
881 }while(Index < UsageListLength);
882 }
883
884 /* are there remaining free list entries */
885 if (BreakUsageListIndex < UsageListLength)
886 {
887 /* zero them */
888 RtlZeroMemory(&BreakUsageList[BreakUsageListIndex], (UsageListLength - BreakUsageListIndex) * sizeof(USAGE_AND_PAGE));
889 }
890
891 /* are there remaining free list entries */
892 if (MakeUsageListIndex < UsageListLength)
893 {
894 /* zero them */
895 RtlZeroMemory(&MakeUsageList[MakeUsageListIndex], (UsageListLength - MakeUsageListIndex) * sizeof(USAGE_AND_PAGE));
896 }
897
898 /* done */
899 return HIDP_STATUS_SUCCESS;
900 }
901
902 HIDAPI
903 NTSTATUS
904 NTAPI
905 HidParser_GetSpecificButtonCaps(
906 IN PHID_PARSER Parser,
907 IN HIDP_REPORT_TYPE ReportType,
908 IN USAGE UsagePage,
909 IN USHORT LinkCollection,
910 IN USAGE Usage,
911 OUT PHIDP_BUTTON_CAPS ButtonCaps,
912 IN OUT PULONG ButtonCapsLength)
913 {
914 UNIMPLEMENTED
915 ASSERT(FALSE);
916 return STATUS_NOT_IMPLEMENTED;
917 }
918
919
920 HIDAPI
921 NTSTATUS
922 NTAPI
923 HidParser_GetData(
924 IN PHID_PARSER Parser,
925 IN HIDP_REPORT_TYPE ReportType,
926 OUT PHIDP_DATA DataList,
927 IN OUT PULONG DataLength,
928 IN PCHAR Report,
929 IN ULONG ReportLength)
930 {
931 UNIMPLEMENTED
932 ASSERT(FALSE);
933 return STATUS_NOT_IMPLEMENTED;
934 }
935
936 HIDAPI
937 NTSTATUS
938 NTAPI
939 HidParser_GetExtendedAttributes(
940 IN PHID_PARSER Parser,
941 IN HIDP_REPORT_TYPE ReportType,
942 IN USHORT DataIndex,
943 OUT PHIDP_EXTENDED_ATTRIBUTES Attributes,
944 IN OUT PULONG LengthAttributes)
945 {
946 UNIMPLEMENTED
947 ASSERT(FALSE);
948 return STATUS_NOT_IMPLEMENTED;
949 }
950
951 HIDAPI
952 NTSTATUS
953 NTAPI
954 HidParser_GetLinkCollectionNodes(
955 IN PHID_PARSER Parser,
956 OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes,
957 IN OUT PULONG LinkCollectionNodesLength)
958 {
959 UNIMPLEMENTED
960 ASSERT(FALSE);
961 return STATUS_NOT_IMPLEMENTED;
962 }
963
964 HIDAPI
965 NTSTATUS
966 NTAPI
967 HidParser_GetUsageValue(
968 IN PHID_PARSER Parser,
969 IN HIDP_REPORT_TYPE ReportType,
970 IN USAGE UsagePage,
971 IN USHORT LinkCollection,
972 IN USAGE Usage,
973 OUT PULONG UsageValue,
974 IN PCHAR Report,
975 IN ULONG ReportLength)
976 {
977 UNIMPLEMENTED
978 ASSERT(FALSE);
979 return STATUS_NOT_IMPLEMENTED;
980 }
981
982 NTSTATUS
983 NTAPI
984 HidParser_SysPowerEvent(
985 IN PHID_PARSER Parser,
986 IN PCHAR HidPacket,
987 IN USHORT HidPacketLength,
988 OUT PULONG OutputBuffer)
989 {
990 UNIMPLEMENTED
991 ASSERT(FALSE);
992 return STATUS_NOT_IMPLEMENTED;
993 }
994
995 NTSTATUS
996 NTAPI
997 HidParser_SysPowerCaps (
998 IN PHID_PARSER Parser,
999 OUT PULONG OutputBuffer)
1000 {
1001 UNIMPLEMENTED
1002 ASSERT(FALSE);
1003 return STATUS_NOT_IMPLEMENTED;
1004 }
1005
1006 HIDAPI
1007 NTSTATUS
1008 NTAPI
1009 HidParser_GetUsageValueArray(
1010 IN PHID_PARSER Parser,
1011 IN HIDP_REPORT_TYPE ReportType,
1012 IN USAGE UsagePage,
1013 IN USHORT LinkCollection OPTIONAL,
1014 IN USAGE Usage,
1015 OUT PCHAR UsageValue,
1016 IN USHORT UsageValueByteLength,
1017 IN PCHAR Report,
1018 IN ULONG ReportLength)
1019 {
1020 UNIMPLEMENTED
1021 ASSERT(FALSE);
1022 return STATUS_NOT_IMPLEMENTED;
1023 }
1024
1025 HIDAPI
1026 NTSTATUS
1027 NTAPI
1028 HidParser_UnsetUsages(
1029 IN PHID_PARSER Parser,
1030 IN HIDP_REPORT_TYPE ReportType,
1031 IN USAGE UsagePage,
1032 IN USHORT LinkCollection,
1033 IN PUSAGE UsageList,
1034 IN OUT PULONG UsageLength,
1035 IN OUT PCHAR Report,
1036 IN ULONG ReportLength)
1037 {
1038 UNIMPLEMENTED
1039 ASSERT(FALSE);
1040 return STATUS_NOT_IMPLEMENTED;
1041 }
1042
1043 HIDAPI
1044 NTSTATUS
1045 NTAPI
1046 HidParser_TranslateUsagesToI8042ScanCodes(
1047 IN PUSAGE ChangedUsageList,
1048 IN ULONG UsageListLength,
1049 IN HIDP_KEYBOARD_DIRECTION KeyAction,
1050 IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,
1051 IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,
1052 IN PVOID InsertCodesContext)
1053 {
1054 UNIMPLEMENTED
1055 ASSERT(FALSE);
1056 return STATUS_NOT_IMPLEMENTED;
1057 }
1058
1059 HIDAPI
1060 NTSTATUS
1061 NTAPI
1062 HidParser_SetUsages(
1063 IN PHID_PARSER Parser,
1064 IN HIDP_REPORT_TYPE ReportType,
1065 IN USAGE UsagePage,
1066 IN USHORT LinkCollection,
1067 IN PUSAGE UsageList,
1068 IN OUT PULONG UsageLength,
1069 IN OUT PCHAR Report,
1070 IN ULONG ReportLength)
1071 {
1072 UNIMPLEMENTED
1073 ASSERT(FALSE);
1074 return STATUS_NOT_IMPLEMENTED;
1075 }
1076
1077 HIDAPI
1078 NTSTATUS
1079 NTAPI
1080 HidParser_SetUsageValueArray(
1081 IN PHID_PARSER Parser,
1082 IN HIDP_REPORT_TYPE ReportType,
1083 IN USAGE UsagePage,
1084 IN USHORT LinkCollection OPTIONAL,
1085 IN USAGE Usage,
1086 IN PCHAR UsageValue,
1087 IN USHORT UsageValueByteLength,
1088 OUT PCHAR Report,
1089 IN ULONG ReportLength)
1090 {
1091 UNIMPLEMENTED
1092 ASSERT(FALSE);
1093 return STATUS_NOT_IMPLEMENTED;
1094 }
1095
1096 HIDAPI
1097 NTSTATUS
1098 NTAPI
1099 HidParser_SetUsageValue(
1100 IN PHID_PARSER Parser,
1101 IN HIDP_REPORT_TYPE ReportType,
1102 IN USAGE UsagePage,
1103 IN USHORT LinkCollection,
1104 IN USAGE Usage,
1105 IN ULONG UsageValue,
1106 IN OUT PCHAR Report,
1107 IN ULONG ReportLength)
1108 {
1109 UNIMPLEMENTED
1110 ASSERT(FALSE);
1111 return STATUS_NOT_IMPLEMENTED;
1112 }
1113
1114 HIDAPI
1115 NTSTATUS
1116 NTAPI
1117 HidParser_SetScaledUsageValue(
1118 IN PHID_PARSER Parser,
1119 IN HIDP_REPORT_TYPE ReportType,
1120 IN USAGE UsagePage,
1121 IN USHORT LinkCollection OPTIONAL,
1122 IN USAGE Usage,
1123 IN LONG UsageValue,
1124 IN OUT PCHAR Report,
1125 IN ULONG ReportLength)
1126 {
1127 UNIMPLEMENTED
1128 ASSERT(FALSE);
1129 return STATUS_NOT_IMPLEMENTED;
1130 }
1131
1132 HIDAPI
1133 NTSTATUS
1134 NTAPI
1135 HidParser_SetData(
1136 IN PHID_PARSER Parser,
1137 IN HIDP_REPORT_TYPE ReportType,
1138 IN PHIDP_DATA DataList,
1139 IN OUT PULONG DataLength,
1140 IN OUT PCHAR Report,
1141 IN ULONG ReportLength)
1142 {
1143 UNIMPLEMENTED
1144 ASSERT(FALSE);
1145 return STATUS_NOT_IMPLEMENTED;
1146 }
1147
1148 HIDAPI
1149 ULONG
1150 NTAPI
1151 HidParser_MaxDataListLength(
1152 IN PHID_PARSER Parser,
1153 IN HIDP_REPORT_TYPE ReportType)
1154 {
1155 UNIMPLEMENTED
1156 ASSERT(FALSE);
1157 return STATUS_NOT_IMPLEMENTED;
1158 }
1159
1160 HIDAPI
1161 NTSTATUS
1162 NTAPI
1163 HidParser_InitializeReportForID(
1164 IN PHID_PARSER Parser,
1165 IN HIDP_REPORT_TYPE ReportType,
1166 IN UCHAR ReportID,
1167 IN OUT PCHAR Report,
1168 IN ULONG ReportLength)
1169 {
1170 UNIMPLEMENTED
1171 ASSERT(FALSE);
1172 return STATUS_NOT_IMPLEMENTED;
1173 }
1174
1175 #undef HidParser_GetValueCaps
1176
1177 HIDAPI
1178 NTSTATUS
1179 NTAPI
1180 HidParser_GetValueCaps(
1181 IN PHID_PARSER Parser,
1182 HIDP_REPORT_TYPE ReportType,
1183 PHIDP_VALUE_CAPS ValueCaps,
1184 PULONG ValueCapsLength)
1185 {
1186 UNIMPLEMENTED
1187 ASSERT(FALSE);
1188 return STATUS_NOT_IMPLEMENTED;
1189 }