You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

confdescparser.h 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
  2. This software may be distributed and modified under the terms of the GNU
  3. General Public License version 2 (GPL2) as published by the Free Software
  4. Foundation and appearing in the file GPL2.TXT included in the packaging of
  5. this file. Please note that GPL2 Section 2[b] requires that all works based
  6. on this software must also be made publicly available under the terms of
  7. the GPL2 ("Copyleft").
  8. Contact information
  9. -------------------
  10. Circuits At Home, LTD
  11. Web : http://www.circuitsathome.com
  12. e-mail : [email protected]
  13. */
  14. #if !defined(_usb_h_) || defined(__CONFDESCPARSER_H__)
  15. #error "Never include confdescparser.h directly; include Usb.h instead"
  16. #else
  17. #define __CONFDESCPARSER_H__
  18. class UsbConfigXtracter {
  19. public:
  20. //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0;
  21. //virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0;
  22. virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep) {
  23. };
  24. };
  25. #define CP_MASK_COMPARE_CLASS 1
  26. #define CP_MASK_COMPARE_SUBCLASS 2
  27. #define CP_MASK_COMPARE_PROTOCOL 4
  28. #define CP_MASK_COMPARE_ALL 7
  29. // Configuration Descriptor Parser Class Template
  30. template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
  31. class ConfigDescParser : public USBReadParser {
  32. UsbConfigXtracter *theXtractor;
  33. MultiValueBuffer theBuffer;
  34. MultiByteValueParser valParser;
  35. ByteSkipper theSkipper;
  36. uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/];
  37. uint8_t stateParseDescr; // ParseDescriptor state
  38. uint8_t dscrLen; // Descriptor length
  39. uint8_t dscrType; // Descriptor type
  40. bool isGoodInterface; // Apropriate interface flag
  41. uint8_t confValue; // Configuration value
  42. uint8_t protoValue; // Protocol value
  43. uint8_t ifaceNumber; // Interface number
  44. uint8_t ifaceAltSet; // Interface alternate settings
  45. bool UseOr;
  46. bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn);
  47. void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
  48. public:
  49. void SetOR(void) {
  50. UseOr = true;
  51. }
  52. ConfigDescParser(UsbConfigXtracter *xtractor);
  53. void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset);
  54. };
  55. template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
  56. ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) :
  57. theXtractor(xtractor),
  58. stateParseDescr(0),
  59. dscrLen(0),
  60. dscrType(0),
  61. UseOr(false) {
  62. theBuffer.pValue = varBuffer;
  63. valParser.Initialize(&theBuffer);
  64. theSkipper.Initialize(&theBuffer);
  65. };
  66. template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
  67. void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) {
  68. uint16_t cntdn = (uint16_t)len;
  69. uint8_t *p = (uint8_t*)pbuf;
  70. while(cntdn)
  71. if(!ParseDescriptor(&p, &cntdn))
  72. return;
  73. }
  74. /* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and
  75. compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */
  76. template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
  77. bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) {
  78. USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer);
  79. USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*>(varBuffer);
  80. switch(stateParseDescr) {
  81. case 0:
  82. theBuffer.valueSize = 2;
  83. valParser.Initialize(&theBuffer);
  84. stateParseDescr = 1;
  85. case 1:
  86. if(!valParser.Parse(pp, pcntdn))
  87. return false;
  88. dscrLen = *((uint8_t*)theBuffer.pValue);
  89. dscrType = *((uint8_t*)theBuffer.pValue + 1);
  90. stateParseDescr = 2;
  91. case 2:
  92. // This is a sort of hack. Assuming that two bytes are all ready in the buffer
  93. // the pointer is positioned two bytes ahead in order for the rest of descriptor
  94. // to be read right after the size and the type fields.
  95. // This should be used carefully. varBuffer should be used directly to handle data
  96. // in the buffer.
  97. theBuffer.pValue = varBuffer + 2;
  98. stateParseDescr = 3;
  99. case 3:
  100. switch(dscrType) {
  101. case USB_DESCRIPTOR_INTERFACE:
  102. isGoodInterface = false;
  103. case USB_DESCRIPTOR_CONFIGURATION:
  104. theBuffer.valueSize = sizeof (USB_CONFIGURATION_DESCRIPTOR) - 2;
  105. break;
  106. case USB_DESCRIPTOR_ENDPOINT:
  107. theBuffer.valueSize = sizeof (USB_ENDPOINT_DESCRIPTOR) - 2;
  108. break;
  109. case HID_DESCRIPTOR_HID:
  110. theBuffer.valueSize = dscrLen - 2;
  111. break;
  112. }
  113. valParser.Initialize(&theBuffer);
  114. stateParseDescr = 4;
  115. case 4:
  116. switch(dscrType) {
  117. case USB_DESCRIPTOR_CONFIGURATION:
  118. if(!valParser.Parse(pp, pcntdn))
  119. return false;
  120. confValue = ucd->bConfigurationValue;
  121. break;
  122. case USB_DESCRIPTOR_INTERFACE:
  123. if(!valParser.Parse(pp, pcntdn))
  124. return false;
  125. if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID)
  126. break;
  127. if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID)
  128. break;
  129. if(UseOr) {
  130. if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol)))
  131. break;
  132. } else {
  133. if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID)
  134. break;
  135. }
  136. isGoodInterface = true;
  137. ifaceNumber = uid->bInterfaceNumber;
  138. ifaceAltSet = uid->bAlternateSetting;
  139. protoValue = uid->bInterfaceProtocol;
  140. break;
  141. case USB_DESCRIPTOR_ENDPOINT:
  142. if(!valParser.Parse(pp, pcntdn))
  143. return false;
  144. if(isGoodInterface)
  145. if(theXtractor)
  146. theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer);
  147. break;
  148. //case HID_DESCRIPTOR_HID:
  149. // if (!valParser.Parse(pp, pcntdn))
  150. // return false;
  151. // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer);
  152. // break;
  153. default:
  154. if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2))
  155. return false;
  156. }
  157. theBuffer.pValue = varBuffer;
  158. stateParseDescr = 0;
  159. }
  160. return true;
  161. }
  162. template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
  163. void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) {
  164. Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80);
  165. Notify(PSTR("bDescLength:\t\t"), 0x80);
  166. PrintHex<uint8_t > (pDesc->bLength, 0x80);
  167. Notify(PSTR("\r\nbDescriptorType:\t"), 0x80);
  168. PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);
  169. Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80);
  170. PrintHex<uint16_t > (pDesc->bcdHID, 0x80);
  171. Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80);
  172. PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);
  173. Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
  174. PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
  175. for(uint8_t i = 0; i < pDesc->bNumDescriptors; i++) {
  176. HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
  177. Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);
  178. PrintHex<uint8_t > (pLT[i].bDescrType, 0x80);
  179. Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80);
  180. PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80);
  181. }
  182. Notify(PSTR("\r\n"), 0x80);
  183. }
  184. #endif // __CONFDESCPARSER_H__