3 Copyright (C) Dean Camera, 2010.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
10 Copyright 2010 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 #include "../../HighLevel/USBMode.h"
33 #if defined(USB_CAN_BE_HOST)
35 #include "HIDParser.h"
37 uint8_t USB_ProcessHIDReport(const uint8_t* ReportData
, uint16_t ReportSize
, 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
& DATA_SIZE_MASK
)
64 ReportItemData
= *((uint32_t*)ReportData
);
69 ReportItemData
= *((uint16_t*)ReportData
);
74 ReportItemData
= *((uint8_t*)ReportData
);
80 switch (HIDReportItem
& (TYPE_MASK
| TAG_MASK
))
82 case (TYPE_GLOBAL
| TAG_GLOBAL_PUSH
):
83 if (CurrStateTable
== &StateTable
[HID_STATETABLE_STACK_DEPTH
- 1])
84 return HID_PARSE_HIDStackOverflow
;
86 memcpy((CurrStateTable
+ 1),
88 sizeof(HID_ReportItem_t
));
92 case (TYPE_GLOBAL
| TAG_GLOBAL_POP
):
93 if (CurrStateTable
== &StateTable
[0])
94 return HID_PARSE_HIDStackUnderflow
;
98 case (TYPE_GLOBAL
| TAG_GLOBAL_USAGEPAGE
):
99 CurrStateTable
->Attributes
.Usage
.Page
= ReportItemData
;
101 case (TYPE_GLOBAL
| TAG_GLOBAL_LOGICALMIN
):
102 CurrStateTable
->Attributes
.Logical
.Minimum
= ReportItemData
;
104 case (TYPE_GLOBAL
| TAG_GLOBAL_LOGICALMAX
):
105 CurrStateTable
->Attributes
.Logical
.Maximum
= ReportItemData
;
107 case (TYPE_GLOBAL
| TAG_GLOBAL_PHYSMIN
):
108 CurrStateTable
->Attributes
.Physical
.Minimum
= ReportItemData
;
110 case (TYPE_GLOBAL
| TAG_GLOBAL_PHYSMAX
):
111 CurrStateTable
->Attributes
.Physical
.Maximum
= ReportItemData
;
113 case (TYPE_GLOBAL
| TAG_GLOBAL_UNITEXP
):
114 CurrStateTable
->Attributes
.Unit
.Exponent
= ReportItemData
;
116 case (TYPE_GLOBAL
| TAG_GLOBAL_UNIT
):
117 CurrStateTable
->Attributes
.Unit
.Type
= ReportItemData
;
119 case (TYPE_GLOBAL
| TAG_GLOBAL_REPORTSIZE
):
120 CurrStateTable
->Attributes
.BitSize
= ReportItemData
;
122 case (TYPE_GLOBAL
| TAG_GLOBAL_REPORTCOUNT
):
123 CurrStateTable
->ReportCount
= ReportItemData
;
125 case (TYPE_GLOBAL
| TAG_GLOBAL_REPORTID
):
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 (TYPE_LOCAL
| TAG_LOCAL_USAGE
):
156 if (UsageListSize
== HID_USAGE_STACK_DEPTH
)
157 return HID_PARSE_UsageListOverflow
;
159 UsageList
[UsageListSize
++] = ReportItemData
;
161 case (TYPE_LOCAL
| TAG_LOCAL_USAGEMIN
):
162 UsageMinMax
.Minimum
= ReportItemData
;
164 case (TYPE_LOCAL
| TAG_LOCAL_USAGEMAX
):
165 UsageMinMax
.Maximum
= ReportItemData
;
167 case (TYPE_MAIN
| TAG_MAIN_COLLECTION
):
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 (TYPE_MAIN
| TAG_MAIN_ENDCOLLECTION
):
208 if (CurrCollectionPath
== NULL
)
209 return HID_PARSE_UnexpectedEndCollection
;
211 CurrCollectionPath
= CurrCollectionPath
->Parent
;
213 case (TYPE_MAIN
| TAG_MAIN_INPUT
):
214 case (TYPE_MAIN
| TAG_MAIN_OUTPUT
):
215 case (TYPE_MAIN
| TAG_MAIN_FEATURE
):
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 ItemTag
= (HIDReportItem
& TAG_MASK
);
244 if (ItemTag
== TAG_MAIN_INPUT
)
245 NewReportItem
.ItemType
= REPORT_ITEM_TYPE_In
;
246 else if (ItemTag
== TAG_MAIN_OUTPUT
)
247 NewReportItem
.ItemType
= REPORT_ITEM_TYPE_Out
;
249 NewReportItem
.ItemType
= REPORT_ITEM_TYPE_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
& 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
& TYPE_MASK
) == 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
, HID_ReportItem_t
* const ReportItem
)
289 uint16_t DataBitsRem
= ReportItem
->Attributes
.BitSize
;
290 uint16_t CurrentBit
= ReportItem
->BitOffset
;
291 uint32_t BitMask
= (1 << 0);
293 ReportItem
->PreviousValue
= ReportItem
->Value
;
294 ReportItem
->Value
= 0;
296 if (ReportItem
->ReportID
)
298 if (ReportItem
->ReportID
!= ReportData
[0])
304 while (DataBitsRem
--)
306 if (ReportData
[CurrentBit
/ 8] & (1 << (CurrentBit
% 8)))
307 ReportItem
->Value
|= BitMask
;
316 void USB_SetHIDReportItemInfo(uint8_t* ReportData
, HID_ReportItem_t
* const ReportItem
)
318 uint16_t DataBitsRem
= ReportItem
->Attributes
.BitSize
;
319 uint16_t CurrentBit
= ReportItem
->BitOffset
;
320 uint32_t BitMask
= (1 << 0);
322 if (ReportItem
->ReportID
)
324 ReportData
[0] = ReportItem
->ReportID
;
328 ReportItem
->PreviousValue
= ReportItem
->Value
;
330 while (DataBitsRem
--)
332 if (ReportItem
->Value
& (1 << (CurrentBit
% 8)))
333 ReportData
[CurrentBit
/ 8] |= BitMask
;
340 uint16_t USB_GetHIDReportSize(HID_ReportInfo_t
* const ParserData
, const uint8_t ReportID
, const uint8_t ReportType
)
342 for (uint8_t i
= 0; i
< HID_MAX_REPORT_IDS
; i
++)
344 uint16_t ReportSizeBits
= ParserData
->ReportIDSizes
[i
].ReportSizeBits
[ReportType
];
346 if (ParserData
->ReportIDSizes
[i
].ReportID
== ReportID
)
347 return ((ReportSizeBits
>> 3) + ((ReportSizeBits
& 0x07) ?
1 : 0));