3      Copyright (C) Dean Camera, 2012. 
   5   dean [at] fourwalledcubicle [dot] com 
  10   Copyright 2012  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 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 #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 
= 0; 
  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]); 
  69                         case HID_RI_DATA_BITS_16
: 
  70                                 ReportItemData  
= (((uint16_t)ReportData
[1] << 8) | (ReportData
[0])); 
  74                         case HID_RI_DATA_BITS_8
: 
  75                                 ReportItemData  
= ReportData
[0]; 
  81                 switch (HIDReportItem 
& (HID_RI_TYPE_MASK 
| HID_RI_TAG_MASK
)) 
  84                                 if (CurrStateTable 
== &StateTable
[HID_STATETABLE_STACK_DEPTH 
- 1]) 
  85                                   return HID_PARSE_HIDStackOverflow
; 
  87                                 memcpy((CurrStateTable 
+ 1), 
  89                                        sizeof(HID_ReportItem_t
)); 
  94                                 if (CurrStateTable 
== &StateTable
[0]) 
  95                                   return HID_PARSE_HIDStackUnderflow
; 
  99                         case HID_RI_USAGE_PAGE(0): 
 100                                 if ((HIDReportItem 
& HID_RI_DATA_SIZE_MASK
) == HID_RI_DATA_BITS_32
) 
 101                                   CurrStateTable
->Attributes
.Usage
.Page 
= (ReportItemData 
>> 16); 
 103                                 CurrStateTable
->Attributes
.Usage
.Page       
= ReportItemData
; 
 105                         case HID_RI_LOGICAL_MINIMUM(0): 
 106                                 CurrStateTable
->Attributes
.Logical
.Minimum  
= ReportItemData
; 
 108                         case HID_RI_LOGICAL_MAXIMUM(0): 
 109                                 CurrStateTable
->Attributes
.Logical
.Maximum  
= ReportItemData
; 
 111                         case HID_RI_PHYSICAL_MINIMUM(0): 
 112                                 CurrStateTable
->Attributes
.Physical
.Minimum 
= ReportItemData
; 
 114                         case HID_RI_PHYSICAL_MAXIMUM(0): 
 115                                 CurrStateTable
->Attributes
.Physical
.Maximum 
= ReportItemData
; 
 117                         case HID_RI_UNIT_EXPONENT(0): 
 118                                 CurrStateTable
->Attributes
.Unit
.Exponent    
= ReportItemData
; 
 121                                 CurrStateTable
->Attributes
.Unit
.Type        
= ReportItemData
; 
 123                         case HID_RI_REPORT_SIZE(0): 
 124                                 CurrStateTable
->Attributes
.BitSize          
= ReportItemData
; 
 126                         case HID_RI_REPORT_COUNT(0): 
 127                                 CurrStateTable
->ReportCount                 
= ReportItemData
; 
 129                         case HID_RI_REPORT_ID(0): 
 130                                 CurrStateTable
->ReportID                    
= ReportItemData
; 
 132                                 if (ParserData
->UsingReportIDs
) 
 134                                         CurrReportIDInfo 
= NULL
; 
 136                                         for (uint8_t i 
= 0; i 
< ParserData
->TotalDeviceReports
; i
++) 
 138                                                 if (ParserData
->ReportIDSizes
[i
].ReportID 
== CurrStateTable
->ReportID
) 
 140                                                         CurrReportIDInfo 
= &ParserData
->ReportIDSizes
[i
]; 
 145                                         if (CurrReportIDInfo 
== NULL
) 
 147                                                 if (ParserData
->TotalDeviceReports 
== HID_MAX_REPORT_IDS
) 
 148                                                   return HID_PARSE_InsufficientReportIDItems
; 
 150                                                 CurrReportIDInfo 
= &ParserData
->ReportIDSizes
[ParserData
->TotalDeviceReports
++]; 
 151                                                 memset(CurrReportIDInfo
, 0x00, sizeof(HID_ReportSizeInfo_t
)); 
 155                                 ParserData
->UsingReportIDs 
= true; 
 157                                 CurrReportIDInfo
->ReportID 
= CurrStateTable
->ReportID
; 
 159                         case HID_RI_USAGE(0): 
 160                                 if (UsageListSize 
== HID_USAGE_STACK_DEPTH
) 
 161                                   return HID_PARSE_UsageListOverflow
; 
 163                                 UsageList
[UsageListSize
++] = ReportItemData
; 
 165                         case HID_RI_USAGE_MINIMUM(0): 
 166                                 UsageMinMax
.Minimum 
= ReportItemData
; 
 168                         case HID_RI_USAGE_MAXIMUM(0): 
 169                                 UsageMinMax
.Maximum 
= ReportItemData
; 
 171                         case HID_RI_COLLECTION(0): 
 172                                 if (CurrCollectionPath 
== NULL
) 
 174                                         CurrCollectionPath 
= &ParserData
->CollectionPaths
[0]; 
 178                                         HID_CollectionPath_t
* ParentCollectionPath 
= CurrCollectionPath
; 
 180                                         CurrCollectionPath 
= &ParserData
->CollectionPaths
[1]; 
 182                                         while (CurrCollectionPath
->Parent 
!= NULL
) 
 184                                                 if (CurrCollectionPath 
== &ParserData
->CollectionPaths
[HID_MAX_COLLECTIONS 
- 1]) 
 185                                                   return HID_PARSE_InsufficientCollectionPaths
; 
 187                                                 CurrCollectionPath
++; 
 190                                         CurrCollectionPath
->Parent 
= ParentCollectionPath
; 
 193                                 CurrCollectionPath
->Type       
= ReportItemData
; 
 194                                 CurrCollectionPath
->Usage
.Page 
= CurrStateTable
->Attributes
.Usage
.Page
; 
 198                                         CurrCollectionPath
->Usage
.Usage 
= UsageList
[0]; 
 200                                         for (uint8_t i 
= 0; i 
< UsageListSize
; i
++) 
 201                                           UsageList
[i
] = UsageList
[i 
+ 1]; 
 205                                 else if (UsageMinMax
.Minimum 
<= UsageMinMax
.Maximum
) 
 207                                         CurrCollectionPath
->Usage
.Usage 
= UsageMinMax
.Minimum
++; 
 211                         case HID_RI_END_COLLECTION(0): 
 212                                 if (CurrCollectionPath 
== NULL
) 
 213                                   return HID_PARSE_UnexpectedEndCollection
; 
 215                                 CurrCollectionPath 
= CurrCollectionPath
->Parent
; 
 217                         case HID_RI_INPUT(0): 
 218                         case HID_RI_OUTPUT(0): 
 219                         case HID_RI_FEATURE(0): 
 220                                 for (uint8_t ReportItemNum 
= 0; ReportItemNum 
< CurrStateTable
->ReportCount
; ReportItemNum
++) 
 222                                         HID_ReportItem_t NewReportItem
; 
 224                                         memcpy(&NewReportItem
.Attributes
, 
 225                                                &CurrStateTable
->Attributes
, 
 226                                                sizeof(HID_ReportItem_Attributes_t
)); 
 228                                         NewReportItem
.ItemFlags      
= ReportItemData
; 
 229                                         NewReportItem
.CollectionPath 
= CurrCollectionPath
; 
 230                                         NewReportItem
.ReportID       
= CurrStateTable
->ReportID
; 
 234                                                 NewReportItem
.Attributes
.Usage
.Usage 
= UsageList
[0]; 
 236                                                 for (uint8_t i 
= 0; i 
< UsageListSize
; i
++) 
 237                                                   UsageList
[i
] = UsageList
[i 
+ 1]; 
 241                                         else if (UsageMinMax
.Minimum 
<= UsageMinMax
.Maximum
) 
 243                                                 NewReportItem
.Attributes
.Usage
.Usage 
= UsageMinMax
.Minimum
++; 
 246                                         uint8_t ItemTypeTag 
= (HIDReportItem 
& (HID_RI_TYPE_MASK 
| HID_RI_TAG_MASK
)); 
 248                                         if (ItemTypeTag 
== HID_RI_INPUT(0)) 
 249                                           NewReportItem
.ItemType 
= HID_REPORT_ITEM_In
; 
 250                                         else if (ItemTypeTag 
== HID_RI_OUTPUT(0)) 
 251                                           NewReportItem
.ItemType 
= HID_REPORT_ITEM_Out
; 
 253                                           NewReportItem
.ItemType 
= HID_REPORT_ITEM_Feature
; 
 255                                         NewReportItem
.BitOffset 
= CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
]; 
 257                                         CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
] += CurrStateTable
->Attributes
.BitSize
; 
 259                                         ParserData
->LargestReportSizeBits 
= MAX(ParserData
->LargestReportSizeBits
, CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
]); 
 261                                         if (ParserData
->TotalReportItems 
== HID_MAX_REPORTITEMS
) 
 262                                           return HID_PARSE_InsufficientReportItems
; 
 264                                         memcpy(&ParserData
->ReportItems
[ParserData
->TotalReportItems
], 
 265                                                &NewReportItem
, sizeof(HID_ReportItem_t
)); 
 267                                         if (!(ReportItemData 
& HID_IOF_CONSTANT
) && CALLBACK_HIDParser_FilterHIDReportItem(&NewReportItem
)) 
 268                                           ParserData
->TotalReportItems
++; 
 274                 if ((HIDReportItem 
& HID_RI_TYPE_MASK
) == HID_RI_TYPE_MAIN
) 
 276                         UsageMinMax
.Minimum 
= 0; 
 277                         UsageMinMax
.Maximum 
= 0; 
 282         if (!(ParserData
->TotalReportItems
)) 
 283           return HID_PARSE_NoUnfilteredReportItems
; 
 285         return HID_PARSE_Successful
; 
 288 bool USB_GetHIDReportItemInfo(const uint8_t* ReportData
, 
 289                               HID_ReportItem_t
* const ReportItem
) 
 291         if (ReportItem 
== NULL
) 
 294         uint16_t DataBitsRem  
= ReportItem
->Attributes
.BitSize
; 
 295         uint16_t CurrentBit   
= ReportItem
->BitOffset
; 
 296         uint32_t BitMask      
= (1 << 0); 
 298         if (ReportItem
->ReportID
) 
 300                 if (ReportItem
->ReportID 
!= ReportData
[0]) 
 306         ReportItem
->PreviousValue 
= ReportItem
->Value
; 
 307         ReportItem
->Value 
= 0; 
 309         while (DataBitsRem
--) 
 311                 if (ReportData
[CurrentBit 
/ 8] & (1 << (CurrentBit 
% 8))) 
 312                   ReportItem
->Value 
|= BitMask
; 
 321 void USB_SetHIDReportItemInfo(uint8_t* ReportData
, 
 322                               HID_ReportItem_t
* const ReportItem
) 
 324         if (ReportItem 
== NULL
) 
 327         uint16_t DataBitsRem  
= ReportItem
->Attributes
.BitSize
; 
 328         uint16_t CurrentBit   
= ReportItem
->BitOffset
; 
 329         uint32_t BitMask      
= (1 << 0); 
 331         if (ReportItem
->ReportID
) 
 333                 ReportData
[0] = ReportItem
->ReportID
; 
 337         ReportItem
->PreviousValue 
= ReportItem
->Value
; 
 339         while (DataBitsRem
--) 
 341                 if (ReportItem
->Value 
& (1 << (CurrentBit 
% 8))) 
 342                   ReportData
[CurrentBit 
/ 8] |= BitMask
; 
 349 uint16_t USB_GetHIDReportSize(HID_ReportInfo_t
* const ParserData
, 
 350                               const uint8_t ReportID
, 
 351                               const uint8_t ReportType
) 
 353         for (uint8_t i 
= 0; i 
< HID_MAX_REPORT_IDS
; i
++) 
 355                 uint16_t ReportSizeBits 
= ParserData
->ReportIDSizes
[i
].ReportSizeBits
[ReportType
]; 
 357                 if (ParserData
->ReportIDSizes
[i
].ReportID 
== ReportID
) 
 358                   return (ReportSizeBits 
/ 8) + ((ReportSizeBits 
% 8) ? 
1 : 0);