3      Copyright (C) Dean Camera, 2010. 
   5   dean [at] fourwalledcubicle [dot] com 
   6       www.fourwalledcubicle.com 
  10   Copyright 2010  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 #include "../../HighLevel/USBMode.h" 
  33 #if defined(USB_CAN_BE_HOST) 
  35 #include "HIDParser.h" 
  37 uint8_t USB_ProcessHIDReport(const uint8_t* ReportData
, 
  39                              HID_ReportInfo_t
* const ParserData
) 
  41         HID_StateTable_t      StateTable
[HID_STATETABLE_STACK_DEPTH
]; 
  42         HID_StateTable_t
*     CurrStateTable          
= &StateTable
[0]; 
  43         HID_CollectionPath_t
* CurrCollectionPath      
= NULL
; 
  44         HID_ReportSizeInfo_t
* CurrReportIDInfo        
= &ParserData
->ReportIDSizes
[0];                   
  45         uint16_t              UsageList
[HID_USAGE_STACK_DEPTH
]; 
  46         uint8_t               UsageListSize           
= 0; 
  47         HID_MinMax_t          UsageMinMax             
= {0, 0}; 
  49         memset(ParserData
,       0x00, sizeof(HID_ReportInfo_t
)); 
  50         memset(CurrStateTable
,   0x00, sizeof(HID_StateTable_t
)); 
  51         memset(CurrReportIDInfo
, 0x00, sizeof(HID_ReportSizeInfo_t
)); 
  53         ParserData
->TotalDeviceReports 
= 1;      
  57                 uint8_t  HIDReportItem  
= *ReportData
; 
  58                 uint32_t ReportItemData 
= 0; 
  63                 switch (HIDReportItem 
& DATA_SIZE_MASK
) 
  66                                 ReportItemData  
= *((uint32_t*)ReportData
); 
  71                                 ReportItemData  
= *((uint16_t*)ReportData
); 
  76                                 ReportItemData  
= *((uint8_t*)ReportData
); 
  82                 switch (HIDReportItem 
& (TYPE_MASK 
| TAG_MASK
)) 
  84                         case (TYPE_GLOBAL 
| TAG_GLOBAL_PUSH
): 
  85                                 if (CurrStateTable 
== &StateTable
[HID_STATETABLE_STACK_DEPTH 
- 1]) 
  86                                   return HID_PARSE_HIDStackOverflow
; 
  88                                 memcpy((CurrStateTable 
+ 1), 
  90                                        sizeof(HID_ReportItem_t
)); 
  94                         case (TYPE_GLOBAL 
| TAG_GLOBAL_POP
): 
  95                                 if (CurrStateTable 
== &StateTable
[0]) 
  96                                   return HID_PARSE_HIDStackUnderflow
; 
 100                         case (TYPE_GLOBAL 
| TAG_GLOBAL_USAGEPAGE
): 
 101                                 CurrStateTable
->Attributes
.Usage
.Page       
= ReportItemData
; 
 103                         case (TYPE_GLOBAL 
| TAG_GLOBAL_LOGICALMIN
): 
 104                                 CurrStateTable
->Attributes
.Logical
.Minimum  
= ReportItemData
; 
 106                         case (TYPE_GLOBAL 
| TAG_GLOBAL_LOGICALMAX
): 
 107                                 CurrStateTable
->Attributes
.Logical
.Maximum  
= ReportItemData
; 
 109                         case (TYPE_GLOBAL 
| TAG_GLOBAL_PHYSMIN
): 
 110                                 CurrStateTable
->Attributes
.Physical
.Minimum 
= ReportItemData
; 
 112                         case (TYPE_GLOBAL 
| TAG_GLOBAL_PHYSMAX
): 
 113                                 CurrStateTable
->Attributes
.Physical
.Maximum 
= ReportItemData
; 
 115                         case (TYPE_GLOBAL 
| TAG_GLOBAL_UNITEXP
): 
 116                                 CurrStateTable
->Attributes
.Unit
.Exponent    
= ReportItemData
; 
 118                         case (TYPE_GLOBAL 
| TAG_GLOBAL_UNIT
): 
 119                                 CurrStateTable
->Attributes
.Unit
.Type        
= ReportItemData
; 
 121                         case (TYPE_GLOBAL 
| TAG_GLOBAL_REPORTSIZE
): 
 122                                 CurrStateTable
->Attributes
.BitSize          
= ReportItemData
; 
 124                         case (TYPE_GLOBAL 
| TAG_GLOBAL_REPORTCOUNT
): 
 125                                 CurrStateTable
->ReportCount                 
= ReportItemData
; 
 127                         case (TYPE_GLOBAL 
| TAG_GLOBAL_REPORTID
): 
 128                                 CurrStateTable
->ReportID                    
= ReportItemData
; 
 130                                 if (ParserData
->UsingReportIDs
) 
 132                                         CurrReportIDInfo 
= NULL
; 
 134                                         for (uint8_t i 
= 0; i 
< ParserData
->TotalDeviceReports
; i
++) 
 136                                                 if (ParserData
->ReportIDSizes
[i
].ReportID 
== CurrStateTable
->ReportID
) 
 138                                                         CurrReportIDInfo 
= &ParserData
->ReportIDSizes
[i
]; 
 143                                         if (CurrReportIDInfo 
== NULL
) 
 145                                                 if (ParserData
->TotalDeviceReports 
== HID_MAX_REPORT_IDS
) 
 146                                                   return HID_PARSE_InsufficientReportIDItems
; 
 148                                                 CurrReportIDInfo 
= &ParserData
->ReportIDSizes
[ParserData
->TotalDeviceReports
++]; 
 149                                                 memset(CurrReportIDInfo
, 0x00, sizeof(HID_ReportSizeInfo_t
)); 
 153                                 ParserData
->UsingReportIDs 
= true;                               
 155                                 CurrReportIDInfo
->ReportID 
= CurrStateTable
->ReportID
; 
 157                         case (TYPE_LOCAL 
| TAG_LOCAL_USAGE
): 
 158                                 if (UsageListSize 
== HID_USAGE_STACK_DEPTH
) 
 159                                   return HID_PARSE_UsageListOverflow
; 
 161                                 UsageList
[UsageListSize
++] = ReportItemData
; 
 163                         case (TYPE_LOCAL 
| TAG_LOCAL_USAGEMIN
): 
 164                                 UsageMinMax
.Minimum 
= ReportItemData
; 
 166                         case (TYPE_LOCAL 
| TAG_LOCAL_USAGEMAX
): 
 167                                 UsageMinMax
.Maximum 
= ReportItemData
; 
 169                         case (TYPE_MAIN 
| TAG_MAIN_COLLECTION
): 
 170                                 if (CurrCollectionPath 
== NULL
) 
 172                                         CurrCollectionPath 
= &ParserData
->CollectionPaths
[0]; 
 176                                         HID_CollectionPath_t
* ParentCollectionPath 
= CurrCollectionPath
; 
 178                                         CurrCollectionPath 
= &ParserData
->CollectionPaths
[1]; 
 180                                         while (CurrCollectionPath
->Parent 
!= NULL
) 
 182                                                 if (CurrCollectionPath 
== &ParserData
->CollectionPaths
[HID_MAX_COLLECTIONS 
- 1]) 
 183                                                   return HID_PARSE_InsufficientCollectionPaths
; 
 185                                                 CurrCollectionPath
++; 
 188                                         CurrCollectionPath
->Parent 
= ParentCollectionPath
; 
 191                                 CurrCollectionPath
->Type 
= ReportItemData
; 
 192                                 CurrCollectionPath
->Usage
.Page 
= CurrStateTable
->Attributes
.Usage
.Page
; 
 196                                         CurrCollectionPath
->Usage
.Usage 
= UsageList
[0]; 
 198                                         for (uint8_t i 
= 0; i 
< UsageListSize
; i
++) 
 199                                           UsageList
[i
] = UsageList
[i 
+ 1]; 
 203                                 else if (UsageMinMax
.Minimum 
<= UsageMinMax
.Maximum
) 
 205                                         CurrCollectionPath
->Usage
.Usage 
= UsageMinMax
.Minimum
++; 
 209                         case (TYPE_MAIN 
| TAG_MAIN_ENDCOLLECTION
): 
 210                                 if (CurrCollectionPath 
== NULL
) 
 211                                   return HID_PARSE_UnexpectedEndCollection
; 
 213                                 CurrCollectionPath 
= CurrCollectionPath
->Parent
; 
 215                         case (TYPE_MAIN 
| TAG_MAIN_INPUT
): 
 216                         case (TYPE_MAIN 
| TAG_MAIN_OUTPUT
): 
 217                         case (TYPE_MAIN 
| TAG_MAIN_FEATURE
): 
 218                                 for (uint8_t ReportItemNum 
= 0; ReportItemNum 
< CurrStateTable
->ReportCount
; ReportItemNum
++) 
 220                                         HID_ReportItem_t NewReportItem
; 
 222                                         memcpy(&NewReportItem
.Attributes
, 
 223                                                &CurrStateTable
->Attributes
, 
 224                                                sizeof(HID_ReportItem_Attributes_t
)); 
 226                                         NewReportItem
.ItemFlags      
= ReportItemData
; 
 227                                         NewReportItem
.CollectionPath 
= CurrCollectionPath
; 
 228                                         NewReportItem
.ReportID       
= CurrStateTable
->ReportID
; 
 232                                                 NewReportItem
.Attributes
.Usage
.Usage 
= UsageList
[0]; 
 234                                                 for (uint8_t i 
= 0; i 
< UsageListSize
; i
++) 
 235                                                   UsageList
[i
] = UsageList
[i 
+ 1]; 
 239                                         else if (UsageMinMax
.Minimum 
<= UsageMinMax
.Maximum
) 
 241                                                 NewReportItem
.Attributes
.Usage
.Usage 
= UsageMinMax
.Minimum
++; 
 244                                         uint8_t ItemTag 
= (HIDReportItem 
& TAG_MASK
); 
 246                                         if (ItemTag 
== TAG_MAIN_INPUT
) 
 247                                           NewReportItem
.ItemType 
= REPORT_ITEM_TYPE_In
; 
 248                                         else if (ItemTag 
== TAG_MAIN_OUTPUT
) 
 249                                           NewReportItem
.ItemType 
= REPORT_ITEM_TYPE_Out
; 
 251                                           NewReportItem
.ItemType 
= REPORT_ITEM_TYPE_Feature
; 
 253                                         NewReportItem
.BitOffset 
= CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
]; 
 255                                         CurrReportIDInfo
->ReportSizeBits
[NewReportItem
.ItemType
] += CurrStateTable
->Attributes
.BitSize
; 
 257                                         if (ParserData
->LargestReportSizeBits 
< NewReportItem
.BitOffset
) 
 258                                           ParserData
->LargestReportSizeBits 
= NewReportItem
.BitOffset
; 
 260                                         if (!(ReportItemData 
& IOF_CONSTANT
) && CALLBACK_HIDParser_FilterHIDReportItem(&NewReportItem
)) 
 262                                                 if (ParserData
->TotalReportItems 
== HID_MAX_REPORTITEMS
) 
 263                                                   return HID_PARSE_InsufficientReportItems
; 
 265                                                 memcpy(&ParserData
->ReportItems
[ParserData
->TotalReportItems
], 
 266                                                        &NewReportItem
, sizeof(HID_ReportItem_t
)); 
 268                                                 ParserData
->TotalReportItems
++; 
 275                 if ((HIDReportItem 
& TYPE_MASK
) == TYPE_MAIN
) 
 277                         UsageMinMax
.Minimum 
= 0; 
 278                         UsageMinMax
.Maximum 
= 0; 
 283         if (!(ParserData
->TotalReportItems
)) 
 284           return HID_PARSE_NoUnfilteredReportItems
; 
 286         return HID_PARSE_Successful
; 
 289 bool USB_GetHIDReportItemInfo(const uint8_t* ReportData
, 
 290                               HID_ReportItem_t
* const ReportItem
) 
 292         uint16_t DataBitsRem  
= ReportItem
->Attributes
.BitSize
; 
 293         uint16_t CurrentBit   
= ReportItem
->BitOffset
; 
 294         uint32_t BitMask      
= (1 << 0); 
 296         if (ReportItem
->ReportID
) 
 298                 if (ReportItem
->ReportID 
!= ReportData
[0]) 
 304         ReportItem
->PreviousValue 
= ReportItem
->Value
; 
 305         ReportItem
->Value 
= 0; 
 307         while (DataBitsRem
--) 
 309                 if (ReportData
[CurrentBit 
/ 8] & (1 << (CurrentBit 
% 8))) 
 310                   ReportItem
->Value 
|= BitMask
; 
 319 void USB_SetHIDReportItemInfo(uint8_t* ReportData
, 
 320                               HID_ReportItem_t
* const ReportItem
) 
 322         uint16_t DataBitsRem  
= ReportItem
->Attributes
.BitSize
; 
 323         uint16_t CurrentBit   
= ReportItem
->BitOffset
; 
 324         uint32_t BitMask      
= (1 << 0); 
 326         if (ReportItem
->ReportID
) 
 328                 ReportData
[0] = ReportItem
->ReportID
; 
 332         ReportItem
->PreviousValue 
= ReportItem
->Value
; 
 334         while (DataBitsRem
--) 
 336                 if (ReportItem
->Value 
& (1 << (CurrentBit 
% 8))) 
 337                   ReportData
[CurrentBit 
/ 8] |= BitMask
; 
 344 uint16_t USB_GetHIDReportSize(HID_ReportInfo_t
* const ParserData
, 
 345                               const uint8_t ReportID
, 
 346                               const uint8_t ReportType
) 
 348         for (uint8_t i 
= 0; i 
< HID_MAX_REPORT_IDS
; i
++) 
 350                 uint16_t ReportSizeBits 
= ParserData
->ReportIDSizes
[i
].ReportSizeBits
[ReportType
]; 
 352                 if (ParserData
->ReportIDSizes
[i
].ReportID 
== ReportID
) 
 353                   return ((ReportSizeBits 
>> 3) + ((ReportSizeBits 
& 0x07) ? 
1 : 0));