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 "message.h"
24 #include "parsetools.h"
25 
26 //#include "hid.h"
27 
29 public:
30  //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0;
31  //virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0;
32  virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep) = 0;
33 };
34 
35 #define CP_MASK_COMPARE_CLASS 1
36 #define CP_MASK_COMPARE_SUBCLASS 2
37 #define CP_MASK_COMPARE_PROTOCOL 4
38 #define CP_MASK_COMPARE_ALL 7
39 
40 // Configuration Descriptor Parser Class Template
41 
42 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
44  UsbConfigXtracter *theXtractor;
45  MultiValueBuffer theBuffer;
46  MultiByteValueParser valParser;
47  ByteSkipper theSkipper;
48  uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/];
49 
50  uint8_t stateParseDescr; // ParseDescriptor state
51 
52  uint8_t dscrLen; // Descriptor length
53  uint8_t dscrType; // Descriptor type
54 
55  bool isGoodInterface; // Apropriate interface flag
56  uint8_t confValue; // Configuration value
57  uint8_t protoValue; // Protocol value
58  uint8_t ifaceNumber; // Interface number
59  uint8_t ifaceAltSet; // Interface alternate settings
60 
61  bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn);
62 
63  void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
64 
65 public:
67  virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset);
68 };
69 
70 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
72 theXtractor(xtractor),
73 stateParseDescr(0),
74 dscrLen(0),
75 dscrType(0) {
76  theBuffer.pValue = varBuffer;
77  valParser.Initialize(&theBuffer);
78  theSkipper.Initialize(&theBuffer);
79 };
80 
81 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
82 void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) {
83  uint16_t cntdn = (uint16_t) len;
84  uint8_t *p = (uint8_t*) pbuf;
85 
86  while(cntdn)
87  if(!ParseDescriptor(&p, &cntdn))
88  return;
89 }
90 
91 /* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and
92  compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */
93 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
95  switch(stateParseDescr) {
96  case 0:
97  theBuffer.valueSize = 2;
98  valParser.Initialize(&theBuffer);
99  stateParseDescr = 1;
100  case 1:
101  if(!valParser.Parse(pp, pcntdn))
102  return false;
103  dscrLen = *((uint8_t*) theBuffer.pValue);
104  dscrType = *((uint8_t*) theBuffer.pValue + 1);
105  stateParseDescr = 2;
106  case 2:
107  // This is a sort of hack. Assuming that two bytes are allready in the buffer
108  // the pointer is positioned two bytes ahead in order for the rest of descriptor
109  // to be read right after the size and the type fields.
110  // This should be used carefuly. varBuffer should be used directly to handle data
111  // in the buffer.
112  theBuffer.pValue = varBuffer + 2;
113  stateParseDescr = 3;
114  case 3:
115  switch(dscrType) {
117  isGoodInterface = false;
119  theBuffer.valueSize = sizeof(USB_CONFIGURATION_DESCRIPTOR) - 2;
120  break;
122  theBuffer.valueSize = sizeof(USB_ENDPOINT_DESCRIPTOR) - 2;
123  break;
124  case HID_DESCRIPTOR_HID:
125  theBuffer.valueSize = dscrLen - 2;
126  break;
127  }
128  valParser.Initialize(&theBuffer);
129  stateParseDescr = 4;
130  case 4:
131  switch(dscrType) {
133  if(!valParser.Parse(pp, pcntdn))
134  return false;
135  confValue = ((USB_CONFIGURATION_DESCRIPTOR*) varBuffer)->bConfigurationValue;
136  break;
138  if(!valParser.Parse(pp, pcntdn))
139  return false;
140  if((MASK & CP_MASK_COMPARE_CLASS) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceClass != CLASS_ID)
141  break;
142  if((MASK & CP_MASK_COMPARE_SUBCLASS) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceSubClass != SUBCLASS_ID)
143  break;
144  if((MASK & CP_MASK_COMPARE_PROTOCOL) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceProtocol != PROTOCOL_ID)
145  break;
146 
147  isGoodInterface = true;
148  ifaceNumber = ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceNumber;
149  ifaceAltSet = ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bAlternateSetting;
150  protoValue = ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceProtocol;
151  break;
153  if(!valParser.Parse(pp, pcntdn))
154  return false;
155  if(isGoodInterface)
156  if(theXtractor)
157  theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*) varBuffer);
158  break;
159  //case HID_DESCRIPTOR_HID:
160  // if (!valParser.Parse(pp, pcntdn))
161  // return false;
162  // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer);
163  // break;
164  default:
165  if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2))
166  return false;
167  }
168  theBuffer.pValue = varBuffer;
169  stateParseDescr = 0;
170  }
171  return true;
172 }
173 
174 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
176  Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80);
177  Notify(PSTR("bDescLength:\t\t"), 0x80);
178  PrintHex<uint8_t > (pDesc->bLength, 0x80);
179 
180  Notify(PSTR("\r\nbDescriptorType:\t"), 0x80);
181  PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);
182 
183  Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80);
184  PrintHex<uint16_t > (pDesc->bcdHID, 0x80);
185 
186  Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80);
187  PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);
188 
189  Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
190  PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
191 
192  //Notify(PSTR("\r\nbDescrType:\t\t"));
193  //PrintHex<uint8_t>(pDesc->bDescrType);
194  //
195  //Notify(PSTR("\r\nwDescriptorLength:\t"));
196  //PrintHex<uint16_t>(pDesc->wDescriptorLength);
197 
198  for(uint8_t i = 0; i < pDesc->bNumDescriptors; i++) {
200 
201  Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);
202  PrintHex<uint8_t > (pLT[i].bDescrType, 0x80);
203 
204  Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80);
205  PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80);
206  }
207  Notify(PSTR("\r\n"), 0x80);
208 }
209 
210 
211 #endif // __CONFDESCPARSER_H__