Пример #1
0
BOOL USB_HIDDeviceEventHandler ( BYTE address, USB_EVENT event, void *data, DWORD size )
{

    // Handle specific events.
    switch (event){

        case EVENT_HID_ATTACH:
            putstr("\r\n"); putstr(deviceName[deviceType[address]]); putstr(" attached.\r\n");
            //putstr(" device address="); putdec(address); putstr("\r\n");

            // update numOfDevice
            numOfDevice[deviceType[address]]++;
            break;

        case EVENT_HID_DETACH:
            putstr("\r\n"); putstr(deviceName[deviceType[address]]); putstr(" detached.\r\n");
            //putstr(" device address="); putdec(address); putstr("\r\n\r\n");

            // update numOfDevice
            numOfDevice[deviceType[address]]--;
            if(Appl_raw_report_buffer[address].ReportData){
                USB_FREE_AND_CLEAR(Appl_raw_report_buffer[address].ReportData);
            }
            deviceType[address] = HID_UNKNOWN;
            break;

        case EVENT_HID_READ_DONE:
        case EVENT_HID_WRITE_DONE:
        case EVENT_HID_BAD_REPORT_DESCRIPTOR:
            break;

        case EVENT_HID_RPT_DESC_PARSED:
#ifdef DEBUG_MODE
            //UART2PrintString( "\r\nHID: device report descriptor parsed\r\n" );
            putstr( "\r\nHID: device report descriptor parsed\r\n" );
#endif
            setHIDDeviceType(address, (BYTE *)data);
            return USB_HID_DataCollectionHandler(address);

        default:
            break;
    }

    return TRUE;

} // USB_HIDDeviceEventHandler
/****************************************************************************
  Function:
    USB_HID_RPT_DESC_ERROR _USBHostHID_Parse_Report(uint8_t* hidReportDescriptor
                                 ,uint16_t lengthOfDescriptor, uint16_t pollRate,
                                  uint8_t interfaceNum)

  Description:
    This function is called by usb_host_hid.c after a valid configuration
    device is found. This function parses the report descriptor and stores
    data in data structures. Application can access these data structures
    to understand report format and device capabilities

  Precondition:
    None

  Parameters:
    uint8_t* hidReportDescriptor - Pointer to raw report descriptor
    uint16_t  lengthOfDescriptor  - Length of Report Descriptor
    uint16_t  pollRate            - Poll rate of the report
    uint8_t interfaceNum         - interface number of the respective report
                                descriptor.

  Return Values:
    USB_HID_RPT_DESC_ERROR    - Returns error code(enum) if found while
                                parsing the report descriptor

  Remarks:
    None
***************************************************************************/
USB_HID_RPT_DESC_ERROR _USBHostHID_Parse_Report(uint8_t* hidReportDescriptor , uint16_t lengthOfDescriptor , uint16_t pollRate, uint8_t interfaceNum)
{
   uint16_t  sizeRequired = 0;
   uint16_t  len_to_be_parsed =0;
   uint8_t* currentRptDescPtr = NULL;
   uint8_t* assignMem = NULL;
   /* Main Item Vars */
   HID_COLLECTION *collectionLocal = NULL;
   HID_REPORT *reportLocal = NULL;

   /* Global Item Vars */
   HID_REPORT *lreport = NULL;
   uint8_t lreportIndex = (uint8_t)0;

   /* Local Item Vars */
   HID_DESIGITEM *ldesignatorItem = NULL;
   HID_STRINGITEM *lstringItem = NULL;
   HID_USAGEITEM *lusageItem = NULL;

   /*HID  Error */
   USB_HID_RPT_DESC_ERROR lhidError = HID_ERR;

   HID_ITEM_INFO item;

   uint8_t  i=0;
   uint8_t  dataByte=0 ;
   uint8_t  ldataSize=0;

   if((hidReportDescriptor == NULL) ||(lengthOfDescriptor == 0))
    {
       /* set error flag */
       return(HID_ERR_NullPointer);
    }

    memset( &deviceRptInfo, 0x00, sizeof( USB_HID_DEVICE_RPT_INFO ) );
    _USBHostHID_InitDeviceRptInfo();
   
    deviceRptInfo.interfaceNumber = interfaceNum;  // update interface number for the report
    deviceRptInfo.reportPollingRate = pollRate;

    len_to_be_parsed = lengthOfDescriptor;
    currentRptDescPtr = hidReportDescriptor;

    while(len_to_be_parsed > 0)    /* First parse to calculate the space required for all the items */
    {
       item.ItemDetails.val = *currentRptDescPtr;
       /* Data need not be parsed at this point */
       ldataSize = item.ItemDetails.ItemSize ;
       if(item.ItemDetails.ItemSize == 3) 
           ldataSize = 4; 

       currentRptDescPtr += (ldataSize+1) ; /* point to next item i.e size of item data + 1(item detail) */
       len_to_be_parsed -= (ldataSize+1);   /* remaining bytes = current - (length of data + 1)*/

        switch (item.ItemDetails.ItemType)
            {
                case HIDType_Main:           /* Main Items */
                    switch (item.ItemDetails.ItemTag)
                    {
                        case HIDTag_Collection:
                            deviceRptInfo.collections++;
                            deviceRptInfo.collectionNesting++;
                            if (deviceRptInfo.collectionNesting > deviceRptInfo.maxCollectionNesting)
                                deviceRptInfo.maxCollectionNesting = deviceRptInfo.collectionNesting;
                            break;
                        case HIDTag_EndCollection:
                            if (deviceRptInfo.collectionNesting-- == 0)
                                  lhidError = HID_ERR_UnexpectedEndCollection ;/* Error: UnexpectedEndCollection */
                            break;
                        case HIDTag_Input:
                        case HIDTag_Output:
                        case HIDTag_Feature:
                            deviceRptInfo.reportItems++;
                            break;
                        default :
                    break;
                    }
                    break;
                case HIDType_Global:         /* Global Items */
                    switch (item.ItemDetails.ItemTag)
                    {
                        case HIDTag_ReportID:
                            deviceRptInfo.reports++;
                            break;
                        case HIDTag_Push:
                            deviceRptInfo.globalsNesting++;
                            if (deviceRptInfo.globalsNesting > deviceRptInfo.maxGlobalsNesting)
                                deviceRptInfo.maxGlobalsNesting = deviceRptInfo.globalsNesting;
                            break;
                        case HIDTag_Pop:
                            deviceRptInfo.globalsNesting--;
                            if (deviceRptInfo.globalsNesting > deviceRptInfo.maxGlobalsNesting)
                                lhidError = HID_ERR_UnexpectedPop ;/* Error: global nesting rolled to negative ... */
                            break;
                        default :
                            break;
                    }
                    break;
                case HIDType_Local:          /* Local Item */
                    switch (item.ItemDetails.ItemTag)
                    {
                        case HIDTag_Usage:
                            deviceRptInfo.usages++;
                            break;
                        case HIDTag_UsageMinimum:
                        case HIDTag_UsageMaximum:
                            deviceRptInfo.usageRanges++;
                            break;
                        case HIDTag_StringIndex:
                            deviceRptInfo.strings++;
                            break;
                        case HIDTag_StringMinimum:
                        case HIDTag_StringMaximum:
                            deviceRptInfo.stringRanges++;
                            break;
                        case HIDTag_DesignatorIndex:
                            deviceRptInfo.designators++;
                            break;
                        case HIDTag_DesignatorMinimum:
                        case HIDTag_DesignatorMaximum:
                            deviceRptInfo.designatorRanges++;
                            break;
                        default :
                            break;
                    }
                  break;
             default :
                  break;

        }
    }

    if(lhidError)
    {
        return(lhidError);
    }

    if (deviceRptInfo.collectionNesting != 0) return(HID_ERR_MissingEndCollection) /* HID_RPT_DESC_FORMAT_IMPROPER */;

    if (deviceRptInfo.collections == 1) return(HID_ERR_MissingTopLevelCollection) /* HID_RPT_DESC_FORMAT_IMPROPER */;

    if (deviceRptInfo.reportItems == 0) return(HID_ERR_NoReports)/* HID_RPT_DESC_FORMAT_IMPROPER */;

    if ((deviceRptInfo.usageRanges & 1) == 1) return(HID_ERR_UnmatchedUsageRange)/* HID_RPT_DESC_FORMAT_IMPROPER */;

    if ((deviceRptInfo.stringRanges & 1) == 1) return(HID_ERR_UnmatchedStringRange)/* HID_RPT_DESC_FORMAT_IMPROPER */;

    if ((deviceRptInfo.designatorRanges & 1) == 1) return(HID_ERR_UnmatchedDesignatorRange)/* HID_RPT_DESC_FORMAT_IMPROPER */;


   /* usages , strings & descriptors are in pair */
    deviceRptInfo.usages += (deviceRptInfo.usageRanges/2);
    deviceRptInfo.strings += (deviceRptInfo.stringRanges/2);
    deviceRptInfo.designators += (deviceRptInfo.designatorRanges/2);

   /* Calculate space required */

    sizeRequired = (sizeof(HID_COLLECTION) * deviceRptInfo.collections)
                   + (sizeof(HID_REPORTITEM) * deviceRptInfo.reportItems)
                   + (sizeof(HID_REPORT) * deviceRptInfo.reports)
                   + (sizeof(HID_USAGEITEM) * deviceRptInfo.usages)
                   + (sizeof(HID_STRINGITEM) * deviceRptInfo.strings)
                   + (sizeof(HID_DESIGITEM) * deviceRptInfo.designators)
                   + (sizeof(int) * deviceRptInfo.maxCollectionNesting)
                   + (sizeof(HID_GLOBALS) * deviceRptInfo.maxGlobalsNesting);

    if (parsedDataMem != NULL)
    {
		USB_FREE_AND_CLEAR( parsedDataMem );
    }

    parsedDataMem = (uint8_t*) USB_MALLOC(sizeRequired);
    
#ifdef DEBUG_MODE
    UART2PrintString( "HID: Memory for Report Descriptor: " );
    UART2PutHex( sizeRequired );
#endif

    if (parsedDataMem == NULL) return(HID_ERR_NotEnoughMemory); /* Error: Not enough memory */
    assignMem = (uint8_t*) parsedDataMem;
    
    /* Allocate Space */   
    itemListPtrs.collectionList = (HID_COLLECTION *) assignMem;
    assignMem += (sizeof(HID_COLLECTION) * deviceRptInfo.collections);
    itemListPtrs.reportItemList = (HID_REPORTITEM *) assignMem;
    assignMem += (sizeof(HID_REPORTITEM) * deviceRptInfo.reportItems);
    itemListPtrs.reportList = (HID_REPORT *) assignMem;
    assignMem += (sizeof(HID_REPORT) * deviceRptInfo.reports);
    itemListPtrs.usageItemList = (HID_USAGEITEM *) assignMem;
    assignMem += (sizeof(HID_USAGEITEM) * deviceRptInfo.usages);
    itemListPtrs.stringItemList = (HID_STRINGITEM *) assignMem;
    assignMem += (sizeof(HID_STRINGITEM) * deviceRptInfo.strings);
    itemListPtrs.designatorItemList = (HID_DESIGITEM *) assignMem;
    assignMem += (sizeof(HID_DESIGITEM) * deviceRptInfo.designators);
    itemListPtrs.collectionStack = (uint8_t *) assignMem;
    assignMem += (sizeof(int) * deviceRptInfo.maxCollectionNesting);
    itemListPtrs.globalsStack = (HID_GLOBALS *) assignMem;

    _USBHostHID_InitDeviceRptInfo();

//  Initialize the virtual collection

    collectionLocal = itemListPtrs.collectionList;
    collectionLocal->data = 0;
    collectionLocal->firstChild = 0;
    collectionLocal->firstReportItem = 0;
    collectionLocal->firstUsageItem = 0;
    collectionLocal->nextSibling = 0;
    collectionLocal->parent = 0;
    collectionLocal->reportItems = 0;
    collectionLocal->usageItems = 0;
    collectionLocal->usagePage = 0;

//  Initialize the default report

    reportLocal = itemListPtrs.reportList;
    reportLocal->featureBits = 0;
    reportLocal->inputBits = 0;
    reportLocal->outputBits = 0;
    reportLocal->reportID = 0;

   /* re-init ptr to Rpt Descp & Length of Descp */
   len_to_be_parsed = lengthOfDescriptor;
   currentRptDescPtr = hidReportDescriptor;

#ifdef DEBUG_MODE
    UART2PrintString( "HID-HOST: ... 2nd Parse \n" );
#endif


    while(len_to_be_parsed > 0)     /* Second parse to fill the tables with each item detail */
    {
       item.ItemDetails.val = *currentRptDescPtr;
       item.Data.uItemData = 0;

       ldataSize = item.ItemDetails.ItemSize ;
       if(item.ItemDetails.ItemSize == 3) 
           ldataSize = 4; 

       currentRptDescPtr++; /* ptr points to data */
       for (i = 0; i < ldataSize; i++)
        {
            dataByte = *currentRptDescPtr++;  /* signed data will be taken care in ItemTag it is expected */
            item.Data.uItemData |= ((uint32_t)dataByte << (i*8));
        }
    
       len_to_be_parsed -= (ldataSize+1);   /* remaining bytes = current - (length of current item + 1)*/

       switch(item.ItemDetails.ItemType)
        {
           case HIDType_Main:   /* look for Main Items*/
                switch(item.ItemDetails.ItemTag)
                {
                    case HIDTag_Input :
                    case HIDTag_Output :
                    case HIDTag_Feature :
                                lhidError = _USBHostHID_Parse_ReportType(&item);
                    break;

                    case HIDTag_Collection :
                                _USBHostHID_Parse_Collection(&item);
                    break;

                    case HIDTag_EndCollection :
                                _USBHostHID_Parse_EndCollection(&item);
                    break;
                }
                break;
                
           case HIDType_Global:   /* look for Global Items*/
                switch(item.ItemDetails.ItemTag)
                {
                    case HIDTag_UsagePage :
                         deviceRptInfo.globals.usagePage = item.Data.uItemData;
                         break;

                    case HIDTag_LogicalMinimum : /* convert to signed val */
                         //  Sign extend one value
                         _USBHostHID_ConvertDataToSigned(&item);
                        deviceRptInfo.globals.logicalMinimum = item.Data.sItemData;
                        break;                         

                    case HIDTag_LogicalMaximum :/* convert to signed val */
                         //  Sign extend one value
                         _USBHostHID_ConvertDataToSigned(&item);
                         deviceRptInfo.globals.logicalMaximum = item.Data.uItemData;
                         break;

                    case HIDTag_PhysicalMinimum :/* convert to signed val */
                         //  Sign extend one value
                         _USBHostHID_ConvertDataToSigned(&item);
                         deviceRptInfo.globals.physicalMinimum = item.Data.uItemData;
                        break;

                    case HIDTag_PhysicalMaximum :/* convert to signed val */
                         //  Sign extend one value
                         _USBHostHID_ConvertDataToSigned(&item);
                         deviceRptInfo.globals.physicalMaximum = item.Data.uItemData;
                         break;

                    case HIDTag_UnitExponent :
                         deviceRptInfo.globals.unitExponent = item.Data.uItemData;
                         break;

                    case HIDTag_ReportSize :
                         deviceRptInfo.globals.reportsize = item.Data.uItemData;
                         if (deviceRptInfo.globals.reportsize == 0)
                              lhidError = HID_ERR_ZeroReportSize;
                         break;

                    case HIDTag_ReportID :
                         if (item.Data.uItemData)
                            {
//                               Look for the Report ID in the table
                                                  
                                 lreportIndex = 0;
                                 while ((lreportIndex < deviceRptInfo.reports)
                                        && (itemListPtrs.reportList[lreportIndex].reportID != item.Data.uItemData))
                                        lreportIndex++;
                                 
//                               initialize the entry if it's new and there's room for it
//                               Start with 8 bits for the Report ID
                                 
                                 if (lreportIndex == deviceRptInfo.reports)
                                 {
                                    lreport = &itemListPtrs.reportList[deviceRptInfo.reports++];
                                    lreport->reportID = item.Data.uItemData;
                                    lreport->inputBits = 8;
                                    lreport->outputBits = 8;
                                    lreport->featureBits = 8;
                                 }
                                 
//                               remember which report is being processed
                                 
                                 deviceRptInfo.globals.reportID = item.Data.uItemData;
                                 deviceRptInfo.globals.reportIndex = lreportIndex;
                            }
                            else
                            {
                                 lhidError = HID_ERR_ZeroReportID;
                            }
                         break;

                    case HIDTag_ReportCount :
                         if (item.Data.uItemData)
                         {
                             deviceRptInfo.globals.reportCount = item.Data.uItemData;
                         }
                         else
                         {
                             lhidError = HID_ERR_ZeroReportCount;
                         }
                         break;

                    case HIDTag_Push :
                         itemListPtrs.globalsStack[deviceRptInfo.globalsNesting++] =  deviceRptInfo.globals;
                         break;

                    case HIDTag_Pop :
                         deviceRptInfo.globals = itemListPtrs.globalsStack[--deviceRptInfo.globalsNesting] ;
                    break;
            
                }
                break;

           case HIDType_Local:  /* look for Local Items*/
                switch(item.ItemDetails.ItemTag)
                {
                    case HIDTag_Usage :
                         lusageItem = &itemListPtrs.usageItemList[deviceRptInfo.usageItems++];
                         lusageItem->isRange = false;
                         if (item.ItemDetails.ItemSize == 3) /* 4 data bytes */
                            {
                                lusageItem->usagePage = item.Data.uItemData >> 16;
                                lusageItem->usage = item.Data.uItemData & 0x00FF;
                            }
                         else
                            {
                                lusageItem->usagePage = deviceRptInfo.globals.usagePage;
                                lusageItem->usage = item.Data.uItemData;
                            }
                         break;

                    case HIDTag_UsageMinimum :
                         if(deviceRptInfo.haveUsageMax)
                             {
                                lusageItem = &itemListPtrs.usageItemList[deviceRptInfo.usageItems++];
                                lusageItem->isRange = true;
                                if(item.ItemDetails.ItemSize == 3)
                                 {
                                    lusageItem->usagePage = item.Data.uItemData >> 16;
                                    lusageItem->usageMinimum = item.Data.uItemData & 0x00FFL;
                                 }
                                else
                                 {