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