3      Copyright (C) Dean Camera, 2009. 
   5   dean [at] fourwalledcubicle [dot] com 
   6       www.fourwalledcubicle.com 
  10   Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com) 
  12   Permission to use, copy, modify, and distribute this software 
  13   and its documentation for any purpose and without fee is hereby 
  14   granted, provided that the above copyright notice appear in all 
  15   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 #include "../../HighLevel/USBMode.h" 
  32 #if defined(USB_CAN_BE_HOST) 
  34 #define INCLUDE_FROM_HID_CLASS_HOST_C 
  37 #warning The HID Host mode Class driver is currently incomplete and is for preview purposes only. 
  39 uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, uint16_t ConfigDescriptorSize
, 
  40                                 uint8_t* ConfigDescriptorData
) 
  42         uint8_t FoundEndpoints 
= 0; 
  44         memset(&HIDInterfaceInfo
->State
, 0x00, sizeof(HIDInterfaceInfo
->State
)); 
  46         if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
) 
  47           return HID_ENUMERROR_InvalidConfigDescriptor
; 
  49         USB_Descriptor_Interface_t
* CurrentHIDInterface
; 
  53                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  54                                                                           DComp_HID_Host_NextHIDInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  56                         return HID_ENUMERROR_NoHIDInterfaceFound
; 
  59                 CurrentHIDInterface 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
); 
  60         } while (HIDInterfaceInfo
->Config
.HIDInterfaceProtocol 
&& 
  61                  (CurrentHIDInterface
->Protocol 
!= HIDInterfaceInfo
->Config
.HIDInterfaceProtocol
)); 
  63         HIDInterfaceInfo
->State
.InterfaceNumber      
= CurrentHIDInterface
->InterfaceNumber
; 
  64         HIDInterfaceInfo
->State
.SupportsBootProtocol 
= (CurrentHIDInterface
->SubClass 
!= HID_NON_BOOT_PROTOCOL
); 
  66         if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, DComp_NextHID
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  68                 return HID_ENUMERROR_NoHIDDescriptorFound
; 
  71         HIDInterfaceInfo
->State
.HIDReportSize 
= DESCRIPTOR_CAST(ConfigDescriptorData
, USB_HID_Descriptor_t
).HIDReportLength
; 
  73         while (FoundEndpoints 
!= (HID_FOUND_DATAPIPE_IN 
| HID_FOUND_DATAPIPE_OUT
)) 
  75                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  76                                               DComp_HID_Host_NextHIDInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  78                         if (FoundEndpoints 
& HID_FOUND_DATAPIPE_IN
) 
  81                         return HID_ENUMERROR_EndpointsNotFound
; 
  84                 USB_Descriptor_Endpoint_t
* EndpointData 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
); 
  86                 if (EndpointData
->EndpointAddress 
& ENDPOINT_DESCRIPTOR_DIR_IN
) 
  88                         Pipe_ConfigurePipe(HIDInterfaceInfo
->Config
.DataINPipeNumber
, EP_TYPE_INTERRUPT
, PIPE_TOKEN_IN
, 
  89                                                            EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
, PIPE_BANK_SINGLE
); 
  90                         HIDInterfaceInfo
->State
.DataINPipeSize 
= EndpointData
->EndpointSize
; 
  92                         FoundEndpoints 
|= HID_FOUND_DATAPIPE_IN
; 
  96                         Pipe_ConfigurePipe(HIDInterfaceInfo
->Config
.DataOUTPipeNumber
, EP_TYPE_INTERRUPT
, PIPE_TOKEN_OUT
, 
  97                                                            EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
, PIPE_BANK_SINGLE
); 
  98                         HIDInterfaceInfo
->State
.DataOUTPipeSize 
= EndpointData
->EndpointSize
; 
 100                         HIDInterfaceInfo
->State
.DeviceUsesOUTPipe 
= true; 
 102                         FoundEndpoints 
|= HID_FOUND_DATAPIPE_OUT
;                
 106         HIDInterfaceInfo
->State
.IsActive 
= true; 
 107         return HID_ENUMERROR_NoError
; 
 110 static uint8_t DComp_HID_Host_NextHIDInterface(void* CurrentDescriptor
) 
 112         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 114                 USB_Descriptor_Interface_t
* CurrentInterface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 115                                                                                 USB_Descriptor_Interface_t
); 
 117                 if (CurrentInterface
->Class 
== HID_INTERFACE_CLASS
) 
 118                   return DESCRIPTOR_SEARCH_Found
; 
 121         return DESCRIPTOR_SEARCH_NotFound
; 
 124 static uint8_t DComp_NextHID(void* CurrentDescriptor
) 
 126         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_HID
) 
 127           return DESCRIPTOR_SEARCH_Found
; 
 128         else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 129           return DESCRIPTOR_SEARCH_Fail
; 
 131           return DESCRIPTOR_SEARCH_NotFound
;       
 134 static uint8_t DComp_HID_Host_NextHIDInterfaceEndpoint(void* CurrentDescriptor
) 
 136         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Endpoint
) 
 138                 USB_Descriptor_Endpoint_t
* CurrentEndpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 139                                                                               USB_Descriptor_Endpoint_t
);        
 141                 if (!(Pipe_IsEndpointBound(CurrentEndpoint
->EndpointAddress
))) 
 142                   return DESCRIPTOR_SEARCH_Found
; 
 144         else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 146                 return DESCRIPTOR_SEARCH_Fail
; 
 149         return DESCRIPTOR_SEARCH_NotFound
; 
 152 void HID_Host_USBTask(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
) 
 157 uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, const bool ControlRequest
, 
 158                                uint8_t* ReportID
, void* Buffer
) 
 160         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
)) 
 165                 USB_ControlRequest 
= (USB_Request_Header_t
) 
 167                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 168                         .bRequest      
= REQ_SetReport
, 
 170                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 171                         .wLength       
= USB_GetHIDReportSize(HIDInterfaceInfo
->Config
.HIDParserData
, *ReportID
, REPORT_ITEM_TYPE_In
), 
 174                 Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 176                 return USB_Host_SendControlRequest(Buffer
); 
 182                 Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataINPipeNumber
); 
 187                 if (HIDInterfaceInfo
->State
.UsingBootProtocol
) 
 189                         ReportSize 
= Pipe_BytesInPipe(); 
 193                         if (HIDInterfaceInfo
->Config
.HIDParserData
->UsingReportIDs
) 
 194                                 *ReportID 
= Pipe_Read_Byte(); 
 198                         ReportSize 
= USB_GetHIDReportSize(HIDInterfaceInfo
->Config
.HIDParserData
, *ReportID
, REPORT_ITEM_TYPE_In
); 
 201                 if ((ErrorCode 
= Pipe_Read_Stream_LE(Buffer
, ReportSize
, NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
) 
 207                 return PIPE_RWSTREAM_NoError
;            
 211 uint8_t HID_Host_SendReport(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
, uint8_t ReportID
, void* Buffer
, 
 212                             const uint16_t ReportSize
) 
 214         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
)) 
 217         if (HIDInterfaceInfo
->State
.DeviceUsesOUTPipe
) 
 219                 USB_ControlRequest 
= (USB_Request_Header_t
) 
 221                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 222                         .bRequest      
= REQ_SetReport
, 
 224                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 225                         .wLength       
= ReportSize
, 
 228                 Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 230                 return USB_Host_SendControlRequest(Buffer
); 
 236                 Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 240                   Pipe_Write_Stream_LE(&ReportID
, sizeof(ReportID
), NO_STREAM_CALLBACK
); 
 242                 if ((ErrorCode 
= Pipe_Write_Stream_LE(Buffer
, ReportSize
, NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
) 
 248                 return PIPE_RWSTREAM_NoError
; 
 252 bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
) 
 254         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
)) 
 259         Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataINPipeNumber
); 
 262         ReportReceived 
= Pipe_IsINReceived(); 
 266         return ReportReceived
; 
 269 uint8_t USB_HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
) 
 273         USB_ControlRequest 
= (USB_Request_Header_t
) 
 275                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 276                         .bRequest      
= REQ_SetProtocol
, 
 278                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 282         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 284         if (!(HIDInterfaceInfo
->State
.SupportsBootProtocol
)) 
 285           return HID_ERROR_LOGICAL
; 
 287         if ((ErrorCode 
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
) 
 290         HIDInterfaceInfo
->State
.UsingBootProtocol 
= true; 
 292         return HOST_SENDCONTROL_Successful
; 
 295 uint8_t USB_HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
) 
 299         uint8_t HIDReportData
[HIDInterfaceInfo
->State
.HIDReportSize
]; 
 301         USB_ControlRequest 
= (USB_Request_Header_t
) 
 303                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_STANDARD 
| REQREC_INTERFACE
), 
 304                         .bRequest      
= REQ_GetDescriptor
, 
 305                         .wValue        
= (DTYPE_Report 
<< 8), 
 306                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 307                         .wLength       
= HIDInterfaceInfo
->State
.HIDReportSize
, 
 310         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 312         if ((ErrorCode 
= USB_Host_SendControlRequest(HIDReportData
)) != HOST_SENDCONTROL_Successful
) 
 315         USB_ControlRequest 
= (USB_Request_Header_t
) 
 317                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 318                         .bRequest      
= REQ_SetProtocol
, 
 320                         .wIndex        
= HIDInterfaceInfo
->State
.InterfaceNumber
, 
 324         if ((ErrorCode 
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
) 
 327         HIDInterfaceInfo
->State
.UsingBootProtocol 
= false; 
 329         if (HIDInterfaceInfo
->Config
.HIDParserData 
== NULL
) 
 330           return HID_ERROR_LOGICAL
; 
 332         if ((ErrorCode 
= USB_ProcessHIDReport(HIDReportData
, HIDInterfaceInfo
->State
.HIDReportSize
, 
 333                                               HIDInterfaceInfo
->Config
.HIDParserData
)) != HID_PARSE_Successful
) 
 335                 return HID_ERROR_LOGICAL 
| ErrorCode
;