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 #include "../../HighLevel/USBMode.h" 
  33 #if defined(USB_CAN_BE_HOST) 
  35 #define  __INCLUDE_FROM_HID_DRIVER 
  36 #define  __INCLUDE_FROM_HID_HOST_C 
  39 uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, 
  40                                 uint16_t ConfigDescriptorSize
, 
  41                                 void* ConfigDescriptorData
) 
  43         USB_Descriptor_Endpoint_t
*  DataINEndpoint  
= NULL
; 
  44         USB_Descriptor_Endpoint_t
*  DataOUTEndpoint 
= NULL
; 
  45         USB_Descriptor_Interface_t
* HIDInterface    
= NULL
; 
  46         USB_HID_Descriptor_HID_t
*   HIDDescriptor   
= NULL
; 
  48         memset(&HIDInterfaceInfo
->State
, 0x00, sizeof(HIDInterfaceInfo
->State
)); 
  50         if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
) 
  51           return HID_ENUMERROR_InvalidConfigDescriptor
; 
  53         while (!(DataINEndpoint
) || !(DataOUTEndpoint
)) 
  55                 if (!(HIDInterface
) || 
  56                     USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  57                                               DCOMP_HID_Host_NextHIDInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  59                         if (DataINEndpoint 
|| DataOUTEndpoint
) 
  64                                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  65                                                               DCOMP_HID_Host_NextHIDInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  67                                         return HID_ENUMERROR_NoCompatibleInterfaceFound
; 
  70                                 HIDInterface 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
); 
  71                         } while (HIDInterfaceInfo
->Config
.HIDInterfaceProtocol 
&& 
  72                                          (HIDInterface
->Protocol 
!= HIDInterfaceInfo
->Config
.HIDInterfaceProtocol
)); 
  74                         if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  75                                                       DCOMP_HID_Host_NextHID
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  77                                 return HID_ENUMERROR_NoCompatibleInterfaceFound
; 
  80                         HIDDescriptor 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_HID_Descriptor_HID_t
); 
  82                         DataINEndpoint  
= NULL
; 
  83                         DataOUTEndpoint 
= NULL
; 
  88                 USB_Descriptor_Endpoint_t
* EndpointData 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
); 
  90                 if (EndpointData
->EndpointAddress 
& ENDPOINT_DESCRIPTOR_DIR_IN
) 
  91                   DataINEndpoint  
= EndpointData
; 
  93                   DataOUTEndpoint 
= EndpointData
; 
  96         for (uint8_t PipeNum 
= 1; PipeNum 
< PIPE_TOTAL_PIPES
; PipeNum
++) 
 101                 uint8_t  EndpointAddress
; 
 102                 uint8_t  InterruptPeriod
; 
 105                 if (PipeNum 
== HIDInterfaceInfo
->Config
.DataINPipeNumber
) 
 107                         Size            
= DataINEndpoint
->EndpointSize
; 
 108                         EndpointAddress 
= DataINEndpoint
->EndpointAddress
; 
 109                         Token           
= PIPE_TOKEN_IN
; 
 110                         Type            
= EP_TYPE_INTERRUPT
; 
 111                         DoubleBanked    
= HIDInterfaceInfo
->Config
.DataINPipeDoubleBank
; 
 112                         InterruptPeriod 
= DataINEndpoint
->PollingIntervalMS
; 
 114                         HIDInterfaceInfo
->State
.DataINPipeSize   
= DataINEndpoint
->EndpointSize
; 
 116                 else if (PipeNum 
== HIDInterfaceInfo
->Config
.DataOUTPipeNumber
) 
 118                         if (DataOUTEndpoint 
== NULL
) 
 121                         Size            
= DataOUTEndpoint
->EndpointSize
; 
 122                         EndpointAddress 
= DataOUTEndpoint
->EndpointAddress
; 
 123                         Token           
= PIPE_TOKEN_OUT
; 
 124                         Type            
= EP_TYPE_INTERRUPT
; 
 125                         DoubleBanked    
= HIDInterfaceInfo
->Config
.DataOUTPipeDoubleBank
; 
 126                         InterruptPeriod 
= DataOUTEndpoint
->PollingIntervalMS
; 
 128                         HIDInterfaceInfo
->State
.DataOUTPipeSize   
= DataOUTEndpoint
->EndpointSize
; 
 129                         HIDInterfaceInfo
->State
.DeviceUsesOUTPipe 
= true; 
 136                 if (!(Pipe_ConfigurePipe(PipeNum
, Type
, Token
, EndpointAddress
, Size
, 
 137                                          DoubleBanked ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
))) 
 139                         return HID_ENUMERROR_PipeConfigurationFailed
; 
 143                   Pipe_SetInterruptPeriod(InterruptPeriod
); 
 146         HIDInterfaceInfo
->State
.InterfaceNumber      
= HIDInterface
->InterfaceNumber
; 
 147         HIDInterfaceInfo
->State
.HIDReportSize        
= HIDDescriptor
->HIDReportLength
; 
 148         HIDInterfaceInfo
->State
.SupportsBootProtocol 
= (HIDInterface
->SubClass 
!= HID_CSCP_NonBootProtocol
); 
 149         HIDInterfaceInfo
->State
.LargestReportSize    
= 8; 
 150         HIDInterfaceInfo
->State
.IsActive 
= true; 
 152         return HID_ENUMERROR_NoError
; 
 155 static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor
) 
 157         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 159         if (Header
->Type 
== DTYPE_Interface
) 
 161                 USB_Descriptor_Interface_t
* Interface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
); 
 163                 if (Interface
->Class 
== HID_CSCP_HIDClass
) 
 164                   return DESCRIPTOR_SEARCH_Found
; 
 167         return DESCRIPTOR_SEARCH_NotFound
; 
 170 static uint8_t DCOMP_HID_Host_NextHID(void* const CurrentDescriptor
) 
 172         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 174         if (Header
->Type 
== HID_DTYPE_HID
) 
 175           return DESCRIPTOR_SEARCH_Found
; 
 176         else if (Header
->Type 
== DTYPE_Interface
) 
 177           return DESCRIPTOR_SEARCH_Fail
; 
 179           return DESCRIPTOR_SEARCH_NotFound
; 
 182 static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor
) 
 184         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 186         if (Header
->Type 
== DTYPE_Endpoint
) 
 188                 USB_Descriptor_Endpoint_t
* Endpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
); 
 190                 if (!(Pipe_IsEndpointBound(Endpoint
->EndpointAddress
))) 
 191                   return DESCRIPTOR_SEARCH_Found
; 
 193         else if (Header
->Type 
== DTYPE_Interface
) 
 195                 return DESCRIPTOR_SEARCH_Fail
; 
 198         return DESCRIPTOR_SEARCH_NotFound
; 
 201 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 202 uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, 
 203                                    const uint8_t ReportID
, 
 206         USB_ControlRequest 
= (USB_Request_Header_t
) 
 208                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 209                 .bRequest      
= HID_REQ_SetReport
, 
 210                 .wValue        
= ((HID_REPORT_ITEM_In 
+ 1) << 8) | ReportID
, 
 211                 .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 212                 .wLength       
= USB_GetHIDReportSize(HIDInterfaceInfo
->Config
.HIDParserData
, ReportID
, HID_REPORT_ITEM_In
), 
 215         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 217         return USB_Host_SendControlRequest(Buffer
); 
 221 uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, 
 224         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
)) 
 225           return PIPE_READYWAIT_DeviceDisconnected
; 
 229         Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataINPipeNumber
); 
 233         uint8_t* BufferPos 
= Buffer
; 
 235 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 236         if (!(HIDInterfaceInfo
->State
.UsingBootProtocol
)) 
 238                 uint8_t ReportID 
= 0; 
 240                 if (HIDInterfaceInfo
->Config
.HIDParserData
->UsingReportIDs
) 
 242                         ReportID 
= Pipe_Read_Byte(); 
 243                         *(BufferPos
++) = ReportID
; 
 246                 ReportSize 
= USB_GetHIDReportSize(HIDInterfaceInfo
->Config
.HIDParserData
, ReportID
, HID_REPORT_ITEM_In
); 
 251                 ReportSize 
= Pipe_BytesInPipe(); 
 254         if ((ErrorCode 
= Pipe_Read_Stream_LE(BufferPos
, ReportSize
, NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
) 
 260         return PIPE_RWSTREAM_NoError
; 
 263 uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, 
 264 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 265                                 const uint8_t ReportID
, 
 267                                 const uint8_t ReportType
, 
 269                                 const uint16_t ReportSize
) 
 271 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 272         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
)) 
 275         if (HIDInterfaceInfo
->State
.DeviceUsesOUTPipe 
&& (ReportType 
== HID_REPORT_ITEM_Out
)) 
 279                 Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 283                   Pipe_Write_Stream_LE(&ReportID
, sizeof(ReportID
), NO_STREAM_CALLBACK
); 
 285                 if ((ErrorCode 
= Pipe_Write_Stream_LE(Buffer
, ReportSize
, NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
) 
 291                 return PIPE_RWSTREAM_NoError
; 
 296                 USB_ControlRequest 
= (USB_Request_Header_t
) 
 298                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 299                         .bRequest      
= HID_REQ_SetReport
, 
 300 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 301                         .wValue        
= ((ReportType 
+ 1) << 8) | ReportID
, 
 303                         .wValue        
= ((ReportType 
+ 1) << 8), 
 305                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 306                         .wLength       
= ReportSize
, 
 309                 Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 311                 return USB_Host_SendControlRequest(Buffer
); 
 315 bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
) 
 317         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
)) 
 322         Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataINPipeNumber
); 
 325         ReportReceived 
= Pipe_IsINReceived(); 
 329         return ReportReceived
; 
 332 uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
) 
 336         USB_ControlRequest 
= (USB_Request_Header_t
) 
 338                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 339                         .bRequest      
= HID_REQ_SetProtocol
, 
 341                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 345         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 347         if (!(HIDInterfaceInfo
->State
.SupportsBootProtocol
)) 
 348           return HID_ERROR_LOGICAL
; 
 350         if ((ErrorCode 
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
) 
 353         HIDInterfaceInfo
->State
.LargestReportSize 
= 8; 
 354         HIDInterfaceInfo
->State
.UsingBootProtocol 
= true; 
 356         return HOST_SENDCONTROL_Successful
; 
 359 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY) 
 360 uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
) 
 364         uint8_t HIDReportData
[HIDInterfaceInfo
->State
.HIDReportSize
]; 
 366         USB_ControlRequest 
= (USB_Request_Header_t
) 
 368                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_STANDARD 
| REQREC_INTERFACE
), 
 369                         .bRequest      
= REQ_GetDescriptor
, 
 370                         .wValue        
= (HID_DTYPE_Report 
<< 8), 
 371                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 372                         .wLength       
= HIDInterfaceInfo
->State
.HIDReportSize
, 
 375         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 377         if ((ErrorCode 
= USB_Host_SendControlRequest(HIDReportData
)) != HOST_SENDCONTROL_Successful
) 
 380         if (HIDInterfaceInfo
->State
.UsingBootProtocol
) 
 382                 USB_ControlRequest 
= (USB_Request_Header_t
) 
 384                                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 385                                 .bRequest      
= HID_REQ_SetProtocol
, 
 387                                 .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 391                 if ((ErrorCode 
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
) 
 394                 HIDInterfaceInfo
->State
.UsingBootProtocol 
= false; 
 397         if (HIDInterfaceInfo
->Config
.HIDParserData 
== NULL
) 
 398           return HID_ERROR_LOGICAL
; 
 400         if ((ErrorCode 
= USB_ProcessHIDReport(HIDReportData
, HIDInterfaceInfo
->State
.HIDReportSize
, 
 401                                               HIDInterfaceInfo
->Config
.HIDParserData
)) != HID_PARSE_Successful
) 
 403                 return HID_ERROR_LOGICAL 
| ErrorCode
; 
 406         uint8_t LargestReportSizeBits 
= HIDInterfaceInfo
->Config
.HIDParserData
->LargestReportSizeBits
; 
 407         HIDInterfaceInfo
->State
.LargestReportSize 
= (LargestReportSizeBits 
>> 3) + ((LargestReportSizeBits 
& 0x07) != 0);