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