]> git.gir.st - tmk_keyboard.git/blob - protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Common/HIDParser.c
Change TOP_DIR to TMK_DIR in makefiles
[tmk_keyboard.git] / protocol / lufa / LUFA-120730 / LUFA / Drivers / USB / Class / Common / HIDParser.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2012.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all 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 #define __INCLUDE_FROM_USB_DRIVER
32 #define __INCLUDE_FROM_HID_DRIVER
33 #include "HIDParser.h"
34
35 uint8_t USB_ProcessHIDReport(const uint8_t* ReportData,
36 uint16_t ReportSize,
37 HID_ReportInfo_t* const ParserData)
38 {
39 HID_StateTable_t StateTable[HID_STATETABLE_STACK_DEPTH];
40 HID_StateTable_t* CurrStateTable = &StateTable[0];
41 HID_CollectionPath_t* CurrCollectionPath = NULL;
42 HID_ReportSizeInfo_t* CurrReportIDInfo = &ParserData->ReportIDSizes[0];
43 uint16_t UsageList[HID_USAGE_STACK_DEPTH];
44 uint8_t UsageListSize = 0;
45 HID_MinMax_t UsageMinMax = {0, 0};
46
47 memset(ParserData, 0x00, sizeof(HID_ReportInfo_t));
48 memset(CurrStateTable, 0x00, sizeof(HID_StateTable_t));
49 memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t));
50
51 ParserData->TotalDeviceReports = 1;
52
53 while (ReportSize)
54 {
55 uint8_t HIDReportItem = *ReportData;
56 uint32_t ReportItemData = 0;
57
58 ReportData++;
59 ReportSize--;
60
61 switch (HIDReportItem & HID_RI_DATA_SIZE_MASK)
62 {
63 case HID_RI_DATA_BITS_32:
64 ReportItemData = (((uint32_t)ReportData[3] << 24) | ((uint32_t)ReportData[2] << 16) |
65 ((uint16_t)ReportData[1] << 8) | ReportData[0]);
66 ReportSize -= 4;
67 ReportData += 4;
68 break;
69 case HID_RI_DATA_BITS_16:
70 ReportItemData = (((uint16_t)ReportData[1] << 8) | (ReportData[0]));
71 ReportSize -= 2;
72 ReportData += 2;
73 break;
74 case HID_RI_DATA_BITS_8:
75 ReportItemData = ReportData[0];
76 ReportSize -= 1;
77 ReportData += 1;
78 break;
79 }
80
81 switch (HIDReportItem & (HID_RI_TYPE_MASK | HID_RI_TAG_MASK))
82 {
83 case HID_RI_PUSH(0):
84 if (CurrStateTable == &StateTable[HID_STATETABLE_STACK_DEPTH - 1])
85 return HID_PARSE_HIDStackOverflow;
86
87 memcpy((CurrStateTable + 1),
88 CurrStateTable,
89 sizeof(HID_ReportItem_t));
90
91 CurrStateTable++;
92 break;
93 case HID_RI_POP(0):
94 if (CurrStateTable == &StateTable[0])
95 return HID_PARSE_HIDStackUnderflow;
96
97 CurrStateTable--;
98 break;
99 case HID_RI_USAGE_PAGE(0):
100 if ((HIDReportItem & HID_RI_DATA_SIZE_MASK) == HID_RI_DATA_BITS_32)
101 CurrStateTable->Attributes.Usage.Page = (ReportItemData >> 16);
102
103 CurrStateTable->Attributes.Usage.Page = ReportItemData;
104 break;
105 case HID_RI_LOGICAL_MINIMUM(0):
106 CurrStateTable->Attributes.Logical.Minimum = ReportItemData;
107 break;
108 case HID_RI_LOGICAL_MAXIMUM(0):
109 CurrStateTable->Attributes.Logical.Maximum = ReportItemData;
110 break;
111 case HID_RI_PHYSICAL_MINIMUM(0):
112 CurrStateTable->Attributes.Physical.Minimum = ReportItemData;
113 break;
114 case HID_RI_PHYSICAL_MAXIMUM(0):
115 CurrStateTable->Attributes.Physical.Maximum = ReportItemData;
116 break;
117 case HID_RI_UNIT_EXPONENT(0):
118 CurrStateTable->Attributes.Unit.Exponent = ReportItemData;
119 break;
120 case HID_RI_UNIT(0):
121 CurrStateTable->Attributes.Unit.Type = ReportItemData;
122 break;
123 case HID_RI_REPORT_SIZE(0):
124 CurrStateTable->Attributes.BitSize = ReportItemData;
125 break;
126 case HID_RI_REPORT_COUNT(0):
127 CurrStateTable->ReportCount = ReportItemData;
128 break;
129 case HID_RI_REPORT_ID(0):
130 CurrStateTable->ReportID = ReportItemData;
131
132 if (ParserData->UsingReportIDs)
133 {
134 CurrReportIDInfo = NULL;
135
136 for (uint8_t i = 0; i < ParserData->TotalDeviceReports; i++)
137 {
138 if (ParserData->ReportIDSizes[i].ReportID == CurrStateTable->ReportID)
139 {
140 CurrReportIDInfo = &ParserData->ReportIDSizes[i];
141 break;
142 }
143 }
144
145 if (CurrReportIDInfo == NULL)
146 {
147 if (ParserData->TotalDeviceReports == HID_MAX_REPORT_IDS)
148 return HID_PARSE_InsufficientReportIDItems;
149
150 CurrReportIDInfo = &ParserData->ReportIDSizes[ParserData->TotalDeviceReports++];
151 memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t));
152 }
153 }
154
155 ParserData->UsingReportIDs = true;
156
157 CurrReportIDInfo->ReportID = CurrStateTable->ReportID;
158 break;
159 case HID_RI_USAGE(0):
160 if (UsageListSize == HID_USAGE_STACK_DEPTH)
161 return HID_PARSE_UsageListOverflow;
162
163 UsageList[UsageListSize++] = ReportItemData;
164 break;
165 case HID_RI_USAGE_MINIMUM(0):
166 UsageMinMax.Minimum = ReportItemData;
167 break;
168 case HID_RI_USAGE_MAXIMUM(0):
169 UsageMinMax.Maximum = ReportItemData;
170 break;
171 case HID_RI_COLLECTION(0):
172 if (CurrCollectionPath == NULL)
173 {
174 CurrCollectionPath = &ParserData->CollectionPaths[0];
175 }
176 else
177 {
178 HID_CollectionPath_t* ParentCollectionPath = CurrCollectionPath;
179
180 CurrCollectionPath = &ParserData->CollectionPaths[1];
181
182 while (CurrCollectionPath->Parent != NULL)
183 {
184 if (CurrCollectionPath == &ParserData->CollectionPaths[HID_MAX_COLLECTIONS - 1])
185 return HID_PARSE_InsufficientCollectionPaths;
186
187 CurrCollectionPath++;
188 }
189
190 CurrCollectionPath->Parent = ParentCollectionPath;
191 }
192
193 CurrCollectionPath->Type = ReportItemData;
194 CurrCollectionPath->Usage.Page = CurrStateTable->Attributes.Usage.Page;
195
196 if (UsageListSize)
197 {
198 CurrCollectionPath->Usage.Usage = UsageList[0];
199
200 for (uint8_t i = 0; i < UsageListSize; i++)
201 UsageList[i] = UsageList[i + 1];
202
203 UsageListSize--;
204 }
205 else if (UsageMinMax.Minimum <= UsageMinMax.Maximum)
206 {
207 CurrCollectionPath->Usage.Usage = UsageMinMax.Minimum++;
208 }
209
210 break;
211 case HID_RI_END_COLLECTION(0):
212 if (CurrCollectionPath == NULL)
213 return HID_PARSE_UnexpectedEndCollection;
214
215 CurrCollectionPath = CurrCollectionPath->Parent;
216 break;
217 case HID_RI_INPUT(0):
218 case HID_RI_OUTPUT(0):
219 case HID_RI_FEATURE(0):
220 for (uint8_t ReportItemNum = 0; ReportItemNum < CurrStateTable->ReportCount; ReportItemNum++)
221 {
222 HID_ReportItem_t NewReportItem;
223
224 memcpy(&NewReportItem.Attributes,
225 &CurrStateTable->Attributes,
226 sizeof(HID_ReportItem_Attributes_t));
227
228 NewReportItem.ItemFlags = ReportItemData;
229 NewReportItem.CollectionPath = CurrCollectionPath;
230 NewReportItem.ReportID = CurrStateTable->ReportID;
231
232 if (UsageListSize)
233 {
234 NewReportItem.Attributes.Usage.Usage = UsageList[0];
235
236 for (uint8_t i = 0; i < UsageListSize; i++)
237 UsageList[i] = UsageList[i + 1];
238
239 UsageListSize--;
240 }
241 else if (UsageMinMax.Minimum <= UsageMinMax.Maximum)
242 {
243 NewReportItem.Attributes.Usage.Usage = UsageMinMax.Minimum++;
244 }
245
246 uint8_t ItemTypeTag = (HIDReportItem & (HID_RI_TYPE_MASK | HID_RI_TAG_MASK));
247
248 if (ItemTypeTag == HID_RI_INPUT(0))
249 NewReportItem.ItemType = HID_REPORT_ITEM_In;
250 else if (ItemTypeTag == HID_RI_OUTPUT(0))
251 NewReportItem.ItemType = HID_REPORT_ITEM_Out;
252 else
253 NewReportItem.ItemType = HID_REPORT_ITEM_Feature;
254
255 NewReportItem.BitOffset = CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType];
256
257 CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType] += CurrStateTable->Attributes.BitSize;
258
259 ParserData->LargestReportSizeBits = MAX(ParserData->LargestReportSizeBits, CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType]);
260
261 if (ParserData->TotalReportItems == HID_MAX_REPORTITEMS)
262 return HID_PARSE_InsufficientReportItems;
263
264 memcpy(&ParserData->ReportItems[ParserData->TotalReportItems],
265 &NewReportItem, sizeof(HID_ReportItem_t));
266
267 if (!(ReportItemData & HID_IOF_CONSTANT) && CALLBACK_HIDParser_FilterHIDReportItem(&NewReportItem))
268 ParserData->TotalReportItems++;
269 }
270
271 break;
272 }
273
274 if ((HIDReportItem & HID_RI_TYPE_MASK) == HID_RI_TYPE_MAIN)
275 {
276 UsageMinMax.Minimum = 0;
277 UsageMinMax.Maximum = 0;
278 UsageListSize = 0;
279 }
280 }
281
282 if (!(ParserData->TotalReportItems))
283 return HID_PARSE_NoUnfilteredReportItems;
284
285 return HID_PARSE_Successful;
286 }
287
288 bool USB_GetHIDReportItemInfo(const uint8_t* ReportData,
289 HID_ReportItem_t* const ReportItem)
290 {
291 if (ReportItem == NULL)
292 return false;
293
294 uint16_t DataBitsRem = ReportItem->Attributes.BitSize;
295 uint16_t CurrentBit = ReportItem->BitOffset;
296 uint32_t BitMask = (1 << 0);
297
298 if (ReportItem->ReportID)
299 {
300 if (ReportItem->ReportID != ReportData[0])
301 return false;
302
303 ReportData++;
304 }
305
306 ReportItem->PreviousValue = ReportItem->Value;
307 ReportItem->Value = 0;
308
309 while (DataBitsRem--)
310 {
311 if (ReportData[CurrentBit / 8] & (1 << (CurrentBit % 8)))
312 ReportItem->Value |= BitMask;
313
314 CurrentBit++;
315 BitMask <<= 1;
316 }
317
318 return true;
319 }
320
321 void USB_SetHIDReportItemInfo(uint8_t* ReportData,
322 HID_ReportItem_t* const ReportItem)
323 {
324 if (ReportItem == NULL)
325 return;
326
327 uint16_t DataBitsRem = ReportItem->Attributes.BitSize;
328 uint16_t CurrentBit = ReportItem->BitOffset;
329 uint32_t BitMask = (1 << 0);
330
331 if (ReportItem->ReportID)
332 {
333 ReportData[0] = ReportItem->ReportID;
334 ReportData++;
335 }
336
337 ReportItem->PreviousValue = ReportItem->Value;
338
339 while (DataBitsRem--)
340 {
341 if (ReportItem->Value & (1 << (CurrentBit % 8)))
342 ReportData[CurrentBit / 8] |= BitMask;
343
344 CurrentBit++;
345 BitMask <<= 1;
346 }
347 }
348
349 uint16_t USB_GetHIDReportSize(HID_ReportInfo_t* const ParserData,
350 const uint8_t ReportID,
351 const uint8_t ReportType)
352 {
353 for (uint8_t i = 0; i < HID_MAX_REPORT_IDS; i++)
354 {
355 uint16_t ReportSizeBits = ParserData->ReportIDSizes[i].ReportSizeBits[ReportType];
356
357 if (ParserData->ReportIDSizes[i].ReportID == ReportID)
358 return (ReportSizeBits / 8) + ((ReportSizeBits % 8) ? 1 : 0);
359 }
360
361 return 0;
362 }
363
Imprint / Impressum