3      Copyright (C) Dean Camera, 2013. 
   5   dean [at] fourwalledcubicle [dot] com 
  10   Copyright 2013  Dean Camera (dean [at] fourwalledcubicle [dot] com) 
  12   Permission to use, copy, modify, distribute, and sell this 
  13   software and its documentation for any purpose is hereby granted 
  14   without fee, provided that the above copyright notice appear in 
  15   all 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 disclaims 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 #define  __INCLUDE_FROM_USB_DRIVER 
  32 #define  __INCLUDE_FROM_HID_DRIVER 
  33 #include "HIDParser.h" 
  35 uint8_t USB_ProcessHIDReport(const uint8_t* ReportData
, 
  37                              HID_ReportInfo_t
* const ParserData
) 
  39         HID_StateTable_t      StateTable
[HID_STATETABLE_STACK_DEPTH
]; 
  40         HID_StateTable_t
*     CurrStateTable          
= &StateTable
[0]; 
  41         HID_CollectionPath_t
* CurrCollectionPath      
= NULL
; 
  42         HID_ReportSizeInfo_t
* CurrReportIDInfo        
= &ParserData
->ReportIDSizes
[0]; 
  43         uint16_t              UsageList
[HID_USAGE_STACK_DEPTH
]; 
  44         uint8_t               UsageListSize           
= 0; 
  45         HID_MinMax_t          UsageMinMax             
= {0, 0}; 
  47         memset(ParserData
,       0x00, sizeof(HID_ReportInfo_t
)); 
  48         memset(CurrStateTable
,   0x00, sizeof(HID_StateTable_t
)); 
  49         memset(CurrReportIDInfo
, 0x00, sizeof(HID_ReportSizeInfo_t
)); 
  51         ParserData
->TotalDeviceReports 
= 1; 
  55                 uint8_t  HIDReportItem  
= *ReportData
; 
  56                 uint32_t ReportItemData
; 
  61                 switch (HIDReportItem 
& HID_RI_DATA_SIZE_MASK
) 
  63                         case HID_RI_DATA_BITS_32
: 
  64                                 ReportItemData  
= (((uint32_t)ReportData
[3] << 24) | ((uint32_t)ReportData
[2] << 16) | 
  65                                                ((uint16_t)ReportData
[1] << 8)  | ReportData
[0]); 
  70                         case HID_RI_DATA_BITS_16
: 
  71                                 ReportItemData  
= (((uint16_t)ReportData
[1] << 8) | (ReportData
[0])); 
  76                         case HID_RI_DATA_BITS_8
: 
  77                                 ReportItemData  
= ReportData
[0]; 
  87                 switch (HIDReportItem 
& (HID_RI_TYPE_MASK 
| HID_RI_TAG_MASK
)) 
  90                                 if (CurrStateTable 
== &StateTable
[HID_STATETABLE_STACK_DEPTH 
- 1]) 
  91                                   return HID_PARSE_HIDStackOverflow
; 
  93                                 memcpy((CurrStateTable 
+ 1), 
  95                                        sizeof(HID_ReportItem_t
)); 
 100                                 if (CurrStateTable 
== &StateTable
[0]) 
 101                                   return HID_PARSE_HIDStackUnderflow
; 
 105                         case HID_RI_USAGE_PAGE(0): 
 106                                 if ((HIDReportItem 
& HID_RI_DATA_SIZE_MASK
) == HID_RI_DATA_BITS_32
) 
 107                                   CurrStateTable
->Attributes
.Usage
.Page 
= (ReportItemData 
>> 16); 
 109                                 CurrStateTable
->Attributes
.Usage
.Page       
= ReportItemData
; 
 111                         case HID_RI_LOGICAL_MINIMUM(0): 
 112                                 CurrStateTable
->Attributes
.Logical
.Minimum  
= ReportItemData
; 
 114                         case HID_RI_LOGICAL_MAXIMUM(0): 
 115                                 CurrStateTable
->Attributes
.Logical
.Maximum  
= ReportItemData
; 
 117                         case HID_RI_PHYSICAL_MINIMUM(0): 
 118                                 CurrStateTable
->Attributes
.Physical
.Minimum 
= ReportItemData
; 
 120                         case HID_RI_PHYSICAL_MAXIMUM(0): 
 121                                 CurrStateTable
->Attributes
.Physical
.Maximum 
= ReportItemData
; 
 123                         case HID_RI_UNIT_EXPONENT(0): 
 124                                 CurrStateTable
->Attributes
.Unit
.Exponent    
= ReportItemData
; 
 127                                 CurrStateTable
->Attributes
.Unit
.Type        
= ReportItemData
; 
 129                         case HID_RI_REPORT_SIZE(0): 
 130                                 CurrStateTable
->Attributes
.BitSize          
= ReportItemData
; 
 132                         case HID_RI_REPORT_COUNT(0): 
 133                                 CurrStateTable
->ReportCount                 
= ReportItemData
; 
 135                         case HID_RI_REPORT_ID(0): 
 136                                 CurrStateTable
->ReportID                    
= ReportItemData
; 
 138                                 if (ParserData
->UsingReportIDs
) 
 140                                         CurrReportIDInfo 
= NULL
; 
 142                                         for (uint8_t i 
= 0; i 
< ParserData
->TotalDeviceReports
; i
++) 
 144                                                 if (ParserData
->ReportIDSizes
[i
].ReportID 
== CurrStateTable
->ReportID
) 
 146                                                         CurrReportIDInfo 
= &ParserData
->ReportIDSizes
[i
]; 
 151                                         if (CurrReportIDInfo 
== NULL
) 
 153                                                 if (ParserData
->TotalDeviceReports 
== HID_MAX_REPORT_IDS
) 
 154                                                   return HID_PARSE_InsufficientReportIDItems
; 
 156                                                 CurrReportIDInfo 
= &ParserData
->ReportIDSizes
[ParserData
->TotalDeviceReports
++]; 
 157                                                 memset(CurrReportIDInfo
, 0x00, sizeof(HID_ReportSizeInfo_t
)); 
 161                                 ParserData
->UsingReportIDs 
= true; 
 163                                 CurrReportIDInfo
->ReportID 
= CurrStateTable
->ReportID
; 
 165                         case HID_RI_USAGE(0): 
 166                                 if (UsageListSize 
== HID_USAGE_STACK_DEPTH
) 
 167                                   return HID_PARSE_UsageListOverflow
; 
 169                                 UsageList
[UsageListSize
++] = ReportItemData
; 
 171                         case HID_RI_USAGE_MINIMUM(0): 
 172                                 UsageMinMax
.Minimum 
= ReportItemData
; 
 174                         case HID_RI_USAGE_MAXIMUM(0): 
 175                                 UsageMinMax
.Maximum 
= ReportItemData
; 
 177                         case HID_RI_COLLECTION(0): 
 178                                 if (CurrCollectionPath 
== NULL
) 
 180                                         CurrCollectionPath 
= &ParserData
->CollectionPaths
[0]; 
 184                                         HID_CollectionPath_t
* ParentCollectionPath 
= CurrCollectionPath
; 
 186                                         CurrCollectionPath 
= &ParserData
->CollectionPaths
[1]; 
 188                                         while (CurrCollectionPath
->Parent 
!= NULL
) 
 190                                                 if (CurrCollectionPath 
== &ParserData
->CollectionPaths
[HID_MAX_COLLECTIONS 
- 1]) 
 191                                                   return HID_PARSE_InsufficientCollectionPaths
; 
 193                                                 CurrCollectionPath
++; 
 196                                         CurrCollectionPath
->Parent 
= ParentCollectionPath
; 
 199                                 CurrCollectionPath
->Type       
= ReportItemData
; 
 200                                 CurrCollectionPath
->Usage
.Page 
= CurrStateTable
->Attributes
.Usage
.Page
; 
 204                                         CurrCollectionPath
->Usage
.Usage 
= UsageList
[0]; 
 206                                         for (uint8_t i 
= 0; i 
< UsageListSize
; i
++) 
 207                                           UsageList
[i
] = UsageList
[i 
+ 1]; 
 211                                 else if (UsageMinMax
.Minimum 
<= UsageMinMax
.Maximum
) 
 213                                         CurrCollectionPath
->Usage
.Usage 
= UsageMinMax
.Minimum
++; 
 217                         case HID_RI_END_COLLECTION(0): 
 218                                 if (CurrCollectionPath 
== NULL
) 
 219                                   return HID_PARSE_UnexpectedEndCollection
; 
 221                                 CurrCollectionPath 
= CurrCollectionPath
->Parent
; 
 223                         case HID_RI_INPUT(0): 
 224                         case HID_RI_OUTPUT(0): 
 225                         case HID_RI_FEATURE(0): 
 226                                 for (uint8_t ReportItemNum 
= 0; ReportItemNum 
< CurrStateTable
->ReportCount
; ReportItemNum
++) 
 228                                         HID_ReportItem_t NewReportItem
; 
 230                                         memcpy(&NewReportItem
.Attributes
, 
 231                                                &CurrStateTable
->Attributes
, 
 232                                                sizeof(HID_ReportItem_Attributes_t
)); 
 234                                         NewReportItem
.ItemFlags      
= ReportItemData
; 
 235                                         NewReportItem
.CollectionPath 
= CurrCollectionPath
; 
 236                                         NewReportItem
.ReportID       
= CurrStateTable
->ReportID
; 
 240                                                 NewReportItem
.Attributes
.Usage
.Usage 
= UsageList
[0]; 
 242                                                 for (uint8_t i 
= 0; i 
< UsageListSize
; i
++) 
 243                                                   UsageList
[i
] = UsageList
[i 
+ 1]; 
 247                                         else if (UsageMinMax
.Minimum 
<= UsageMinMax
.Maximum
) 
 249                                                 NewReportItem
.Attributes
.Usage
.Usage 
= UsageMinMax
.Minimum
++; 
 252                                         uint8_t ItemTypeTag 
= (HIDReportItem 
& (HID_RI_TYPE_MASK 
| HID_RI_TAG_MASK
)); 
 254                                         if (ItemTypeTag 
== HID_RI_INPUT(0)) 
 255                                           NewReportItem
.ItemType 
= HID_REPORT_ITEM_In
; 
 256                                         else if (ItemTypeTag 
== HID_RI_OUTPUT(0)) 
 257                                           NewReportItem
.ItemType 
= HID_REPORT_ITEM_Out
; 
 259                                           NewReportItem
.ItemType 
= HID_REPORT_ITEM_Feature
; 
 261                                         NewReportItem
.BitOffset 
= CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
]; 
 263                                         CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
] += CurrStateTable
->Attributes
.BitSize
; 
 265                                         ParserData
->LargestReportSizeBits 
= MAX(ParserData
->LargestReportSizeBits
, CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
]); 
 267                                         if (ParserData
->TotalReportItems 
== HID_MAX_REPORTITEMS
) 
 268                                           return HID_PARSE_InsufficientReportItems
; 
 270                                         memcpy(&ParserData
->ReportItems
[ParserData
->TotalReportItems
], 
 271                                                &NewReportItem
, sizeof(HID_ReportItem_t
)); 
 273                                         if (!(ReportItemData 
& HID_IOF_CONSTANT
) && CALLBACK_HIDParser_FilterHIDReportItem(&NewReportItem
)) 
 274                                           ParserData
->TotalReportItems
++; 
 283                 if ((HIDReportItem 
& HID_RI_TYPE_MASK
) == HID_RI_TYPE_MAIN
) 
 285                         UsageMinMax
.Minimum 
= 0; 
 286                         UsageMinMax
.Maximum 
= 0; 
 291         if (!(ParserData
->TotalReportItems
)) 
 292           return HID_PARSE_NoUnfilteredReportItems
; 
 294         return HID_PARSE_Successful
; 
 297 bool USB_GetHIDReportItemInfo(const uint8_t* ReportData
, 
 298                               HID_ReportItem_t
* const ReportItem
) 
 300         if (ReportItem 
== NULL
) 
 303         uint16_t DataBitsRem  
= ReportItem
->Attributes
.BitSize
; 
 304         uint16_t CurrentBit   
= ReportItem
->BitOffset
; 
 305         uint32_t BitMask      
= (1 << 0); 
 307         if (ReportItem
->ReportID
) 
 309                 if (ReportItem
->ReportID 
!= ReportData
[0]) 
 315         ReportItem
->PreviousValue 
= ReportItem
->Value
; 
 316         ReportItem
->Value 
= 0; 
 318         while (DataBitsRem
--) 
 320                 if (ReportData
[CurrentBit 
/ 8] & (1 << (CurrentBit 
% 8))) 
 321                   ReportItem
->Value 
|= BitMask
; 
 330 void USB_SetHIDReportItemInfo(uint8_t* ReportData
, 
 331                               HID_ReportItem_t
* const ReportItem
) 
 333         if (ReportItem 
== NULL
) 
 336         uint16_t DataBitsRem  
= ReportItem
->Attributes
.BitSize
; 
 337         uint16_t CurrentBit   
= ReportItem
->BitOffset
; 
 338         uint32_t BitMask      
= (1 << 0); 
 340         if (ReportItem
->ReportID
) 
 342                 ReportData
[0] = ReportItem
->ReportID
; 
 346         ReportItem
->PreviousValue 
= ReportItem
->Value
; 
 348         while (DataBitsRem
--) 
 350                 if (ReportItem
->Value 
& (1 << (CurrentBit 
% 8))) 
 351                   ReportData
[CurrentBit 
/ 8] |= BitMask
; 
 358 uint16_t USB_GetHIDReportSize(HID_ReportInfo_t
* const ParserData
, 
 359                               const uint8_t ReportID
, 
 360                               const uint8_t ReportType
) 
 362         for (uint8_t i 
= 0; i 
< HID_MAX_REPORT_IDS
; i
++) 
 364                 uint16_t ReportSizeBits 
= ParserData
->ReportIDSizes
[i
].ReportSizeBits
[ReportType
]; 
 366                 if (ParserData
->ReportIDSizes
[i
].ReportID 
== ReportID
) 
 367                   return (ReportSizeBits 
/ 8) + ((ReportSizeBits 
% 8) ? 
1 : 0);