3      Copyright (C) Dean Camera, 2015. 
   5   dean [at] fourwalledcubicle [dot] com 
  10   Copyright 2015  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 #include "../../Core/USBMode.h" 
  34 #if defined(USB_CAN_BE_HOST) 
  36 #define  __INCLUDE_FROM_HID_DRIVER 
  37 #define  __INCLUDE_FROM_HID_HOST_C 
  38 #include "HIDClassHost.h" 
  40 uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, 
  41                                 uint16_t ConfigDescriptorSize
, 
  42                                 void* ConfigDescriptorData
) 
  44         USB_Descriptor_Endpoint_t
*  DataINEndpoint  
= NULL
; 
  45         USB_Descriptor_Endpoint_t
*  DataOUTEndpoint 
= NULL
; 
  46         USB_Descriptor_Interface_t
* HIDInterface    
= NULL
; 
  47         USB_HID_Descriptor_HID_t
*   HIDDescriptor   
= NULL
; 
  49         memset(&HIDInterfaceInfo
->State
, 0x00, sizeof(HIDInterfaceInfo
->State
)); 
  51         if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
) 
  52           return HID_ENUMERROR_InvalidConfigDescriptor
; 
  54         while (!(DataINEndpoint
) || !(DataOUTEndpoint
)) 
  56                 if (!(HIDInterface
) || 
  57                     USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  58                                               DCOMP_HID_Host_NextHIDInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  65                                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  66                                                               DCOMP_HID_Host_NextHIDInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  68                                         return HID_ENUMERROR_NoCompatibleInterfaceFound
; 
  71                                 HIDInterface 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
); 
  72                         } while (HIDInterfaceInfo
->Config
.HIDInterfaceProtocol 
&& 
  73                                          (HIDInterface
->Protocol 
!= HIDInterfaceInfo
->Config
.HIDInterfaceProtocol
)); 
  75                         if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  76                                                       DCOMP_HID_Host_NextHIDDescriptor
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  78                                 return HID_ENUMERROR_NoCompatibleInterfaceFound
; 
  81                         HIDDescriptor 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_HID_Descriptor_HID_t
); 
  83                         DataINEndpoint  
= NULL
; 
  84                         DataOUTEndpoint 
= NULL
; 
  89                 USB_Descriptor_Endpoint_t
* EndpointData 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
); 
  91                 if ((EndpointData
->EndpointAddress 
& ENDPOINT_DIR_MASK
) == ENDPOINT_DIR_IN
) 
  92                   DataINEndpoint  
= EndpointData
; 
  94                   DataOUTEndpoint 
= EndpointData
; 
  97         HIDInterfaceInfo
->Config
.DataINPipe
.Size  
= le16_to_cpu(DataINEndpoint
->EndpointSize
); 
  98         HIDInterfaceInfo
->Config
.DataINPipe
.EndpointAddress 
= DataINEndpoint
->EndpointAddress
; 
  99         HIDInterfaceInfo
->Config
.DataINPipe
.Type  
= EP_TYPE_INTERRUPT
; 
 101         if (!(Pipe_ConfigurePipeTable(&HIDInterfaceInfo
->Config
.DataINPipe
, 1))) 
 102           return HID_ENUMERROR_PipeConfigurationFailed
; 
 106                 HIDInterfaceInfo
->Config
.DataOUTPipe
.Size 
= le16_to_cpu(DataOUTEndpoint
->EndpointSize
); 
 107                 HIDInterfaceInfo
->Config
.DataOUTPipe
.EndpointAddress 
= DataOUTEndpoint
->EndpointAddress
; 
 108                 HIDInterfaceInfo
->Config
.DataOUTPipe
.Type 
= EP_TYPE_INTERRUPT
; 
 110                 if (!(Pipe_ConfigurePipeTable(&HIDInterfaceInfo
->Config
.DataOUTPipe
, 1))) 
 111                   return HID_ENUMERROR_PipeConfigurationFailed
; 
 114         HIDInterfaceInfo
->State
.InterfaceNumber      
= HIDInterface
->InterfaceNumber
; 
 115         HIDInterfaceInfo
->State
.HIDReportSize        
= LE16_TO_CPU(HIDDescriptor
->HIDReportLength
); 
 116         HIDInterfaceInfo
->State
.SupportsBootProtocol 
= (HIDInterface
->SubClass 
!= HID_CSCP_NonBootProtocol
); 
 117         HIDInterfaceInfo
->State
.LargestReportSize    
= 8; 
 118         HIDInterfaceInfo
->State
.IsActive             
= true; 
 120         return HID_ENUMERROR_NoError
; 
 123 static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor
) 
 125         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 127         if (Header
->Type 
== DTYPE_Interface
) 
 129                 USB_Descriptor_Interface_t
* Interface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
); 
 131                 if (Interface
->Class 
== HID_CSCP_HIDClass
) 
 132                   return DESCRIPTOR_SEARCH_Found
; 
 135         return DESCRIPTOR_SEARCH_NotFound
; 
 138 static uint8_t DCOMP_HID_Host_NextHIDDescriptor(void* const CurrentDescriptor
) 
 140         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 142         if (Header
->Type 
== HID_DTYPE_HID
) 
 143           return DESCRIPTOR_SEARCH_Found
; 
 144         else if (Header
->Type 
== DTYPE_Interface
) 
 145           return DESCRIPTOR_SEARCH_Fail
; 
 147           return DESCRIPTOR_SEARCH_NotFound
; 
 150 static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor
) 
 152         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 154         if (Header
->Type 
== DTYPE_Endpoint
) 
 156                 USB_Descriptor_Endpoint_t
* Endpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
); 
 158                 if (!(Pipe_IsEndpointBound(Endpoint
->EndpointAddress
))) 
 159                   return DESCRIPTOR_SEARCH_Found
; 
 161         else if (Header
->Type 
== DTYPE_Interface
) 
 163                 return DESCRIPTOR_SEARCH_Fail
; 
 166         return DESCRIPTOR_SEARCH_NotFound
; 
 169 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 170 uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, 
 171                                    const uint8_t ReportID
, 
 174         USB_ControlRequest 
= (USB_Request_Header_t
) 
 176                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 177                 .bRequest      
= HID_REQ_SetReport
, 
 178                 .wValue        
= ((HID_REPORT_ITEM_In 
+ 1) << 8) | ReportID
, 
 179                 .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 180                 .wLength       
= USB_GetHIDReportSize(HIDInterfaceInfo
->Config
.HIDParserData
, ReportID
, HID_REPORT_ITEM_In
), 
 183         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 185         return USB_Host_SendControlRequest(Buffer
); 
 189 uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, 
 192         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
)) 
 193           return PIPE_READYWAIT_DeviceDisconnected
; 
 197         Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataINPipe
.Address
); 
 201         uint8_t* BufferPos 
= Buffer
; 
 203 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 204         if (!(HIDInterfaceInfo
->State
.UsingBootProtocol
)) 
 206                 uint8_t ReportID 
= 0; 
 208                 if (HIDInterfaceInfo
->Config
.HIDParserData
->UsingReportIDs
) 
 210                         ReportID 
= Pipe_Read_8(); 
 211                         *(BufferPos
++) = ReportID
; 
 214                 ReportSize 
= USB_GetHIDReportSize(HIDInterfaceInfo
->Config
.HIDParserData
, ReportID
, HID_REPORT_ITEM_In
); 
 219                 ReportSize 
= Pipe_BytesInPipe(); 
 222         if ((ErrorCode 
= Pipe_Read_Stream_LE(BufferPos
, ReportSize
, NULL
)) != PIPE_RWSTREAM_NoError
) 
 228         return PIPE_RWSTREAM_NoError
; 
 231 uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, 
 232 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 233                                 const uint8_t ReportID
, 
 235                                 const uint8_t ReportType
, 
 237                                 const uint16_t ReportSize
) 
 239 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 240         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
)) 
 241           return PIPE_RWSTREAM_NoError
; 
 243         if (HIDInterfaceInfo
->State
.DeviceUsesOUTPipe 
&& (ReportType 
== HID_REPORT_ITEM_Out
)) 
 247                 Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataOUTPipe
.Address
); 
 251                   Pipe_Write_Stream_LE(&ReportID
, sizeof(ReportID
), NULL
); 
 253                 if ((ErrorCode 
= Pipe_Write_Stream_LE(Buffer
, ReportSize
, NULL
)) != PIPE_RWSTREAM_NoError
) 
 259                 return PIPE_RWSTREAM_NoError
; 
 264                 USB_ControlRequest 
= (USB_Request_Header_t
) 
 266                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 267                         .bRequest      
= HID_REQ_SetReport
, 
 268 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 269                         .wValue        
= ((ReportType 
+ 1) << 8) | ReportID
, 
 271                         .wValue        
= ((ReportType 
+ 1) << 8), 
 273                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 274                         .wLength       
= ReportSize
, 
 277                 Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 279                 return USB_Host_SendControlRequest(Buffer
); 
 283 bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
) 
 285         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
)) 
 290         Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataINPipe
.Address
); 
 293         ReportReceived 
= Pipe_IsINReceived(); 
 297         return ReportReceived
; 
 300 uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
) 
 304         if (!(HIDInterfaceInfo
->State
.SupportsBootProtocol
)) 
 305           return HID_ERROR_LOGICAL
; 
 307         USB_ControlRequest 
= (USB_Request_Header_t
) 
 309                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 310                         .bRequest      
= HID_REQ_SetProtocol
, 
 312                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 316         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 318         if ((ErrorCode 
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
) 
 321         HIDInterfaceInfo
->State
.LargestReportSize 
= 8; 
 322         HIDInterfaceInfo
->State
.UsingBootProtocol 
= true; 
 324         return HOST_SENDCONTROL_Successful
; 
 327 uint8_t HID_Host_SetIdlePeriod(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, 
 330         USB_ControlRequest 
= (USB_Request_Header_t
) 
 332                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 333                         .bRequest      
= HID_REQ_SetIdle
, 
 334                         .wValue        
= ((MS 
<< 6) & 0xFF00), 
 335                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 339         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 341         return USB_Host_SendControlRequest(NULL
); 
 344 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 345 uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
) 
 349         uint8_t HIDReportData
[HIDInterfaceInfo
->State
.HIDReportSize
]; 
 351         USB_ControlRequest 
= (USB_Request_Header_t
) 
 353                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_STANDARD 
| REQREC_INTERFACE
), 
 354                         .bRequest      
= REQ_GetDescriptor
, 
 355                         .wValue        
= (HID_DTYPE_Report 
<< 8), 
 356                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 357                         .wLength       
= HIDInterfaceInfo
->State
.HIDReportSize
, 
 360         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 362         if ((ErrorCode 
= USB_Host_SendControlRequest(HIDReportData
)) != HOST_SENDCONTROL_Successful
) 
 365         if (HIDInterfaceInfo
->State
.UsingBootProtocol
) 
 367                 USB_ControlRequest 
= (USB_Request_Header_t
) 
 369                                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 370                                 .bRequest      
= HID_REQ_SetProtocol
, 
 372                                 .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 376                 if ((ErrorCode 
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
) 
 379                 HIDInterfaceInfo
->State
.UsingBootProtocol 
= false; 
 382         if (HIDInterfaceInfo
->Config
.HIDParserData 
== NULL
) 
 383           return HID_ERROR_LOGICAL
; 
 385         if ((ErrorCode 
= USB_ProcessHIDReport(HIDReportData
, HIDInterfaceInfo
->State
.HIDReportSize
, 
 386                                               HIDInterfaceInfo
->Config
.HIDParserData
)) != HID_PARSE_Successful
) 
 388                 return HID_ERROR_LOGICAL 
| ErrorCode
; 
 391         uint16_t LargestReportSizeBits 
= HIDInterfaceInfo
->Config
.HIDParserData
->LargestReportSizeBits
; 
 392         HIDInterfaceInfo
->State
.LargestReportSize 
= (LargestReportSizeBits 
>> 3) + ((LargestReportSizeBits 
& 0x07) != 0);