3 Copyright (C) Dean Camera, 2012.
5 dean [at] fourwalledcubicle [dot] com
10 Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
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.
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
31 #define __INCLUDE_FROM_USB_DRIVER
32 #define __INCLUDE_FROM_HID_DRIVER
33 #include "HIDParser.h"
35 uint8_t USB_ProcessHIDReport(const uint8_t* ReportData
,
37 HID_ReportInfo_t
* const ParserData
)
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};
47 memset(ParserData
, 0x00, sizeof(HID_ReportInfo_t
));
48 memset(CurrStateTable
, 0x00, sizeof(HID_StateTable_t
));
49 memset(CurrReportIDInfo
, 0x00, sizeof(HID_ReportSizeInfo_t
));
51 ParserData
->TotalDeviceReports
= 1;
55 uint8_t HIDReportItem
= *ReportData
;
56 uint32_t ReportItemData
= 0;
61 switch (HIDReportItem
& HID_RI_DATA_SIZE_MASK
)
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]);
69 case HID_RI_DATA_BITS_16
:
70 ReportItemData
= (((uint16_t)ReportData
[1] << 8) | (ReportData
[0]));
74 case HID_RI_DATA_BITS_8
:
75 ReportItemData
= ReportData
[0];
81 switch (HIDReportItem
& (HID_RI_TYPE_MASK
| HID_RI_TAG_MASK
))
84 if (CurrStateTable
== &StateTable
[HID_STATETABLE_STACK_DEPTH
- 1])
85 return HID_PARSE_HIDStackOverflow
;
87 memcpy((CurrStateTable
+ 1),
89 sizeof(HID_ReportItem_t
));
94 if (CurrStateTable
== &StateTable
[0])
95 return HID_PARSE_HIDStackUnderflow
;
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);
103 CurrStateTable
->Attributes
.Usage
.Page
= ReportItemData
;
105 case HID_RI_LOGICAL_MINIMUM(0):
106 CurrStateTable
->Attributes
.Logical
.Minimum
= ReportItemData
;
108 case HID_RI_LOGICAL_MAXIMUM(0):
109 CurrStateTable
->Attributes
.Logical
.Maximum
= ReportItemData
;
111 case HID_RI_PHYSICAL_MINIMUM(0):
112 CurrStateTable
->Attributes
.Physical
.Minimum
= ReportItemData
;
114 case HID_RI_PHYSICAL_MAXIMUM(0):
115 CurrStateTable
->Attributes
.Physical
.Maximum
= ReportItemData
;
117 case HID_RI_UNIT_EXPONENT(0):
118 CurrStateTable
->Attributes
.Unit
.Exponent
= ReportItemData
;
121 CurrStateTable
->Attributes
.Unit
.Type
= ReportItemData
;
123 case HID_RI_REPORT_SIZE(0):
124 CurrStateTable
->Attributes
.BitSize
= ReportItemData
;
126 case HID_RI_REPORT_COUNT(0):
127 CurrStateTable
->ReportCount
= ReportItemData
;
129 case HID_RI_REPORT_ID(0):
130 CurrStateTable
->ReportID
= ReportItemData
;
132 if (ParserData
->UsingReportIDs
)
134 CurrReportIDInfo
= NULL
;
136 for (uint8_t i
= 0; i
< ParserData
->TotalDeviceReports
; i
++)
138 if (ParserData
->ReportIDSizes
[i
].ReportID
== CurrStateTable
->ReportID
)
140 CurrReportIDInfo
= &ParserData
->ReportIDSizes
[i
];
145 if (CurrReportIDInfo
== NULL
)
147 if (ParserData
->TotalDeviceReports
== HID_MAX_REPORT_IDS
)
148 return HID_PARSE_InsufficientReportIDItems
;
150 CurrReportIDInfo
= &ParserData
->ReportIDSizes
[ParserData
->TotalDeviceReports
++];
151 memset(CurrReportIDInfo
, 0x00, sizeof(HID_ReportSizeInfo_t
));
155 ParserData
->UsingReportIDs
= true;
157 CurrReportIDInfo
->ReportID
= CurrStateTable
->ReportID
;
159 case HID_RI_USAGE(0):
160 if (UsageListSize
== HID_USAGE_STACK_DEPTH
)
161 return HID_PARSE_UsageListOverflow
;
163 UsageList
[UsageListSize
++] = ReportItemData
;
165 case HID_RI_USAGE_MINIMUM(0):
166 UsageMinMax
.Minimum
= ReportItemData
;
168 case HID_RI_USAGE_MAXIMUM(0):
169 UsageMinMax
.Maximum
= ReportItemData
;
171 case HID_RI_COLLECTION(0):
172 if (CurrCollectionPath
== NULL
)
174 CurrCollectionPath
= &ParserData
->CollectionPaths
[0];
178 HID_CollectionPath_t
* ParentCollectionPath
= CurrCollectionPath
;
180 CurrCollectionPath
= &ParserData
->CollectionPaths
[1];
182 while (CurrCollectionPath
->Parent
!= NULL
)
184 if (CurrCollectionPath
== &ParserData
->CollectionPaths
[HID_MAX_COLLECTIONS
- 1])
185 return HID_PARSE_InsufficientCollectionPaths
;
187 CurrCollectionPath
++;
190 CurrCollectionPath
->Parent
= ParentCollectionPath
;
193 CurrCollectionPath
->Type
= ReportItemData
;
194 CurrCollectionPath
->Usage
.Page
= CurrStateTable
->Attributes
.Usage
.Page
;
198 CurrCollectionPath
->Usage
.Usage
= UsageList
[0];
200 for (uint8_t i
= 0; i
< UsageListSize
; i
++)
201 UsageList
[i
] = UsageList
[i
+ 1];
205 else if (UsageMinMax
.Minimum
<= UsageMinMax
.Maximum
)
207 CurrCollectionPath
->Usage
.Usage
= UsageMinMax
.Minimum
++;
211 case HID_RI_END_COLLECTION(0):
212 if (CurrCollectionPath
== NULL
)
213 return HID_PARSE_UnexpectedEndCollection
;
215 CurrCollectionPath
= CurrCollectionPath
->Parent
;
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
++)
222 HID_ReportItem_t NewReportItem
;
224 memcpy(&NewReportItem
.Attributes
,
225 &CurrStateTable
->Attributes
,
226 sizeof(HID_ReportItem_Attributes_t
));
228 NewReportItem
.ItemFlags
= ReportItemData
;
229 NewReportItem
.CollectionPath
= CurrCollectionPath
;
230 NewReportItem
.ReportID
= CurrStateTable
->ReportID
;
234 NewReportItem
.Attributes
.Usage
.Usage
= UsageList
[0];
236 for (uint8_t i
= 0; i
< UsageListSize
; i
++)
237 UsageList
[i
] = UsageList
[i
+ 1];
241 else if (UsageMinMax
.Minimum
<= UsageMinMax
.Maximum
)
243 NewReportItem
.Attributes
.Usage
.Usage
= UsageMinMax
.Minimum
++;
246 uint8_t ItemTypeTag
= (HIDReportItem
& (HID_RI_TYPE_MASK
| HID_RI_TAG_MASK
));
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
;
253 NewReportItem
.ItemType
= HID_REPORT_ITEM_Feature
;
255 NewReportItem
.BitOffset
= CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
];
257 CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
] += CurrStateTable
->Attributes
.BitSize
;
259 ParserData
->LargestReportSizeBits
= MAX(ParserData
->LargestReportSizeBits
, CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
]);
261 if (ParserData
->TotalReportItems
== HID_MAX_REPORTITEMS
)
262 return HID_PARSE_InsufficientReportItems
;
264 memcpy(&ParserData
->ReportItems
[ParserData
->TotalReportItems
],
265 &NewReportItem
, sizeof(HID_ReportItem_t
));
267 if (!(ReportItemData
& HID_IOF_CONSTANT
) && CALLBACK_HIDParser_FilterHIDReportItem(&NewReportItem
))
268 ParserData
->TotalReportItems
++;
274 if ((HIDReportItem
& HID_RI_TYPE_MASK
) == HID_RI_TYPE_MAIN
)
276 UsageMinMax
.Minimum
= 0;
277 UsageMinMax
.Maximum
= 0;
282 if (!(ParserData
->TotalReportItems
))
283 return HID_PARSE_NoUnfilteredReportItems
;
285 return HID_PARSE_Successful
;
288 bool USB_GetHIDReportItemInfo(const uint8_t* ReportData
,
289 HID_ReportItem_t
* const ReportItem
)
291 if (ReportItem
== NULL
)
294 uint16_t DataBitsRem
= ReportItem
->Attributes
.BitSize
;
295 uint16_t CurrentBit
= ReportItem
->BitOffset
;
296 uint32_t BitMask
= (1 << 0);
298 if (ReportItem
->ReportID
)
300 if (ReportItem
->ReportID
!= ReportData
[0])
306 ReportItem
->PreviousValue
= ReportItem
->Value
;
307 ReportItem
->Value
= 0;
309 while (DataBitsRem
--)
311 if (ReportData
[CurrentBit
/ 8] & (1 << (CurrentBit
% 8)))
312 ReportItem
->Value
|= BitMask
;
321 void USB_SetHIDReportItemInfo(uint8_t* ReportData
,
322 HID_ReportItem_t
* const ReportItem
)
324 if (ReportItem
== NULL
)
327 uint16_t DataBitsRem
= ReportItem
->Attributes
.BitSize
;
328 uint16_t CurrentBit
= ReportItem
->BitOffset
;
329 uint32_t BitMask
= (1 << 0);
331 if (ReportItem
->ReportID
)
333 ReportData
[0] = ReportItem
->ReportID
;
337 ReportItem
->PreviousValue
= ReportItem
->Value
;
339 while (DataBitsRem
--)
341 if (ReportItem
->Value
& (1 << (CurrentBit
% 8)))
342 ReportData
[CurrentBit
/ 8] |= BitMask
;
349 uint16_t USB_GetHIDReportSize(HID_ReportInfo_t
* const ParserData
,
350 const uint8_t ReportID
,
351 const uint8_t ReportType
)
353 for (uint8_t i
= 0; i
< HID_MAX_REPORT_IDS
; i
++)
355 uint16_t ReportSizeBits
= ParserData
->ReportIDSizes
[i
].ReportSizeBits
[ReportType
];
357 if (ParserData
->ReportIDSizes
[i
].ReportID
== ReportID
)
358 return (ReportSizeBits
/ 8) + ((ReportSizeBits
% 8) ?
1 : 0);