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 #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
) 
  60                         if (DataINEndpoint 
|| DataOUTEndpoint
) 
  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         HIDInterfaceInfo
->Config
.DataOUTPipe
.Size 
= le16_to_cpu(DataOUTEndpoint
->EndpointSize
); 
 102         HIDInterfaceInfo
->Config
.DataOUTPipe
.EndpointAddress 
= DataOUTEndpoint
->EndpointAddress
; 
 103         HIDInterfaceInfo
->Config
.DataOUTPipe
.Type 
= EP_TYPE_INTERRUPT
; 
 105         if (!(Pipe_ConfigurePipeTable(&HIDInterfaceInfo
->Config
.DataINPipe
, 1))) 
 108         if (!(Pipe_ConfigurePipeTable(&HIDInterfaceInfo
->Config
.DataOUTPipe
, 1))) 
 111         HIDInterfaceInfo
->State
.InterfaceNumber      
= HIDInterface
->InterfaceNumber
; 
 112         HIDInterfaceInfo
->State
.HIDReportSize        
= LE16_TO_CPU(HIDDescriptor
->HIDReportLength
); 
 113         HIDInterfaceInfo
->State
.SupportsBootProtocol 
= (HIDInterface
->SubClass 
!= HID_CSCP_NonBootProtocol
); 
 114         HIDInterfaceInfo
->State
.LargestReportSize    
= 8; 
 115         HIDInterfaceInfo
->State
.IsActive             
= true; 
 117         return HID_ENUMERROR_NoError
; 
 120 static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor
) 
 122         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 124         if (Header
->Type 
== DTYPE_Interface
) 
 126                 USB_Descriptor_Interface_t
* Interface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
); 
 128                 if (Interface
->Class 
== HID_CSCP_HIDClass
) 
 129                   return DESCRIPTOR_SEARCH_Found
; 
 132         return DESCRIPTOR_SEARCH_NotFound
; 
 135 static uint8_t DCOMP_HID_Host_NextHIDDescriptor(void* const CurrentDescriptor
) 
 137         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 139         if (Header
->Type 
== HID_DTYPE_HID
) 
 140           return DESCRIPTOR_SEARCH_Found
; 
 141         else if (Header
->Type 
== DTYPE_Interface
) 
 142           return DESCRIPTOR_SEARCH_Fail
; 
 144           return DESCRIPTOR_SEARCH_NotFound
; 
 147 static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor
) 
 149         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 151         if (Header
->Type 
== DTYPE_Endpoint
) 
 153                 USB_Descriptor_Endpoint_t
* Endpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
); 
 155                 if (!(Pipe_IsEndpointBound(Endpoint
->EndpointAddress
))) 
 156                   return DESCRIPTOR_SEARCH_Found
; 
 158         else if (Header
->Type 
== DTYPE_Interface
) 
 160                 return DESCRIPTOR_SEARCH_Fail
; 
 163         return DESCRIPTOR_SEARCH_NotFound
; 
 166 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 167 uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, 
 168                                    const uint8_t ReportID
, 
 171         USB_ControlRequest 
= (USB_Request_Header_t
) 
 173                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 174                 .bRequest      
= HID_REQ_SetReport
, 
 175                 .wValue        
= ((HID_REPORT_ITEM_In 
+ 1) << 8) | ReportID
, 
 176                 .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 177                 .wLength       
= USB_GetHIDReportSize(HIDInterfaceInfo
->Config
.HIDParserData
, ReportID
, HID_REPORT_ITEM_In
), 
 180         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 182         return USB_Host_SendControlRequest(Buffer
); 
 186 uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, 
 189         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
)) 
 190           return PIPE_READYWAIT_DeviceDisconnected
; 
 194         Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataINPipe
.Address
); 
 198         uint8_t* BufferPos 
= Buffer
; 
 200 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 201         if (!(HIDInterfaceInfo
->State
.UsingBootProtocol
)) 
 203                 uint8_t ReportID 
= 0; 
 205                 if (HIDInterfaceInfo
->Config
.HIDParserData
->UsingReportIDs
) 
 207                         ReportID 
= Pipe_Read_8(); 
 208                         *(BufferPos
++) = ReportID
; 
 211                 ReportSize 
= USB_GetHIDReportSize(HIDInterfaceInfo
->Config
.HIDParserData
, ReportID
, HID_REPORT_ITEM_In
); 
 216                 ReportSize 
= Pipe_BytesInPipe(); 
 219         if ((ErrorCode 
= Pipe_Read_Stream_LE(BufferPos
, ReportSize
, NULL
)) != PIPE_RWSTREAM_NoError
) 
 225         return PIPE_RWSTREAM_NoError
; 
 228 uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, 
 229 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 230                                 const uint8_t ReportID
, 
 232                                 const uint8_t ReportType
, 
 234                                 const uint16_t ReportSize
) 
 236 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 237         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
)) 
 240         if (HIDInterfaceInfo
->State
.DeviceUsesOUTPipe 
&& (ReportType 
== HID_REPORT_ITEM_Out
)) 
 244                 Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataOUTPipe
.Address
); 
 248                   Pipe_Write_Stream_LE(&ReportID
, sizeof(ReportID
), NULL
); 
 250                 if ((ErrorCode 
= Pipe_Write_Stream_LE(Buffer
, ReportSize
, NULL
)) != PIPE_RWSTREAM_NoError
) 
 256                 return PIPE_RWSTREAM_NoError
; 
 261                 USB_ControlRequest 
= (USB_Request_Header_t
) 
 263                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 264                         .bRequest      
= HID_REQ_SetReport
, 
 265 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 266                         .wValue        
= ((ReportType 
+ 1) << 8) | ReportID
, 
 268                         .wValue        
= ((ReportType 
+ 1) << 8), 
 270                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 271                         .wLength       
= ReportSize
, 
 274                 Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 276                 return USB_Host_SendControlRequest(Buffer
); 
 280 bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
) 
 282         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
)) 
 287         Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataINPipe
.Address
); 
 290         ReportReceived 
= Pipe_IsINReceived(); 
 294         return ReportReceived
; 
 297 uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
) 
 301         if (!(HIDInterfaceInfo
->State
.SupportsBootProtocol
)) 
 302           return HID_ERROR_LOGICAL
; 
 304         USB_ControlRequest 
= (USB_Request_Header_t
) 
 306                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 307                         .bRequest      
= HID_REQ_SetProtocol
, 
 309                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 313         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 315         if ((ErrorCode 
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
) 
 318         HIDInterfaceInfo
->State
.LargestReportSize 
= 8; 
 319         HIDInterfaceInfo
->State
.UsingBootProtocol 
= true; 
 321         return HOST_SENDCONTROL_Successful
; 
 324 uint8_t HID_Host_SetIdlePeriod(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, 
 327         USB_ControlRequest 
= (USB_Request_Header_t
) 
 329                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 330                         .bRequest      
= HID_REQ_SetIdle
, 
 331                         .wValue        
= ((MS 
<< 6) & 0xFF00), 
 332                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 336         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 338         return USB_Host_SendControlRequest(NULL
); 
 341 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 342 uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
) 
 346         uint8_t HIDReportData
[HIDInterfaceInfo
->State
.HIDReportSize
]; 
 348         USB_ControlRequest 
= (USB_Request_Header_t
) 
 350                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_STANDARD 
| REQREC_INTERFACE
), 
 351                         .bRequest      
= REQ_GetDescriptor
, 
 352                         .wValue        
= (HID_DTYPE_Report 
<< 8), 
 353                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 354                         .wLength       
= HIDInterfaceInfo
->State
.HIDReportSize
, 
 357         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 359         if ((ErrorCode 
= USB_Host_SendControlRequest(HIDReportData
)) != HOST_SENDCONTROL_Successful
) 
 362         if (HIDInterfaceInfo
->State
.UsingBootProtocol
) 
 364                 USB_ControlRequest 
= (USB_Request_Header_t
) 
 366                                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 367                                 .bRequest      
= HID_REQ_SetProtocol
, 
 369                                 .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 373                 if ((ErrorCode 
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
) 
 376                 HIDInterfaceInfo
->State
.UsingBootProtocol 
= false; 
 379         if (HIDInterfaceInfo
->Config
.HIDParserData 
== NULL
) 
 380           return HID_ERROR_LOGICAL
; 
 382         if ((ErrorCode 
= USB_ProcessHIDReport(HIDReportData
, HIDInterfaceInfo
->State
.HIDReportSize
, 
 383                                               HIDInterfaceInfo
->Config
.HIDParserData
)) != HID_PARSE_Successful
) 
 385                 return HID_ERROR_LOGICAL 
| ErrorCode
; 
 388         uint16_t LargestReportSizeBits 
= HIDInterfaceInfo
->Config
.HIDParserData
->LargestReportSizeBits
; 
 389         HIDInterfaceInfo
->State
.LargestReportSize 
= (LargestReportSizeBits 
>> 3) + ((LargestReportSizeBits 
& 0x07) != 0);