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((void*)ParserData
, 0x00, sizeof(HID_ReportInfo_t
));
50 memset((void*)StateTable
, 0x00, sizeof(StateTable
));
54 uint32_t ReportItemData
= 0;
56 switch (*ReportData
& DATA_SIZE_MASK
)
59 ReportItemData
= *((uint32_t*)(ReportData
+ 1));
62 ReportItemData
= *((uint16_t*)(ReportData
+ 1));
65 ReportItemData
= *((uint8_t*)(ReportData
+ 1));
69 switch (*ReportData
& (TYPE_MASK
| TAG_MASK
))
71 case (TYPE_GLOBAL
| TAG_GLOBAL_PUSH
):
72 if (CurrStateTable
== &StateTable
[HID_STATETABLE_STACK_DEPTH
])
73 return HID_PARSE_HIDStackOverflow
;
75 memcpy((CurrStateTable
- 1),
77 sizeof(HID_ReportItem_t
));
81 case (TYPE_GLOBAL
| TAG_GLOBAL_POP
):
82 if (CurrStateTable
== &StateTable
[0])
83 return HID_PARSE_HIDStackUnderflow
;
87 case (TYPE_GLOBAL
| TAG_GLOBAL_USAGEPAGE
):
88 CurrStateTable
->Attributes
.Usage
.Page
= ReportItemData
;
90 case (TYPE_GLOBAL
| TAG_GLOBAL_LOGICALMIN
):
91 CurrStateTable
->Attributes
.Logical
.Minimum
= ReportItemData
;
93 case (TYPE_GLOBAL
| TAG_GLOBAL_LOGICALMAX
):
94 CurrStateTable
->Attributes
.Logical
.Maximum
= ReportItemData
;
96 case (TYPE_GLOBAL
| TAG_GLOBAL_PHYSMIN
):
97 CurrStateTable
->Attributes
.Physical
.Minimum
= ReportItemData
;
99 case (TYPE_GLOBAL
| TAG_GLOBAL_PHYSMAX
):
100 CurrStateTable
->Attributes
.Physical
.Maximum
= ReportItemData
;
102 case (TYPE_GLOBAL
| TAG_GLOBAL_UNITEXP
):
103 CurrStateTable
->Attributes
.Unit
.Exponent
= ReportItemData
;
105 case (TYPE_GLOBAL
| TAG_GLOBAL_UNIT
):
106 CurrStateTable
->Attributes
.Unit
.Type
= ReportItemData
;
108 case (TYPE_GLOBAL
| TAG_GLOBAL_REPORTSIZE
):
109 CurrStateTable
->Attributes
.BitSize
= ReportItemData
;
111 case (TYPE_GLOBAL
| TAG_GLOBAL_REPORTCOUNT
):
112 CurrStateTable
->ReportCount
= ReportItemData
;
114 case (TYPE_GLOBAL
| TAG_GLOBAL_REPORTID
):
115 CurrStateTable
->ReportID
= ReportItemData
;
119 case (TYPE_LOCAL
| TAG_LOCAL_USAGE
):
120 if (UsageStackSize
== HID_USAGE_STACK_DEPTH
)
121 return HID_PARSE_UsageStackOverflow
;
123 UsageStack
[UsageStackSize
++] = ReportItemData
;
125 case (TYPE_LOCAL
| TAG_LOCAL_USAGEMIN
):
126 CurrStateTable
->Attributes
.Usage
.MinMax
.Minimum
= ReportItemData
;
128 case (TYPE_LOCAL
| TAG_LOCAL_USAGEMAX
):
129 CurrStateTable
->Attributes
.Usage
.MinMax
.Maximum
= ReportItemData
;
131 case (TYPE_MAIN
| TAG_MAIN_COLLECTION
):
132 if (CurrCollectionPath
== NULL
)
134 CurrCollectionPath
= &ParserData
->CollectionPaths
[0];
138 HID_CollectionPath_t
* ParentCollectionPath
= CurrCollectionPath
;
140 CurrCollectionPath
= &ParserData
->CollectionPaths
[1];
142 while (CurrCollectionPath
->Parent
!= NULL
);
144 if (CurrCollectionPath
== &ParserData
->CollectionPaths
[HID_MAX_COLLECTIONS
])
145 return HID_PARSE_InsufficientCollectionPaths
;
147 CurrCollectionPath
++;
150 CurrCollectionPath
->Parent
= ParentCollectionPath
;
153 CurrCollectionPath
->Type
= ReportItemData
;
154 CurrCollectionPath
->Usage
.Page
= CurrStateTable
->Attributes
.Usage
.Page
;
158 CurrCollectionPath
->Usage
.Usage
= UsageStack
[0];
160 for (uint8_t i
= 0; i
< UsageStackSize
; i
++)
161 UsageStack
[i
] = UsageStack
[i
+ 1];
167 CurrCollectionPath
->Usage
.Usage
= 0;
171 case (TYPE_MAIN
| TAG_MAIN_ENDCOLLECTION
):
172 if (CurrCollectionPath
== NULL
)
173 return HID_PARSE_UnexpectedEndCollection
;
175 CurrCollectionPath
= CurrCollectionPath
->Parent
;
178 case (TYPE_MAIN
| TAG_MAIN_INPUT
):
179 case (TYPE_MAIN
| TAG_MAIN_OUTPUT
):
180 #if defined(HID_ENABLE_FEATURE_PROCESSING)
181 case (TYPE_MAIN
| TAG_MAIN_FEATURE
):
183 for (uint8_t ReportItemNum
= 0; ReportItemNum
< CurrStateTable
->ReportCount
; ReportItemNum
++)
185 HID_ReportItem_t
* CurrReportItem
= &ParserData
->ReportItems
[ParserData
->TotalReportItems
];
187 if (ParserData
->TotalReportItems
== HID_MAX_REPORTITEMS
)
188 return HID_PARSE_InsufficientReportItems
;
190 memcpy(&CurrReportItem
->Attributes
,
191 &CurrStateTable
->Attributes
,
192 sizeof(HID_ReportItem_Attributes_t
));
194 CurrReportItem
->ItemFlags
= ReportItemData
;
195 CurrReportItem
->CollectionPath
= CurrCollectionPath
;
196 CurrReportItem
->ReportID
= CurrStateTable
->ReportID
;
200 CurrReportItem
->Attributes
.Usage
.Usage
= UsageStack
[0];
202 for (uint8_t i
= 0; i
< UsageStackSize
; i
++)
203 UsageStack
[i
] = UsageStack
[i
+ 1];
209 CurrReportItem
->Attributes
.Usage
.Usage
= 0;
212 switch (*ReportData
& TAG_MASK
)
215 CurrReportItem
->ItemType
= REPORT_ITEM_TYPE_In
;
216 CurrReportItem
->BitOffset
= BitOffsetIn
;
218 BitOffsetIn
+= CurrStateTable
->Attributes
.BitSize
;
221 case TAG_MAIN_OUTPUT
:
222 CurrReportItem
->ItemType
= REPORT_ITEM_TYPE_Out
;
223 CurrReportItem
->BitOffset
= BitOffsetOut
;
225 BitOffsetOut
+= CurrStateTable
->Attributes
.BitSize
;
228 #if defined(HID_ENABLE_FEATURE_PROCESSING)
229 case TAG_MAIN_FEATURE
:
230 CurrReportItem
->ItemType
= REPORT_ITEM_TYPE_Feature
;
231 CurrReportItem
->BitOffset
= BitOffsetFeature
;
233 BitOffsetFeature
+= CurrStateTable
->Attributes
.BitSize
;
239 #if !defined(HID_INCLUDE_CONSTANT_DATA_ITEMS)
240 if (!(ReportItemData
& IOF_CONSTANT
))
241 ParserData
->TotalReportItems
++;
243 ParserData
->TotalReportItems
++;
252 if ((*ReportData
& TYPE_MASK
) == TYPE_MAIN
)
254 CurrStateTable
->Attributes
.Usage
.MinMax
.Minimum
= 0;
255 CurrStateTable
->Attributes
.Usage
.MinMax
.Maximum
= 0;
259 switch (*ReportData
& DATA_SIZE_MASK
)
280 return HID_PARSE_Successful
;
283 bool USB_GetHIDReportItemInfo(const uint8_t* ReportData
, HID_ReportItem_t
* const ReportItem
)
285 uint16_t DataBitsRem
= ReportItem
->Attributes
.BitSize
;
286 uint16_t CurrentBit
= ReportItem
->BitOffset
;
287 uint32_t BitMask
= (1 << 0);
289 ReportItem
->Value
= 0;
291 if (ReportItem
->ReportID
)
293 if (ReportItem
->ReportID
!= ReportData
[0])
299 while (DataBitsRem
--)
301 if (ReportData
[CurrentBit
/ 8] & (1 << (CurrentBit
% 8)))
302 ReportItem
->Value
|= BitMask
;
311 void USB_SetHIDReportItemInfo(uint8_t* ReportData
, const HID_ReportItem_t
* ReportItem
)
313 uint16_t DataBitsRem
= ReportItem
->Attributes
.BitSize
;
314 uint16_t CurrentBit
= ReportItem
->BitOffset
;
315 uint32_t BitMask
= (1 << 0);
317 if (ReportItem
->ReportID
)
319 ReportData
[0] = ReportItem
->ReportID
;
323 while (DataBitsRem
--)
325 if (ReportItem
->Value
& (1 << (CurrentBit
% 8)))
326 ReportData
[CurrentBit
/ 8] |= BitMask
;