3      Copyright (C) Dean Camera, 2011. 
   5   dean [at] fourwalledcubicle [dot] com 
  10   Copyright 2011  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
); 
  68                         case HID_RI_DATA_BITS_16
: 
  69                                 ReportItemData  
= *((uint16_t*)ReportData
); 
  73                         case HID_RI_DATA_BITS_8
: 
  74                                 ReportItemData  
= *((uint8_t*)ReportData
); 
  80                 switch (HIDReportItem 
& (HID_RI_TYPE_MASK 
| HID_RI_TAG_MASK
)) 
  83                                 if (CurrStateTable 
== &StateTable
[HID_STATETABLE_STACK_DEPTH 
- 1]) 
  84                                   return HID_PARSE_HIDStackOverflow
; 
  86                                 memcpy((CurrStateTable 
+ 1), 
  88                                        sizeof(HID_ReportItem_t
)); 
  93                                 if (CurrStateTable 
== &StateTable
[0]) 
  94                                   return HID_PARSE_HIDStackUnderflow
; 
  98                         case HID_RI_USAGE_PAGE(0): 
  99                                 if ((HIDReportItem 
& HID_RI_DATA_SIZE_MASK
) == HID_RI_DATA_BITS_32
) 
 100                                   CurrStateTable
->Attributes
.Usage
.Page 
= (ReportItemData 
>> 16); 
 102                                 CurrStateTable
->Attributes
.Usage
.Page       
= ReportItemData
; 
 104                         case HID_RI_LOGICAL_MINIMUM(0): 
 105                                 CurrStateTable
->Attributes
.Logical
.Minimum  
= ReportItemData
; 
 107                         case HID_RI_LOGICAL_MAXIMUM(0): 
 108                                 CurrStateTable
->Attributes
.Logical
.Maximum  
= ReportItemData
; 
 110                         case HID_RI_PHYSICAL_MINIMUM(0): 
 111                                 CurrStateTable
->Attributes
.Physical
.Minimum 
= ReportItemData
; 
 113                         case HID_RI_PHYSICAL_MAXIMUM(0): 
 114                                 CurrStateTable
->Attributes
.Physical
.Maximum 
= ReportItemData
; 
 116                         case HID_RI_UNIT_EXPONENT(0): 
 117                                 CurrStateTable
->Attributes
.Unit
.Exponent    
= ReportItemData
; 
 120                                 CurrStateTable
->Attributes
.Unit
.Type        
= ReportItemData
; 
 122                         case HID_RI_REPORT_SIZE(0): 
 123                                 CurrStateTable
->Attributes
.BitSize          
= ReportItemData
; 
 125                         case HID_RI_REPORT_COUNT(0): 
 126                                 CurrStateTable
->ReportCount                 
= ReportItemData
; 
 128                         case HID_RI_REPORT_ID(0): 
 129                                 CurrStateTable
->ReportID                    
= ReportItemData
; 
 131                                 if (ParserData
->UsingReportIDs
) 
 133                                         CurrReportIDInfo 
= NULL
; 
 135                                         for (uint8_t i 
= 0; i 
< ParserData
->TotalDeviceReports
; i
++) 
 137                                                 if (ParserData
->ReportIDSizes
[i
].ReportID 
== CurrStateTable
->ReportID
) 
 139                                                         CurrReportIDInfo 
= &ParserData
->ReportIDSizes
[i
]; 
 144                                         if (CurrReportIDInfo 
== NULL
) 
 146                                                 if (ParserData
->TotalDeviceReports 
== HID_MAX_REPORT_IDS
) 
 147                                                   return HID_PARSE_InsufficientReportIDItems
; 
 149                                                 CurrReportIDInfo 
= &ParserData
->ReportIDSizes
[ParserData
->TotalDeviceReports
++]; 
 150                                                 memset(CurrReportIDInfo
, 0x00, sizeof(HID_ReportSizeInfo_t
)); 
 154                                 ParserData
->UsingReportIDs 
= true; 
 156                                 CurrReportIDInfo
->ReportID 
= CurrStateTable
->ReportID
; 
 158                         case HID_RI_USAGE(0): 
 159                                 if (UsageListSize 
== HID_USAGE_STACK_DEPTH
) 
 160                                   return HID_PARSE_UsageListOverflow
; 
 162                                 UsageList
[UsageListSize
++] = ReportItemData
; 
 164                         case HID_RI_USAGE_MINIMUM(0): 
 165                                 UsageMinMax
.Minimum 
= ReportItemData
; 
 167                         case HID_RI_USAGE_MAXIMUM(0): 
 168                                 UsageMinMax
.Maximum 
= ReportItemData
; 
 170                         case HID_RI_COLLECTION(0): 
 171                                 if (CurrCollectionPath 
== NULL
) 
 173                                         CurrCollectionPath 
= &ParserData
->CollectionPaths
[0]; 
 177                                         HID_CollectionPath_t
* ParentCollectionPath 
= CurrCollectionPath
; 
 179                                         CurrCollectionPath 
= &ParserData
->CollectionPaths
[1]; 
 181                                         while (CurrCollectionPath
->Parent 
!= NULL
) 
 183                                                 if (CurrCollectionPath 
== &ParserData
->CollectionPaths
[HID_MAX_COLLECTIONS 
- 1]) 
 184                                                   return HID_PARSE_InsufficientCollectionPaths
; 
 186                                                 CurrCollectionPath
++; 
 189                                         CurrCollectionPath
->Parent 
= ParentCollectionPath
; 
 192                                 CurrCollectionPath
->Type 
= ReportItemData
; 
 193                                 CurrCollectionPath
->Usage
.Page 
= CurrStateTable
->Attributes
.Usage
.Page
; 
 197                                         CurrCollectionPath
->Usage
.Usage 
= UsageList
[0]; 
 199                                         for (uint8_t i 
= 0; i 
< UsageListSize
; i
++) 
 200                                           UsageList
[i
] = UsageList
[i 
+ 1]; 
 204                                 else if (UsageMinMax
.Minimum 
<= UsageMinMax
.Maximum
) 
 206                                         CurrCollectionPath
->Usage
.Usage 
= UsageMinMax
.Minimum
++; 
 210                         case HID_RI_END_COLLECTION(0): 
 211                                 if (CurrCollectionPath 
== NULL
) 
 212                                   return HID_PARSE_UnexpectedEndCollection
; 
 214                                 CurrCollectionPath 
= CurrCollectionPath
->Parent
; 
 216                         case HID_RI_INPUT(0): 
 217                         case HID_RI_OUTPUT(0): 
 218                         case HID_RI_FEATURE(0): 
 219                                 for (uint8_t ReportItemNum 
= 0; ReportItemNum 
< CurrStateTable
->ReportCount
; ReportItemNum
++) 
 221                                         HID_ReportItem_t NewReportItem
; 
 223                                         memcpy(&NewReportItem
.Attributes
, 
 224                                                &CurrStateTable
->Attributes
, 
 225                                                sizeof(HID_ReportItem_Attributes_t
)); 
 227                                         NewReportItem
.ItemFlags      
= ReportItemData
; 
 228                                         NewReportItem
.CollectionPath 
= CurrCollectionPath
; 
 229                                         NewReportItem
.ReportID       
= CurrStateTable
->ReportID
; 
 233                                                 NewReportItem
.Attributes
.Usage
.Usage 
= UsageList
[0]; 
 235                                                 for (uint8_t i 
= 0; i 
< UsageListSize
; i
++) 
 236                                                   UsageList
[i
] = UsageList
[i 
+ 1]; 
 240                                         else if (UsageMinMax
.Minimum 
<= UsageMinMax
.Maximum
) 
 242                                                 NewReportItem
.Attributes
.Usage
.Usage 
= UsageMinMax
.Minimum
++; 
 245                                         uint8_t ItemTypeTag 
= (HIDReportItem 
& (HID_RI_TYPE_MASK 
| HID_RI_TAG_MASK
)); 
 247                                         if (ItemTypeTag 
== HID_RI_INPUT(0)) 
 248                                           NewReportItem
.ItemType 
= HID_REPORT_ITEM_In
; 
 249                                         else if (ItemTypeTag 
== HID_RI_OUTPUT(0)) 
 250                                           NewReportItem
.ItemType 
= HID_REPORT_ITEM_Out
; 
 252                                           NewReportItem
.ItemType 
= HID_REPORT_ITEM_Feature
; 
 254                                         NewReportItem
.BitOffset 
= CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
]; 
 256                                         CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
] += CurrStateTable
->Attributes
.BitSize
; 
 258                                         if (ParserData
->LargestReportSizeBits 
< NewReportItem
.BitOffset
) 
 259                                           ParserData
->LargestReportSizeBits 
= NewReportItem
.BitOffset
; 
 261                                         if (!(ReportItemData 
& HID_IOF_CONSTANT
) && CALLBACK_HIDParser_FilterHIDReportItem(&NewReportItem
)) 
 263                                                 if (ParserData
->TotalReportItems 
== HID_MAX_REPORTITEMS
) 
 264                                                   return HID_PARSE_InsufficientReportItems
; 
 266                                                 memcpy(&ParserData
->ReportItems
[ParserData
->TotalReportItems
], 
 267                                                        &NewReportItem
, sizeof(HID_ReportItem_t
)); 
 269                                                 ParserData
->TotalReportItems
++; 
 276                 if ((HIDReportItem 
& HID_RI_TYPE_MASK
) == HID_RI_TYPE_MAIN
) 
 278                         UsageMinMax
.Minimum 
= 0; 
 279                         UsageMinMax
.Maximum 
= 0; 
 284         if (!(ParserData
->TotalReportItems
)) 
 285           return HID_PARSE_NoUnfilteredReportItems
; 
 287         return HID_PARSE_Successful
; 
 290 bool USB_GetHIDReportItemInfo(const uint8_t* ReportData
, 
 291                               HID_ReportItem_t
* const ReportItem
) 
 293         uint16_t DataBitsRem  
= ReportItem
->Attributes
.BitSize
; 
 294         uint16_t CurrentBit   
= ReportItem
->BitOffset
; 
 295         uint32_t BitMask      
= (1 << 0); 
 297         if (ReportItem
->ReportID
) 
 299                 if (ReportItem
->ReportID 
!= ReportData
[0]) 
 305         ReportItem
->PreviousValue 
= ReportItem
->Value
; 
 306         ReportItem
->Value 
= 0; 
 308         while (DataBitsRem
--) 
 310                 if (ReportData
[CurrentBit 
/ 8] & (1 << (CurrentBit 
% 8))) 
 311                   ReportItem
->Value 
|= BitMask
; 
 320 void USB_SetHIDReportItemInfo(uint8_t* ReportData
, 
 321                               HID_ReportItem_t
* const ReportItem
) 
 323         uint16_t DataBitsRem  
= ReportItem
->Attributes
.BitSize
; 
 324         uint16_t CurrentBit   
= ReportItem
->BitOffset
; 
 325         uint32_t BitMask      
= (1 << 0); 
 327         if (ReportItem
->ReportID
) 
 329                 ReportData
[0] = ReportItem
->ReportID
; 
 333         ReportItem
->PreviousValue 
= ReportItem
->Value
; 
 335         while (DataBitsRem
--) 
 337                 if (ReportItem
->Value 
& (1 << (CurrentBit 
% 8))) 
 338                   ReportData
[CurrentBit 
/ 8] |= BitMask
; 
 345 uint16_t USB_GetHIDReportSize(HID_ReportInfo_t
* const ParserData
, 
 346                               const uint8_t ReportID
, 
 347                               const uint8_t ReportType
) 
 349         for (uint8_t i 
= 0; i 
< HID_MAX_REPORT_IDS
; i
++) 
 351                 uint16_t ReportSizeBits 
= ParserData
->ReportIDSizes
[i
].ReportSizeBits
[ReportType
]; 
 353                 if (ParserData
->ReportIDSizes
[i
].ReportID 
== ReportID
) 
 354                   return ((ReportSizeBits 
>> 3) + ((ReportSizeBits 
& 0x07) ? 
1 : 0));