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