xref: /reactos/sdk/lib/drivers/hidparser/api.c (revision c4055c45)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:     ReactOS HID Parser Library
3c2c66affSColin Finck  * LICENSE:     GPL - See COPYING in the top level directory
4c2c66affSColin Finck  * FILE:        lib/drivers/hidparser/api.c
5c2c66affSColin Finck  * PURPOSE:     HID Parser
6c2c66affSColin Finck  * PROGRAMMERS:
7c2c66affSColin Finck  *              Michael Martin (michael.martin@reactos.org)
8c2c66affSColin Finck  *              Johannes Anderwald (johannes.anderwald@reactos.org)
9c2c66affSColin Finck  */
10c2c66affSColin Finck 
11c2c66affSColin Finck #include "parser.h"
12c2c66affSColin Finck 
13c2c66affSColin Finck #define NDEBUG
14c2c66affSColin Finck #include <debug.h>
15c2c66affSColin Finck 
16c2c66affSColin Finck static ULONG KeyboardScanCodes[256] =
17c2c66affSColin Finck { /*    0       1       2       3       4       5       6       7       8       9       A       B       C       D       E       F */
18c2c66affSColin Finck /* 0 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020, 0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
19c2c66affSColin Finck /* 1 */ 0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014, 0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
20c2c66affSColin Finck /* 2 */ 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
21c2c66affSColin Finck /* 3 */ 0x001b, 0x002b, 0x002b, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034, 0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
22c2c66affSColin Finck /* 4 */ 0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xE037, 0x0046, 0x0045, 0xE052, 0xE047, 0xE049, 0xE053, 0xE04F, 0xE051, 0xE04D,
23c2c66affSColin Finck /* 5 */ 0xE04B, 0xE050, 0xE048, 0x0045, 0xE035, 0x0037, 0x004a, 0x004e, 0xE01C, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
24c2c66affSColin Finck /* 6 */ 0x0048, 0x0049, 0x0052, 0x0053, 0x0056, 0xE05D, 0xE05E, 0x0075, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be,
25c2c66affSColin Finck /* 7 */ 0x00bf, 0x00c0, 0x00c1, 0x00c2, 0x0086, 0x008a, 0x0082, 0x0084, 0x0080, 0x0081, 0x0083, 0x0089, 0x0085, 0x0087, 0x0088, 0x0071,
26c2c66affSColin Finck /* 8 */ 0x0073, 0x0072, 0x0000, 0x0000, 0x0000, 0x0079, 0x0000, 0x0059, 0x005d, 0x007c, 0x005c, 0x005e, 0x005f, 0x0000, 0x0000, 0x0000,
27c2c66affSColin Finck /* 9 */ 0x007a, 0x007b, 0x005a, 0x005b, 0x0055, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
28c2c66affSColin Finck /* A */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
29c2c66affSColin Finck /* B */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
30c2c66affSColin Finck /* C */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
31c2c66affSColin Finck /* D */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
32c2c66affSColin Finck /* E */ 0x001D, 0x002A, 0x0038, 0xE05B, 0xE01D, 0x0036, 0xE038, 0xE05C, 0x00a4, 0x00a6, 0x00a5, 0x00a3, 0x00a1, 0x0073, 0x0072, 0x0071,
33c2c66affSColin Finck /* F */ 0x0096, 0x009e, 0x009f, 0x0080, 0x0088, 0x00b1, 0x00b2, 0x00b0, 0x008e, 0x0098, 0x00ad, 0x008c, 0x0000, 0x0000, 0x0000, 0x0000,
34c2c66affSColin Finck };
35c2c66affSColin Finck 
36c2c66affSColin Finck static struct
37c2c66affSColin Finck {
38c2c66affSColin Finck     USAGE Usage;
39c2c66affSColin Finck     ULONG ScanCode;
40c2c66affSColin Finck } CustomerScanCodes[] =
41c2c66affSColin Finck {
42c2c66affSColin Finck     { 0x00B5, 0xE019 },
43c2c66affSColin Finck     { 0x00B6, 0xE010 },
44c2c66affSColin Finck     { 0x00B7, 0xE024 },
45c2c66affSColin Finck     { 0x00CD, 0xE022 },
46c2c66affSColin Finck     { 0x00E2, 0xE020 },
47c2c66affSColin Finck     { 0x00E9, 0xE030 },
48c2c66affSColin Finck     { 0x00EA, 0xE02E },
49c2c66affSColin Finck     { 0x0183, 0xE06D },
50c2c66affSColin Finck     { 0x018A, 0xE06C },
51c2c66affSColin Finck     { 0x0192, 0xE021 },
52c2c66affSColin Finck     { 0x0194, 0xE06B },
53c2c66affSColin Finck     { 0x0221, 0xE065 },
54c2c66affSColin Finck     { 0x0223, 0xE032 },
55c2c66affSColin Finck     { 0x0224, 0xE06A },
56c2c66affSColin Finck     { 0x0225, 0xE069 },
57c2c66affSColin Finck     { 0x0226, 0xE068 },
58c2c66affSColin Finck     { 0x0227, 0xE067 },
59c2c66affSColin Finck     { 0x022A, 0xE066 },
60c2c66affSColin Finck };
61c2c66affSColin Finck 
62c2c66affSColin Finck #define NTOHS(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
63c2c66affSColin Finck 
64*c4055c45SHervé Poussineau NTSTATUS
HidParser_GetCollectionUsagePage(IN PVOID CollectionContext,OUT PUSHORT Usage,OUT PUSHORT UsagePage)65c2c66affSColin Finck HidParser_GetCollectionUsagePage(
66c2c66affSColin Finck     IN PVOID CollectionContext,
67c2c66affSColin Finck     OUT PUSHORT Usage,
68c2c66affSColin Finck     OUT PUSHORT UsagePage)
69c2c66affSColin Finck {
70c2c66affSColin Finck     PHID_COLLECTION Collection;
71c2c66affSColin Finck 
72c2c66affSColin Finck     //
73c2c66affSColin Finck     // find collection
74c2c66affSColin Finck     //
75c2c66affSColin Finck     Collection = HidParser_GetCollectionFromContext(CollectionContext);
76c2c66affSColin Finck     if (!Collection)
77c2c66affSColin Finck     {
78c2c66affSColin Finck         //
79c2c66affSColin Finck         // collection not found
80c2c66affSColin Finck         //
81*c4055c45SHervé Poussineau         return HIDP_STATUS_USAGE_NOT_FOUND;
82c2c66affSColin Finck     }
83c2c66affSColin Finck 
84c2c66affSColin Finck     //
85c2c66affSColin Finck     // store result
86c2c66affSColin Finck     //
87c2c66affSColin Finck     *UsagePage = (Collection->Usage >> 16);
88c2c66affSColin Finck     *Usage = (Collection->Usage & 0xFFFF);
89*c4055c45SHervé Poussineau     return HIDP_STATUS_SUCCESS;
90c2c66affSColin Finck }
91c2c66affSColin Finck 
92c2c66affSColin Finck ULONG
HidParser_GetReportLength(IN PVOID CollectionContext,IN UCHAR ReportType)93c2c66affSColin Finck HidParser_GetReportLength(
94c2c66affSColin Finck     IN PVOID CollectionContext,
95c2c66affSColin Finck     IN UCHAR ReportType)
96c2c66affSColin Finck {
97c2c66affSColin Finck     PHID_REPORT Report;
98c2c66affSColin Finck     ULONG ReportLength;
99c2c66affSColin Finck 
100c2c66affSColin Finck     //
101c2c66affSColin Finck     // get first report
102c2c66affSColin Finck     //
103c2c66affSColin Finck     Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
104c2c66affSColin Finck     if (!Report)
105c2c66affSColin Finck     {
106c2c66affSColin Finck         //
107c2c66affSColin Finck         // no report found
108c2c66affSColin Finck         //
109c2c66affSColin Finck         return 0;
110c2c66affSColin Finck     }
111c2c66affSColin Finck 
112c2c66affSColin Finck     //
113c2c66affSColin Finck     // get report length
114c2c66affSColin Finck     //
115c2c66affSColin Finck     ReportLength = Report->ReportSize;
116c2c66affSColin Finck 
117c2c66affSColin Finck     //
118c2c66affSColin Finck     // done
119c2c66affSColin Finck     //
120c2c66affSColin Finck     if (ReportLength)
121c2c66affSColin Finck     {
122c2c66affSColin Finck         //
123c2c66affSColin Finck         // byte aligned length
124c2c66affSColin Finck         //
125c2c66affSColin Finck         ASSERT(ReportLength % 8 == 0);
126c2c66affSColin Finck         return ReportLength / 8;
127c2c66affSColin Finck     }
128c2c66affSColin Finck     return ReportLength;
129c2c66affSColin Finck }
130c2c66affSColin Finck 
131c2c66affSColin Finck ULONG
HidParser_GetReportItemCountFromReportType(IN PVOID CollectionContext,IN UCHAR ReportType)132c2c66affSColin Finck HidParser_GetReportItemCountFromReportType(
133c2c66affSColin Finck     IN PVOID CollectionContext,
134c2c66affSColin Finck     IN UCHAR ReportType)
135c2c66affSColin Finck {
136c2c66affSColin Finck     PHID_REPORT Report;
137c2c66affSColin Finck 
138c2c66affSColin Finck     //
139c2c66affSColin Finck     // get report
140c2c66affSColin Finck     //
141c2c66affSColin Finck     Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
142c2c66affSColin Finck     if (!Report)
143c2c66affSColin Finck     {
144c2c66affSColin Finck         //
145c2c66affSColin Finck         // no such report
146c2c66affSColin Finck         //
147c2c66affSColin Finck         return 0;
148c2c66affSColin Finck     }
149c2c66affSColin Finck 
150c2c66affSColin Finck     //
151c2c66affSColin Finck     // return report item count
152c2c66affSColin Finck     //
153c2c66affSColin Finck     return Report->ItemCount;
154c2c66affSColin Finck }
155c2c66affSColin Finck 
156c2c66affSColin Finck 
157c2c66affSColin Finck ULONG
HidParser_GetReportItemTypeCountFromReportType(IN PVOID CollectionContext,IN UCHAR ReportType,IN ULONG bData)158c2c66affSColin Finck HidParser_GetReportItemTypeCountFromReportType(
159c2c66affSColin Finck     IN PVOID CollectionContext,
160c2c66affSColin Finck     IN UCHAR ReportType,
161c2c66affSColin Finck     IN ULONG bData)
162c2c66affSColin Finck {
163c2c66affSColin Finck     ULONG Index;
164c2c66affSColin Finck     PHID_REPORT Report;
165c2c66affSColin Finck     ULONG ItemCount = 0;
166c2c66affSColin Finck 
167c2c66affSColin Finck     //
168c2c66affSColin Finck     // get report
169c2c66affSColin Finck     //
170c2c66affSColin Finck     Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
171c2c66affSColin Finck     if (!Report)
172c2c66affSColin Finck     {
173c2c66affSColin Finck         //
174c2c66affSColin Finck         // no such report
175c2c66affSColin Finck         //
176c2c66affSColin Finck         return 0;
177c2c66affSColin Finck     }
178c2c66affSColin Finck 
179c2c66affSColin Finck     //
180c2c66affSColin Finck     // enumerate all items
181c2c66affSColin Finck     //
182c2c66affSColin Finck     for(Index = 0; Index < Report->ItemCount; Index++)
183c2c66affSColin Finck     {
184c2c66affSColin Finck         //
185c2c66affSColin Finck         // check item type
186c2c66affSColin Finck         //
187c2c66affSColin Finck         if (Report->Items[Index].HasData && bData)
188c2c66affSColin Finck         {
189c2c66affSColin Finck             //
190c2c66affSColin Finck             // found data item
191c2c66affSColin Finck             //
192c2c66affSColin Finck             ItemCount++;
193c2c66affSColin Finck         }
194c2c66affSColin Finck         else if (Report->Items[Index].HasData == FALSE && bData == FALSE)
195c2c66affSColin Finck         {
196c2c66affSColin Finck             //
197c2c66affSColin Finck             // found value item
198c2c66affSColin Finck             //
199c2c66affSColin Finck             ItemCount++;
200c2c66affSColin Finck         }
201c2c66affSColin Finck     }
202c2c66affSColin Finck 
203c2c66affSColin Finck     //
204c2c66affSColin Finck     // no report items
205c2c66affSColin Finck     //
206c2c66affSColin Finck     return ItemCount;
207c2c66affSColin Finck }
208c2c66affSColin Finck 
209c2c66affSColin Finck ULONG
HidParser_GetMaxUsageListLengthWithReportAndPage(IN PVOID CollectionContext,IN UCHAR ReportType,IN USAGE UsagePage OPTIONAL)210c2c66affSColin Finck HidParser_GetMaxUsageListLengthWithReportAndPage(
211c2c66affSColin Finck     IN PVOID CollectionContext,
212c2c66affSColin Finck     IN UCHAR ReportType,
213c2c66affSColin Finck     IN USAGE  UsagePage  OPTIONAL)
214c2c66affSColin Finck {
215c2c66affSColin Finck     ULONG Index;
216c2c66affSColin Finck     PHID_REPORT Report;
217c2c66affSColin Finck     ULONG ItemCount = 0;
218c2c66affSColin Finck     USHORT CurrentUsagePage;
219c2c66affSColin Finck 
220c2c66affSColin Finck     //
221c2c66affSColin Finck     // get report
222c2c66affSColin Finck     //
223c2c66affSColin Finck     Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
224c2c66affSColin Finck     if (!Report)
225c2c66affSColin Finck     {
226c2c66affSColin Finck         //
227c2c66affSColin Finck         // no such report
228c2c66affSColin Finck         //
229c2c66affSColin Finck         return 0;
230c2c66affSColin Finck     }
231c2c66affSColin Finck 
232c2c66affSColin Finck     for(Index = 0; Index < Report->ItemCount; Index++)
233c2c66affSColin Finck     {
234c2c66affSColin Finck         //
235c2c66affSColin Finck         // check usage page
236c2c66affSColin Finck         //
237c2c66affSColin Finck         CurrentUsagePage = (Report->Items[Index].UsageMinimum >> 16);
238c2c66affSColin Finck         if (CurrentUsagePage == UsagePage && Report->Items[Index].HasData)
239c2c66affSColin Finck         {
240c2c66affSColin Finck             //
241c2c66affSColin Finck             // found item
242c2c66affSColin Finck             //
243c2c66affSColin Finck             ItemCount++;
244c2c66affSColin Finck         }
245c2c66affSColin Finck     }
246c2c66affSColin Finck 
247c2c66affSColin Finck     //
248c2c66affSColin Finck     // done
249c2c66affSColin Finck     //
250c2c66affSColin Finck     return ItemCount;
251c2c66affSColin Finck }
252c2c66affSColin Finck 
253*c4055c45SHervé Poussineau NTSTATUS
HidParser_GetSpecificValueCapsWithReport(IN PVOID CollectionContext,IN UCHAR ReportType,IN USHORT UsagePage,IN USHORT Usage,OUT PHIDP_VALUE_CAPS ValueCaps,IN OUT PUSHORT ValueCapsLength)254c2c66affSColin Finck HidParser_GetSpecificValueCapsWithReport(
255c2c66affSColin Finck     IN PVOID CollectionContext,
256c2c66affSColin Finck     IN UCHAR ReportType,
257c2c66affSColin Finck     IN USHORT UsagePage,
258c2c66affSColin Finck     IN USHORT Usage,
259c2c66affSColin Finck     OUT PHIDP_VALUE_CAPS  ValueCaps,
260c2c66affSColin Finck     IN OUT PUSHORT  ValueCapsLength)
261c2c66affSColin Finck {
262c2c66affSColin Finck     ULONG Index;
263c2c66affSColin Finck     PHID_REPORT Report;
264c2c66affSColin Finck     USHORT ItemCount = 0;
265c2c66affSColin Finck     USHORT CurrentUsagePage;
266c2c66affSColin Finck     USHORT CurrentUsage;
267c2c66affSColin Finck 
268c2c66affSColin Finck     //
269c2c66affSColin Finck     // get report
270c2c66affSColin Finck     //
271c2c66affSColin Finck     Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
272c2c66affSColin Finck     if (!Report)
273c2c66affSColin Finck     {
274c2c66affSColin Finck         //
275c2c66affSColin Finck         // no such report
276c2c66affSColin Finck         //
277*c4055c45SHervé Poussineau         return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
278c2c66affSColin Finck     }
279c2c66affSColin Finck 
280c2c66affSColin Finck     for(Index = 0; Index < Report->ItemCount; Index++)
281c2c66affSColin Finck     {
282c2c66affSColin Finck         //
283c2c66affSColin Finck         // check usage page
284c2c66affSColin Finck         //
285c2c66affSColin Finck         CurrentUsagePage = (Report->Items[Index].UsageMinimum >> 16);
286c2c66affSColin Finck         CurrentUsage = (Report->Items[Index].UsageMinimum & 0xFFFF);
287c2c66affSColin Finck 
288c2c66affSColin Finck         if ((Usage == CurrentUsage && UsagePage == CurrentUsagePage) || (Usage == 0 && UsagePage == CurrentUsagePage) || (Usage == CurrentUsage && UsagePage == 0) || (Usage == 0 && UsagePage == 0))
289c2c66affSColin Finck         {
290c2c66affSColin Finck             //
291c2c66affSColin Finck             // check if there is enough place for the caps
292c2c66affSColin Finck             //
293c2c66affSColin Finck             if (ItemCount < *ValueCapsLength)
294c2c66affSColin Finck             {
295c2c66affSColin Finck                 //
296c2c66affSColin Finck                 // zero caps
297c2c66affSColin Finck                 //
298c151f8a1SHervé Poussineau                 ZeroFunction(&ValueCaps[ItemCount], sizeof(HIDP_VALUE_CAPS));
299c2c66affSColin Finck 
300c2c66affSColin Finck                 //
301c2c66affSColin Finck                 // init caps
302c2c66affSColin Finck                 //
303c2c66affSColin Finck                 ValueCaps[ItemCount].UsagePage = CurrentUsagePage;
304c2c66affSColin Finck                 ValueCaps[ItemCount].ReportID = Report->ReportID;
305c2c66affSColin Finck                 ValueCaps[ItemCount].LogicalMin = Report->Items[Index].Minimum;
306c2c66affSColin Finck                 ValueCaps[ItemCount].LogicalMax = Report->Items[Index].Maximum;
307c2c66affSColin Finck                 ValueCaps[ItemCount].IsAbsolute = !Report->Items[Index].Relative;
308c2c66affSColin Finck                 ValueCaps[ItemCount].BitSize = Report->Items[Index].BitCount;
309c2c66affSColin Finck 
310c2c66affSColin Finck                 //
311c2c66affSColin Finck                 // FIXME: FILLMEIN
312c2c66affSColin Finck                 //
313c2c66affSColin Finck             }
314c2c66affSColin Finck 
315c2c66affSColin Finck 
316c2c66affSColin Finck             //
317c2c66affSColin Finck             // found item
318c2c66affSColin Finck             //
319c2c66affSColin Finck             ItemCount++;
320c2c66affSColin Finck         }
321c2c66affSColin Finck     }
322c2c66affSColin Finck 
323c2c66affSColin Finck     //
324c2c66affSColin Finck     // store result
325c2c66affSColin Finck     //
326c2c66affSColin Finck     *ValueCapsLength = ItemCount;
327c2c66affSColin Finck 
328c2c66affSColin Finck     if (ItemCount)
329c2c66affSColin Finck     {
330c2c66affSColin Finck         //
331c2c66affSColin Finck         // success
332c2c66affSColin Finck         //
333*c4055c45SHervé Poussineau         return HIDP_STATUS_SUCCESS;
334c2c66affSColin Finck     }
335c2c66affSColin Finck 
336c2c66affSColin Finck     //
337c2c66affSColin Finck     // item not found
338c2c66affSColin Finck     //
339*c4055c45SHervé Poussineau     return HIDP_STATUS_USAGE_NOT_FOUND;
340c2c66affSColin Finck }
341c2c66affSColin Finck 
342*c4055c45SHervé Poussineau NTSTATUS
HidParser_GetUsagesWithReport(IN PVOID CollectionContext,IN UCHAR ReportType,IN USAGE UsagePage,OUT USAGE * UsageList,IN OUT PULONG UsageLength,IN PCHAR ReportDescriptor,IN ULONG ReportDescriptorLength)343c2c66affSColin Finck HidParser_GetUsagesWithReport(
344c2c66affSColin Finck     IN PVOID CollectionContext,
345c2c66affSColin Finck     IN UCHAR  ReportType,
346c2c66affSColin Finck     IN USAGE  UsagePage,
347c2c66affSColin Finck     OUT USAGE  *UsageList,
348c2c66affSColin Finck     IN OUT PULONG UsageLength,
349c2c66affSColin Finck     IN PCHAR  ReportDescriptor,
350c2c66affSColin Finck     IN ULONG  ReportDescriptorLength)
351c2c66affSColin Finck {
352c2c66affSColin Finck     ULONG Index;
353c2c66affSColin Finck     PHID_REPORT Report;
354c2c66affSColin Finck     ULONG ItemCount = 0;
355c2c66affSColin Finck     USHORT CurrentUsagePage;
356c2c66affSColin Finck     PHID_REPORT_ITEM ReportItem;
357c2c66affSColin Finck     UCHAR Activated;
358c2c66affSColin Finck     ULONG Data;
359c2c66affSColin Finck     PUSAGE_AND_PAGE UsageAndPage = NULL;
360c2c66affSColin Finck 
361c2c66affSColin Finck     //
362c2c66affSColin Finck     // get report
363c2c66affSColin Finck     //
364c2c66affSColin Finck     Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
365c2c66affSColin Finck     if (!Report)
366c2c66affSColin Finck     {
367c2c66affSColin Finck         //
368c2c66affSColin Finck         // no such report
369c2c66affSColin Finck         //
370*c4055c45SHervé Poussineau         return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
371c2c66affSColin Finck     }
372c2c66affSColin Finck 
373c2c66affSColin Finck     if (Report->ReportSize / 8 != (ReportDescriptorLength - 1))
374c2c66affSColin Finck     {
375c2c66affSColin Finck         //
376c2c66affSColin Finck         // invalid report descriptor length
377c2c66affSColin Finck         //
378*c4055c45SHervé Poussineau         return HIDP_STATUS_INVALID_REPORT_LENGTH;
379c2c66affSColin Finck     }
380c2c66affSColin Finck 
381c2c66affSColin Finck     //
382c2c66affSColin Finck     // cast to usage and page
383c2c66affSColin Finck     //
384c2c66affSColin Finck     if (UsagePage == HID_USAGE_PAGE_UNDEFINED)
385c2c66affSColin Finck     {
386c2c66affSColin Finck         //
387c2c66affSColin Finck         // the caller requested any set usages
388c2c66affSColin Finck         //
389c2c66affSColin Finck         UsageAndPage = (PUSAGE_AND_PAGE)UsageList;
390c2c66affSColin Finck     }
391c2c66affSColin Finck 
392c2c66affSColin Finck     for(Index = 0; Index < Report->ItemCount; Index++)
393c2c66affSColin Finck     {
394c2c66affSColin Finck         //
395c2c66affSColin Finck         // get report item
396c2c66affSColin Finck         //
397c2c66affSColin Finck         ReportItem = &Report->Items[Index];
398c2c66affSColin Finck 
399c2c66affSColin Finck         //
400c2c66affSColin Finck         // does it have data
401c2c66affSColin Finck         //
402c2c66affSColin Finck         if (!ReportItem->HasData)
403c2c66affSColin Finck             continue;
404c2c66affSColin Finck 
405c2c66affSColin Finck         //
406c2c66affSColin Finck         // check usage page
407c2c66affSColin Finck         //
408c2c66affSColin Finck         CurrentUsagePage = (ReportItem->UsageMinimum >> 16);
409c2c66affSColin Finck 
410c2c66affSColin Finck         if (UsagePage != HID_USAGE_PAGE_UNDEFINED)
411c2c66affSColin Finck         {
412c2c66affSColin Finck             //
413c2c66affSColin Finck             // does usage match
414c2c66affSColin Finck             //
415c2c66affSColin Finck             if (UsagePage != CurrentUsagePage)
416c2c66affSColin Finck                 continue;
417c2c66affSColin Finck         }
418c2c66affSColin Finck 
419c2c66affSColin Finck         //
420c2c66affSColin Finck         // check if the specified usage is activated
421c2c66affSColin Finck         //
422c2c66affSColin Finck         ASSERT(ReportItem->ByteOffset < ReportDescriptorLength);
423c2c66affSColin Finck         ASSERT(ReportItem->BitCount <= 8);
424c2c66affSColin Finck 
425c2c66affSColin Finck         //
426c2c66affSColin Finck         // one extra shift for skipping the prepended report id
427c2c66affSColin Finck         //
428c2c66affSColin Finck         Data = ReportDescriptor[ReportItem->ByteOffset + 1];
429c2c66affSColin Finck 
430c2c66affSColin Finck         //
431c2c66affSColin Finck         // shift data
432c2c66affSColin Finck         //
433c2c66affSColin Finck         Data >>= ReportItem->Shift;
434c2c66affSColin Finck 
435c2c66affSColin Finck         //
436c2c66affSColin Finck         // clear unwanted bits
437c2c66affSColin Finck         //
438c2c66affSColin Finck         Data &= ReportItem->Mask;
439c2c66affSColin Finck 
440c2c66affSColin Finck         //
441c2c66affSColin Finck         // is it activated
442c2c66affSColin Finck         //
443c2c66affSColin Finck         Activated = (Data != 0);
444c2c66affSColin Finck 
445c2c66affSColin Finck         if (!Activated)
446c2c66affSColin Finck             continue;
447c2c66affSColin Finck 
448c2c66affSColin Finck         //
449c2c66affSColin Finck         // is there enough space for the usage
450c2c66affSColin Finck         //
451c2c66affSColin Finck         if (ItemCount >= *UsageLength)
452c2c66affSColin Finck         {
453c2c66affSColin Finck             ItemCount++;
454c2c66affSColin Finck             continue;
455c2c66affSColin Finck         }
456c2c66affSColin Finck 
457c2c66affSColin Finck         if (UsagePage != HID_USAGE_PAGE_UNDEFINED)
458c2c66affSColin Finck         {
459c2c66affSColin Finck             //
460c2c66affSColin Finck             // store item
461c2c66affSColin Finck             //
462c2c66affSColin Finck             UsageList[ItemCount] = (ReportItem->UsageMinimum & 0xFFFF);
463c2c66affSColin Finck         }
464c2c66affSColin Finck         else
465c2c66affSColin Finck         {
466c2c66affSColin Finck             //
467c2c66affSColin Finck             // store usage and page
468c2c66affSColin Finck             //
469c2c66affSColin Finck             if (ReportItem->BitCount == 1)
470c2c66affSColin Finck             {
471c2c66affSColin Finck                 //
472c2c66affSColin Finck                 // use usage minimum
473c2c66affSColin Finck                 //
474c2c66affSColin Finck                 UsageAndPage[ItemCount].Usage =(ReportItem->UsageMinimum & 0xFFFF);
475c2c66affSColin Finck             }
476c2c66affSColin Finck             else
477c2c66affSColin Finck             {
478c2c66affSColin Finck                 //
479c2c66affSColin Finck                 // use value from control
480c2c66affSColin Finck                 //
481c2c66affSColin Finck                 UsageAndPage[ItemCount].Usage = (USHORT)Data;
482c2c66affSColin Finck             }
483c2c66affSColin Finck             UsageAndPage[ItemCount].UsagePage = CurrentUsagePage;
484c2c66affSColin Finck         }
485c2c66affSColin Finck         ItemCount++;
486c2c66affSColin Finck     }
487c2c66affSColin Finck 
488c2c66affSColin Finck     if (ItemCount > *UsageLength)
489c2c66affSColin Finck     {
490c2c66affSColin Finck         //
491c2c66affSColin Finck         // list too small
492c2c66affSColin Finck         //
493*c4055c45SHervé Poussineau         return HIDP_STATUS_BUFFER_TOO_SMALL;
494c2c66affSColin Finck     }
495c2c66affSColin Finck 
496c2c66affSColin Finck     if (UsagePage == HID_USAGE_PAGE_UNDEFINED)
497c2c66affSColin Finck     {
498c2c66affSColin Finck         //
499c2c66affSColin Finck         // success, clear rest of array
500c2c66affSColin Finck         //
501c151f8a1SHervé Poussineau         ZeroFunction(&UsageAndPage[ItemCount], (*UsageLength - ItemCount) * sizeof(USAGE_AND_PAGE));
502c2c66affSColin Finck     }
503c2c66affSColin Finck     else
504c2c66affSColin Finck     {
505c2c66affSColin Finck         //
506c2c66affSColin Finck         // success, clear rest of array
507c2c66affSColin Finck         //
508c151f8a1SHervé Poussineau         ZeroFunction(&UsageList[ItemCount], (*UsageLength - ItemCount) * sizeof(USAGE));
509c2c66affSColin Finck     }
510c2c66affSColin Finck 
511c2c66affSColin Finck 
512c2c66affSColin Finck     //
513c2c66affSColin Finck     // store result size
514c2c66affSColin Finck     //
515c2c66affSColin Finck     *UsageLength = ItemCount;
516c2c66affSColin Finck 
517c2c66affSColin Finck     //
518c2c66affSColin Finck     // done
519c2c66affSColin Finck     //
520*c4055c45SHervé Poussineau     return HIDP_STATUS_SUCCESS;
521c2c66affSColin Finck }
522c2c66affSColin Finck 
523c2c66affSColin Finck ULONG
HidParser_UsesReportId(IN PVOID CollectionContext,IN UCHAR ReportType)524c2c66affSColin Finck HidParser_UsesReportId(
525c2c66affSColin Finck     IN PVOID CollectionContext,
526c2c66affSColin Finck     IN UCHAR  ReportType)
527c2c66affSColin Finck {
528c2c66affSColin Finck     PHID_REPORT Report;
529c2c66affSColin Finck 
530c2c66affSColin Finck     //
531c2c66affSColin Finck     // get report
532c2c66affSColin Finck     //
533c2c66affSColin Finck     Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
534c2c66affSColin Finck     if (!Report)
535c2c66affSColin Finck     {
536c2c66affSColin Finck         //
537c2c66affSColin Finck         // no such report
538c2c66affSColin Finck         //
539c2c66affSColin Finck         return 0;
540c2c66affSColin Finck     }
541c2c66affSColin Finck 
542c2c66affSColin Finck     //
543c2c66affSColin Finck     // returns true when report id != 0
544c2c66affSColin Finck     //
545c2c66affSColin Finck     return (Report->ReportID != 0);
546c2c66affSColin Finck 
547c2c66affSColin Finck }
548c2c66affSColin Finck 
549*c4055c45SHervé Poussineau NTSTATUS
HidParser_GetUsageValueWithReport(IN PVOID CollectionContext,IN UCHAR ReportType,IN USAGE UsagePage,IN USAGE Usage,OUT PULONG UsageValue,IN PCHAR ReportDescriptor,IN ULONG ReportDescriptorLength)550c2c66affSColin Finck HidParser_GetUsageValueWithReport(
551c2c66affSColin Finck     IN PVOID CollectionContext,
552c2c66affSColin Finck     IN UCHAR ReportType,
553c2c66affSColin Finck     IN USAGE UsagePage,
554c2c66affSColin Finck     IN USAGE  Usage,
555c2c66affSColin Finck     OUT PULONG UsageValue,
556c2c66affSColin Finck     IN PCHAR ReportDescriptor,
557c2c66affSColin Finck     IN ULONG ReportDescriptorLength)
558c2c66affSColin Finck {
559c2c66affSColin Finck     ULONG Index;
560c2c66affSColin Finck     PHID_REPORT Report;
561c2c66affSColin Finck     USHORT CurrentUsagePage;
562c2c66affSColin Finck     PHID_REPORT_ITEM ReportItem;
563c2c66affSColin Finck     ULONG Data;
564c2c66affSColin Finck 
565c2c66affSColin Finck     //
566c2c66affSColin Finck     // get report
567c2c66affSColin Finck     //
568c2c66affSColin Finck     Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
569c2c66affSColin Finck     if (!Report)
570c2c66affSColin Finck     {
571c2c66affSColin Finck         //
572c2c66affSColin Finck         // no such report
573c2c66affSColin Finck         //
574*c4055c45SHervé Poussineau         return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
575c2c66affSColin Finck     }
576c2c66affSColin Finck 
577c2c66affSColin Finck     if (Report->ReportSize / 8 != (ReportDescriptorLength - 1))
578c2c66affSColin Finck     {
579c2c66affSColin Finck         //
580c2c66affSColin Finck         // invalid report descriptor length
581c2c66affSColin Finck         //
582*c4055c45SHervé Poussineau         return HIDP_STATUS_INVALID_REPORT_LENGTH;
583c2c66affSColin Finck     }
584c2c66affSColin Finck 
585c2c66affSColin Finck     for (Index = 0; Index < Report->ItemCount; Index++)
586c2c66affSColin Finck     {
587c2c66affSColin Finck         //
588c2c66affSColin Finck         // get report item
589c2c66affSColin Finck         //
590c2c66affSColin Finck         ReportItem = &Report->Items[Index];
591c2c66affSColin Finck 
592c2c66affSColin Finck         //
593c2c66affSColin Finck         // check usage page
594c2c66affSColin Finck         //
595c2c66affSColin Finck         CurrentUsagePage = (ReportItem->UsageMinimum >> 16);
596c2c66affSColin Finck 
597c2c66affSColin Finck         //
598c2c66affSColin Finck         // does usage page match
599c2c66affSColin Finck         //
600c2c66affSColin Finck         if (UsagePage != CurrentUsagePage)
601c2c66affSColin Finck             continue;
602c2c66affSColin Finck 
603c2c66affSColin Finck         //
604c2c66affSColin Finck         // does the usage match
605c2c66affSColin Finck         //
606c2c66affSColin Finck         if (Usage != (ReportItem->UsageMinimum & 0xFFFF))
607c2c66affSColin Finck             continue;
608c2c66affSColin Finck 
609c2c66affSColin Finck         //
610c2c66affSColin Finck         // check if the specified usage is activated
611c2c66affSColin Finck         //
612c2c66affSColin Finck         ASSERT(ReportItem->ByteOffset < ReportDescriptorLength);
613c2c66affSColin Finck 
614c2c66affSColin Finck         //
615c2c66affSColin Finck         // one extra shift for skipping the prepended report id
616c2c66affSColin Finck         //
617c2c66affSColin Finck         Data = 0;
618c151f8a1SHervé Poussineau         CopyFunction(&Data, &ReportDescriptor[ReportItem->ByteOffset + 1], min(sizeof(ULONG), ReportDescriptorLength - (ReportItem->ByteOffset + 1)));
619c2c66affSColin Finck 
620c2c66affSColin Finck         //
621c2c66affSColin Finck         // shift data
622c2c66affSColin Finck         //
623c2c66affSColin Finck         Data >>= ReportItem->Shift;
624c2c66affSColin Finck 
625c2c66affSColin Finck         //
626c2c66affSColin Finck         // clear unwanted bits
627c2c66affSColin Finck         //
628c2c66affSColin Finck         Data &= ReportItem->Mask;
629c2c66affSColin Finck 
630c2c66affSColin Finck         //
631c2c66affSColin Finck         // store result
632c2c66affSColin Finck         //
633c2c66affSColin Finck         *UsageValue = Data;
634*c4055c45SHervé Poussineau         return HIDP_STATUS_SUCCESS;
635c2c66affSColin Finck     }
636c2c66affSColin Finck 
637c2c66affSColin Finck     //
638c2c66affSColin Finck     // usage not found
639c2c66affSColin Finck     //
640*c4055c45SHervé Poussineau     return HIDP_STATUS_USAGE_NOT_FOUND;
641c2c66affSColin Finck }
642c2c66affSColin Finck 
643c2c66affSColin Finck 
644c2c66affSColin Finck 
645*c4055c45SHervé Poussineau NTSTATUS
HidParser_GetScaledUsageValueWithReport(IN PVOID CollectionContext,IN UCHAR ReportType,IN USAGE UsagePage,IN USAGE Usage,OUT PLONG UsageValue,IN PCHAR ReportDescriptor,IN ULONG ReportDescriptorLength)646c2c66affSColin Finck HidParser_GetScaledUsageValueWithReport(
647c2c66affSColin Finck     IN PVOID CollectionContext,
648c2c66affSColin Finck     IN UCHAR ReportType,
649c2c66affSColin Finck     IN USAGE UsagePage,
650c2c66affSColin Finck     IN USAGE  Usage,
651c2c66affSColin Finck     OUT PLONG UsageValue,
652c2c66affSColin Finck     IN PCHAR ReportDescriptor,
653c2c66affSColin Finck     IN ULONG ReportDescriptorLength)
654c2c66affSColin Finck {
655c2c66affSColin Finck     ULONG Index;
656c2c66affSColin Finck     PHID_REPORT Report;
657c2c66affSColin Finck     USHORT CurrentUsagePage;
658c2c66affSColin Finck     PHID_REPORT_ITEM ReportItem;
659c2c66affSColin Finck     ULONG Data;
660c2c66affSColin Finck 
661c2c66affSColin Finck     //
662c2c66affSColin Finck     // get report
663c2c66affSColin Finck     //
664c2c66affSColin Finck     Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
665c2c66affSColin Finck     if (!Report)
666c2c66affSColin Finck     {
667c2c66affSColin Finck         //
668c2c66affSColin Finck         // no such report
669c2c66affSColin Finck         //
670*c4055c45SHervé Poussineau         return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
671c2c66affSColin Finck     }
672c2c66affSColin Finck 
673c2c66affSColin Finck     if (Report->ReportSize / 8 != (ReportDescriptorLength - 1))
674c2c66affSColin Finck     {
675c2c66affSColin Finck         //
676c2c66affSColin Finck         // invalid report descriptor length
677c2c66affSColin Finck         //
678*c4055c45SHervé Poussineau         return HIDP_STATUS_INVALID_REPORT_LENGTH;
679c2c66affSColin Finck     }
680c2c66affSColin Finck 
681c2c66affSColin Finck     for (Index = 0; Index < Report->ItemCount; Index++)
682c2c66affSColin Finck     {
683c2c66affSColin Finck         //
684c2c66affSColin Finck         // get report item
685c2c66affSColin Finck         //
686c2c66affSColin Finck         ReportItem = &Report->Items[Index];
687c2c66affSColin Finck 
688c2c66affSColin Finck         //
689c2c66affSColin Finck         // check usage page
690c2c66affSColin Finck         //
691c2c66affSColin Finck         CurrentUsagePage = (ReportItem->UsageMinimum >> 16);
692c2c66affSColin Finck 
693c2c66affSColin Finck         //
694c2c66affSColin Finck         // does usage page match
695c2c66affSColin Finck         //
696c2c66affSColin Finck         if (UsagePage != CurrentUsagePage)
697c2c66affSColin Finck             continue;
698c2c66affSColin Finck 
699c2c66affSColin Finck         //
700c2c66affSColin Finck         // does the usage match
701c2c66affSColin Finck         //
702c2c66affSColin Finck         if (Usage != (ReportItem->UsageMinimum & 0xFFFF))
703c2c66affSColin Finck             continue;
704c2c66affSColin Finck 
705c2c66affSColin Finck         //
706c2c66affSColin Finck         // check if the specified usage is activated
707c2c66affSColin Finck         //
708c2c66affSColin Finck         ASSERT(ReportItem->ByteOffset < ReportDescriptorLength);
709c2c66affSColin Finck 
710c2c66affSColin Finck         //
711c2c66affSColin Finck         // one extra shift for skipping the prepended report id
712c2c66affSColin Finck         //
713c2c66affSColin Finck         Data = 0;
714c151f8a1SHervé Poussineau         CopyFunction(&Data, &ReportDescriptor[ReportItem->ByteOffset + 1], min(sizeof(ULONG), ReportDescriptorLength - (ReportItem->ByteOffset + 1)));
715c2c66affSColin Finck 
716c2c66affSColin Finck         //
717c2c66affSColin Finck         // shift data
718c2c66affSColin Finck         //
719c2c66affSColin Finck         Data >>= ReportItem->Shift;
720c2c66affSColin Finck 
721c2c66affSColin Finck         //
722c2c66affSColin Finck         // clear unwanted bits
723c2c66affSColin Finck         //
724c2c66affSColin Finck         Data &= ReportItem->Mask;
725c2c66affSColin Finck 
726c2c66affSColin Finck         if (ReportItem->Minimum > ReportItem->Maximum)
727c2c66affSColin Finck         {
728c2c66affSColin Finck             //
729c2c66affSColin Finck             // logical boundaries are signed values
730c2c66affSColin Finck             //
731c2c66affSColin Finck 
732c2c66affSColin Finck             // FIXME: scale with physical min/max
733c2c66affSColin Finck             if ((Data & ~(ReportItem->Mask >> 1)) != 0)
734c2c66affSColin Finck             {
735c2c66affSColin Finck                 Data |= ~ReportItem->Mask;
736c2c66affSColin Finck             }
737c2c66affSColin Finck         }
738c2c66affSColin Finck         else
739c2c66affSColin Finck         {
740c2c66affSColin Finck             // logical boundaries are absolute values
741*c4055c45SHervé Poussineau             return HIDP_STATUS_BAD_LOG_PHY_VALUES;
742c2c66affSColin Finck         }
743c2c66affSColin Finck 
744c2c66affSColin Finck         //
745c2c66affSColin Finck         // store result
746c2c66affSColin Finck         //
747c2c66affSColin Finck         *UsageValue = Data;
748*c4055c45SHervé Poussineau         return HIDP_STATUS_SUCCESS;
749c2c66affSColin Finck     }
750c2c66affSColin Finck 
751c2c66affSColin Finck     //
752c2c66affSColin Finck     // usage not found
753c2c66affSColin Finck     //
754*c4055c45SHervé Poussineau     return HIDP_STATUS_USAGE_NOT_FOUND;
755c2c66affSColin Finck }
756c2c66affSColin Finck 
757c2c66affSColin Finck ULONG
HidParser_GetScanCodeFromKbdUsage(IN USAGE Usage)758c2c66affSColin Finck HidParser_GetScanCodeFromKbdUsage(
759c2c66affSColin Finck     IN USAGE Usage)
760c2c66affSColin Finck {
761c2c66affSColin Finck     if (Usage < sizeof(KeyboardScanCodes) / sizeof(KeyboardScanCodes[0]))
762c2c66affSColin Finck     {
763c2c66affSColin Finck         //
764c2c66affSColin Finck         // valid usage
765c2c66affSColin Finck         //
766c2c66affSColin Finck         return KeyboardScanCodes[Usage];
767c2c66affSColin Finck     }
768c2c66affSColin Finck 
769c2c66affSColin Finck     //
770c2c66affSColin Finck     // invalid usage
771c2c66affSColin Finck     //
772c2c66affSColin Finck     return 0;
773c2c66affSColin Finck }
774c2c66affSColin Finck 
775c2c66affSColin Finck ULONG
HidParser_GetScanCodeFromCustUsage(IN USAGE Usage)776c2c66affSColin Finck HidParser_GetScanCodeFromCustUsage(
777c2c66affSColin Finck     IN USAGE Usage)
778c2c66affSColin Finck {
779c2c66affSColin Finck     ULONG i;
780c2c66affSColin Finck 
781c2c66affSColin Finck     //
782c2c66affSColin Finck     // find usage in array
783c2c66affSColin Finck     //
784c2c66affSColin Finck     for (i = 0; i < sizeof(CustomerScanCodes) / sizeof(CustomerScanCodes[0]); ++i)
785c2c66affSColin Finck     {
786c2c66affSColin Finck         if (CustomerScanCodes[i].Usage == Usage)
787c2c66affSColin Finck         {
788c2c66affSColin Finck             //
789c2c66affSColin Finck             // valid usage
790c2c66affSColin Finck             //
791c2c66affSColin Finck             return CustomerScanCodes[i].ScanCode;
792c2c66affSColin Finck         }
793c2c66affSColin Finck     }
794c2c66affSColin Finck 
795c2c66affSColin Finck     //
796c2c66affSColin Finck     // invalid usage
797c2c66affSColin Finck     //
798c2c66affSColin Finck     return 0;
799c2c66affSColin Finck }
800c2c66affSColin Finck 
801c2c66affSColin Finck VOID
HidParser_DispatchKey(IN PCHAR ScanCodes,IN HIDP_KEYBOARD_DIRECTION KeyAction,IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,IN PVOID InsertCodesContext)802c2c66affSColin Finck HidParser_DispatchKey(
803c2c66affSColin Finck     IN PCHAR ScanCodes,
804c2c66affSColin Finck     IN HIDP_KEYBOARD_DIRECTION KeyAction,
805c2c66affSColin Finck     IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,
806c2c66affSColin Finck     IN PVOID InsertCodesContext)
807c2c66affSColin Finck {
808c2c66affSColin Finck     ULONG Index;
809c2c66affSColin Finck     ULONG Length = 0;
810c2c66affSColin Finck 
811c2c66affSColin Finck     //
812c2c66affSColin Finck     // count code length
813c2c66affSColin Finck     //
814c2c66affSColin Finck     for(Index = 0; Index < sizeof(ULONG); Index++)
815c2c66affSColin Finck     {
816c2c66affSColin Finck         if (ScanCodes[Index] == 0)
817c2c66affSColin Finck         {
818c2c66affSColin Finck             //
819c2c66affSColin Finck             // last scan code
820c2c66affSColin Finck             //
821c2c66affSColin Finck             break;
822c2c66affSColin Finck         }
823c2c66affSColin Finck 
824c2c66affSColin Finck         //
825c2c66affSColin Finck         // is this a key break
826c2c66affSColin Finck         //
827c2c66affSColin Finck         if (KeyAction == HidP_Keyboard_Break)
828c2c66affSColin Finck         {
829c2c66affSColin Finck             //
830c2c66affSColin Finck             // add break - see USB HID to PS/2 Scan Code Translation Table
831c2c66affSColin Finck             //
832c2c66affSColin Finck             ScanCodes[Index] |= 0x80;
833c2c66affSColin Finck         }
834c2c66affSColin Finck 
835c2c66affSColin Finck         //
836c2c66affSColin Finck         // more scan counts
837c2c66affSColin Finck         //
838c2c66affSColin Finck         Length++;
839c2c66affSColin Finck     }
840c2c66affSColin Finck 
841c2c66affSColin Finck     if (Length > 0)
842c2c66affSColin Finck     {
843c2c66affSColin Finck          //
844c2c66affSColin Finck          // dispatch scan codes
845c2c66affSColin Finck          //
846c2c66affSColin Finck          InsertCodesProcedure(InsertCodesContext, ScanCodes, Length);
847c2c66affSColin Finck     }
848c2c66affSColin Finck }
849c2c66affSColin Finck 
850*c4055c45SHervé Poussineau NTSTATUS
HidParser_TranslateKbdUsage(IN USAGE Usage,IN HIDP_KEYBOARD_DIRECTION KeyAction,IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,IN PVOID InsertCodesContext)851c2c66affSColin Finck HidParser_TranslateKbdUsage(
852c2c66affSColin Finck     IN USAGE Usage,
853c2c66affSColin Finck     IN HIDP_KEYBOARD_DIRECTION  KeyAction,
854c2c66affSColin Finck     IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
855c2c66affSColin Finck     IN PHIDP_INSERT_SCANCODES  InsertCodesProcedure,
856c2c66affSColin Finck     IN PVOID  InsertCodesContext)
857c2c66affSColin Finck {
858c2c66affSColin Finck     ULONG ScanCode;
859c2c66affSColin Finck     CHAR FakeShift[] = {0xE0, 0x2A, 0x00};
860c2c66affSColin Finck     CHAR FakeCtrl[] = {0xE1, 0x1D, 0x00};
861c2c66affSColin Finck 
862c2c66affSColin Finck     //
863c2c66affSColin Finck     // get scan code
864c2c66affSColin Finck     //
865c2c66affSColin Finck     ScanCode = HidParser_GetScanCodeFromKbdUsage(Usage);
866c2c66affSColin Finck     if (!ScanCode)
867c2c66affSColin Finck     {
868c2c66affSColin Finck         //
869c2c66affSColin Finck         // invalid lookup or no scan code available
870c2c66affSColin Finck         //
871c2c66affSColin Finck         DPRINT1("No Scan code for Usage %x\n", Usage);
872*c4055c45SHervé Poussineau         return HIDP_STATUS_I8042_TRANS_UNKNOWN;
873c2c66affSColin Finck     }
874c2c66affSColin Finck 
875c2c66affSColin Finck     if (ScanCode & 0xFF00)
876c2c66affSColin Finck     {
877c2c66affSColin Finck         //
878c2c66affSColin Finck         // swap scan code
879c2c66affSColin Finck         //
880c2c66affSColin Finck         ScanCode = NTOHS(ScanCode);
881c2c66affSColin Finck     }
882c2c66affSColin Finck 
883c2c66affSColin Finck     if (Usage == 0x46 && KeyAction == HidP_Keyboard_Make)
884c2c66affSColin Finck     {
885c2c66affSColin Finck         // Print Screen generates additional FakeShift
886c2c66affSColin Finck         HidParser_DispatchKey(FakeShift, KeyAction, InsertCodesProcedure, InsertCodesContext);
887c2c66affSColin Finck     }
888c2c66affSColin Finck 
889c2c66affSColin Finck     if (Usage == 0x48)
890c2c66affSColin Finck     {
891c2c66affSColin Finck         // Pause/Break generates additional FakeCtrl. Note: it's always before key press/release.
892c2c66affSColin Finck         HidParser_DispatchKey(FakeCtrl, KeyAction, InsertCodesProcedure, InsertCodesContext);
893c2c66affSColin Finck     }
894c2c66affSColin Finck 
895c2c66affSColin Finck     //
896c2c66affSColin Finck     // FIXME: translate modifier states
897c2c66affSColin Finck     //
898c2c66affSColin Finck     HidParser_DispatchKey((PCHAR)&ScanCode, KeyAction, InsertCodesProcedure, InsertCodesContext);
899c2c66affSColin Finck 
900c2c66affSColin Finck     if (Usage == 0x46 && KeyAction == HidP_Keyboard_Break)
901c2c66affSColin Finck     {
902c2c66affSColin Finck         // Print Screen generates additional FakeShift
903c2c66affSColin Finck         HidParser_DispatchKey(FakeShift, KeyAction, InsertCodesProcedure, InsertCodesContext);
904c2c66affSColin Finck     }
905c2c66affSColin Finck 
906c2c66affSColin Finck     //
907c2c66affSColin Finck     // done
908c2c66affSColin Finck     //
909*c4055c45SHervé Poussineau     return HIDP_STATUS_SUCCESS;
910c2c66affSColin Finck }
911c2c66affSColin Finck 
912*c4055c45SHervé Poussineau NTSTATUS
HidParser_TranslateCustUsage(IN USAGE Usage,IN HIDP_KEYBOARD_DIRECTION KeyAction,IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,IN PVOID InsertCodesContext)913c2c66affSColin Finck HidParser_TranslateCustUsage(
914c2c66affSColin Finck     IN USAGE Usage,
915c2c66affSColin Finck     IN HIDP_KEYBOARD_DIRECTION  KeyAction,
916c2c66affSColin Finck     IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
917c2c66affSColin Finck     IN PHIDP_INSERT_SCANCODES  InsertCodesProcedure,
918c2c66affSColin Finck     IN PVOID  InsertCodesContext)
919c2c66affSColin Finck {
920c2c66affSColin Finck     ULONG ScanCode;
921c2c66affSColin Finck 
922c2c66affSColin Finck     //
923c2c66affSColin Finck     // get scan code
924c2c66affSColin Finck     //
925c2c66affSColin Finck     ScanCode = HidParser_GetScanCodeFromCustUsage(Usage);
926c2c66affSColin Finck     if (!ScanCode)
927c2c66affSColin Finck     {
928c2c66affSColin Finck         //
929c2c66affSColin Finck         // invalid lookup or no scan code available
930c2c66affSColin Finck         //
931c2c66affSColin Finck         DPRINT1("No Scan code for Usage %x\n", Usage);
932*c4055c45SHervé Poussineau         return HIDP_STATUS_I8042_TRANS_UNKNOWN;
933c2c66affSColin Finck     }
934c2c66affSColin Finck 
935c2c66affSColin Finck     if (ScanCode & 0xFF00)
936c2c66affSColin Finck     {
937c2c66affSColin Finck         //
938c2c66affSColin Finck         // swap scan code
939c2c66affSColin Finck         //
940c2c66affSColin Finck         ScanCode = NTOHS(ScanCode);
941c2c66affSColin Finck     }
942c2c66affSColin Finck 
943c2c66affSColin Finck     //
944c2c66affSColin Finck     // FIXME: translate modifier states
945c2c66affSColin Finck     //
946c2c66affSColin Finck     HidParser_DispatchKey((PCHAR)&ScanCode, KeyAction, InsertCodesProcedure, InsertCodesContext);
947c2c66affSColin Finck 
948c2c66affSColin Finck     //
949c2c66affSColin Finck     // done
950c2c66affSColin Finck     //
951*c4055c45SHervé Poussineau     return HIDP_STATUS_SUCCESS;
952c2c66affSColin Finck }
953