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