Line No. | Rev | Author | Line |
---|---|---|---|
1 | 32 | kaklik | /****************************************************************************** |
2 | |||
3 | USB Host HID Parser |
||
4 | |||
5 | This is the Human Interface Device Class report parser file for a USB |
||
6 | Embedded Host device. This file should be used in a project with usb_host_hid.c |
||
7 | to provided the functional interface. |
||
8 | |||
9 | Acronyms/abbreviations used by this class: |
||
10 | * HID - Human Interface Device |
||
11 | |||
12 | This file consists of HID parser. Report descriptor received from device is |
||
13 | validated for proper format. If the report descriptor is not in proper format |
||
14 | as mandated by USB forum the device is not allowed on the bus. Only after the |
||
15 | report descriptor is validated, the information is populated in data structures. |
||
16 | Interface functions provided in file 'usb_host_hid.c' can be |
||
17 | used to understand the device capabilities. User of this code is advised to |
||
18 | refer document "Device Class Definition for Human Interface Devices (HID)" |
||
19 | available on website 'www.usb.org' for more details on content and format |
||
20 | of report descriptor. |
||
21 | |||
22 | FileName: usb_host_hid_parser.c |
||
23 | Dependencies: None |
||
24 | Processor: PIC24/dsPIC30/dsPIC33/PIC32MX |
||
25 | Compiler: C30/C32 |
||
26 | Company: Microchip Technology, Inc. |
||
27 | |||
28 | Software License Agreement |
||
29 | |||
30 | The software supplied herewith by Microchip Technology Incorporated |
||
31 | (the Company) for its PICmicro® Microcontroller is intended and |
||
32 | supplied to you, the Companys customer, for use solely and |
||
33 | exclusively on Microchip PICmicro Microcontroller products. The |
||
34 | software is owned by the Company and/or its supplier, and is |
||
35 | protected under applicable copyright laws. All rights are reserved. |
||
36 | Any use in violation of the foregoing restrictions may subject the |
||
37 | user to criminal sanctions under applicable laws, as well as to |
||
38 | civil liability for the breach of the terms and conditions of this |
||
39 | license. |
||
40 | |||
41 | THIS SOFTWARE IS PROVIDED IN AN AS IS CONDITION. NO WARRANTIES, |
||
42 | WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED |
||
43 | TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||
44 | PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, |
||
45 | IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR |
||
46 | CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. |
||
47 | |||
48 | Change History: |
||
49 | Rev Description |
||
50 | ---------- ---------------------------------------------------------- |
||
51 | 2.6 - 2.7 No change |
||
52 | |||
53 | 2.7a Provided macro wrapped versions of malloc() and free() |
||
54 | so that a user can override these functions easily. |
||
55 | |||
56 | Fixed initialization issue where HID parse result information |
||
57 | wasn't cleared before loading with new parse result data. |
||
58 | |||
59 | *******************************************************************************/ |
||
60 | #include "GenericTypeDefs.h" |
||
61 | #include "HardwareProfile.h" |
||
62 | #include "usb_config.h" |
||
63 | #include "USB\usb.h" |
||
64 | #include "USB\usb_host_hid.h" |
||
65 | #include "USB\usb_host_hid_parser.h" |
||
66 | #include <stdlib.h> |
||
67 | #include <string.h> |
||
68 | |||
69 | //#define DEBUG_MODE |
||
70 | #ifdef DEBUG_MODE |
||
71 | #include "uart2.h" |
||
72 | #endif |
||
73 | |||
74 | // ***************************************************************************** |
||
75 | // ***************************************************************************** |
||
76 | // Section: Constants |
||
77 | // ***************************************************************************** |
||
78 | // ***************************************************************************** |
||
79 | |||
80 | |||
81 | //****************************************************************************** |
||
82 | //****************************************************************************** |
||
83 | // Section: Data Structures |
||
84 | //****************************************************************************** |
||
85 | //****************************************************************************** |
||
86 | |||
87 | |||
88 | //****************************************************************************** |
||
89 | //****************************************************************************** |
||
90 | // Section: Macros |
||
91 | //****************************************************************************** |
||
92 | //****************************************************************************** |
||
93 | #ifndef USB_MALLOC |
||
94 | #define USB_MALLOC(size) malloc(size) |
||
95 | #endif |
||
96 | |||
97 | #ifndef USB_FREE |
||
98 | #define USB_FREE(ptr) free(ptr) |
||
99 | #endif |
||
100 | |||
101 | #define USB_FREE_AND_CLEAR(ptr) {USB_FREE(ptr); ptr = NULL;} |
||
102 | |||
103 | //****************************************************************************** |
||
104 | //****************************************************************************** |
||
105 | // Section: Local Prototypes |
||
106 | //****************************************************************************** |
||
107 | //****************************************************************************** |
||
108 | |||
109 | static void _USBHostHID_InitDeviceRptInfo(void); |
||
110 | static void _USBHostHID_Parse_Collection(HID_ITEM_INFO* ptrItem); |
||
111 | static void _USBHostHID_Parse_EndCollection(HID_ITEM_INFO* ptrItem); |
||
112 | static USB_HID_RPT_DESC_ERROR _USBHostHID_Parse_ReportType(HID_ITEM_INFO* item); |
||
113 | static void _USBHostHID_ConvertDataToSigned(HID_ITEM_INFO* item); |
||
114 | |||
115 | //****************************************************************************** |
||
116 | //****************************************************************************** |
||
117 | // Section: HID Host Global Variables |
||
118 | //****************************************************************************** |
||
119 | //****************************************************************************** |
||
120 | |||
121 | USB_HID_DEVICE_RPT_INFO deviceRptInfo = {0}; |
||
122 | USB_HID_ITEM_LIST itemListPtrs ={NULL}; |
||
123 | BYTE* parsedDataMem = NULL; |
||
124 | |||
125 | /**************************************************************************** |
||
126 | Function: |
||
127 | USB_HID_RPT_DESC_ERROR _USBHostHID_Parse_Report(BYTE* hidReportDescriptor |
||
128 | ,WORD lengthOfDescriptor, WORD pollRate, |
||
129 | BYTE interfaceNum) |
||
130 | |||
131 | Description: |
||
132 | This function is called by usb_host_hid.c after a valid configuration |
||
133 | device is found. This function parses the report descriptor and stores |
||
134 | data in data structures. Application can access these data structures |
||
135 | to understand report format and device capabilities |
||
136 | |||
137 | Precondition: |
||
138 | None |
||
139 | |||
140 | Parameters: |
||
141 | BYTE* hidReportDescriptor - Pointer to raw report descriptor |
||
142 | WORD lengthOfDescriptor - Length of Report Descriptor |
||
143 | WORD pollRate - Poll rate of the report |
||
144 | BYTE interfaceNum - interface number of the respective report |
||
145 | descriptor. |
||
146 | |||
147 | Return Values: |
||
148 | USB_HID_RPT_DESC_ERROR - Returns error code(enum) if found while |
||
149 | parsing the report descriptor |
||
150 | |||
151 | Remarks: |
||
152 | None |
||
153 | ***************************************************************************/ |
||
154 | USB_HID_RPT_DESC_ERROR _USBHostHID_Parse_Report(BYTE* hidReportDescriptor , WORD lengthOfDescriptor , WORD pollRate, BYTE interfaceNum) |
||
155 | { |
||
156 | WORD sizeRequired = 0; |
||
157 | WORD len_to_be_parsed =0; |
||
158 | BYTE* currentRptDescPtr = NULL; |
||
159 | BYTE* assignMem = NULL; |
||
160 | /* Main Item Vars */ |
||
161 | HID_COLLECTION *collectionLocal = NULL; |
||
162 | HID_REPORT *reportLocal = NULL; |
||
163 | |||
164 | /* Global Item Vars */ |
||
165 | HID_REPORT *lreport = NULL; |
||
166 | BYTE lreportIndex = (BYTE)NULL; |
||
167 | |||
168 | /* Local Item Vars */ |
||
169 | HID_DESIGITEM *ldesignatorItem = NULL; |
||
170 | HID_STRINGITEM *lstringItem = NULL; |
||
171 | HID_USAGEITEM *lusageItem = NULL; |
||
172 | |||
173 | /*HID Error */ |
||
174 | USB_HID_RPT_DESC_ERROR lhidError = HID_ERR; |
||
175 | |||
176 | HID_ITEM_INFO item; |
||
177 | |||
178 | BYTE i=0; |
||
179 | BYTE dataByte=0 ; |
||
180 | BYTE ldataSize=0; |
||
181 | |||
182 | if((hidReportDescriptor == NULL) ||(lengthOfDescriptor == 0)) |
||
183 | { |
||
184 | /* set error flag */ |
||
185 | return(HID_ERR_NullPointer); |
||
186 | } |
||
187 | |||
188 | memset( &deviceRptInfo, 0x00, sizeof( USB_HID_DEVICE_RPT_INFO ) ); |
||
189 | _USBHostHID_InitDeviceRptInfo(); |
||
190 | |||
191 | deviceRptInfo.interfaceNumber = interfaceNum; // update interface number for the report |
||
192 | deviceRptInfo.reportPollingRate = pollRate; |
||
193 | |||
194 | len_to_be_parsed = lengthOfDescriptor; |
||
195 | currentRptDescPtr = hidReportDescriptor; |
||
196 | |||
197 | while(len_to_be_parsed > 0) /* First parse to calculate the space required for all the items */ |
||
198 | { |
||
199 | item.ItemDetails.val = *currentRptDescPtr; |
||
200 | /* Data need not be parsed at this point */ |
||
201 | ldataSize = item.ItemDetails.ItemSize ; |
||
202 | if(item.ItemDetails.ItemSize == 3) |
||
203 | ldataSize = 4; |
||
204 | |||
205 | currentRptDescPtr += (ldataSize+1) ; /* point to next item i.e size of item data + 1(item detail) */ |
||
206 | len_to_be_parsed -= (ldataSize+1); /* remaining bytes = current - (length of data + 1)*/ |
||
207 | |||
208 | switch (item.ItemDetails.ItemType) |
||
209 | { |
||
210 | case HIDType_Main: /* Main Items */ |
||
211 | switch (item.ItemDetails.ItemTag) |
||
212 | { |
||
213 | case HIDTag_Collection: |
||
214 | deviceRptInfo.collections++; |
||
215 | deviceRptInfo.collectionNesting++; |
||
216 | if (deviceRptInfo.collectionNesting > deviceRptInfo.maxCollectionNesting) |
||
217 | deviceRptInfo.maxCollectionNesting = deviceRptInfo.collectionNesting; |
||
218 | break; |
||
219 | case HIDTag_EndCollection: |
||
220 | if (deviceRptInfo.collectionNesting-- == 0) |
||
221 | lhidError = HID_ERR_UnexpectedEndCollection ;/* Error: UnexpectedEndCollection */ |
||
222 | break; |
||
223 | case HIDTag_Input: |
||
224 | case HIDTag_Output: |
||
225 | case HIDTag_Feature: |
||
226 | deviceRptInfo.reportItems++; |
||
227 | break; |
||
228 | default : |
||
229 | break; |
||
230 | } |
||
231 | break; |
||
232 | case HIDType_Global: /* Global Items */ |
||
233 | switch (item.ItemDetails.ItemTag) |
||
234 | { |
||
235 | case HIDTag_ReportID: |
||
236 | deviceRptInfo.reports++; |
||
237 | break; |
||
238 | case HIDTag_Push: |
||
239 | deviceRptInfo.globalsNesting++; |
||
240 | if (deviceRptInfo.globalsNesting > deviceRptInfo.maxGlobalsNesting) |
||
241 | deviceRptInfo.maxGlobalsNesting = deviceRptInfo.globalsNesting; |
||
242 | break; |
||
243 | case HIDTag_Pop: |
||
244 | deviceRptInfo.globalsNesting--; |
||
245 | if (deviceRptInfo.globalsNesting > deviceRptInfo.maxGlobalsNesting) |
||
246 | lhidError = HID_ERR_UnexpectedPop ;/* Error: global nesting rolled to negative ... */ |
||
247 | break; |
||
248 | default : |
||
249 | break; |
||
250 | } |
||
251 | break; |
||
252 | case HIDType_Local: /* Local Item */ |
||
253 | switch (item.ItemDetails.ItemTag) |
||
254 | { |
||
255 | case HIDTag_Usage: |
||
256 | deviceRptInfo.usages++; |
||
257 | break; |
||
258 | case HIDTag_UsageMinimum: |
||
259 | case HIDTag_UsageMaximum: |
||
260 | deviceRptInfo.usageRanges++; |
||
261 | break; |
||
262 | case HIDTag_StringIndex: |
||
263 | deviceRptInfo.strings++; |
||
264 | break; |
||
265 | case HIDTag_StringMinimum: |
||
266 | case HIDTag_StringMaximum: |
||
267 | deviceRptInfo.stringRanges++; |
||
268 | break; |
||
269 | case HIDTag_DesignatorIndex: |
||
270 | deviceRptInfo.designators++; |
||
271 | break; |
||
272 | case HIDTag_DesignatorMinimum: |
||
273 | case HIDTag_DesignatorMaximum: |
||
274 | deviceRptInfo.designatorRanges++; |
||
275 | break; |
||
276 | default : |
||
277 | break; |
||
278 | } |
||
279 | break; |
||
280 | default : |
||
281 | break; |
||
282 | |||
283 | } |
||
284 | } |
||
285 | |||
286 | if(lhidError) |
||
287 | { |
||
288 | return(lhidError); |
||
289 | } |
||
290 | |||
291 | if (deviceRptInfo.collectionNesting != 0) return(HID_ERR_MissingEndCollection) /* HID_RPT_DESC_FORMAT_IMPROPER */; |
||
292 | |||
293 | if (deviceRptInfo.collections == 1) return(HID_ERR_MissingTopLevelCollection) /* HID_RPT_DESC_FORMAT_IMPROPER */; |
||
294 | |||
295 | if (deviceRptInfo.reportItems == 0) return(HID_ERR_NoReports)/* HID_RPT_DESC_FORMAT_IMPROPER */; |
||
296 | |||
297 | if ((deviceRptInfo.usageRanges & 1) == 1) return(HID_ERR_UnmatchedUsageRange)/* HID_RPT_DESC_FORMAT_IMPROPER */; |
||
298 | |||
299 | if ((deviceRptInfo.stringRanges & 1) == 1) return(HID_ERR_UnmatchedStringRange)/* HID_RPT_DESC_FORMAT_IMPROPER */; |
||
300 | |||
301 | if ((deviceRptInfo.designatorRanges & 1) == 1) return(HID_ERR_UnmatchedDesignatorRange)/* HID_RPT_DESC_FORMAT_IMPROPER */; |
||
302 | |||
303 | |||
304 | /* usages , strings & descriptors are in pair */ |
||
305 | deviceRptInfo.usages += (deviceRptInfo.usageRanges/2); |
||
306 | deviceRptInfo.strings += (deviceRptInfo.stringRanges/2); |
||
307 | deviceRptInfo.designators += (deviceRptInfo.designatorRanges/2); |
||
308 | |||
309 | /* Calculate space required */ |
||
310 | |||
311 | sizeRequired = (sizeof(HID_COLLECTION) * deviceRptInfo.collections) |
||
312 | + (sizeof(HID_REPORTITEM) * deviceRptInfo.reportItems) |
||
313 | + (sizeof(HID_REPORT) * deviceRptInfo.reports) |
||
314 | + (sizeof(HID_USAGEITEM) * deviceRptInfo.usages) |
||
315 | + (sizeof(HID_STRINGITEM) * deviceRptInfo.strings) |
||
316 | + (sizeof(HID_DESIGITEM) * deviceRptInfo.designators) |
||
317 | + (sizeof(int) * deviceRptInfo.maxCollectionNesting) |
||
318 | + (sizeof(HID_GLOBALS) * deviceRptInfo.maxGlobalsNesting); |
||
319 | |||
320 | if (parsedDataMem != NULL) |
||
321 | { |
||
322 | USB_FREE_AND_CLEAR( parsedDataMem ); |
||
323 | } |
||
324 | |||
325 | parsedDataMem = (BYTE*) USB_MALLOC(sizeRequired); |
||
326 | |||
327 | #ifdef DEBUG_MODE |
||
328 | UART2PrintString( "HID: Memory for Report Descriptor: " ); |
||
329 | UART2PutHex( sizeRequired ); |
||
330 | #endif |
||
331 | |||
332 | if (parsedDataMem == NULL) return(HID_ERR_NotEnoughMemory); /* Error: Not enough memory */ |
||
333 | assignMem = (BYTE*) parsedDataMem; |
||
334 | |||
335 | /* Allocate Space */ |
||
336 | itemListPtrs.collectionList = (HID_COLLECTION *) assignMem; |
||
337 | assignMem += (sizeof(HID_COLLECTION) * deviceRptInfo.collections); |
||
338 | itemListPtrs.reportItemList = (HID_REPORTITEM *) assignMem; |
||
339 | assignMem += (sizeof(HID_REPORTITEM) * deviceRptInfo.reportItems); |
||
340 | itemListPtrs.reportList = (HID_REPORT *) assignMem; |
||
341 | assignMem += (sizeof(HID_REPORT) * deviceRptInfo.reports); |
||
342 | itemListPtrs.usageItemList = (HID_USAGEITEM *) assignMem; |
||
343 | assignMem += (sizeof(HID_USAGEITEM) * deviceRptInfo.usages); |
||
344 | itemListPtrs.stringItemList = (HID_STRINGITEM *) assignMem; |
||
345 | assignMem += (sizeof(HID_STRINGITEM) * deviceRptInfo.strings); |
||
346 | itemListPtrs.designatorItemList = (HID_DESIGITEM *) assignMem; |
||
347 | assignMem += (sizeof(HID_DESIGITEM) * deviceRptInfo.designators); |
||
348 | itemListPtrs.collectionStack = (BYTE *) assignMem; |
||
349 | assignMem += (sizeof(int) * deviceRptInfo.maxCollectionNesting); |
||
350 | itemListPtrs.globalsStack = (HID_GLOBALS *) assignMem; |
||
351 | |||
352 | _USBHostHID_InitDeviceRptInfo(); |
||
353 | |||
354 | // Initialize the virtual collection |
||
355 | |||
356 | collectionLocal = itemListPtrs.collectionList; |
||
357 | collectionLocal->data = 0; |
||
358 | collectionLocal->firstChild = 0; |
||
359 | collectionLocal->firstReportItem = 0; |
||
360 | collectionLocal->firstUsageItem = 0; |
||
361 | collectionLocal->nextSibling = 0; |
||
362 | collectionLocal->parent = 0; |
||
363 | collectionLocal->reportItems = 0; |
||
364 | collectionLocal->usageItems = 0; |
||
365 | collectionLocal->usagePage = 0; |
||
366 | |||
367 | // Initialize the default report |
||
368 | |||
369 | reportLocal = itemListPtrs.reportList; |
||
370 | reportLocal->featureBits = 0; |
||
371 | reportLocal->inputBits = 0; |
||
372 | reportLocal->outputBits = 0; |
||
373 | reportLocal->reportID = 0; |
||
374 | |||
375 | /* re-init ptr to Rpt Descp & Length of Descp */ |
||
376 | len_to_be_parsed = lengthOfDescriptor; |
||
377 | currentRptDescPtr = hidReportDescriptor; |
||
378 | |||
379 | #ifdef DEBUG_MODE |
||
380 | UART2PrintString( "HID-HOST: ... 2nd Parse \n" ); |
||
381 | #endif |
||
382 | |||
383 | |||
384 | while(len_to_be_parsed > 0) /* Second parse to fill the tables with each item detail */ |
||
385 | { |
||
386 | item.ItemDetails.val = *currentRptDescPtr; |
||
387 | item.Data.uItemData = 0; |
||
388 | |||
389 | ldataSize = item.ItemDetails.ItemSize ; |
||
390 | if(item.ItemDetails.ItemSize == 3) |
||
391 | ldataSize = 4; |
||
392 | |||
393 | currentRptDescPtr++; /* ptr points to data */ |
||
394 | for (i = 0; i < ldataSize; i++) |
||
395 | { |
||
396 | dataByte = *currentRptDescPtr++; /* signed data will be taken care in ItemTag it is expected */ |
||
397 | item.Data.uItemData |= ((DWORD)dataByte << (i*8)); |
||
398 | } |
||
399 | |||
400 | len_to_be_parsed -= (ldataSize+1); /* remaining bytes = current - (length of current item + 1)*/ |
||
401 | |||
402 | switch(item.ItemDetails.ItemType) |
||
403 | { |
||
404 | case HIDType_Main: /* look for Main Items*/ |
||
405 | switch(item.ItemDetails.ItemTag) |
||
406 | { |
||
407 | case HIDTag_Input : |
||
408 | case HIDTag_Output : |
||
409 | case HIDTag_Feature : |
||
410 | lhidError = _USBHostHID_Parse_ReportType(&item); |
||
411 | break; |
||
412 | |||
413 | case HIDTag_Collection : |
||
414 | _USBHostHID_Parse_Collection(&item); |
||
415 | break; |
||
416 | |||
417 | case HIDTag_EndCollection : |
||
418 | _USBHostHID_Parse_EndCollection(&item); |
||
419 | break; |
||
420 | } |
||
421 | break; |
||
422 | |||
423 | case HIDType_Global: /* look for Global Items*/ |
||
424 | switch(item.ItemDetails.ItemTag) |
||
425 | { |
||
426 | case HIDTag_UsagePage : |
||
427 | deviceRptInfo.globals.usagePage = item.Data.uItemData; |
||
428 | break; |
||
429 | |||
430 | case HIDTag_LogicalMinimum : /* convert to signed val */ |
||
431 | // Sign extend one value |
||
432 | _USBHostHID_ConvertDataToSigned(&item); |
||
433 | deviceRptInfo.globals.logicalMinimum = item.Data.sItemData; |
||
434 | break; |
||
435 | |||
436 | case HIDTag_LogicalMaximum :/* convert to signed val */ |
||
437 | // Sign extend one value |
||
438 | _USBHostHID_ConvertDataToSigned(&item); |
||
439 | deviceRptInfo.globals.logicalMaximum = item.Data.uItemData; |
||
440 | break; |
||
441 | |||
442 | case HIDTag_PhysicalMinimum :/* convert to signed val */ |
||
443 | // Sign extend one value |
||
444 | _USBHostHID_ConvertDataToSigned(&item); |
||
445 | deviceRptInfo.globals.physicalMinimum = item.Data.uItemData; |
||
446 | break; |
||
447 | |||
448 | case HIDTag_PhysicalMaximum :/* convert to signed val */ |
||
449 | // Sign extend one value |
||
450 | _USBHostHID_ConvertDataToSigned(&item); |
||
451 | deviceRptInfo.globals.physicalMaximum = item.Data.uItemData; |
||
452 | break; |
||
453 | |||
454 | case HIDTag_UnitExponent : |
||
455 | deviceRptInfo.globals.unitExponent = item.Data.uItemData; |
||
456 | break; |
||
457 | |||
458 | case HIDTag_ReportSize : |
||
459 | deviceRptInfo.globals.reportsize = item.Data.uItemData; |
||
460 | if (deviceRptInfo.globals.reportsize == 0) |
||
461 | lhidError = HID_ERR_ZeroReportSize; |
||
462 | break; |
||
463 | |||
464 | case HIDTag_ReportID : |
||
465 | if (item.Data.uItemData) |
||
466 | { |
||
467 | // Look for the Report ID in the table |
||
468 | |||
469 | lreportIndex = 0; |
||
470 | while ((lreportIndex < deviceRptInfo.reports) |
||
471 | && (itemListPtrs.reportList[lreportIndex].reportID != item.Data.uItemData)) |
||
472 | lreportIndex++; |
||
473 | |||
474 | // initialize the entry if it's new and there's room for it |
||
475 | // Start with 8 bits for the Report ID |
||
476 | |||
477 | if (lreportIndex == deviceRptInfo.reports) |
||
478 | { |
||
479 | lreport = &itemListPtrs.reportList[deviceRptInfo.reports++]; |
||
480 | lreport->reportID = item.Data.uItemData; |
||
481 | lreport->inputBits = 8; |
||
482 | lreport->outputBits = 8; |
||
483 | lreport->featureBits = 8; |
||
484 | } |
||
485 | |||
486 | // remember which report is being processed |
||
487 | |||
488 | deviceRptInfo.globals.reportID = item.Data.uItemData; |
||
489 | deviceRptInfo.globals.reportIndex = lreportIndex; |
||
490 | } |
||
491 | else |
||
492 | { |
||
493 | lhidError = HID_ERR_ZeroReportID; |
||
494 | } |
||
495 | break; |
||
496 | |||
497 | case HIDTag_ReportCount : |
||
498 | if (item.Data.uItemData) |
||
499 | { |
||
500 | deviceRptInfo.globals.reportCount = item.Data.uItemData; |
||
501 | } |
||
502 | else |
||
503 | { |
||
504 | lhidError = HID_ERR_ZeroReportCount; |
||
505 | } |
||
506 | break; |
||
507 | |||
508 | case HIDTag_Push : |
||
509 | itemListPtrs.globalsStack[deviceRptInfo.globalsNesting++] = deviceRptInfo.globals; |
||
510 | break; |
||
511 | |||
512 | case HIDTag_Pop : |
||
513 | deviceRptInfo.globals = itemListPtrs.globalsStack[--deviceRptInfo.globalsNesting] ; |
||
514 | break; |
||
515 | |||
516 | } |
||
517 | break; |
||
518 | |||
519 | case HIDType_Local: /* look for Local Items*/ |
||
520 | switch(item.ItemDetails.ItemTag) |
||
521 | { |
||
522 | case HIDTag_Usage : |
||
523 | lusageItem = &itemListPtrs.usageItemList[deviceRptInfo.usageItems++]; |
||
524 | lusageItem->isRange = FALSE; |
||
525 | if (item.ItemDetails.ItemSize == 3) /* 4 data bytes */ |
||
526 | { |
||
527 | lusageItem->usagePage = item.Data.uItemData >> 16; |
||
528 | lusageItem->usage = item.Data.uItemData & 0x00FF; |
||
529 | } |
||
530 | else |
||
531 | { |
||
532 | lusageItem->usagePage = deviceRptInfo.globals.usagePage; |
||
533 | lusageItem->usage = item.Data.uItemData; |
||
534 | } |
||
535 | break; |
||
536 | |||
537 | case HIDTag_UsageMinimum : |
||
538 | if(deviceRptInfo.haveUsageMax) |
||
539 | { |
||
540 | lusageItem = &itemListPtrs.usageItemList[deviceRptInfo.usageItems++]; |
||
541 | lusageItem->isRange = TRUE; |
||
542 | if(item.ItemDetails.ItemSize == 3) |
||
543 | { |
||
544 | lusageItem->usagePage = item.Data.uItemData >> 16; |
||
545 | lusageItem->usageMinimum = item.Data.uItemData & 0x00FFL; |
||
546 | } |
||
547 | else |
||
548 | { |
||
549 | lusageItem->usagePage = deviceRptInfo.globals.usagePage; |
||
550 | lusageItem->usageMinimum = item.Data.uItemData; |
||
551 | } |
||
552 | |||
553 | if (lusageItem->usagePage != deviceRptInfo.rangeUsagePage); |
||
554 | lhidError = HID_ERR_BadUsageRangePage; /* Error: BadUsageRangePage */ |
||
555 | |||
556 | lusageItem->usageMaximum = deviceRptInfo.usageMaximum; |
||
557 | |||
558 | if (lusageItem->usageMaximum < lusageItem->usageMinimum) |
||
559 | lhidError = HID_ERR_BadUsageRange; /* Error: BadUsageRange */ |
||
560 | |||
561 | deviceRptInfo.haveUsageMax = FALSE; |
||
562 | deviceRptInfo.haveUsageMin = FALSE; |
||
563 | } |
||
564 | else |
||
565 | { |
||
566 | if(item.ItemDetails.ItemSize == 3) |
||
567 | { |
||
568 | deviceRptInfo.rangeUsagePage = item.Data.uItemData >> 16; |
||
569 | deviceRptInfo.usageMinimum = item.Data.uItemData & 0x00FFL; |
||
570 | } |
||
571 | else |
||
572 | { |
||
573 | deviceRptInfo.rangeUsagePage = deviceRptInfo.globals.usagePage; |
||
574 | deviceRptInfo.usageMinimum = item.Data.uItemData; |
||
575 | } |
||
576 | |||
577 | deviceRptInfo.haveUsageMin = TRUE; |
||
578 | } |
||
579 | break; |
||
580 | |||
581 | case HIDTag_UsageMaximum : |
||
582 | if(deviceRptInfo.haveUsageMin) |
||
583 | { |
||
584 | lusageItem = &itemListPtrs.usageItemList[deviceRptInfo.usageItems++]; |
||
585 | lusageItem->isRange = TRUE; |
||
586 | if(item.ItemDetails.ItemSize == 3) |
||
587 | { |
||
588 | lusageItem->usagePage = item.Data.uItemData >> 16; |
||
589 | lusageItem->usageMaximum = item.Data.uItemData & 0x00FFL; |
||
590 | } |
||
591 | else |
||
592 | { |
||
593 | lusageItem->usagePage = deviceRptInfo.globals.usagePage; |
||
594 | lusageItem->usageMaximum = item.Data.uItemData; |
||
595 | } |
||
596 | |||
597 | if (lusageItem->usagePage != deviceRptInfo.rangeUsagePage) |
||
598 | lhidError = HID_ERR_BadUsageRangePage; /* Error: BadUsageRangePage */ |
||
599 | |||
600 | lusageItem->usageMinimum = deviceRptInfo.usageMinimum; |
||
601 | |||
602 | if (lusageItem->usageMaximum < lusageItem->usageMinimum) |
||
603 | lhidError = HID_ERR_BadUsageRange; /* Error: BadUsageRange */ |
||
604 | |||
605 | deviceRptInfo.haveUsageMax = FALSE; |
||
606 | deviceRptInfo.haveUsageMin = FALSE; |
||
607 | } |
||
608 | else |
||
609 | { |
||
610 | if(item.ItemDetails.ItemSize == 3) |
||
611 | { |
||
612 | deviceRptInfo.rangeUsagePage = item.Data.uItemData >> 16; |
||
613 | deviceRptInfo.usageMaximum = item.Data.uItemData & 0x00FFL; |
||
614 | } |
||
615 | else |
||
616 | { |
||
617 | deviceRptInfo.rangeUsagePage = deviceRptInfo.globals.usagePage; |
||
618 | deviceRptInfo.usageMaximum = item.Data.uItemData; |
||
619 | } |
||
620 | |||
621 | deviceRptInfo.haveUsageMax = TRUE; |
||
622 | } |
||
623 | break; |
||
624 | |||
625 | case HIDTag_DesignatorIndex : |
||
626 | ldesignatorItem = &itemListPtrs.designatorItemList[deviceRptInfo.designatorItems++]; |
||
627 | ldesignatorItem->isRange = FALSE; |
||
628 | ldesignatorItem->index = item.Data.uItemData; |
||
629 | |||
630 | break; |
||
631 | |||
632 | case HIDTag_DesignatorMinimum : |
||
633 | if(deviceRptInfo.haveDesignatorMax) |
||
634 | { |
||
635 | ldesignatorItem = &itemListPtrs.designatorItemList[deviceRptInfo.designatorItems++]; |
||
636 | ldesignatorItem->isRange = TRUE; |
||
637 | ldesignatorItem->minimum = item.Data.uItemData; |
||
638 | ldesignatorItem->maximum = deviceRptInfo.designatorMaximum; |
||
639 | deviceRptInfo.haveDesignatorMin = FALSE; |
||
640 | deviceRptInfo.haveDesignatorMax = FALSE; |
||
641 | } |
||
642 | else |
||
643 | { |
||
644 | deviceRptInfo.designatorMinimum = item.Data.uItemData; |
||
645 | deviceRptInfo.haveDesignatorMin = TRUE; |
||
646 | } |
||
647 | break; |
||
648 | |||
649 | case HIDTag_DesignatorMaximum : |
||
650 | if(deviceRptInfo.haveDesignatorMin) |
||
651 | { |
||
652 | ldesignatorItem = &itemListPtrs.designatorItemList[deviceRptInfo.designatorItems++]; |
||
653 | ldesignatorItem->isRange = TRUE; |
||
654 | ldesignatorItem->maximum = item.Data.uItemData; |
||
655 | ldesignatorItem->minimum = deviceRptInfo.designatorMinimum; |
||
656 | deviceRptInfo.haveDesignatorMin = FALSE; |
||
657 | deviceRptInfo.haveDesignatorMax = FALSE; |
||
658 | } |
||
659 | else |
||
660 | { |
||
661 | deviceRptInfo.designatorMaximum = item.Data.uItemData; |
||
662 | deviceRptInfo.haveDesignatorMax = TRUE; |
||
663 | } |
||
664 | break; |
||
665 | |||
666 | case HIDTag_StringIndex : |
||
667 | lstringItem = &itemListPtrs.stringItemList[deviceRptInfo.stringItems++]; |
||
668 | lstringItem->isRange = FALSE; |
||
669 | lstringItem->index = item.Data.uItemData; |
||
670 | break; |
||
671 | |||
672 | case HIDTag_StringMinimum : |
||
673 | if (deviceRptInfo.haveStringMax) { |
||
674 | lstringItem = &itemListPtrs.stringItemList[deviceRptInfo.stringItems++]; |
||
675 | lstringItem->isRange = TRUE; |
||
676 | lstringItem->minimum = item.Data.uItemData; |
||
677 | lstringItem->maximum = deviceRptInfo.stringMaximum; |
||
678 | deviceRptInfo.haveStringMin = FALSE; |
||
679 | deviceRptInfo.haveStringMax = FALSE; |
||
680 | } |
||
681 | else { |
||
682 | deviceRptInfo.stringMinimum = item.Data.uItemData; |
||
683 | deviceRptInfo.haveStringMin = TRUE; |
||
684 | } |
||
685 | break; |
||
686 | |||
687 | case HIDTag_StringMaximum : |
||
688 | if (deviceRptInfo.haveStringMin) { |
||
689 | lstringItem = &itemListPtrs.stringItemList[deviceRptInfo.stringItems++]; |
||
690 | lstringItem->isRange = TRUE; |
||
691 | lstringItem->maximum = item.Data.uItemData; |
||
692 | lstringItem->minimum = deviceRptInfo.stringMinimum; |
||
693 | deviceRptInfo.haveStringMin = FALSE; |
||
694 | deviceRptInfo.haveStringMax = FALSE; |
||
695 | } |
||
696 | else { |
||
697 | deviceRptInfo.stringMaximum = item.Data.uItemData; |
||
698 | deviceRptInfo.haveStringMax = TRUE; |
||
699 | } |
||
700 | break; |
||
701 | break; |
||
702 | |||
703 | case HIDTag_SetDelimiter : |
||
704 | break; |
||
705 | |||
706 | } |
||
707 | |||
708 | break; |
||
709 | |||
710 | default: |
||
711 | break; |
||
712 | } |
||
713 | /* during 2nd parse if any anomaly is found in report format abort parsing and return */ |
||
714 | if(lhidError) |
||
715 | { |
||
716 | return(lhidError); |
||
717 | } |
||
718 | } |
||
719 | |||
720 | // Update the virtual collection |
||
721 | |||
722 | // itemListPtrs.collectionList[0].reportItems = deviceRptInfo.reportItems; |
||
723 | |||
724 | // Remove reports that have just the report id |
||
725 | |||
726 | for (i=1; i<deviceRptInfo.reports; i++) { |
||
727 | if (itemListPtrs.reportList[i].inputBits == 8) itemListPtrs.reportList[i].inputBits = 0; |
||
728 | if (itemListPtrs.reportList[i].outputBits == 8) itemListPtrs.reportList[i].outputBits = 0; |
||
729 | if (itemListPtrs.reportList[i].featureBits == 8) itemListPtrs.reportList[i].featureBits = 0; |
||
730 | } |
||
731 | |||
732 | return(lhidError); |
||
733 | } |
||
734 | |||
735 | /**************************************************************************** |
||
736 | Function: |
||
737 | static void _USBHostHID_InitDeviceRptInfo(void) |
||
738 | |||
739 | Description: |
||
740 | This function is called by _USBHostHID_Parse_Report() to Initialize |
||
741 | report information to default value before every parse. Note that not |
||
742 | all values are reset. |
||
743 | |||
744 | Precondition: |
||
745 | None |
||
746 | |||
747 | Parameters: |
||
748 | None |
||
749 | |||
750 | Return Values: |
||
751 | None |
||
752 | |||
753 | Remarks: |
||
754 | None |
||
755 | ***************************************************************************/ |
||
756 | static void _USBHostHID_InitDeviceRptInfo(void) |
||
757 | { |
||
758 | deviceRptInfo.collectionNesting = 0; |
||
759 | deviceRptInfo.collections = 1; |
||
760 | deviceRptInfo.designatorRanges = 0; |
||
761 | deviceRptInfo.designators = 0; |
||
762 | deviceRptInfo.globalsNesting = 0; |
||
763 | deviceRptInfo.maxCollectionNesting = 0; |
||
764 | deviceRptInfo.maxGlobalsNesting = 0; |
||
765 | deviceRptInfo.reportItems = 0; |
||
766 | deviceRptInfo.reports = 1; |
||
767 | deviceRptInfo.stringRanges = 0; |
||
768 | deviceRptInfo.strings = 0; |
||
769 | deviceRptInfo.usages = 0; |
||
770 | deviceRptInfo.usageRanges = 0; |
||
771 | deviceRptInfo.usageItems = 0; |
||
772 | |||
773 | deviceRptInfo.haveDesignatorMax = FALSE; |
||
774 | deviceRptInfo.haveDesignatorMin = FALSE; |
||
775 | deviceRptInfo.haveStringMax = FALSE; |
||
776 | deviceRptInfo.haveStringMin = FALSE; |
||
777 | deviceRptInfo.haveUsageMax = FALSE; |
||
778 | deviceRptInfo.haveUsageMin = FALSE; |
||
779 | |||
780 | deviceRptInfo.globals.logicalMaximum = 0; |
||
781 | deviceRptInfo.globals.logicalMinimum = 0; |
||
782 | deviceRptInfo.globals.physicalMaximum = 0; |
||
783 | deviceRptInfo.globals.physicalMinimum = 0; |
||
784 | deviceRptInfo.globals.reportCount = 0; |
||
785 | deviceRptInfo.globals.reportID = 0; |
||
786 | deviceRptInfo.globals.reportIndex = 0; |
||
787 | deviceRptInfo.globals.reportsize = 0; |
||
788 | deviceRptInfo.globals.unit = 0; |
||
789 | deviceRptInfo.globals.unitExponent = 0; |
||
790 | deviceRptInfo.globals.usagePage = 0; |
||
791 | } |
||
792 | |||
793 | |||
794 | /**************************************************************************** |
||
795 | Function: |
||
796 | static void _USBHostHID_Parse_Collection(HID_ITEM_INFO* ptrItem) |
||
797 | |||
798 | Description: |
||
799 | This function is called by _USBHostHID_Parse_Report() to parse |
||
800 | collection item. |
||
801 | |||
802 | Precondition: |
||
803 | None |
||
804 | |||
805 | Parameters: |
||
806 | HID_ITEM_INFO* ptrItem - pointer to item structure containg raw |
||
807 | information from the report |
||
808 | Return Values: |
||
809 | None |
||
810 | |||
811 | Remarks: |
||
812 | None |
||
813 | ***************************************************************************/ |
||
814 | static void _USBHostHID_Parse_Collection(HID_ITEM_INFO* ptrItem) |
||
815 | { |
||
816 | HID_COLLECTION *lcollection; |
||
817 | WORD i; |
||
818 | |||
819 | // Initialize the new Collection Structure |
||
820 | |||
821 | i = deviceRptInfo.collections++; |
||
822 | lcollection = &itemListPtrs.collectionList[i]; |
||
823 | lcollection->data = ptrItem->Data.uItemData; |
||
824 | lcollection->firstUsageItem = deviceRptInfo.firstUsageItem; |
||
825 | lcollection->usageItems = deviceRptInfo.usageItems - deviceRptInfo.firstUsageItem; |
||
826 | deviceRptInfo.firstUsageItem = deviceRptInfo.usageItems; |
||
827 | lcollection->nextSibling = deviceRptInfo.sibling; |
||
828 | deviceRptInfo.sibling = 0; |
||
829 | lcollection->firstChild = 0; |
||
830 | lcollection->usagePage = deviceRptInfo.globals.usagePage; |
||
831 | lcollection->firstReportItem = deviceRptInfo.reportItems; |
||
832 | |||
833 | // Set up the relationship with the Parent Collection |
||
834 | |||
835 | lcollection->parent = deviceRptInfo.parent; |
||
836 | itemListPtrs.collectionList[deviceRptInfo.parent].firstChild = i; |
||
837 | |||
838 | // Save the Parent Collection Information on the stack |
||
839 | itemListPtrs.collectionStack[deviceRptInfo.collectionNesting++] = deviceRptInfo.parent; |
||
840 | deviceRptInfo.parent = i; |
||
841 | } |
||
842 | |||
843 | /**************************************************************************** |
||
844 | Function: |
||
845 | static void _USBHostHID_Parse_EndCollection(HID_ITEM_INFO* ptrItem) |
||
846 | |||
847 | Description: |
||
848 | This function is called by _USBHostHID_Parse_Report() to parse end of |
||
849 | collection item. |
||
850 | |||
851 | Precondition: |
||
852 | None |
||
853 | |||
854 | Parameters: |
||
855 | HID_ITEM_INFO* ptrItem - pointer to item structure containg raw |
||
856 | information from the report |
||
857 | Return Values: |
||
858 | None |
||
859 | |||
860 | Remarks: |
||
861 | None |
||
862 | ***************************************************************************/ |
||
863 | static void _USBHostHID_Parse_EndCollection(HID_ITEM_INFO* ptrItem) |
||
864 | { |
||
865 | HID_COLLECTION *lcollection; |
||
866 | BYTE i; |
||
867 | |||
868 | // Remember the number of reportItem MainItems in this Collection |
||
869 | |||
870 | lcollection = &itemListPtrs.collectionList[deviceRptInfo.parent]; |
||
871 | lcollection->reportItems = deviceRptInfo.reportItems - lcollection->firstReportItem; |
||
872 | |||
873 | // Restore the Parent Collection Data |
||
874 | |||
875 | i = itemListPtrs.collectionStack[--deviceRptInfo.collectionNesting]; |
||
876 | deviceRptInfo.sibling = deviceRptInfo.parent; |
||
877 | deviceRptInfo.parent = i; |
||
878 | } |
||
879 | |||
880 | /**************************************************************************** |
||
881 | Function: |
||
882 | static USB_HID_RPT_DESC_ERROR _USBHostHID_Parse_ReportType(HID_ITEM_INFO* item) |
||
883 | |||
884 | Description: |
||
885 | This function is called by _USBHostHID_Parse_Report() to parse |
||
886 | input, output & report item. |
||
887 | |||
888 | Precondition: |
||
889 | None |
||
890 | |||
891 | Parameters: |
||
892 | HID_ITEM_INFO* ptrItem - pointer to item structure containg raw |
||
893 | information from the report |
||
894 | |||
895 | Return Values: |
||
896 | USB_HID_RPT_DESC_ERROR - Returns error code if any error is encountered |
||
897 | in report descriptor. |
||
898 | |||
899 | Remarks: |
||
900 | None |
||
901 | ***************************************************************************/ |
||
902 | static USB_HID_RPT_DESC_ERROR _USBHostHID_Parse_ReportType(HID_ITEM_INFO* item) |
||
903 | { |
||
904 | HID_REPORTITEM *lreportItem = NULL; |
||
905 | HID_REPORT *lreport = NULL; |
||
906 | WORD bits = 0; |
||
907 | |||
908 | if(item == NULL) |
||
909 | return(HID_ERR_NullPointer); |
||
910 | |||
911 | // Reality Check on the Report Main Item |
||
912 | |||
913 | if (deviceRptInfo.globals.logicalMinimum >= ((LONG)1<<deviceRptInfo.globals.reportsize)) return(HID_ERR_BadLogicalMin) ; |
||
914 | if (deviceRptInfo.globals.logicalMaximum >= ((LONG)1<<deviceRptInfo.globals.reportsize))return(HID_ERR_BadLogicalMax); |
||
915 | // The barcode scanner has this issue. We'll ignore it. |
||
916 | // if (deviceRptInfo.globals.logicalMinimum > deviceRptInfo.globals.logicalMaximum)return(HID_ERR_BadLogical); |
||
917 | if (deviceRptInfo.haveUsageMin || deviceRptInfo.haveUsageMax)return(HID_ERR_UnmatchedUsageRange); |
||
918 | if (deviceRptInfo.haveStringMin || deviceRptInfo.haveStringMax)return(HID_ERR_UnmatchedStringRange); |
||
919 | if (deviceRptInfo.haveDesignatorMin || deviceRptInfo.haveDesignatorMax)return(HID_ERR_UnmatchedDesignatorRange); |
||
920 | |||
921 | // Initialize the new Report Item structure |
||
922 | |||
923 | lreportItem = &itemListPtrs.reportItemList[deviceRptInfo.reportItems++]; |
||
924 | lreportItem->dataModes = item->Data.uItemData; |
||
925 | lreportItem->globals = deviceRptInfo.globals; |
||
926 | lreportItem->parent = deviceRptInfo.parent; |
||
927 | lreportItem->firstUsageItem = deviceRptInfo.firstUsageItem; |
||
928 | deviceRptInfo.firstUsageItem = deviceRptInfo.usageItems; |
||
929 | lreportItem->usageItems = deviceRptInfo.usageItems - lreportItem->firstUsageItem; |
||
930 | lreportItem->firstStringItem = deviceRptInfo.firstStringItem; |
||
931 | deviceRptInfo.firstStringItem = deviceRptInfo.stringItems; |
||
932 | lreportItem->stringItems = deviceRptInfo.stringItems - lreportItem->firstStringItem; |
||
933 | lreportItem->firstDesignatorItem = deviceRptInfo.firstDesignatorItem; |
||
934 | deviceRptInfo.firstDesignatorItem = deviceRptInfo.designatorItems; |
||
935 | lreportItem->designatorItems = deviceRptInfo.designatorItems - lreportItem->firstDesignatorItem; |
||
936 | |||
937 | // Update the Report by the size of this item |
||
938 | |||
939 | lreport = &itemListPtrs.reportList[deviceRptInfo.globals.reportIndex]; |
||
940 | bits = deviceRptInfo.globals.reportsize * deviceRptInfo.globals.reportCount; |
||
941 | switch (item->ItemDetails.ItemTag) |
||
942 | { |
||
943 | case HIDTag_Feature: |
||
944 | lreportItem->reportType = hidReportFeature; |
||
945 | lreportItem->startBit = lreport->featureBits; |
||
946 | lreport->featureBits += bits; |
||
947 | break; |
||
948 | case HIDTag_Output: |
||
949 | lreportItem->reportType = hidReportOutput; |
||
950 | lreportItem->startBit = lreport->outputBits; |
||
951 | lreport->outputBits += bits; |
||
952 | break; |
||
953 | case HIDTag_Input: |
||
954 | lreportItem->reportType = hidReportInput; |
||
955 | lreportItem->startBit = lreport->inputBits; |
||
956 | lreport->inputBits += bits; |
||
957 | break; |
||
958 | default: |
||
959 | lreportItem->reportType = hidReportUnknown; |
||
960 | break; |
||
961 | } |
||
962 | |||
963 | return HID_ERR; |
||
964 | } |
||
965 | |||
966 | /**************************************************************************** |
||
967 | Function: |
||
968 | static void _USBHostHID_ConvertDataToSigned(HID_ITEM_INFO* item) |
||
969 | |||
970 | Description: |
||
971 | This function is called by _USBHostHID_Parse_Report() convert data |
||
972 | to signed whenever required |
||
973 | |||
974 | Precondition: |
||
975 | None |
||
976 | |||
977 | Parameters: |
||
978 | HID_ITEM_INFO* ptrItem - pointer to item structure containg raw |
||
979 | information from the report |
||
980 | |||
981 | Return Values: |
||
982 | None |
||
983 | |||
984 | Remarks: |
||
985 | None |
||
986 | ***************************************************************************/ |
||
987 | static void _USBHostHID_ConvertDataToSigned(HID_ITEM_INFO* item) |
||
988 | { |
||
989 | BYTE dataByte=0; |
||
990 | BYTE index; |
||
991 | |||
992 | index = item->ItemDetails.ItemSize; |
||
993 | |||
994 | if(index) |
||
995 | { |
||
996 | if(item->ItemDetails.ItemSize == 3) |
||
997 | index = 4; |
||
998 | |||
999 | dataByte = item->Data.bItemData[index-1]; |
||
1000 | if ((dataByte & 0x80) != 0) |
||
1001 | { |
||
1002 | while (index < sizeof(LONG)) |
||
1003 | item->Data.sItemData |= (0xFF << ((index++)*8)); /* extend one */ |
||
1004 | } |
||
1005 | } |
||
1006 | } |
||
1007 | |||
1008 | |||
1009 | /**************************************************************************** |
||
1010 | Function: |
||
1011 | BOOL USBHostHID_HasUsage(HID_REPORTITEM *reportItem,WORD usagePage, |
||
1012 | WORD usage,WORD *pindex) |
||
1013 | |||
1014 | Description: |
||
1015 | This function is used to locate the usage in a report descriptor. |
||
1016 | Function will look into the data structures created by the HID parser |
||
1017 | and return the appropriate location. |
||
1018 | |||
1019 | Precondition: |
||
1020 | None |
||
1021 | |||
1022 | Parameters: |
||
1023 | HID_REPORTITEM *reportItem - Report item index to be searched |
||
1024 | WORD usagePage - Application needs to pass the usagePage as |
||
1025 | the search criteria for the usage |
||
1026 | WORD usage - Application needs to pass the usageto be |
||
1027 | searched |
||
1028 | WORD *pindex - returns index to the usage item requested. |
||
1029 | |||
1030 | Return Values: |
||
1031 | BOOL - FALSE - If requested usage is not found |
||
1032 | TRUE - if requested usage is found |
||
1033 | Remarks: |
||
1034 | None |
||
1035 | ***************************************************************************/ |
||
1036 | BOOL USBHostHID_HasUsage(HID_REPORTITEM *reportItem,WORD usagePage, WORD usage,WORD *pindex,BYTE* count) |
||
1037 | { |
||
1038 | HID_USAGEITEM *hidUsageItem; |
||
1039 | WORD usageIndex; |
||
1040 | SHORT usages; |
||
1041 | BOOL onPage; |
||
1042 | BYTE usageItem; |
||
1043 | BYTE countsLeft; |
||
1044 | BYTE i; |
||
1045 | |||
1046 | // Disallow Null Pointers |
||
1047 | |||
1048 | if ((reportItem == NULL)|(pindex == NULL)) |
||
1049 | return FALSE; |
||
1050 | |||
1051 | // Look through the Usage Items for this Usage |
||
1052 | |||
1053 | usageItem = reportItem->firstUsageItem; |
||
1054 | usageIndex = 0; |
||
1055 | for (i=0; i<reportItem->usageItems; i++) { |
||
1056 | // Each Usage Item is either a Usage or a Usage Range |
||
1057 | |||
1058 | hidUsageItem = &itemListPtrs.usageItemList[usageItem++]; |
||
1059 | onPage = ((usagePage == 0) || (usagePage == hidUsageItem->usagePage)); |
||
1060 | if (hidUsageItem->isRange) |
||
1061 | { |
||
1062 | // For Usage Ranges |
||
1063 | // If the index is in the range |
||
1064 | // then return the Usage |
||
1065 | // Otherwise adjust the index by the size of the range |
||
1066 | |||
1067 | if ((usage >= hidUsageItem->usageMinimum)&& (usage <= hidUsageItem->usageMaximum)) |
||
1068 | { |
||
1069 | if (pindex != NULL) |
||
1070 | *pindex = usageIndex + (usage - hidUsageItem->usageMinimum); |
||
1071 | |||
1072 | // If this usage is the last one for this reportItem |
||
1073 | // then it gets all of the remaining ReportCount |
||
1074 | |||
1075 | if (count != NULL) |
||
1076 | { |
||
1077 | if (((i+1) == reportItem->usageItems)&& (usage == hidUsageItem->usageMaximum)) |
||
1078 | { |
||
1079 | countsLeft = reportItem->globals.reportCount - usageIndex; |
||
1080 | if (countsLeft > 1) |
||
1081 | *count = countsLeft; |
||
1082 | else |
||
1083 | *count = 1; |
||
1084 | } |
||
1085 | else |
||
1086 | *count = 1; |
||
1087 | } |
||
1088 | if(onPage) |
||
1089 | return TRUE; |
||
1090 | } |
||
1091 | usages = hidUsageItem->usageMaximum - hidUsageItem->usageMinimum + 1; |
||
1092 | if (usages < 0) usages = -usages; |
||
1093 | usageIndex += usages; |
||
1094 | } |
||
1095 | else |
||
1096 | { |
||
1097 | // For Usages |
||
1098 | // If the index is zero |
||
1099 | // then return this Usage |
||
1100 | // Otherwise one less to index through |
||
1101 | |||
1102 | if (usage == hidUsageItem->usage) |
||
1103 | { |
||
1104 | if (pindex != NULL) |
||
1105 | *pindex = usageIndex; |
||
1106 | if (count != NULL) |
||
1107 | { |
||
1108 | if ((i+1) == reportItem->usageItems) |
||
1109 | { |
||
1110 | countsLeft = reportItem->globals.reportCount - usageIndex; |
||
1111 | if (countsLeft > 1) |
||
1112 | *count = countsLeft; |
||
1113 | else |
||
1114 | *count = 1; |
||
1115 | } |
||
1116 | else |
||
1117 | *count = 1; |
||
1118 | } |
||
1119 | if (onPage) |
||
1120 | return TRUE; |
||
1121 | } |
||
1122 | usageIndex++; |
||
1123 | } |
||
1124 | } |
||
1125 | return FALSE; |
||
1126 | } |
||
1127 | |||
1128 | #ifdef DEBUG_MODE |
||
1129 | void USBHID_ReportDecriptor_Dump(void) |
||
1130 | { |
||
1131 | HID_COLLECTION *lcollection; |
||
1132 | HID_REPORT *lreport; |
||
1133 | HID_REPORTITEM *lreportItem; |
||
1134 | HID_USAGEITEM *lusageItem; |
||
1135 | WORD j; |
||
1136 | BYTE i; |
||
1137 | |||
1138 | |||
1139 | UART2PrintString("\r\n ======================= Report Descriptor Dump ======================= \n\n"); |
||
1140 | |||
1141 | UART2PrintString("\r\nCollections: "); |
||
1142 | UART2PutHex( deviceRptInfo.collections ); |
||
1143 | |||
1144 | UART2PrintString("\r\nMax Nesting: "); |
||
1145 | UART2PutHex( deviceRptInfo.maxCollectionNesting ); |
||
1146 | |||
1147 | UART2PrintString("\r\nReports: "); |
||
1148 | UART2PutHex( deviceRptInfo.reports ); |
||
1149 | |||
1150 | UART2PrintString("\r\nReportItems: "); |
||
1151 | UART2PutHex( deviceRptInfo.reportItems ); |
||
1152 | |||
1153 | UART2PrintString("\r\nUsageItems: "); |
||
1154 | UART2PutHex( deviceRptInfo.usageItems ); |
||
1155 | |||
1156 | for (i=0;i<deviceRptInfo.collections;i++) |
||
1157 | { |
||
1158 | UART2PrintString("\n\r------------------------\n"); |
||
1159 | UART2PrintString("\r\nCollection : ");UART2PutHex(i); |
||
1160 | lcollection = &itemListPtrs.collectionList[i]; |
||
1161 | UART2PrintString("\r\n Data : "); |
||
1162 | UART2PutHex( lcollection->data); |
||
1163 | UART2PrintString("\r\n Usage Page : "); |
||
1164 | UART2PutHex( lcollection->usagePage); |
||
1165 | UART2PrintString("\r\n 1st Usage Item : "); |
||
1166 | UART2PutHex( lcollection->firstUsageItem); |
||
1167 | UART2PrintString("\r\n # Usage Items : "); |
||
1168 | UART2PutHex( lcollection->usageItems); |
||
1169 | UART2PrintString("\r\n 1st Report Item : "); |
||
1170 | UART2PutHex( lcollection->firstReportItem); |
||
1171 | UART2PrintString("\r\n # Report Items : "); |
||
1172 | UART2PutHex( lcollection->reportItems); |
||
1173 | UART2PrintString("\r\n Parent : "); |
||
1174 | UART2PutHex( lcollection->parent); |
||
1175 | UART2PrintString("\r\n 1st Child : "); |
||
1176 | UART2PutHex( lcollection->firstChild); |
||
1177 | UART2PrintString("\r\n Next Sibling : "); |
||
1178 | UART2PutHex( lcollection->nextSibling); |
||
1179 | } |
||
1180 | |||
1181 | |||
1182 | for (i=0; i<deviceRptInfo.reports; i++) |
||
1183 | { |
||
1184 | UART2PrintString("\n------------------------\n"); |
||
1185 | UART2PrintString("\r\nReport : ");UART2PutHex(i); |
||
1186 | lreport = &itemListPtrs.reportList[i]; |
||
1187 | UART2PrintString("\r\nReportID : ");UART2PutHex(lreport->reportID); |
||
1188 | if (lreport->inputBits > 0) |
||
1189 | UART2PrintString("\r\nInbits : ");UART2PutHex(lreport->inputBits); |
||
1190 | if (lreport->outputBits > 0) |
||
1191 | UART2PrintString("\r\nOutbits : ");UART2PutHex(lreport->outputBits); |
||
1192 | if (lreport->featureBits > 0) |
||
1193 | UART2PrintString("\r\nFeatbits : ");UART2PutHex(lreport->featureBits); |
||
1194 | } |
||
1195 | for (i=0; i<deviceRptInfo.reportItems; i++) { |
||
1196 | // getchar(); |
||
1197 | UART2PrintString("\n------------------------\n"); |
||
1198 | UART2PrintString("\r\nReportItem : ");UART2PutHex(i); |
||
1199 | lreportItem = &itemListPtrs.reportItemList[i]; |
||
1200 | UART2PrintString("\r\nReportType : ");UART2PutHex(lreportItem->reportType); |
||
1201 | // HIDGlobals globals; |
||
1202 | UART2PrintString("\r\nStart Bit : ");UART2PutHex(lreportItem->startBit); |
||
1203 | UART2PrintString("\r\nBits : ");UART2PutHex(lreportItem->globals.reportsize); |
||
1204 | UART2PrintString("\r\nParent : ");UART2PutHex(lreportItem->parent); |
||
1205 | UART2PrintString("\r\nDataModes : ");UART2PutHex(lreportItem->dataModes); |
||
1206 | UART2PrintString("\r\n1st Usage : ");UART2PutHex(lreportItem->firstUsageItem); |
||
1207 | UART2PrintString("\r\nUsage Items : ");UART2PutHex(lreportItem->usageItems); |
||
1208 | UART2PrintString("\r\n Globals "); |
||
1209 | UART2PrintString("\r\nusagePage : ");UART2PutHex(lreportItem->globals.usagePage); |
||
1210 | UART2PrintString("\r\nreportsize : ");UART2PutHex(lreportItem->globals.reportsize); |
||
1211 | UART2PrintString("\r\nreportID : ");UART2PutHex(lreportItem->globals.reportID); |
||
1212 | UART2PrintString("\r\nreportCount : ");UART2PutHex(lreportItem->globals.reportCount); |
||
1213 | |||
1214 | } |
||
1215 | |||
1216 | UART2PrintString("\n------------------------\n"); |
||
1217 | UART2PrintString("\r\nUsageItem : ");UART2PutHex(i); |
||
1218 | for (i=0; i<deviceRptInfo.usageItems; i++) |
||
1219 | { |
||
1220 | |||
1221 | if (itemListPtrs.usageItemList[i].isRange) |
||
1222 | { |
||
1223 | UART2PrintString("\r\nUsages Minimum Maximum \n\r"); |
||
1224 | UART2PrintString("\t\t"); |
||
1225 | j = itemListPtrs.usageItemList[i].usageMaximum; |
||
1226 | UART2PutHex(j); |
||
1227 | UART2PrintString("\t"); |
||
1228 | j = itemListPtrs.usageItemList[i].usageMinimum; |
||
1229 | UART2PutHex(j); |
||
1230 | } |
||
1231 | else |
||
1232 | UART2PrintString("\r\nUsage: ");UART2PutHex(itemListPtrs.usageItemList[i].usage); |
||
1233 | } |
||
1234 | } |
||
1235 | #endif |
||
1236 |
Powered by WebSVN v2.8.3