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