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 #define __INCLUDE_FROM_HID_CLASS_HOST_C
36 #define __INCLUDE_FROM_HID_DRIVER
39 uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
,
40 uint16_t ConfigDescriptorSize
,
41 void* ConfigDescriptorData
)
43 USB_Descriptor_Interface_t
* CurrentHIDInterface
;
45 USB_Descriptor_Endpoint_t
* DataINEndpoint
= NULL
;
46 USB_Descriptor_Endpoint_t
* DataOUTEndpoint
= NULL
;
48 memset(&HIDInterfaceInfo
->State
, 0x00, sizeof(HIDInterfaceInfo
->State
));
50 if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
)
51 return HID_ENUMERROR_InvalidConfigDescriptor
;
55 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
56 DCOMP_HID_Host_NextHIDInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
58 return HID_ENUMERROR_NoCompatibleInterfaceFound
;
61 CurrentHIDInterface
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
);
62 } while (HIDInterfaceInfo
->Config
.HIDInterfaceProtocol
&&
63 (CurrentHIDInterface
->Protocol
!= HIDInterfaceInfo
->Config
.HIDInterfaceProtocol
));
65 HIDInterfaceInfo
->State
.InterfaceNumber
= CurrentHIDInterface
->InterfaceNumber
;
66 HIDInterfaceInfo
->State
.SupportsBootProtocol
= (CurrentHIDInterface
->SubClass
!= HID_BOOTP_NonBootProtocol
);
68 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
69 DCOMP_HID_Host_NextHID
) != DESCRIPTOR_SEARCH_COMP_Found
)
71 return HID_ENUMERROR_NoCompatibleInterfaceFound
;
74 HIDInterfaceInfo
->State
.HIDReportSize
= DESCRIPTOR_PCAST(ConfigDescriptorData
,
75 USB_HID_Descriptor_HID_t
)->HIDReportLength
;
77 while (!(DataINEndpoint
) || !(DataOUTEndpoint
))
79 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
80 DCOMP_HID_Host_NextHIDInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
82 if (DataINEndpoint
|| DataOUTEndpoint
)
87 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
88 DCOMP_HID_Host_NextHIDInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
90 return HID_ENUMERROR_NoCompatibleInterfaceFound
;
93 CurrentHIDInterface
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
);
94 } while (HIDInterfaceInfo
->Config
.HIDInterfaceProtocol
&&
95 (CurrentHIDInterface
->Protocol
!= HIDInterfaceInfo
->Config
.HIDInterfaceProtocol
));
97 HIDInterfaceInfo
->State
.InterfaceNumber
= CurrentHIDInterface
->InterfaceNumber
;
98 HIDInterfaceInfo
->State
.SupportsBootProtocol
= (CurrentHIDInterface
->SubClass
!= HID_BOOTP_NonBootProtocol
);
100 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
101 DCOMP_HID_Host_NextHID
) != DESCRIPTOR_SEARCH_COMP_Found
)
103 return HID_ENUMERROR_NoCompatibleInterfaceFound
;
106 HIDInterfaceInfo
->State
.HIDReportSize
= DESCRIPTOR_PCAST(ConfigDescriptorData
,
107 USB_HID_Descriptor_HID_t
)->HIDReportLength
;
109 DataINEndpoint
= NULL
;
110 DataOUTEndpoint
= NULL
;
115 USB_Descriptor_Endpoint_t
* EndpointData
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
);
117 if (EndpointData
->EndpointAddress
& ENDPOINT_DESCRIPTOR_DIR_IN
)
118 DataINEndpoint
= EndpointData
;
120 DataOUTEndpoint
= EndpointData
;
123 for (uint8_t PipeNum
= 1; PipeNum
< PIPE_TOTAL_PIPES
; PipeNum
++)
125 if (PipeNum
== HIDInterfaceInfo
->Config
.DataINPipeNumber
)
127 Pipe_ConfigurePipe(PipeNum
, EP_TYPE_INTERRUPT
, PIPE_TOKEN_IN
,
128 DataINEndpoint
->EndpointAddress
, DataINEndpoint
->EndpointSize
,
129 HIDInterfaceInfo
->Config
.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
);
130 Pipe_SetInterruptPeriod(DataINEndpoint
->PollingIntervalMS
);
132 HIDInterfaceInfo
->State
.DataINPipeSize
= DataINEndpoint
->EndpointSize
;
134 else if (PipeNum
== HIDInterfaceInfo
->Config
.DataOUTPipeNumber
)
136 Pipe_ConfigurePipe(PipeNum
, EP_TYPE_INTERRUPT
, PIPE_TOKEN_OUT
,
137 DataOUTEndpoint
->EndpointAddress
, DataOUTEndpoint
->EndpointSize
,
138 HIDInterfaceInfo
->Config
.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
);
139 Pipe_SetInterruptPeriod(DataOUTEndpoint
->PollingIntervalMS
);
141 HIDInterfaceInfo
->State
.DataOUTPipeSize
= DataOUTEndpoint
->EndpointSize
;
142 HIDInterfaceInfo
->State
.DeviceUsesOUTPipe
= true;
146 HIDInterfaceInfo
->State
.LargestReportSize
= 8;
147 HIDInterfaceInfo
->State
.IsActive
= true;
149 return HID_ENUMERROR_NoError
;
152 static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor
)
154 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
156 USB_Descriptor_Interface_t
* CurrentInterface
= DESCRIPTOR_PCAST(CurrentDescriptor
,
157 USB_Descriptor_Interface_t
);
159 if (CurrentInterface
->Class
== HID_INTERFACE_CLASS
)
160 return DESCRIPTOR_SEARCH_Found
;
163 return DESCRIPTOR_SEARCH_NotFound
;
166 static uint8_t DCOMP_HID_Host_NextHID(void* const CurrentDescriptor
)
168 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == HID_DTYPE_HID
)
169 return DESCRIPTOR_SEARCH_Found
;
170 else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
171 return DESCRIPTOR_SEARCH_Fail
;
173 return DESCRIPTOR_SEARCH_NotFound
;
176 static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor
)
178 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Endpoint
)
180 USB_Descriptor_Endpoint_t
* CurrentEndpoint
= DESCRIPTOR_PCAST(CurrentDescriptor
,
181 USB_Descriptor_Endpoint_t
);
183 if (!(Pipe_IsEndpointBound(CurrentEndpoint
->EndpointAddress
)))
184 return DESCRIPTOR_SEARCH_Found
;
186 else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
188 return DESCRIPTOR_SEARCH_Fail
;
191 return DESCRIPTOR_SEARCH_NotFound
;
194 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
195 uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
,
196 const uint8_t ReportID
,
199 USB_ControlRequest
= (USB_Request_Header_t
)
201 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
),
202 .bRequest
= HID_REQ_SetReport
,
203 .wValue
= ((HID_REPORT_ITEM_In
+ 1) << 8) | ReportID
,
204 .wIndex
= HIDInterfaceInfo
->State
.InterfaceNumber
,
205 .wLength
= USB_GetHIDReportSize(HIDInterfaceInfo
->Config
.HIDParserData
, ReportID
, HID_REPORT_ITEM_In
),
208 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
210 return USB_Host_SendControlRequest(Buffer
);
214 uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
,
217 if ((USB_HostState
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
))
218 return PIPE_READYWAIT_DeviceDisconnected
;
222 Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataINPipeNumber
);
226 uint8_t* BufferPos
= Buffer
;
228 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
229 if (!(HIDInterfaceInfo
->State
.UsingBootProtocol
))
231 uint8_t ReportID
= 0;
233 if (HIDInterfaceInfo
->Config
.HIDParserData
->UsingReportIDs
)
235 ReportID
= Pipe_Read_Byte();
236 *(BufferPos
++) = ReportID
;
239 ReportSize
= USB_GetHIDReportSize(HIDInterfaceInfo
->Config
.HIDParserData
, ReportID
, HID_REPORT_ITEM_In
);
244 ReportSize
= Pipe_BytesInPipe();
247 if ((ErrorCode
= Pipe_Read_Stream_LE(BufferPos
, ReportSize
, NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
253 return PIPE_RWSTREAM_NoError
;
256 uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
,
257 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
258 const uint8_t ReportID
,
260 const uint8_t ReportType
,
262 const uint16_t ReportSize
)
264 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
265 if ((USB_HostState
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
))
268 if (HIDInterfaceInfo
->State
.DeviceUsesOUTPipe
&& (ReportType
== HID_REPORT_ITEM_Out
))
272 Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataOUTPipeNumber
);
276 Pipe_Write_Stream_LE(&ReportID
, sizeof(ReportID
), NO_STREAM_CALLBACK
);
278 if ((ErrorCode
= Pipe_Write_Stream_LE(Buffer
, ReportSize
, NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
284 return PIPE_RWSTREAM_NoError
;
289 USB_ControlRequest
= (USB_Request_Header_t
)
291 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
),
292 .bRequest
= HID_REQ_SetReport
,
293 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
294 .wValue
= ((ReportType
+ 1) << 8) | ReportID
,
296 .wValue
= ((ReportType
+ 1) << 8),
298 .wIndex
= HIDInterfaceInfo
->State
.InterfaceNumber
,
299 .wLength
= ReportSize
,
302 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
304 return USB_Host_SendControlRequest(Buffer
);
308 bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
)
310 if ((USB_HostState
!= HOST_STATE_Configured
) || !(HIDInterfaceInfo
->State
.IsActive
))
315 Pipe_SelectPipe(HIDInterfaceInfo
->Config
.DataINPipeNumber
);
318 ReportReceived
= Pipe_IsINReceived();
322 return ReportReceived
;
325 uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
)
329 USB_ControlRequest
= (USB_Request_Header_t
)
331 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
),
332 .bRequest
= HID_REQ_SetProtocol
,
334 .wIndex
= HIDInterfaceInfo
->State
.InterfaceNumber
,
338 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
340 if (!(HIDInterfaceInfo
->State
.SupportsBootProtocol
))
341 return HID_ERROR_LOGICAL
;
343 if ((ErrorCode
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
)
346 HIDInterfaceInfo
->State
.LargestReportSize
= 8;
347 HIDInterfaceInfo
->State
.UsingBootProtocol
= true;
349 return HOST_SENDCONTROL_Successful
;
352 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
353 uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t
* const HIDInterfaceInfo
)
357 uint8_t HIDReportData
[HIDInterfaceInfo
->State
.HIDReportSize
];
359 USB_ControlRequest
= (USB_Request_Header_t
)
361 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_STANDARD
| REQREC_INTERFACE
),
362 .bRequest
= REQ_GetDescriptor
,
363 .wValue
= (HID_DTYPE_Report
<< 8),
364 .wIndex
= HIDInterfaceInfo
->State
.InterfaceNumber
,
365 .wLength
= HIDInterfaceInfo
->State
.HIDReportSize
,
368 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
370 if ((ErrorCode
= USB_Host_SendControlRequest(HIDReportData
)) != HOST_SENDCONTROL_Successful
)
373 if (HIDInterfaceInfo
->State
.UsingBootProtocol
)
375 USB_ControlRequest
= (USB_Request_Header_t
)
377 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
),
378 .bRequest
= HID_REQ_SetProtocol
,
380 .wIndex
= HIDInterfaceInfo
->State
.InterfaceNumber
,
384 if ((ErrorCode
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
)
387 HIDInterfaceInfo
->State
.UsingBootProtocol
= false;
390 if (HIDInterfaceInfo
->Config
.HIDParserData
== NULL
)
391 return HID_ERROR_LOGICAL
;
393 if ((ErrorCode
= USB_ProcessHIDReport(HIDReportData
, HIDInterfaceInfo
->State
.HIDReportSize
,
394 HIDInterfaceInfo
->Config
.HIDParserData
)) != HID_PARSE_Successful
)
396 return HID_ERROR_LOGICAL
| ErrorCode
;
399 uint8_t LargestReportSizeBits
= HIDInterfaceInfo
->Config
.HIDParserData
->LargestReportSizeBits
;
400 HIDInterfaceInfo
->State
.LargestReportSize
= (LargestReportSizeBits
>> 3) + ((LargestReportSizeBits
& 0x07) != 0);