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
;
117 case (TYPE_LOCAL
| TAG_LOCAL_USAGE
):
118 if (UsageStackSize
== HID_USAGE_STACK_DEPTH
)
119 return HID_PARSE_UsageStackOverflow
;
121 UsageStack
[UsageStackSize
++] = ReportItemData
;
123 case (TYPE_LOCAL
| TAG_LOCAL_USAGEMIN
):
124 CurrStateTable
->Attributes
.Usage
.MinMax
.Minimum
= ReportItemData
;
126 case (TYPE_LOCAL
| TAG_LOCAL_USAGEMAX
):
127 CurrStateTable
->Attributes
.Usage
.MinMax
.Maximum
= ReportItemData
;
129 case (TYPE_MAIN
| TAG_MAIN_COLLECTION
):
130 if (CurrCollectionPath
== NULL
)
132 CurrCollectionPath
= &ParserData
->CollectionPaths
[0];
136 HID_CollectionPath_t
* ParentCollectionPath
= CurrCollectionPath
;
138 CurrCollectionPath
= &ParserData
->CollectionPaths
[1];
140 while (CurrCollectionPath
->Parent
!= NULL
);
142 if (CurrCollectionPath
== &ParserData
->CollectionPaths
[HID_MAX_COLLECTIONS
])
143 return HID_PARSE_InsufficientCollectionPaths
;
145 CurrCollectionPath
++;
148 CurrCollectionPath
->Parent
= ParentCollectionPath
;
151 CurrCollectionPath
->Type
= ReportItemData
;
152 CurrCollectionPath
->Usage
.Page
= CurrStateTable
->Attributes
.Usage
.Page
;
156 CurrCollectionPath
->Usage
.Usage
= UsageStack
[0];
158 for (uint8_t i
= 0; i
< UsageStackSize
; i
++)
159 UsageStack
[i
] = UsageStack
[i
+ 1];
165 CurrCollectionPath
->Usage
.Usage
= 0;
169 case (TYPE_MAIN
| TAG_MAIN_ENDCOLLECTION
):
170 if (CurrCollectionPath
== NULL
)
171 return HID_PARSE_UnexpectedEndCollection
;
173 CurrCollectionPath
= CurrCollectionPath
->Parent
;
176 case (TYPE_MAIN
| TAG_MAIN_INPUT
):
177 case (TYPE_MAIN
| TAG_MAIN_OUTPUT
):
178 #if defined(HID_ENABLE_FEATURE_PROCESSING)
179 case (TYPE_MAIN
| TAG_MAIN_FEATURE
):
181 for (uint8_t ReportItemNum
= 0; ReportItemNum
< CurrStateTable
->ReportCount
; ReportItemNum
++)
183 HID_ReportItem_t
* CurrReportItem
= &ParserData
->ReportItems
[ParserData
->TotalReportItems
];
185 if (ParserData
->TotalReportItems
== HID_MAX_REPORTITEMS
)
186 return HID_PARSE_InsufficientReportItems
;
188 memcpy(&CurrReportItem
->Attributes
,
189 &CurrStateTable
->Attributes
,
190 sizeof(HID_ReportItem_Attributes_t
));
192 CurrReportItem
->ItemFlags
= ReportItemData
;
193 CurrReportItem
->CollectionPath
= CurrCollectionPath
;
194 CurrReportItem
->ReportID
= CurrStateTable
->ReportID
;
198 CurrReportItem
->Attributes
.Usage
.Usage
= UsageStack
[0];
200 for (uint8_t i
= 0; i
< UsageStackSize
; i
++)
201 UsageStack
[i
] = UsageStack
[i
+ 1];
207 CurrReportItem
->Attributes
.Usage
.Usage
= 0;
210 switch (*ReportData
& TAG_MASK
)
213 CurrReportItem
->ItemType
= REPORT_ITEM_TYPE_In
;
214 CurrReportItem
->BitOffset
= BitOffsetIn
;
216 BitOffsetIn
+= CurrStateTable
->Attributes
.BitSize
;
219 case TAG_MAIN_OUTPUT
:
220 CurrReportItem
->ItemType
= REPORT_ITEM_TYPE_Out
;
221 CurrReportItem
->BitOffset
= BitOffsetOut
;
223 BitOffsetOut
+= CurrStateTable
->Attributes
.BitSize
;
226 #if defined(HID_ENABLE_FEATURE_PROCESSING)
227 case TAG_MAIN_FEATURE
:
228 CurrReportItem
->ItemType
= REPORT_ITEM_TYPE_Feature
;
229 CurrReportItem
->BitOffset
= BitOffsetFeature
;
231 BitOffsetFeature
+= CurrStateTable
->Attributes
.BitSize
;
237 #if !defined(HID_INCLUDE_CONSTANT_DATA_ITEMS)
238 if (!(ReportItemData
& IOF_CONSTANT
))
239 ParserData
->TotalReportItems
++;
241 ParserData
->TotalReportItems
++;
250 if ((*ReportData
& TYPE_MASK
) == TYPE_MAIN
)
252 CurrStateTable
->Attributes
.Usage
.MinMax
.Minimum
= 0;
253 CurrStateTable
->Attributes
.Usage
.MinMax
.Maximum
= 0;
257 switch (*ReportData
& DATA_SIZE_MASK
)
278 return HID_PARSE_Successful
;
281 bool USB_GetHIDReportItemInfo(const uint8_t* ReportData
, HID_ReportItem_t
* const ReportItem
)
283 uint16_t DataBitsRem
= ReportItem
->Attributes
.BitSize
;
284 uint16_t CurrentBit
= ReportItem
->BitOffset
;
285 uint32_t BitMask
= (1 << 0);
287 ReportItem
->Value
= 0;
289 if (ReportItem
->ReportID
)
291 if (ReportItem
->ReportID
!= ReportData
[0])
297 while (DataBitsRem
--)
299 if (ReportData
[CurrentBit
/ 8] & (1 << (CurrentBit
% 8)))
300 ReportItem
->Value
|= BitMask
;
309 void USB_SetHIDReportItemInfo(uint8_t* ReportData
, const HID_ReportItem_t
* ReportItem
)
311 uint16_t DataBitsRem
= ReportItem
->Attributes
.BitSize
;
312 uint16_t CurrentBit
= ReportItem
->BitOffset
;
313 uint32_t BitMask
= (1 << 0);
315 if (ReportItem
->ReportID
)
317 ReportData
[0] = ReportItem
->ReportID
;
321 while (DataBitsRem
--)
323 if (ReportItem
->Value
& (1 << (CurrentBit
% 8)))
324 ReportData
[CurrentBit
/ 8] |= BitMask
;