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         ParserData
->TotalReportItems     
= 0; 
  50         ParserData
->UsingMultipleReports 
= false; 
  52         for (uint8_t CurrCollection 
= 0; CurrCollection 
< HID_MAX_COLLECTIONS
; CurrCollection
++) 
  53           ParserData
->CollectionPaths
[CurrCollection
].Parent 
= NULL
; 
  55         memset(&StateTable
[0], 0x00, sizeof(HID_StateTable_t
)); 
  59                 uint8_t  HIDReportItem  
= *ReportData
; 
  60                 uint32_t ReportItemData 
= 0; 
  65                 switch (HIDReportItem 
& DATA_SIZE_MASK
) 
  68                                 ReportItemData  
= *((uint32_t*)ReportData
); 
  73                                 ReportItemData  
= *((uint16_t*)ReportData
); 
  78                                 ReportItemData  
= *((uint8_t*)ReportData
); 
  84                 switch (HIDReportItem 
& (TYPE_MASK 
| TAG_MASK
)) 
  86                         case (TYPE_GLOBAL 
| TAG_GLOBAL_PUSH
): 
  87                                 if (CurrStateTable 
== &StateTable
[HID_STATETABLE_STACK_DEPTH 
- 1]) 
  88                                   return HID_PARSE_HIDStackOverflow
; 
  90                                 memcpy((CurrStateTable 
+ 1), 
  92                                        sizeof(HID_ReportItem_t
)); 
  96                         case (TYPE_GLOBAL 
| TAG_GLOBAL_POP
): 
  97                                 if (CurrStateTable 
== &StateTable
[0]) 
  98                                   return HID_PARSE_HIDStackUnderflow
; 
 102                         case (TYPE_GLOBAL 
| TAG_GLOBAL_USAGEPAGE
): 
 103                                 CurrStateTable
->Attributes
.Usage
.Page       
= ReportItemData
; 
 105                         case (TYPE_GLOBAL 
| TAG_GLOBAL_LOGICALMIN
): 
 106                                 CurrStateTable
->Attributes
.Logical
.Minimum  
= ReportItemData
; 
 108                         case (TYPE_GLOBAL 
| TAG_GLOBAL_LOGICALMAX
): 
 109                                 CurrStateTable
->Attributes
.Logical
.Maximum  
= ReportItemData
; 
 111                         case (TYPE_GLOBAL 
| TAG_GLOBAL_PHYSMIN
): 
 112                                 CurrStateTable
->Attributes
.Physical
.Minimum 
= ReportItemData
; 
 114                         case (TYPE_GLOBAL 
| TAG_GLOBAL_PHYSMAX
): 
 115                                 CurrStateTable
->Attributes
.Physical
.Maximum 
= ReportItemData
; 
 117                         case (TYPE_GLOBAL 
| TAG_GLOBAL_UNITEXP
): 
 118                                 CurrStateTable
->Attributes
.Unit
.Exponent    
= ReportItemData
; 
 120                         case (TYPE_GLOBAL 
| TAG_GLOBAL_UNIT
): 
 121                                 CurrStateTable
->Attributes
.Unit
.Type        
= ReportItemData
; 
 123                         case (TYPE_GLOBAL 
| TAG_GLOBAL_REPORTSIZE
): 
 124                                 CurrStateTable
->Attributes
.BitSize          
= ReportItemData
; 
 126                         case (TYPE_GLOBAL 
| TAG_GLOBAL_REPORTCOUNT
): 
 127                                 CurrStateTable
->ReportCount                 
= ReportItemData
; 
 129                         case (TYPE_GLOBAL 
| TAG_GLOBAL_REPORTID
): 
 130                                 CurrStateTable
->ReportID                    
= ReportItemData
; 
 131                                 ParserData
->UsingMultipleReports 
= true; 
 135                                 #if defined(HID_ENABLE_FEATURE_PROCESSING) 
 136                                 BitOffsetFeature 
= 0; 
 139                         case (TYPE_LOCAL 
| TAG_LOCAL_USAGE
): 
 140                                 if (UsageStackSize 
== HID_USAGE_STACK_DEPTH
) 
 141                                   return HID_PARSE_UsageStackOverflow
; 
 143                                 UsageStack
[UsageStackSize
++] = ReportItemData
; 
 145                         case (TYPE_LOCAL 
| TAG_LOCAL_USAGEMIN
): 
 146                                 CurrStateTable
->Attributes
.Usage
.MinMax
.Minimum 
= ReportItemData
; 
 148                         case (TYPE_LOCAL 
| TAG_LOCAL_USAGEMAX
): 
 149                                 CurrStateTable
->Attributes
.Usage
.MinMax
.Maximum 
= ReportItemData
; 
 151                         case (TYPE_MAIN 
| TAG_MAIN_COLLECTION
): 
 152                                 if (CurrCollectionPath 
== NULL
) 
 154                                         CurrCollectionPath 
= &ParserData
->CollectionPaths
[0]; 
 158                                         HID_CollectionPath_t
* ParentCollectionPath 
= CurrCollectionPath
; 
 160                                         CurrCollectionPath 
= &ParserData
->CollectionPaths
[1]; 
 162                                         while (CurrCollectionPath
->Parent 
!= NULL
); 
 164                                                 if (CurrCollectionPath 
== &ParserData
->CollectionPaths
[HID_MAX_COLLECTIONS 
- 1]) 
 165                                                   return HID_PARSE_InsufficientCollectionPaths
; 
 167                                                 CurrCollectionPath
++; 
 170                                         CurrCollectionPath
->Parent 
= ParentCollectionPath
; 
 173                                 CurrCollectionPath
->Type 
= ReportItemData
; 
 174                                 CurrCollectionPath
->Usage
.Page 
= CurrStateTable
->Attributes
.Usage
.Page
; 
 178                                         CurrCollectionPath
->Usage
.Usage 
= UsageStack
[0]; 
 180                                         for (uint8_t i 
= 0; i 
< UsageStackSize
; i
++) 
 181                                           UsageStack
[i
] = UsageStack
[i 
+ 1]; 
 187                                         CurrCollectionPath
->Usage
.Usage 
= 0; 
 191                         case (TYPE_MAIN 
| TAG_MAIN_ENDCOLLECTION
): 
 192                                 if (CurrCollectionPath 
== NULL
) 
 193                                   return HID_PARSE_UnexpectedEndCollection
; 
 195                                 CurrCollectionPath 
= CurrCollectionPath
->Parent
; 
 198                         case (TYPE_MAIN 
| TAG_MAIN_INPUT
): 
 199                         case (TYPE_MAIN 
| TAG_MAIN_OUTPUT
): 
 200 #if defined(HID_ENABLE_FEATURE_PROCESSING) 
 201                         case (TYPE_MAIN 
| TAG_MAIN_FEATURE
): 
 203                                 for (uint8_t ReportItemNum 
= 0; ReportItemNum 
< CurrStateTable
->ReportCount
; ReportItemNum
++) 
 205                                         HID_ReportItem_t
* CurrReportItem 
= &ParserData
->ReportItems
[ParserData
->TotalReportItems
]; 
 207                                         if (ParserData
->TotalReportItems 
== HID_MAX_REPORTITEMS
) 
 208                                           return HID_PARSE_InsufficientReportItems
; 
 210                                         memcpy(&CurrReportItem
->Attributes
, 
 211                                                &CurrStateTable
->Attributes
, 
 212                                                sizeof(HID_ReportItem_Attributes_t
)); 
 214                                         CurrReportItem
->ItemFlags      
= ReportItemData
; 
 215                                         CurrReportItem
->CollectionPath 
= CurrCollectionPath
; 
 216                                         CurrReportItem
->ReportID       
= CurrStateTable
->ReportID
; 
 220                                                 CurrReportItem
->Attributes
.Usage
.Usage 
= UsageStack
[0]; 
 222                                                 for (uint8_t i 
= 0; i 
< UsageStackSize
; i
++) 
 223                                                   UsageStack
[i
] = UsageStack
[i 
+ 1]; 
 229                                                 CurrReportItem
->Attributes
.Usage
.Usage 
= 0; 
 232                                         switch (HIDReportItem 
& TAG_MASK
) 
 235                                                         CurrReportItem
->ItemType  
= REPORT_ITEM_TYPE_In
; 
 236                                                         CurrReportItem
->BitOffset 
= BitOffsetIn
; 
 238                                                         BitOffsetIn 
+= CurrStateTable
->Attributes
.BitSize
; 
 241                                                 case TAG_MAIN_OUTPUT
: 
 242                                                         CurrReportItem
->ItemType  
= REPORT_ITEM_TYPE_Out
; 
 243                                                         CurrReportItem
->BitOffset 
= BitOffsetOut
; 
 245                                                         BitOffsetOut 
+= CurrStateTable
->Attributes
.BitSize
; 
 248 #if defined(HID_ENABLE_FEATURE_PROCESSING) 
 249                                                 case TAG_MAIN_FEATURE
: 
 250                                                         CurrReportItem
->ItemType  
= REPORT_ITEM_TYPE_Feature
;                                            
 251                                                         CurrReportItem
->BitOffset 
= BitOffsetFeature
; 
 253                                                         BitOffsetFeature 
+= CurrStateTable
->Attributes
.BitSize
;          
 259 #if defined(HID_INCLUDE_CONSTANT_DATA_ITEMS) 
 260                                         ParserData
->TotalReportItems
++; 
 262                                         if (!(ReportItemData 
& IOF_CONSTANT
)) 
 263                                           ParserData
->TotalReportItems
++; 
 272                 if ((HIDReportItem 
& TYPE_MASK
) == TYPE_MAIN
) 
 274                         CurrStateTable
->Attributes
.Usage
.MinMax
.Minimum 
= 0; 
 275                         CurrStateTable
->Attributes
.Usage
.MinMax
.Maximum 
= 0; 
 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
;