| 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