Zoltan Hudak / UsbHostMAX3421E

Dependents:   UsbHostMAX3421E_Hello

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers confdescparser.h Source File

confdescparser.h

00001 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
00002 
00003 This program is free software; you can redistribute it and/or modify
00004 it under the terms of the GNU General Public License as published by
00005 the Free Software Foundation; either version 2 of the License, or
00006 (at your option) any later version.
00007 
00008 This program is distributed in the hope that it will be useful,
00009 but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 GNU General Public License for more details.
00012 
00013 You should have received a copy of the GNU General Public License
00014 along with this program; if not, write to the Free Software
00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00016 
00017 Contact information
00018 -------------------
00019 
00020 Circuits At Home, LTD
00021 Web      :  http://www.circuitsathome.com
00022 e-mail   :  support@circuitsathome.com
00023  */
00024 #if !defined(_usb_h_) || defined(__CONFDESCPARSER_H__)
00025 #error "Never include confdescparser.h directly; include Usb.h instead"
00026 #else
00027 
00028 #define __CONFDESCPARSER_H__
00029 
00030 class UsbConfigXtracter {
00031 public:
00032         //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0;
00033         //virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0;
00034 
00035         virtual void EndpointXtract(uint8_t conf __attribute__((unused)), uint8_t iface __attribute__((unused)), uint8_t alt __attribute__((unused)), uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR *ep __attribute__((unused))) {
00036         };
00037 };
00038 
00039 #define CP_MASK_COMPARE_CLASS                   1
00040 #define CP_MASK_COMPARE_SUBCLASS                2
00041 #define CP_MASK_COMPARE_PROTOCOL                4
00042 #define CP_MASK_COMPARE_ALL                     7
00043 
00044 // Configuration Descriptor Parser Class Template
00045 
00046 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
00047 class ConfigDescParser : public USBReadParser {
00048         UsbConfigXtracter *theXtractor;
00049         MultiValueBuffer theBuffer;
00050         MultiByteValueParser valParser;
00051         ByteSkipper theSkipper;
00052         uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/];
00053 
00054         uint8_t stateParseDescr; // ParseDescriptor state
00055 
00056         uint8_t dscrLen; // Descriptor length
00057         uint8_t dscrType; // Descriptor type
00058 
00059         bool isGoodInterface; // Apropriate interface flag
00060         uint8_t confValue; // Configuration value
00061         uint8_t protoValue; // Protocol value
00062         uint8_t ifaceNumber; // Interface number
00063         uint8_t ifaceAltSet; // Interface alternate settings
00064 
00065         bool UseOr;
00066         bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn);
00067         void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
00068 
00069 public:
00070 
00071         void SetOR(void) {
00072                 UseOr = true;
00073         }
00074         ConfigDescParser(UsbConfigXtracter *xtractor);
00075         void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset);
00076 };
00077 
00078 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
00079 ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) :
00080 theXtractor(xtractor),
00081 stateParseDescr(0),
00082 dscrLen(0),
00083 dscrType(0),
00084 UseOr(false) {
00085         theBuffer.pValue = varBuffer;
00086         valParser.Initialize(&theBuffer);
00087         theSkipper.Initialize(&theBuffer);
00088 };
00089 
00090 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
00091 void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset __attribute__((unused))) {
00092         uint16_t cntdn = (uint16_t)len;
00093         uint8_t *p = (uint8_t*)pbuf;
00094 
00095         while(cntdn)
00096                 if(!ParseDescriptor(&p, &cntdn))
00097                         return;
00098 }
00099 
00100 /* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and
00101   compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */
00102 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
00103 bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) {
00104         USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer);
00105         USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*>(varBuffer);
00106         switch(stateParseDescr) {
00107                 case 0:
00108                         theBuffer.valueSize = 2;
00109                         valParser.Initialize(&theBuffer);
00110                         stateParseDescr = 1;
00111                 case 1:
00112                         if(!valParser.Parse(pp, pcntdn))
00113                                 return false;
00114                         dscrLen = *((uint8_t*)theBuffer.pValue);
00115                         dscrType = *((uint8_t*)theBuffer.pValue + 1);
00116                         stateParseDescr = 2;
00117                 case 2:
00118                         // This is a sort of hack. Assuming that two bytes are all ready in the buffer
00119                         //      the pointer is positioned two bytes ahead in order for the rest of descriptor
00120                         //      to be read right after the size and the type fields.
00121                         // This should be used carefully. varBuffer should be used directly to handle data
00122                         //      in the buffer.
00123                         theBuffer.pValue = varBuffer + 2;
00124                         stateParseDescr = 3;
00125                 case 3:
00126                         switch(dscrType) {
00127                                 case USB_DESCRIPTOR_INTERFACE:
00128                                         isGoodInterface = false;
00129                                         break;
00130                                 case USB_DESCRIPTOR_CONFIGURATION:
00131                                 case USB_DESCRIPTOR_ENDPOINT:
00132                                 case HID_DESCRIPTOR_HID:
00133                                         break;
00134                         }
00135                         theBuffer.valueSize = dscrLen - 2;
00136                         valParser.Initialize(&theBuffer);
00137                         stateParseDescr = 4;
00138                 case 4:
00139                         switch(dscrType) {
00140                                 case USB_DESCRIPTOR_CONFIGURATION:
00141                                         if(!valParser.Parse(pp, pcntdn))
00142                                                 return false;
00143                                         confValue = ucd->bConfigurationValue;
00144                                         break;
00145                                 case USB_DESCRIPTOR_INTERFACE:
00146                                         if(!valParser.Parse(pp, pcntdn))
00147                                                 return false;
00148                                         if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID)
00149                                                 break;
00150                                         if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID)
00151                                                 break;
00152                                         if(UseOr) {
00153                                                 if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol)))
00154                                                         break;
00155                                         } else {
00156                                                 if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID)
00157                                                         break;
00158                                         }
00159                                         isGoodInterface = true;
00160                                         ifaceNumber = uid->bInterfaceNumber;
00161                                         ifaceAltSet = uid->bAlternateSetting;
00162                                         protoValue = uid->bInterfaceProtocol;
00163                                         break;
00164                                 case USB_DESCRIPTOR_ENDPOINT:
00165                                         if(!valParser.Parse(pp, pcntdn))
00166                                                 return false;
00167                                         if(isGoodInterface)
00168                                                 if(theXtractor)
00169                                                         theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer);
00170                                         break;
00171                                         //case HID_DESCRIPTOR_HID:
00172                                         //      if (!valParser.Parse(pp, pcntdn))
00173                                         //              return false;
00174                                         //      PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer);
00175                                         //      break;
00176                                 default:
00177                                         if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2))
00178                                                 return false;
00179                         }
00180                         theBuffer.pValue = varBuffer;
00181                         stateParseDescr = 0;
00182         }
00183         return true;
00184 }
00185 
00186 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
00187 void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) {
00188         Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80);
00189         Notify(PSTR("bDescLength:\t\t"), 0x80);
00190         PrintHex<uint8_t > (pDesc->bLength, 0x80);
00191 
00192         Notify(PSTR("\r\nbDescriptorType:\t"), 0x80);
00193         PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);
00194 
00195         Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80);
00196         PrintHex<uint16_t > (pDesc->bcdHID, 0x80);
00197 
00198         Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80);
00199         PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);
00200 
00201         Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
00202         PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
00203 
00204         for(uint8_t i = 0; i < pDesc->bNumDescriptors; i++) {
00205                 HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
00206 
00207                 Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);
00208                 PrintHex<uint8_t > (pLT[i].bDescrType, 0x80);
00209 
00210                 Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80);
00211                 PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80);
00212         }
00213         Notify(PSTR("\r\n"), 0x80);
00214 }
00215 
00216 
00217 #endif // __CONFDESCPARSER_H__