]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/confdescparser.h
lufa: usb-usb: Use LUFA startup instead of cusotom
[max/tmk_keyboard.git] / tmk_core / 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__