| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
HIDParser.c
Go to the documentation of this file.
1 /*
2 * @brief USB Human Interface Device (HID) Class report descriptor parser
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * Copyright(C) Dean Camera, 2011, 2012
7 * All rights reserved.
8 *
9 * @par
10 * Software that is described herein is for illustrative purposes only
11 * which provides customers with programming information regarding the
12 * LPC products. This software is supplied "AS IS" without any warranties of
13 * any kind, and NXP Semiconductors and its licensor disclaim any and
14 * all warranties, express or implied, including all implied warranties of
15 * merchantability, fitness for a particular purpose and non-infringement of
16 * intellectual property rights. NXP Semiconductors assumes no responsibility
17 * or liability for the use of the software, conveys no license or rights under any
18 * patent, copyright, mask work right, or any other intellectual property rights in
19 * or to any products. NXP Semiconductors reserves the right to make changes
20 * in the software without notification. NXP Semiconductors also makes no
21 * representation or warranty that such application will be suitable for the
22 * specified use without further testing or modification.
23 *
24 * @par
25 * Permission to use, copy, modify, and distribute this software and its
26 * documentation is hereby granted, under NXP Semiconductors' and its
27 * licensor's relevant copyrights in the software, without fee, provided that it
28 * is used in conjunction with NXP Semiconductors microcontrollers. This
29 * copyright, permission, and disclaimer notice must appear in all copies of
30 * this code.
31 */
32
33
34 #define __INCLUDE_FROM_USB_DRIVER
35 #define __INCLUDE_FROM_HID_DRIVER
36 #include "HIDParser.h"
37
38 uint8_t USB_ProcessHIDReport(const uint8_t* ReportData,
39 uint16_t ReportSize,
40 HID_ReportInfo_t* const ParserData)
41 {
42 HID_StateTable_t StateTable[HID_STATETABLE_STACK_DEPTH];
43 HID_StateTable_t* CurrStateTable = &StateTable[0];
44 HID_CollectionPath_t* CurrCollectionPath = NULL;
45 HID_ReportSizeInfo_t* CurrReportIDInfo = &ParserData->ReportIDSizes[0];
46 uint16_t UsageList[HID_USAGE_STACK_DEPTH];
47 uint8_t UsageListSize = 0;
48 HID_MinMax_t UsageMinMax = {0, 0};
49
50 memset(ParserData, 0x00, sizeof(HID_ReportInfo_t));
51 memset(CurrStateTable, 0x00, sizeof(HID_StateTable_t));
52 memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t));
53
54 ParserData->TotalDeviceReports = 1;
55
56 while (ReportSize)
57 {
58 uint8_t HIDReportItem = *ReportData;
59 uint32_t ReportItemData = 0;
60
61 ReportData++;
62 ReportSize--;
63
64 switch (HIDReportItem & HID_RI_DATA_SIZE_MASK)
65 {
66 case HID_RI_DATA_BITS_32:
67 ReportItemData = le32_to_cpu(*((uint32_t*)ReportData));
68 ReportSize -= 4;
69 ReportData += 4;
70 break;
71 case HID_RI_DATA_BITS_16:
72 ReportItemData = le16_to_cpu(*((uint16_t*)ReportData));
73 ReportSize -= 2;
74 ReportData += 2;
75 break;
76 case HID_RI_DATA_BITS_8:
77 ReportItemData = *((uint8_t*)ReportData);
78 ReportSize -= 1;
79 ReportData += 1;
80 break;
81 }
82
83 switch (HIDReportItem & (HID_RI_TYPE_MASK | HID_RI_TAG_MASK))
84 {
85 case HID_RI_PUSH(0):
86 if (CurrStateTable == &StateTable[HID_STATETABLE_STACK_DEPTH - 1])
87 return HID_PARSE_HIDStackOverflow;
88
89 memcpy((CurrStateTable + 1),
90 CurrStateTable,
91 sizeof(HID_ReportItem_t));
92
93 CurrStateTable++;
94 break;
95 case HID_RI_POP(0):
96 if (CurrStateTable == &StateTable[0])
97 return HID_PARSE_HIDStackUnderflow;
98
99 CurrStateTable--;
100 break;
101 case HID_RI_USAGE_PAGE(0):
102 if ((HIDReportItem & HID_RI_DATA_SIZE_MASK) == HID_RI_DATA_BITS_32)
103 CurrStateTable->Attributes.Usage.Page = (ReportItemData >> 16);
104
105 CurrStateTable->Attributes.Usage.Page = ReportItemData;
106 break;
107 case HID_RI_LOGICAL_MINIMUM(0):
108 CurrStateTable->Attributes.Logical.Minimum = ReportItemData;
109 break;
110 case HID_RI_LOGICAL_MAXIMUM(0):
111 CurrStateTable->Attributes.Logical.Maximum = ReportItemData;
112 break;
113 case HID_RI_PHYSICAL_MINIMUM(0):
114 CurrStateTable->Attributes.Physical.Minimum = ReportItemData;
115 break;
116 case HID_RI_PHYSICAL_MAXIMUM(0):
117 CurrStateTable->Attributes.Physical.Maximum = ReportItemData;
118 break;
119 case HID_RI_UNIT_EXPONENT(0):
120 CurrStateTable->Attributes.Unit.Exponent = ReportItemData;
121 break;
122 case HID_RI_UNIT(0):
123 CurrStateTable->Attributes.Unit.Type = ReportItemData;
124 break;
125 case HID_RI_REPORT_SIZE(0):
126 CurrStateTable->Attributes.BitSize = ReportItemData;
127 break;
128 case HID_RI_REPORT_COUNT(0):
129 CurrStateTable->ReportCount = ReportItemData;
130 break;
131 case HID_RI_REPORT_ID(0):
132 CurrStateTable->ReportID = ReportItemData;
133
134 if (ParserData->UsingReportIDs)
135 {
136 CurrReportIDInfo = NULL;
137
138 for (uint8_t i = 0; i < ParserData->TotalDeviceReports; i++)
139 {
140 if (ParserData->ReportIDSizes[i].ReportID == CurrStateTable->ReportID)
141 {
142 CurrReportIDInfo = &ParserData->ReportIDSizes[i];
143 break;
144 }
145 }
146
147 if (CurrReportIDInfo == NULL)
148 {
149 if (ParserData->TotalDeviceReports == HID_MAX_REPORT_IDS)
150 return HID_PARSE_InsufficientReportIDItems;
151
152 CurrReportIDInfo = &ParserData->ReportIDSizes[ParserData->TotalDeviceReports++];
153 memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t));
154 }
155 }
156
157 ParserData->UsingReportIDs = true;
158
159 CurrReportIDInfo->ReportID = CurrStateTable->ReportID;
160 break;
161 case HID_RI_USAGE(0):
162 if (UsageListSize == HID_USAGE_STACK_DEPTH)
163 return HID_PARSE_UsageListOverflow;
164
165 UsageList[UsageListSize++] = ReportItemData;
166 break;
167 case HID_RI_USAGE_MINIMUM(0):
168 UsageMinMax.Minimum = ReportItemData;
169 break;
170 case HID_RI_USAGE_MAXIMUM(0):
171 UsageMinMax.Maximum = ReportItemData;
172 break;
173 case HID_RI_COLLECTION(0):
174 if (CurrCollectionPath == NULL)
175 {
176 CurrCollectionPath = &ParserData->CollectionPaths[0];
177 }
178 else
179 {
180 HID_CollectionPath_t* ParentCollectionPath = CurrCollectionPath;
181
182 CurrCollectionPath = &ParserData->CollectionPaths[1];
183
184 while (CurrCollectionPath->Parent != NULL)
185 {
186 if (CurrCollectionPath == &ParserData->CollectionPaths[HID_MAX_COLLECTIONS - 1])
187 return HID_PARSE_InsufficientCollectionPaths;
188
189 CurrCollectionPath++;
190 }
191
192 CurrCollectionPath->Parent = ParentCollectionPath;
193 }
194
195 CurrCollectionPath->Type = ReportItemData;
196 CurrCollectionPath->Usage.Page = CurrStateTable->Attributes.Usage.Page;
197
198 if (UsageListSize)
199 {
200 CurrCollectionPath->Usage.Usage = UsageList[0];
201
202 for (uint8_t i = 0; i < UsageListSize; i++)
203 UsageList[i] = UsageList[i + 1];
204
205 UsageListSize--;
206 }
207 else if (UsageMinMax.Minimum <= UsageMinMax.Maximum)
208 {
209 CurrCollectionPath->Usage.Usage = UsageMinMax.Minimum++;
210 }
211
212 break;
213 case HID_RI_END_COLLECTION(0):
214 if (CurrCollectionPath == NULL)
215 return HID_PARSE_UnexpectedEndCollection;
216
217 CurrCollectionPath = CurrCollectionPath->Parent;
218 break;
219 case HID_RI_INPUT(0):
220 case HID_RI_OUTPUT(0):
221 case HID_RI_FEATURE(0):
222 for (uint8_t ReportItemNum = 0; ReportItemNum < CurrStateTable->ReportCount; ReportItemNum++)
223 {
224 HID_ReportItem_t NewReportItem;
225
226 memcpy(&NewReportItem.Attributes,
227 &CurrStateTable->Attributes,
228 sizeof(HID_ReportItem_Attributes_t));
229
230 NewReportItem.ItemFlags = ReportItemData;
231 NewReportItem.CollectionPath = CurrCollectionPath;
232 NewReportItem.ReportID = CurrStateTable->ReportID;
233
234 if (UsageListSize)
235 {
236 NewReportItem.Attributes.Usage.Usage = UsageList[0];
237
238 for (uint8_t i = 0; i < UsageListSize; i++)
239 UsageList[i] = UsageList[i + 1];
240
241 UsageListSize--;
242 }
243 else if (UsageMinMax.Minimum <= UsageMinMax.Maximum)
244 {
245 NewReportItem.Attributes.Usage.Usage = UsageMinMax.Minimum++;
246 }
247
248 uint8_t ItemTypeTag = (HIDReportItem & (HID_RI_TYPE_MASK | HID_RI_TAG_MASK));
249
250 if (ItemTypeTag == HID_RI_INPUT(0))
251 NewReportItem.ItemType = HID_REPORT_ITEM_In;
252 else if (ItemTypeTag == HID_RI_OUTPUT(0))
253 NewReportItem.ItemType = HID_REPORT_ITEM_Out;
254 else
255 NewReportItem.ItemType = HID_REPORT_ITEM_Feature;
256
257 NewReportItem.BitOffset = CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType];
258
259 CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType] += CurrStateTable->Attributes.BitSize;
260
261 if (ParserData->LargestReportSizeBits < NewReportItem.BitOffset)
262 ParserData->LargestReportSizeBits = NewReportItem.BitOffset;
263
264 if (ParserData->TotalReportItems == HID_MAX_REPORTITEMS)
265 return HID_PARSE_InsufficientReportItems;
266
267 memcpy(&ParserData->ReportItems[ParserData->TotalReportItems],
268 &NewReportItem, sizeof(HID_ReportItem_t));
269
270 if (!(ReportItemData & HID_IOF_CONSTANT) && CALLBACK_HIDParser_FilterHIDReportItem(&NewReportItem))
271 ParserData->TotalReportItems++;
272 }
273
274 break;
275 }
276
277 if ((HIDReportItem & HID_RI_TYPE_MASK) == HID_RI_TYPE_MAIN)
278 {
279 UsageMinMax.Minimum = 0;
280 UsageMinMax.Maximum = 0;
281 UsageListSize = 0;
282 }
283 }
284
285 if (!(ParserData->TotalReportItems))
286 return HID_PARSE_NoUnfilteredReportItems;
287
288 return HID_PARSE_Successful;
289 }
290
291 bool USB_GetHIDReportItemInfo(const uint8_t* ReportData,
292 HID_ReportItem_t* const ReportItem)
293 {
294 if (ReportItem == NULL)
295 return false;
296
297 uint16_t DataBitsRem = ReportItem->Attributes.BitSize;
298 uint16_t CurrentBit = ReportItem->BitOffset;
299 uint32_t BitMask = (1 << 0);
300
301 if (ReportItem->ReportID)
302 {
303 if (ReportItem->ReportID != ReportData[0])
304 return false;
305
306 ReportData++;
307 }
308
309 ReportItem->PreviousValue = ReportItem->Value;
310 ReportItem->Value = 0;
311
312 while (DataBitsRem--)
313 {
314 if (ReportData[CurrentBit / 8] & (1 << (CurrentBit % 8)))
315 ReportItem->Value |= BitMask;
316
317 CurrentBit++;
318 BitMask <<= 1;
319 }
320
321 return true;
322 }
323
324 void USB_SetHIDReportItemInfo(uint8_t* ReportData,
325 HID_ReportItem_t* const ReportItem)
326 {
327 if (ReportItem == NULL)
328 return;
329
330 uint16_t DataBitsRem = ReportItem->Attributes.BitSize;
331 uint16_t CurrentBit = ReportItem->BitOffset;
332 uint32_t BitMask = (1 << 0);
333
334 if (ReportItem->ReportID)
335 {
336 ReportData[0] = ReportItem->ReportID;
337 ReportData++;
338 }
339
340 ReportItem->PreviousValue = ReportItem->Value;
341
342 while (DataBitsRem--)
343 {
344 if (ReportItem->Value & (1 << (CurrentBit % 8)))
345 ReportData[CurrentBit / 8] |= BitMask;
346
347 CurrentBit++;
348 BitMask <<= 1;
349 }
350 }
351
352 uint16_t USB_GetHIDReportSize(HID_ReportInfo_t* const ParserData,
353 const uint8_t ReportID,
354 const uint8_t ReportType)
355 {
356 for (uint8_t i = 0; i < HID_MAX_REPORT_IDS; i++)
357 {
358 uint16_t ReportSizeBits = ParserData->ReportIDSizes[i].ReportSizeBits[ReportType];
359
360 if (ParserData->ReportIDSizes[i].ReportID == ReportID)
361 return (ReportSizeBits / 8) + ((ReportSizeBits % 8) ? 1 : 0);
362 }
363
364 return 0;
365 }