USB Host Shield 2.0
confdescparser.h
Go to the documentation of this file.
1 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
2 
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
7 
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 
17 Contact information
18 -------------------
19 
20 Circuits At Home, LTD
21 Web : http://www.circuitsathome.com
22 e-mail : support@circuitsathome.com
23  */
24 #if !defined(_usb_h_) || defined(__CONFDESCPARSER_H__)
25 #error "Never include confdescparser.h directly; include Usb.h instead"
26 #else
27 
28 #define __CONFDESCPARSER_H__
29 
31 public:
32  //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0;
33  //virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0;
34 
35  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))) {
36  };
37 };
38 
39 #define CP_MASK_COMPARE_CLASS 1
40 #define CP_MASK_COMPARE_SUBCLASS 2
41 #define CP_MASK_COMPARE_PROTOCOL 4
42 #define CP_MASK_COMPARE_ALL 7
43 
44 // Configuration Descriptor Parser Class Template
45 
46 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
48  UsbConfigXtracter *theXtractor;
49  MultiValueBuffer theBuffer;
50  MultiByteValueParser valParser;
51  ByteSkipper theSkipper;
52  uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/];
53 
54  uint8_t stateParseDescr; // ParseDescriptor state
55 
56  uint8_t dscrLen; // Descriptor length
57  uint8_t dscrType; // Descriptor type
58 
59  bool isGoodInterface; // Apropriate interface flag
60  uint8_t confValue; // Configuration value
61  uint8_t protoValue; // Protocol value
62  uint8_t ifaceNumber; // Interface number
63  uint8_t ifaceAltSet; // Interface alternate settings
64 
65  bool UseOr;
66  bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn);
67  void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
68 
69 public:
70 
71  void SetOR(void) {
72  UseOr = true;
73  }
75  void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset);
76 };
77 
78 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
80 theXtractor(xtractor),
81 stateParseDescr(0),
82 dscrLen(0),
83 dscrType(0),
84 UseOr(false) {
85  theBuffer.pValue = varBuffer;
86  valParser.Initialize(&theBuffer);
87  theSkipper.Initialize(&theBuffer);
88 };
89 
90 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
91 void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset __attribute__((unused))) {
92  uint16_t cntdn = (uint16_t)len;
93  uint8_t *p = (uint8_t*)pbuf;
94 
95  while(cntdn)
96  if(!ParseDescriptor(&p, &cntdn))
97  return;
98 }
99 
100 /* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and
101  compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */
102 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
104  USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer);
105  USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*>(varBuffer);
106  switch(stateParseDescr) {
107  case 0:
108  theBuffer.valueSize = 2;
109  valParser.Initialize(&theBuffer);
110  stateParseDescr = 1;
111  // fall through
112  case 1:
113  if(!valParser.Parse(pp, pcntdn))
114  return false;
115  dscrLen = *((uint8_t*)theBuffer.pValue);
116  dscrType = *((uint8_t*)theBuffer.pValue + 1);
117  stateParseDescr = 2;
118  // fall through
119  case 2:
120  // This is a sort of hack. Assuming that two bytes are all ready in the buffer
121  // the pointer is positioned two bytes ahead in order for the rest of descriptor
122  // to be read right after the size and the type fields.
123  // This should be used carefully. varBuffer should be used directly to handle data
124  // in the buffer.
125  theBuffer.pValue = varBuffer + 2;
126  stateParseDescr = 3;
127  // fall through
128  case 3:
129  switch(dscrType) {
131  isGoodInterface = false;
132  break;
135  case HID_DESCRIPTOR_HID:
136  break;
137  }
138  theBuffer.valueSize = dscrLen - 2;
139  valParser.Initialize(&theBuffer);
140  stateParseDescr = 4;
141  // fall through
142  case 4:
143  switch(dscrType) {
145  if(!valParser.Parse(pp, pcntdn))
146  return false;
147  confValue = ucd->bConfigurationValue;
148  break;
150  if(!valParser.Parse(pp, pcntdn))
151  return false;
152  if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID)
153  break;
154  if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID)
155  break;
156  if(UseOr) {
157  if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol)))
158  break;
159  } else {
160  if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID)
161  break;
162  }
163  isGoodInterface = true;
164  ifaceNumber = uid->bInterfaceNumber;
165  ifaceAltSet = uid->bAlternateSetting;
166  protoValue = uid->bInterfaceProtocol;
167  break;
169  if(!valParser.Parse(pp, pcntdn))
170  return false;
171  if(isGoodInterface)
172  if(theXtractor)
173  theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer);
174  break;
175  //case HID_DESCRIPTOR_HID:
176  // if (!valParser.Parse(pp, pcntdn))
177  // return false;
178  // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer);
179  // break;
180  default:
181  if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2))
182  return false;
183  }
184  theBuffer.pValue = varBuffer;
185  stateParseDescr = 0;
186  }
187  return true;
188 }
189 
190 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
192  Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80);
193  Notify(PSTR("bDescLength:\t\t"), 0x80);
194  PrintHex<uint8_t > (pDesc->bLength, 0x80);
195 
196  Notify(PSTR("\r\nbDescriptorType:\t"), 0x80);
197  PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);
198 
199  Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80);
200  PrintHex<uint16_t > (pDesc->bcdHID, 0x80);
201 
202  Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80);
203  PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);
204 
205  Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
206  PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
207 
208  for(uint8_t i = 0; i < pDesc->bNumDescriptors; i++) {
210 
211  Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);
212  PrintHex<uint8_t > (pLT[i].bDescrType, 0x80);
213 
214  Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80);
215  PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80);
216  }
217  Notify(PSTR("\r\n"), 0x80);
218 }
219 
220 
221 #endif // __CONFDESCPARSER_H__
#define CP_MASK_COMPARE_PROTOCOL
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
#define USB_DESCRIPTOR_ENDPOINT
Definition: usb_ch9.h:74
uint8_t bLength
Definition: usb_ch9.h:159
void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset)
#define CP_MASK_COMPARE_CLASS
#define USB_DESCRIPTOR_CONFIGURATION
Definition: usb_ch9.h:71
#define Notify(...)
Definition: message.h:51
bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip)
Definition: parsetools.h:77
void Initialize(MultiValueBuffer *pbuf)
Definition: parsetools.h:72
uint8_t bCountryCode
Definition: usb_ch9.h:162
#define CP_MASK_COMPARE_SUBCLASS
void SetOR(void)
uint8_t bNumDescriptors
Definition: usb_ch9.h:163
bool Parse(uint8_t **pp, uint16_t *pcntdn)
Definition: parsetools.cpp:26
uint8_t bDescriptorType
Definition: usb_ch9.h:160
#define PSTR(str)
#define HID_DESCRIPTOR_HID
Definition: usb_ch9.h:80
uint8_t valueSize
Definition: parsetools.h:31
ConfigDescParser(UsbConfigXtracter *xtractor)
void Initialize(MultiValueBuffer *const pbuf)
Definition: parsetools.h:54
uint8_t bInterfaceSubClass
Definition: usb_ch9.h:142
uint16_t bcdHID
Definition: usb_ch9.h:161
uint8_t bInterfaceProtocol
Definition: usb_ch9.h:143
uint8_t bDescrType
Definition: usb_ch9.h:164
#define USB_DESCRIPTOR_INTERFACE
Definition: usb_ch9.h:73