3 Copyright (C) Dean Camera, 2009.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
12 Permission to use, copy, modify, and distribute this software
13 and its documentation for any purpose and without fee is hereby
14 granted, provided that the above copyright notice appear in all
15 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 #include "../../HighLevel/USBMode.h"
32 #if defined(USB_CAN_BE_HOST)
34 #include "HIDParser.h"
36 uint8_t USB_ProcessHIDReport(const uint8_t* ReportData
, uint16_t ReportSize
, HID_ReportInfo_t
* const ParserData
)
38 HID_StateTable_t StateTable
[HID_STATETABLE_STACK_DEPTH
];
39 HID_StateTable_t
* CurrStateTable
= &StateTable
[0];
40 uint16_t UsageStack
[HID_USAGE_STACK_DEPTH
];
41 uint8_t UsageStackSize
= 0;
42 uint16_t BitOffsetIn
= 0;
43 uint16_t BitOffsetOut
= 0;
44 #if defined(HID_ENABLE_FEATURE_PROCESSING)
45 uint16_t BitOffsetFeature
= 0;
47 HID_CollectionPath_t
* CurrCollectionPath
= NULL
;
49 memset(ParserData
, 0x00, sizeof(HID_ReportInfo_t
));
50 memset(StateTable
, 0x00, sizeof(StateTable
));
54 uint8_t HIDReportItem
= *ReportData
;
55 uint32_t ReportItemData
= 0;
60 switch (HIDReportItem
& DATA_SIZE_MASK
)
63 ReportItemData
= *((uint32_t*)ReportData
);
68 ReportItemData
= *((uint16_t*)ReportData
);
73 ReportItemData
= *((uint8_t*)ReportData
);
79 switch (HIDReportItem
& (TYPE_MASK
| TAG_MASK
))
81 case (TYPE_GLOBAL
| TAG_GLOBAL_PUSH
):
82 if (CurrStateTable
== &StateTable
[HID_STATETABLE_STACK_DEPTH
- 1])
83 return HID_PARSE_HIDStackOverflow
;
85 memcpy((CurrStateTable
+ 1),
87 sizeof(HID_ReportItem_t
));
91 case (TYPE_GLOBAL
| TAG_GLOBAL_POP
):
92 if (CurrStateTable
== &StateTable
[0])
93 return HID_PARSE_HIDStackUnderflow
;
97 case (TYPE_GLOBAL
| TAG_GLOBAL_USAGEPAGE
):
98 CurrStateTable
->Attributes
.Usage
.Page
= ReportItemData
;
100 case (TYPE_GLOBAL
| TAG_GLOBAL_LOGICALMIN
):
101 CurrStateTable
->Attributes
.Logical
.Minimum
= ReportItemData
;
103 case (TYPE_GLOBAL
| TAG_GLOBAL_LOGICALMAX
):
104 CurrStateTable
->Attributes
.Logical
.Maximum
= ReportItemData
;
106 case (TYPE_GLOBAL
| TAG_GLOBAL_PHYSMIN
):
107 CurrStateTable
->Attributes
.Physical
.Minimum
= ReportItemData
;
109 case (TYPE_GLOBAL
| TAG_GLOBAL_PHYSMAX
):
110 CurrStateTable
->Attributes
.Physical
.Maximum
= ReportItemData
;
112 case (TYPE_GLOBAL
| TAG_GLOBAL_UNITEXP
):
113 CurrStateTable
->Attributes
.Unit
.Exponent
= ReportItemData
;
115 case (TYPE_GLOBAL
| TAG_GLOBAL_UNIT
):
116 CurrStateTable
->Attributes
.Unit
.Type
= ReportItemData
;
118 case (TYPE_GLOBAL
| TAG_GLOBAL_REPORTSIZE
):
119 CurrStateTable
->Attributes
.BitSize
= ReportItemData
;
121 case (TYPE_GLOBAL
| TAG_GLOBAL_REPORTCOUNT
):
122 CurrStateTable
->ReportCount
= ReportItemData
;
124 case (TYPE_GLOBAL
| TAG_GLOBAL_REPORTID
):
125 CurrStateTable
->ReportID
= ReportItemData
;
126 ParserData
->UsingMultipleReports
= true;
130 #if defined(HID_ENABLE_FEATURE_PROCESSING)
131 BitOffsetFeature
= 0;
134 case (TYPE_LOCAL
| TAG_LOCAL_USAGE
):
135 if (UsageStackSize
== HID_USAGE_STACK_DEPTH
)
136 return HID_PARSE_UsageStackOverflow
;
138 UsageStack
[UsageStackSize
++] = ReportItemData
;
140 case (TYPE_LOCAL
| TAG_LOCAL_USAGEMIN
):
141 CurrStateTable
->Attributes
.Usage
.MinMax
.Minimum
= ReportItemData
;
143 case (TYPE_LOCAL
| TAG_LOCAL_USAGEMAX
):
144 CurrStateTable
->Attributes
.Usage
.MinMax
.Maximum
= ReportItemData
;
146 case (TYPE_MAIN
| TAG_MAIN_COLLECTION
):
147 if (CurrCollectionPath
== NULL
)
149 CurrCollectionPath
= &ParserData
->CollectionPaths
[0];
153 HID_CollectionPath_t
* ParentCollectionPath
= CurrCollectionPath
;
155 CurrCollectionPath
= &ParserData
->CollectionPaths
[1];
157 while (CurrCollectionPath
->Parent
!= NULL
);
159 if (CurrCollectionPath
== &ParserData
->CollectionPaths
[HID_MAX_COLLECTIONS
- 1])
160 return HID_PARSE_InsufficientCollectionPaths
;
162 CurrCollectionPath
++;
165 CurrCollectionPath
->Parent
= ParentCollectionPath
;
168 CurrCollectionPath
->Type
= ReportItemData
;
169 CurrCollectionPath
->Usage
.Page
= CurrStateTable
->Attributes
.Usage
.Page
;
173 CurrCollectionPath
->Usage
.Usage
= UsageStack
[0];
175 for (uint8_t i
= 0; i
< UsageStackSize
; i
++)
176 UsageStack
[i
] = UsageStack
[i
+ 1];
182 CurrCollectionPath
->Usage
.Usage
= 0;
186 case (TYPE_MAIN
| TAG_MAIN_ENDCOLLECTION
):
187 if (CurrCollectionPath
== NULL
)
188 return HID_PARSE_UnexpectedEndCollection
;
190 CurrCollectionPath
= CurrCollectionPath
->Parent
;
193 case (TYPE_MAIN
| TAG_MAIN_INPUT
):
194 case (TYPE_MAIN
| TAG_MAIN_OUTPUT
):
195 #if defined(HID_ENABLE_FEATURE_PROCESSING)
196 case (TYPE_MAIN
| TAG_MAIN_FEATURE
):
198 for (uint8_t ReportItemNum
= 0; ReportItemNum
< CurrStateTable
->ReportCount
; ReportItemNum
++)
200 HID_ReportItem_t
* CurrReportItem
= &ParserData
->ReportItems
[ParserData
->TotalReportItems
];
202 if (ParserData
->TotalReportItems
== HID_MAX_REPORTITEMS
)
203 return HID_PARSE_InsufficientReportItems
;
205 memcpy(&CurrReportItem
->Attributes
,
206 &CurrStateTable
->Attributes
,
207 sizeof(HID_ReportItem_Attributes_t
));
209 CurrReportItem
->ItemFlags
= ReportItemData
;
210 CurrReportItem
->CollectionPath
= CurrCollectionPath
;
211 CurrReportItem
->ReportID
= CurrStateTable
->ReportID
;
215 CurrReportItem
->Attributes
.Usage
.Usage
= UsageStack
[0];
217 for (uint8_t i
= 0; i
< UsageStackSize
; i
++)
218 UsageStack
[i
] = UsageStack
[i
+ 1];
224 CurrReportItem
->Attributes
.Usage
.Usage
= 0;
227 switch (HIDReportItem
& TAG_MASK
)
230 CurrReportItem
->ItemType
= REPORT_ITEM_TYPE_In
;
231 CurrReportItem
->BitOffset
= BitOffsetIn
;
233 BitOffsetIn
+= CurrStateTable
->Attributes
.BitSize
;
236 case TAG_MAIN_OUTPUT
:
237 CurrReportItem
->ItemType
= REPORT_ITEM_TYPE_Out
;
238 CurrReportItem
->BitOffset
= BitOffsetOut
;
240 BitOffsetOut
+= CurrStateTable
->Attributes
.BitSize
;
243 #if defined(HID_ENABLE_FEATURE_PROCESSING)
244 case TAG_MAIN_FEATURE
:
245 CurrReportItem
->ItemType
= REPORT_ITEM_TYPE_Feature
;
246 CurrReportItem
->BitOffset
= BitOffsetFeature
;
248 BitOffsetFeature
+= CurrStateTable
->Attributes
.BitSize
;
254 #if defined(HID_INCLUDE_CONSTANT_DATA_ITEMS)
255 ParserData
->TotalReportItems
++;
257 if (!(ReportItemData
& IOF_CONSTANT
))
258 ParserData
->TotalReportItems
++;
267 if ((HIDReportItem
& TYPE_MASK
) == TYPE_MAIN
)
269 CurrStateTable
->Attributes
.Usage
.MinMax
.Minimum
= 0;
270 CurrStateTable
->Attributes
.Usage
.MinMax
.Maximum
= 0;
275 return HID_PARSE_Successful
;
278 bool USB_GetHIDReportItemInfo(const uint8_t* ReportData
, HID_ReportItem_t
* const ReportItem
)
280 uint16_t DataBitsRem
= ReportItem
->Attributes
.BitSize
;
281 uint16_t CurrentBit
= ReportItem
->BitOffset
;
282 uint32_t BitMask
= (1 << 0);
284 ReportItem
->Value
= 0;
286 if (ReportItem
->ReportID
)
288 if (ReportItem
->ReportID
!= ReportData
[0])
294 while (DataBitsRem
--)
296 if (ReportData
[CurrentBit
/ 8] & (1 << (CurrentBit
% 8)))
297 ReportItem
->Value
|= BitMask
;
306 void USB_SetHIDReportItemInfo(uint8_t* ReportData
, const HID_ReportItem_t
* ReportItem
)
308 uint16_t DataBitsRem
= ReportItem
->Attributes
.BitSize
;
309 uint16_t CurrentBit
= ReportItem
->BitOffset
;
310 uint32_t BitMask
= (1 << 0);
312 if (ReportItem
->ReportID
)
314 ReportData
[0] = ReportItem
->ReportID
;
318 while (DataBitsRem
--)
320 if (ReportItem
->Value
& (1 << (CurrentBit
% 8)))
321 ReportData
[CurrentBit
/ 8] |= BitMask
;