Add host mode USB Class driver stubs, add beginnings of a CDC host class driver.
[pub/USBasp.git] / LUFA / Drivers / USB / Class / Host / HIDParser.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2009.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, and distribute this software
13 and its documentation for any purpose and without fee is hereby
14 granted, provided that the above copyright notice appear in all
15 copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaim all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29 */
30
31 #include "HIDParser.h"
32 #if defined(CAN_BE_HOST)
33
34 uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, uint16_t ReportSize, HID_ReportInfo_t* const ParserData)
35 {
36 HID_StateTable_t StateTable[HID_STATETABLE_STACK_DEPTH];
37 HID_StateTable_t* CurrStateTable = &StateTable[0];
38 uint16_t UsageStack[HID_USAGE_STACK_DEPTH];
39 uint8_t UsageStackSize = 0;
40 uint16_t BitOffsetIn = 0;
41 uint16_t BitOffsetOut = 0;
42 #if defined(HID_ENABLE_FEATURE_PROCESSING)
43 uint16_t BitOffsetFeature = 0;
44 #endif
45 HID_CollectionPath_t* CurrCollectionPath = NULL;
46
47 memset((void*)ParserData, 0x00, sizeof(HID_ReportInfo_t));
48 memset((void*)StateTable, 0x00, sizeof(StateTable));
49
50 while (ReportSize)
51 {
52 uint32_t ReportItemData = 0;
53
54 switch (*ReportData & DATA_SIZE_MASK)
55 {
56 case DATA_SIZE_4:
57 ReportItemData = *((uint32_t*)(ReportData + 1));
58 break;
59 case DATA_SIZE_2:
60 ReportItemData = *((uint16_t*)(ReportData + 1));
61 break;
62 case DATA_SIZE_1:
63 ReportItemData = *((uint8_t*)(ReportData + 1));
64 break;
65 }
66
67 switch (*ReportData & (TYPE_MASK | TAG_MASK))
68 {
69 case (TYPE_GLOBAL | TAG_GLOBAL_PUSH):
70 if (CurrStateTable == &StateTable[HID_STATETABLE_STACK_DEPTH])
71 return HID_PARSE_HIDStackOverflow;
72
73 memcpy((CurrStateTable - 1),
74 CurrStateTable,
75 sizeof(HID_ReportItem_t));
76
77 CurrStateTable++;
78 break;
79 case (TYPE_GLOBAL | TAG_GLOBAL_POP):
80 if (CurrStateTable == &StateTable[0])
81 return HID_PARSE_HIDStackUnderflow;
82
83 CurrStateTable--;
84 break;
85 case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE):
86 CurrStateTable->Attributes.Usage.Page = ReportItemData;
87 break;
88 case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN):
89 CurrStateTable->Attributes.Logical.Minimum = ReportItemData;
90 break;
91 case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX):
92 CurrStateTable->Attributes.Logical.Maximum = ReportItemData;
93 break;
94 case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN):
95 CurrStateTable->Attributes.Physical.Minimum = ReportItemData;
96 break;
97 case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX):
98 CurrStateTable->Attributes.Physical.Maximum = ReportItemData;
99 break;
100 case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP):
101 CurrStateTable->Attributes.Unit.Exponent = ReportItemData;
102 break;
103 case (TYPE_GLOBAL | TAG_GLOBAL_UNIT):
104 CurrStateTable->Attributes.Unit.Type = ReportItemData;
105 break;
106 case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE):
107 CurrStateTable->Attributes.BitSize = ReportItemData;
108 break;
109 case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT):
110 CurrStateTable->ReportCount = ReportItemData;
111 break;
112 case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID):
113 CurrStateTable->ReportID = ReportItemData;
114 break;
115 case (TYPE_LOCAL | TAG_LOCAL_USAGE):
116 if (UsageStackSize == HID_USAGE_STACK_DEPTH)
117 return HID_PARSE_UsageStackOverflow;
118
119 UsageStack[UsageStackSize++] = ReportItemData;
120 break;
121 case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN):
122 CurrStateTable->Attributes.Usage.MinMax.Minimum = ReportItemData;
123 break;
124 case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX):
125 CurrStateTable->Attributes.Usage.MinMax.Maximum = ReportItemData;
126 break;
127 case (TYPE_MAIN | TAG_MAIN_COLLECTION):
128 if (CurrCollectionPath == NULL)
129 {
130 CurrCollectionPath = &ParserData->CollectionPaths[0];
131 }
132 else
133 {
134 HID_CollectionPath_t* ParentCollectionPath = CurrCollectionPath;
135
136 CurrCollectionPath = &ParserData->CollectionPaths[1];
137
138 while (CurrCollectionPath->Parent != NULL);
139 {
140 if (CurrCollectionPath == &ParserData->CollectionPaths[HID_MAX_COLLECTIONS])
141 return HID_PARSE_InsufficientCollectionPaths;
142
143 CurrCollectionPath++;
144 }
145
146 CurrCollectionPath->Parent = ParentCollectionPath;
147 }
148
149 CurrCollectionPath->Type = ReportItemData;
150 CurrCollectionPath->Usage.Page = CurrStateTable->Attributes.Usage.Page;
151
152 if (UsageStackSize)
153 {
154 CurrCollectionPath->Usage.Usage = UsageStack[0];
155
156 for (uint8_t i = 0; i < UsageStackSize; i++)
157 UsageStack[i] = UsageStack[i + 1];
158
159 UsageStackSize--;
160 }
161 else
162 {
163 CurrCollectionPath->Usage.Usage = 0;
164 }
165
166 break;
167 case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION):
168 if (CurrCollectionPath == NULL)
169 return HID_PARSE_UnexpectedEndCollection;
170
171 CurrCollectionPath = CurrCollectionPath->Parent;
172
173 break;
174 case (TYPE_MAIN | TAG_MAIN_INPUT):
175 case (TYPE_MAIN | TAG_MAIN_OUTPUT):
176 #if defined(HID_ENABLE_FEATURE_PROCESSING)
177 case (TYPE_MAIN | TAG_MAIN_FEATURE):
178 #endif
179 for (uint8_t ReportItemNum = 0; ReportItemNum < CurrStateTable->ReportCount; ReportItemNum++)
180 {
181 HID_ReportItem_t* CurrReportItem = &ParserData->ReportItems[ParserData->TotalReportItems];
182
183 if (ParserData->TotalReportItems == HID_MAX_REPORTITEMS)
184 return HID_PARSE_InsufficientReportItems;
185
186 memcpy(&CurrReportItem->Attributes,
187 &CurrStateTable->Attributes,
188 sizeof(HID_ReportItem_Attributes_t));
189
190 CurrReportItem->ItemFlags = ReportItemData;
191 CurrReportItem->CollectionPath = CurrCollectionPath;
192 CurrReportItem->ReportID = CurrStateTable->ReportID;
193
194 if (UsageStackSize)
195 {
196 CurrReportItem->Attributes.Usage.Usage = UsageStack[0];
197
198 for (uint8_t i = 0; i < UsageStackSize; i++)
199 UsageStack[i] = UsageStack[i + 1];
200
201 UsageStackSize--;
202 }
203 else
204 {
205 CurrReportItem->Attributes.Usage.Usage = 0;
206 }
207
208 switch (*ReportData & TAG_MASK)
209 {
210 case TAG_MAIN_INPUT:
211 CurrReportItem->ItemType = REPORT_ITEM_TYPE_In;
212 CurrReportItem->BitOffset = BitOffsetIn;
213
214 BitOffsetIn += CurrStateTable->Attributes.BitSize;
215
216 break;
217 case TAG_MAIN_OUTPUT:
218 CurrReportItem->ItemType = REPORT_ITEM_TYPE_Out;
219 CurrReportItem->BitOffset = BitOffsetOut;
220
221 BitOffsetOut += CurrStateTable->Attributes.BitSize;
222
223 break;
224 #if defined(HID_ENABLE_FEATURE_PROCESSING)
225 case TAG_MAIN_FEATURE:
226 CurrReportItem->ItemType = REPORT_ITEM_TYPE_Feature;
227 CurrReportItem->BitOffset = BitOffsetFeature;
228
229 BitOffsetFeature += CurrStateTable->Attributes.BitSize;
230
231 break;
232 #endif
233 }
234
235 #if !defined(HID_INCLUDE_CONSTANT_DATA_ITEMS)
236 if (!(ReportItemData & IOF_CONSTANT))
237 ParserData->TotalReportItems++;
238 #else
239 ParserData->TotalReportItems++;
240 #endif
241 }
242
243 UsageStackSize = 0;
244
245 break;
246 }
247
248 if ((*ReportData & TYPE_MASK) == TYPE_MAIN)
249 {
250 CurrStateTable->Attributes.Usage.MinMax.Minimum = 0;
251 CurrStateTable->Attributes.Usage.MinMax.Maximum = 0;
252 UsageStackSize = 0;
253 }
254
255 switch (*ReportData & DATA_SIZE_MASK)
256 {
257 case DATA_SIZE_4:
258 ReportSize -= 5;
259 ReportData += 5;
260 break;
261 case DATA_SIZE_2:
262 ReportSize -= 3;
263 ReportData += 3;
264 break;
265 case DATA_SIZE_1:
266 ReportSize -= 2;
267 ReportData += 2;
268 break;
269 case DATA_SIZE_0:
270 ReportSize -= 1;
271 ReportData += 1;
272 break;
273 }
274 }
275
276 return HID_PARSE_Successful;
277 }
278
279 bool USB_GetHIDReportItemInfo(const uint8_t* ReportData, HID_ReportItem_t* const ReportItem)
280 {
281 uint16_t DataBitsRem = ReportItem->Attributes.BitSize;
282 uint16_t CurrentBit = ReportItem->BitOffset;
283 uint32_t BitMask = (1 << 0);
284
285 ReportItem->Value = 0;
286
287 if (ReportItem->ReportID)
288 {
289 if (ReportItem->ReportID != ReportData[0])
290 return false;
291
292 ReportData++;
293 }
294
295 while (DataBitsRem--)
296 {
297 if (ReportData[CurrentBit / 8] & (1 << (CurrentBit % 8)))
298 ReportItem->Value |= BitMask;
299
300 CurrentBit++;
301 BitMask <<= 1;
302 }
303
304 return true;
305 }
306
307 void USB_SetHIDReportItemInfo(uint8_t* ReportData, const HID_ReportItem_t* ReportItem)
308 {
309 uint16_t DataBitsRem = ReportItem->Attributes.BitSize;
310 uint16_t CurrentBit = ReportItem->BitOffset;
311 uint32_t BitMask = (1 << 0);
312
313 if (ReportItem->ReportID)
314 {
315 ReportData[0] = ReportItem->ReportID;
316 ReportData++;
317 }
318
319 while (DataBitsRem--)
320 {
321 if (ReportItem->Value & (1 << (CurrentBit % 8)))
322 ReportData[CurrentBit / 8] |= BitMask;
323
324 CurrentBit++;
325 BitMask <<= 1;
326 }
327 }
328
329 #endif