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 "HIDParser.h"
32 #if defined(CAN_BE_HOST)
34 uint8_t USB_ProcessHIDReport(const uint8_t* ReportData
, uint16_t ReportSize
, HID_ReportInfo_t
* const ParserData
)
36 HID_StateTable_t StateTable
[HID_STATETABLE_STACK_DEPTH
];
37 HID_StateTable_t
* CurrStateTable
= &StateTable
[0];
38 uint16_t UsageStack
[HID_USAGE_STACK_DEPTH
];
39 uint8_t UsageStackSize
= 0;
40 uint16_t BitOffsetIn
= 0;
41 uint16_t BitOffsetOut
= 0;
42 #if defined(HID_ENABLE_FEATURE_PROCESSING)
43 uint16_t BitOffsetFeature
= 0;
45 HID_CollectionPath_t
* CurrCollectionPath
= NULL
;
47 memset((void*)ParserData
, 0x00, sizeof(HID_ReportInfo_t
));
48 memset((void*)StateTable
, 0x00, sizeof(StateTable
));
52 uint32_t ReportItemData
= 0;
54 switch (*ReportData
& DATA_SIZE_MASK
)
57 ReportItemData
= *((uint32_t*)(ReportData
+ 1));
60 ReportItemData
= *((uint16_t*)(ReportData
+ 1));
63 ReportItemData
= *((uint8_t*)(ReportData
+ 1));
67 switch (*ReportData
& (TYPE_MASK
| TAG_MASK
))
69 case (TYPE_GLOBAL
| TAG_GLOBAL_PUSH
):
70 if (CurrStateTable
== &StateTable
[HID_STATETABLE_STACK_DEPTH
])
71 return HID_PARSE_HIDStackOverflow
;
73 memcpy((CurrStateTable
- 1),
75 sizeof(HID_ReportItem_t
));
79 case (TYPE_GLOBAL
| TAG_GLOBAL_POP
):
80 if (CurrStateTable
== &StateTable
[0])
81 return HID_PARSE_HIDStackUnderflow
;
85 case (TYPE_GLOBAL
| TAG_GLOBAL_USAGEPAGE
):
86 CurrStateTable
->Attributes
.Usage
.Page
= ReportItemData
;
88 case (TYPE_GLOBAL
| TAG_GLOBAL_LOGICALMIN
):
89 CurrStateTable
->Attributes
.Logical
.Minimum
= ReportItemData
;
91 case (TYPE_GLOBAL
| TAG_GLOBAL_LOGICALMAX
):
92 CurrStateTable
->Attributes
.Logical
.Maximum
= ReportItemData
;
94 case (TYPE_GLOBAL
| TAG_GLOBAL_PHYSMIN
):
95 CurrStateTable
->Attributes
.Physical
.Minimum
= ReportItemData
;
97 case (TYPE_GLOBAL
| TAG_GLOBAL_PHYSMAX
):
98 CurrStateTable
->Attributes
.Physical
.Maximum
= ReportItemData
;
100 case (TYPE_GLOBAL
| TAG_GLOBAL_UNITEXP
):
101 CurrStateTable
->Attributes
.Unit
.Exponent
= ReportItemData
;
103 case (TYPE_GLOBAL
| TAG_GLOBAL_UNIT
):
104 CurrStateTable
->Attributes
.Unit
.Type
= ReportItemData
;
106 case (TYPE_GLOBAL
| TAG_GLOBAL_REPORTSIZE
):
107 CurrStateTable
->Attributes
.BitSize
= ReportItemData
;
109 case (TYPE_GLOBAL
| TAG_GLOBAL_REPORTCOUNT
):
110 CurrStateTable
->ReportCount
= ReportItemData
;
112 case (TYPE_GLOBAL
| TAG_GLOBAL_REPORTID
):
113 CurrStateTable
->ReportID
= ReportItemData
;
115 case (TYPE_LOCAL
| TAG_LOCAL_USAGE
):
116 if (UsageStackSize
== HID_USAGE_STACK_DEPTH
)
117 return HID_PARSE_UsageStackOverflow
;
119 UsageStack
[UsageStackSize
++] = ReportItemData
;
121 case (TYPE_LOCAL
| TAG_LOCAL_USAGEMIN
):
122 CurrStateTable
->Attributes
.Usage
.MinMax
.Minimum
= ReportItemData
;
124 case (TYPE_LOCAL
| TAG_LOCAL_USAGEMAX
):
125 CurrStateTable
->Attributes
.Usage
.MinMax
.Maximum
= ReportItemData
;
127 case (TYPE_MAIN
| TAG_MAIN_COLLECTION
):
128 if (CurrCollectionPath
== NULL
)
130 CurrCollectionPath
= &ParserData
->CollectionPaths
[0];
134 HID_CollectionPath_t
* ParentCollectionPath
= CurrCollectionPath
;
136 CurrCollectionPath
= &ParserData
->CollectionPaths
[1];
138 while (CurrCollectionPath
->Parent
!= NULL
);
140 if (CurrCollectionPath
== &ParserData
->CollectionPaths
[HID_MAX_COLLECTIONS
])
141 return HID_PARSE_InsufficientCollectionPaths
;
143 CurrCollectionPath
++;
146 CurrCollectionPath
->Parent
= ParentCollectionPath
;
149 CurrCollectionPath
->Type
= ReportItemData
;
150 CurrCollectionPath
->Usage
.Page
= CurrStateTable
->Attributes
.Usage
.Page
;
154 CurrCollectionPath
->Usage
.Usage
= UsageStack
[0];
156 for (uint8_t i
= 0; i
< UsageStackSize
; i
++)
157 UsageStack
[i
] = UsageStack
[i
+ 1];
163 CurrCollectionPath
->Usage
.Usage
= 0;
167 case (TYPE_MAIN
| TAG_MAIN_ENDCOLLECTION
):
168 if (CurrCollectionPath
== NULL
)
169 return HID_PARSE_UnexpectedEndCollection
;
171 CurrCollectionPath
= CurrCollectionPath
->Parent
;
174 case (TYPE_MAIN
| TAG_MAIN_INPUT
):
175 case (TYPE_MAIN
| TAG_MAIN_OUTPUT
):
176 #if defined(HID_ENABLE_FEATURE_PROCESSING)
177 case (TYPE_MAIN
| TAG_MAIN_FEATURE
):
179 for (uint8_t ReportItemNum
= 0; ReportItemNum
< CurrStateTable
->ReportCount
; ReportItemNum
++)
181 HID_ReportItem_t
* CurrReportItem
= &ParserData
->ReportItems
[ParserData
->TotalReportItems
];
183 if (ParserData
->TotalReportItems
== HID_MAX_REPORTITEMS
)
184 return HID_PARSE_InsufficientReportItems
;
186 memcpy(&CurrReportItem
->Attributes
,
187 &CurrStateTable
->Attributes
,
188 sizeof(HID_ReportItem_Attributes_t
));
190 CurrReportItem
->ItemFlags
= ReportItemData
;
191 CurrReportItem
->CollectionPath
= CurrCollectionPath
;
192 CurrReportItem
->ReportID
= CurrStateTable
->ReportID
;
196 CurrReportItem
->Attributes
.Usage
.Usage
= UsageStack
[0];
198 for (uint8_t i
= 0; i
< UsageStackSize
; i
++)
199 UsageStack
[i
] = UsageStack
[i
+ 1];
205 CurrReportItem
->Attributes
.Usage
.Usage
= 0;
208 switch (*ReportData
& TAG_MASK
)
211 CurrReportItem
->ItemType
= REPORT_ITEM_TYPE_In
;
212 CurrReportItem
->BitOffset
= BitOffsetIn
;
214 BitOffsetIn
+= CurrStateTable
->Attributes
.BitSize
;
217 case TAG_MAIN_OUTPUT
:
218 CurrReportItem
->ItemType
= REPORT_ITEM_TYPE_Out
;
219 CurrReportItem
->BitOffset
= BitOffsetOut
;
221 BitOffsetOut
+= CurrStateTable
->Attributes
.BitSize
;
224 #if defined(HID_ENABLE_FEATURE_PROCESSING)
225 case TAG_MAIN_FEATURE
:
226 CurrReportItem
->ItemType
= REPORT_ITEM_TYPE_Feature
;
227 CurrReportItem
->BitOffset
= BitOffsetFeature
;
229 BitOffsetFeature
+= CurrStateTable
->Attributes
.BitSize
;
235 #if !defined(HID_INCLUDE_CONSTANT_DATA_ITEMS)
236 if (!(ReportItemData
& IOF_CONSTANT
))
237 ParserData
->TotalReportItems
++;
239 ParserData
->TotalReportItems
++;
248 if ((*ReportData
& TYPE_MASK
) == TYPE_MAIN
)
250 CurrStateTable
->Attributes
.Usage
.MinMax
.Minimum
= 0;
251 CurrStateTable
->Attributes
.Usage
.MinMax
.Maximum
= 0;
255 switch (*ReportData
& DATA_SIZE_MASK
)
276 return HID_PARSE_Successful
;
279 bool USB_GetHIDReportItemInfo(const uint8_t* ReportData
, HID_ReportItem_t
* const ReportItem
)
281 uint16_t DataBitsRem
= ReportItem
->Attributes
.BitSize
;
282 uint16_t CurrentBit
= ReportItem
->BitOffset
;
283 uint32_t BitMask
= (1 << 0);
285 ReportItem
->Value
= 0;
287 if (ReportItem
->ReportID
)
289 if (ReportItem
->ReportID
!= ReportData
[0])
295 while (DataBitsRem
--)
297 if (ReportData
[CurrentBit
/ 8] & (1 << (CurrentBit
% 8)))
298 ReportItem
->Value
|= BitMask
;
307 void USB_SetHIDReportItemInfo(uint8_t* ReportData
, const HID_ReportItem_t
* ReportItem
)
309 uint16_t DataBitsRem
= ReportItem
->Attributes
.BitSize
;
310 uint16_t CurrentBit
= ReportItem
->BitOffset
;
311 uint32_t BitMask
= (1 << 0);
313 if (ReportItem
->ReportID
)
315 ReportData
[0] = ReportItem
->ReportID
;
319 while (DataBitsRem
--)
321 if (ReportItem
->Value
& (1 << (CurrentBit
% 8)))
322 ReportData
[CurrentBit
/ 8] |= BitMask
;