3 Copyright (C) Dean Camera, 2011.
5 dean [at] fourwalledcubicle [dot] com
10 Copyright 2011 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
);
68 case HID_RI_DATA_BITS_16
:
69 ReportItemData
= *((uint16_t*)ReportData
);
73 case HID_RI_DATA_BITS_8
:
74 ReportItemData
= *((uint8_t*)ReportData
);
80 switch (HIDReportItem
& (HID_RI_TYPE_MASK
| HID_RI_TAG_MASK
))
83 if (CurrStateTable
== &StateTable
[HID_STATETABLE_STACK_DEPTH
- 1])
84 return HID_PARSE_HIDStackOverflow
;
86 memcpy((CurrStateTable
+ 1),
88 sizeof(HID_ReportItem_t
));
93 if (CurrStateTable
== &StateTable
[0])
94 return HID_PARSE_HIDStackUnderflow
;
98 case HID_RI_USAGE_PAGE(0):
99 CurrStateTable
->Attributes
.Usage
.Page
= ReportItemData
;
101 case HID_RI_LOGICAL_MINIMUM(0):
102 CurrStateTable
->Attributes
.Logical
.Minimum
= ReportItemData
;
104 case HID_RI_LOGICAL_MAXIMUM(0):
105 CurrStateTable
->Attributes
.Logical
.Maximum
= ReportItemData
;
107 case HID_RI_PHYSICAL_MINIMUM(0):
108 CurrStateTable
->Attributes
.Physical
.Minimum
= ReportItemData
;
110 case HID_RI_PHYSICAL_MAXIMUM(0):
111 CurrStateTable
->Attributes
.Physical
.Maximum
= ReportItemData
;
113 case HID_RI_UNIT_EXPONENT(0):
114 CurrStateTable
->Attributes
.Unit
.Exponent
= ReportItemData
;
117 CurrStateTable
->Attributes
.Unit
.Type
= ReportItemData
;
119 case HID_RI_REPORT_SIZE(0):
120 CurrStateTable
->Attributes
.BitSize
= ReportItemData
;
122 case HID_RI_REPORT_COUNT(0):
123 CurrStateTable
->ReportCount
= ReportItemData
;
125 case HID_RI_REPORT_ID(0):
126 CurrStateTable
->ReportID
= ReportItemData
;
128 if (ParserData
->UsingReportIDs
)
130 CurrReportIDInfo
= NULL
;
132 for (uint8_t i
= 0; i
< ParserData
->TotalDeviceReports
; i
++)
134 if (ParserData
->ReportIDSizes
[i
].ReportID
== CurrStateTable
->ReportID
)
136 CurrReportIDInfo
= &ParserData
->ReportIDSizes
[i
];
141 if (CurrReportIDInfo
== NULL
)
143 if (ParserData
->TotalDeviceReports
== HID_MAX_REPORT_IDS
)
144 return HID_PARSE_InsufficientReportIDItems
;
146 CurrReportIDInfo
= &ParserData
->ReportIDSizes
[ParserData
->TotalDeviceReports
++];
147 memset(CurrReportIDInfo
, 0x00, sizeof(HID_ReportSizeInfo_t
));
151 ParserData
->UsingReportIDs
= true;
153 CurrReportIDInfo
->ReportID
= CurrStateTable
->ReportID
;
155 case HID_RI_USAGE(0):
156 if (UsageListSize
== HID_USAGE_STACK_DEPTH
)
157 return HID_PARSE_UsageListOverflow
;
159 UsageList
[UsageListSize
++] = ReportItemData
;
161 case HID_RI_USAGE_MINIMUM(0):
162 UsageMinMax
.Minimum
= ReportItemData
;
164 case HID_RI_USAGE_MAXIMUM(0):
165 UsageMinMax
.Maximum
= ReportItemData
;
167 case HID_RI_COLLECTION(0):
168 if (CurrCollectionPath
== NULL
)
170 CurrCollectionPath
= &ParserData
->CollectionPaths
[0];
174 HID_CollectionPath_t
* ParentCollectionPath
= CurrCollectionPath
;
176 CurrCollectionPath
= &ParserData
->CollectionPaths
[1];
178 while (CurrCollectionPath
->Parent
!= NULL
)
180 if (CurrCollectionPath
== &ParserData
->CollectionPaths
[HID_MAX_COLLECTIONS
- 1])
181 return HID_PARSE_InsufficientCollectionPaths
;
183 CurrCollectionPath
++;
186 CurrCollectionPath
->Parent
= ParentCollectionPath
;
189 CurrCollectionPath
->Type
= ReportItemData
;
190 CurrCollectionPath
->Usage
.Page
= CurrStateTable
->Attributes
.Usage
.Page
;
194 CurrCollectionPath
->Usage
.Usage
= UsageList
[0];
196 for (uint8_t i
= 0; i
< UsageListSize
; i
++)
197 UsageList
[i
] = UsageList
[i
+ 1];
201 else if (UsageMinMax
.Minimum
<= UsageMinMax
.Maximum
)
203 CurrCollectionPath
->Usage
.Usage
= UsageMinMax
.Minimum
++;
207 case HID_RI_END_COLLECTION(0):
208 if (CurrCollectionPath
== NULL
)
209 return HID_PARSE_UnexpectedEndCollection
;
211 CurrCollectionPath
= CurrCollectionPath
->Parent
;
213 case HID_RI_INPUT(0):
214 case HID_RI_OUTPUT(0):
215 case HID_RI_FEATURE(0):
216 for (uint8_t ReportItemNum
= 0; ReportItemNum
< CurrStateTable
->ReportCount
; ReportItemNum
++)
218 HID_ReportItem_t NewReportItem
;
220 memcpy(&NewReportItem
.Attributes
,
221 &CurrStateTable
->Attributes
,
222 sizeof(HID_ReportItem_Attributes_t
));
224 NewReportItem
.ItemFlags
= ReportItemData
;
225 NewReportItem
.CollectionPath
= CurrCollectionPath
;
226 NewReportItem
.ReportID
= CurrStateTable
->ReportID
;
230 NewReportItem
.Attributes
.Usage
.Usage
= UsageList
[0];
232 for (uint8_t i
= 0; i
< UsageListSize
; i
++)
233 UsageList
[i
] = UsageList
[i
+ 1];
237 else if (UsageMinMax
.Minimum
<= UsageMinMax
.Maximum
)
239 NewReportItem
.Attributes
.Usage
.Usage
= UsageMinMax
.Minimum
++;
242 uint8_t ItemTypeTag
= (HIDReportItem
& (HID_RI_TYPE_MASK
| HID_RI_TAG_MASK
));
244 if (ItemTypeTag
== HID_RI_INPUT(0))
245 NewReportItem
.ItemType
= HID_REPORT_ITEM_In
;
246 else if (ItemTypeTag
== HID_RI_OUTPUT(0))
247 NewReportItem
.ItemType
= HID_REPORT_ITEM_Out
;
249 NewReportItem
.ItemType
= HID_REPORT_ITEM_Feature
;
251 NewReportItem
.BitOffset
= CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
];
253 CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
] += CurrStateTable
->Attributes
.BitSize
;
255 if (ParserData
->LargestReportSizeBits
< NewReportItem
.BitOffset
)
256 ParserData
->LargestReportSizeBits
= NewReportItem
.BitOffset
;
258 if (!(ReportItemData
& HID_IOF_CONSTANT
) && CALLBACK_HIDParser_FilterHIDReportItem(&NewReportItem
))
260 if (ParserData
->TotalReportItems
== HID_MAX_REPORTITEMS
)
261 return HID_PARSE_InsufficientReportItems
;
263 memcpy(&ParserData
->ReportItems
[ParserData
->TotalReportItems
],
264 &NewReportItem
, sizeof(HID_ReportItem_t
));
266 ParserData
->TotalReportItems
++;
273 if ((HIDReportItem
& HID_RI_TYPE_MASK
) == HID_RI_TYPE_MAIN
)
275 UsageMinMax
.Minimum
= 0;
276 UsageMinMax
.Maximum
= 0;
281 if (!(ParserData
->TotalReportItems
))
282 return HID_PARSE_NoUnfilteredReportItems
;
284 return HID_PARSE_Successful
;
287 bool USB_GetHIDReportItemInfo(const uint8_t* ReportData
,
288 HID_ReportItem_t
* const ReportItem
)
290 uint16_t DataBitsRem
= ReportItem
->Attributes
.BitSize
;
291 uint16_t CurrentBit
= ReportItem
->BitOffset
;
292 uint32_t BitMask
= (1 << 0);
294 if (ReportItem
->ReportID
)
296 if (ReportItem
->ReportID
!= ReportData
[0])
302 ReportItem
->PreviousValue
= ReportItem
->Value
;
303 ReportItem
->Value
= 0;
305 while (DataBitsRem
--)
307 if (ReportData
[CurrentBit
/ 8] & (1 << (CurrentBit
% 8)))
308 ReportItem
->Value
|= BitMask
;
317 void USB_SetHIDReportItemInfo(uint8_t* ReportData
,
318 HID_ReportItem_t
* const ReportItem
)
320 uint16_t DataBitsRem
= ReportItem
->Attributes
.BitSize
;
321 uint16_t CurrentBit
= ReportItem
->BitOffset
;
322 uint32_t BitMask
= (1 << 0);
324 if (ReportItem
->ReportID
)
326 ReportData
[0] = ReportItem
->ReportID
;
330 ReportItem
->PreviousValue
= ReportItem
->Value
;
332 while (DataBitsRem
--)
334 if (ReportItem
->Value
& (1 << (CurrentBit
% 8)))
335 ReportData
[CurrentBit
/ 8] |= BitMask
;
342 uint16_t USB_GetHIDReportSize(HID_ReportInfo_t
* const ParserData
,
343 const uint8_t ReportID
,
344 const uint8_t ReportType
)
346 for (uint8_t i
= 0; i
< HID_MAX_REPORT_IDS
; i
++)
348 uint16_t ReportSizeBits
= ParserData
->ReportIDSizes
[i
].ReportSizeBits
[ReportType
];
350 if (ParserData
->ReportIDSizes
[i
].ReportID
== ReportID
)
351 return ((ReportSizeBits
>> 3) + ((ReportSizeBits
& 0x07) ?
1 : 0));