Added new HID_Host_SetIdlePeriod() function to the HID Host Class driver.
[pub/USBasp.git] / LUFA / Drivers / USB / Class / Host / HID.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2011.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
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.
20
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
28 this software.
29 */
30
31 #define __INCLUDE_FROM_USB_DRIVER
32 #include "../../Core/USBMode.h"
33
34 #if defined(USB_CAN_BE_HOST)
35
36 #define __INCLUDE_FROM_HID_DRIVER
37 #define __INCLUDE_FROM_HID_HOST_C
38 #include "HID.h"
39
40 uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
41 uint16_t ConfigDescriptorSize,
42 void* ConfigDescriptorData)
43 {
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;
48
49 memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State));
50
51 if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
52 return HID_ENUMERROR_InvalidConfigDescriptor;
53
54 while (!(DataINEndpoint) || !(DataOUTEndpoint))
55 {
56 if (!(HIDInterface) ||
57 USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
58 DCOMP_HID_Host_NextHIDInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
59 {
60 if (DataINEndpoint || DataOUTEndpoint)
61 break;
62
63 do
64 {
65 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
66 DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
67 {
68 return HID_ENUMERROR_NoCompatibleInterfaceFound;
69 }
70
71 HIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
72 } while (HIDInterfaceInfo->Config.HIDInterfaceProtocol &&
73 (HIDInterface->Protocol != HIDInterfaceInfo->Config.HIDInterfaceProtocol));
74
75 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
76 DCOMP_HID_Host_NextHID) != DESCRIPTOR_SEARCH_COMP_Found)
77 {
78 return HID_ENUMERROR_NoCompatibleInterfaceFound;
79 }
80
81 HIDDescriptor = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_HID_Descriptor_HID_t);
82
83 DataINEndpoint = NULL;
84 DataOUTEndpoint = NULL;
85
86 continue;
87 }
88
89 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
90
91 if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
92 DataINEndpoint = EndpointData;
93 else
94 DataOUTEndpoint = EndpointData;
95 }
96
97 for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
98 {
99 uint16_t Size;
100 uint8_t Type;
101 uint8_t Token;
102 uint8_t EndpointAddress;
103 uint8_t InterruptPeriod;
104 bool DoubleBanked;
105
106 if (PipeNum == HIDInterfaceInfo->Config.DataINPipeNumber)
107 {
108 Size = DataINEndpoint->EndpointSize;
109 EndpointAddress = DataINEndpoint->EndpointAddress;
110 Token = PIPE_TOKEN_IN;
111 Type = EP_TYPE_INTERRUPT;
112 DoubleBanked = HIDInterfaceInfo->Config.DataINPipeDoubleBank;
113 InterruptPeriod = DataINEndpoint->PollingIntervalMS;
114
115 HIDInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
116 }
117 else if (PipeNum == HIDInterfaceInfo->Config.DataOUTPipeNumber)
118 {
119 if (DataOUTEndpoint == NULL)
120 continue;
121
122 Size = DataOUTEndpoint->EndpointSize;
123 EndpointAddress = DataOUTEndpoint->EndpointAddress;
124 Token = PIPE_TOKEN_OUT;
125 Type = EP_TYPE_INTERRUPT;
126 DoubleBanked = HIDInterfaceInfo->Config.DataOUTPipeDoubleBank;
127 InterruptPeriod = DataOUTEndpoint->PollingIntervalMS;
128
129 HIDInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
130 HIDInterfaceInfo->State.DeviceUsesOUTPipe = true;
131 }
132 else
133 {
134 continue;
135 }
136
137 if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size,
138 DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE)))
139 {
140 return HID_ENUMERROR_PipeConfigurationFailed;
141 }
142
143 if (InterruptPeriod)
144 Pipe_SetInterruptPeriod(InterruptPeriod);
145 }
146
147 HIDInterfaceInfo->State.InterfaceNumber = HIDInterface->InterfaceNumber;
148 HIDInterfaceInfo->State.HIDReportSize = HIDDescriptor->HIDReportLength;
149 HIDInterfaceInfo->State.SupportsBootProtocol = (HIDInterface->SubClass != HID_CSCP_NonBootProtocol);
150 HIDInterfaceInfo->State.LargestReportSize = 8;
151 HIDInterfaceInfo->State.IsActive = true;
152
153 return HID_ENUMERROR_NoError;
154 }
155
156 static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor)
157 {
158 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
159
160 if (Header->Type == DTYPE_Interface)
161 {
162 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
163
164 if (Interface->Class == HID_CSCP_HIDClass)
165 return DESCRIPTOR_SEARCH_Found;
166 }
167
168 return DESCRIPTOR_SEARCH_NotFound;
169 }
170
171 static uint8_t DCOMP_HID_Host_NextHID(void* const CurrentDescriptor)
172 {
173 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
174
175 if (Header->Type == HID_DTYPE_HID)
176 return DESCRIPTOR_SEARCH_Found;
177 else if (Header->Type == DTYPE_Interface)
178 return DESCRIPTOR_SEARCH_Fail;
179 else
180 return DESCRIPTOR_SEARCH_NotFound;
181 }
182
183 static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor)
184 {
185 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
186
187 if (Header->Type == DTYPE_Endpoint)
188 {
189 USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
190
191 if (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
192 return DESCRIPTOR_SEARCH_Found;
193 }
194 else if (Header->Type == DTYPE_Interface)
195 {
196 return DESCRIPTOR_SEARCH_Fail;
197 }
198
199 return DESCRIPTOR_SEARCH_NotFound;
200 }
201
202 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
203 uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
204 const uint8_t ReportID,
205 void* Buffer)
206 {
207 USB_ControlRequest = (USB_Request_Header_t)
208 {
209 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
210 .bRequest = HID_REQ_SetReport,
211 .wValue = ((HID_REPORT_ITEM_In + 1) << 8) | ReportID,
212 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
213 .wLength = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, HID_REPORT_ITEM_In),
214 };
215
216 Pipe_SelectPipe(PIPE_CONTROLPIPE);
217
218 return USB_Host_SendControlRequest(Buffer);
219 }
220 #endif
221
222 uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
223 void* Buffer)
224 {
225 if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
226 return PIPE_READYWAIT_DeviceDisconnected;
227
228 uint8_t ErrorCode;
229
230 Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipeNumber);
231 Pipe_Unfreeze();
232
233 uint16_t ReportSize;
234 uint8_t* BufferPos = Buffer;
235
236 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
237 if (!(HIDInterfaceInfo->State.UsingBootProtocol))
238 {
239 uint8_t ReportID = 0;
240
241 if (HIDInterfaceInfo->Config.HIDParserData->UsingReportIDs)
242 {
243 ReportID = Pipe_Read_8();
244 *(BufferPos++) = ReportID;
245 }
246
247 ReportSize = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, HID_REPORT_ITEM_In);
248 }
249 else
250 #endif
251 {
252 ReportSize = Pipe_BytesInPipe();
253 }
254
255 if ((ErrorCode = Pipe_Read_Stream_LE(BufferPos, ReportSize, NULL)) != PIPE_RWSTREAM_NoError)
256 return ErrorCode;
257
258 Pipe_ClearIN();
259 Pipe_Freeze();
260
261 return PIPE_RWSTREAM_NoError;
262 }
263
264 uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
265 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
266 const uint8_t ReportID,
267 #endif
268 const uint8_t ReportType,
269 void* Buffer,
270 const uint16_t ReportSize)
271 {
272 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
273 if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
274 return false;
275
276 if (HIDInterfaceInfo->State.DeviceUsesOUTPipe && (ReportType == HID_REPORT_ITEM_Out))
277 {
278 uint8_t ErrorCode;
279
280 Pipe_SelectPipe(HIDInterfaceInfo->Config.DataOUTPipeNumber);
281 Pipe_Unfreeze();
282
283 if (ReportID)
284 Pipe_Write_Stream_LE(&ReportID, sizeof(ReportID), NULL);
285
286 if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, ReportSize, NULL)) != PIPE_RWSTREAM_NoError)
287 return ErrorCode;
288
289 Pipe_ClearOUT();
290 Pipe_Freeze();
291
292 return PIPE_RWSTREAM_NoError;
293 }
294 else
295 #endif
296 {
297 USB_ControlRequest = (USB_Request_Header_t)
298 {
299 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
300 .bRequest = HID_REQ_SetReport,
301 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
302 .wValue = ((ReportType + 1) << 8) | ReportID,
303 #else
304 .wValue = ((ReportType + 1) << 8),
305 #endif
306 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
307 .wLength = ReportSize,
308 };
309
310 Pipe_SelectPipe(PIPE_CONTROLPIPE);
311
312 return USB_Host_SendControlRequest(Buffer);
313 }
314 }
315
316 bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
317 {
318 if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
319 return false;
320
321 bool ReportReceived;
322
323 Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipeNumber);
324 Pipe_Unfreeze();
325
326 ReportReceived = Pipe_IsINReceived();
327
328 Pipe_Freeze();
329
330 return ReportReceived;
331 }
332
333 uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
334 {
335 uint8_t ErrorCode;
336
337 USB_ControlRequest = (USB_Request_Header_t)
338 {
339 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
340 .bRequest = HID_REQ_SetProtocol,
341 .wValue = 0,
342 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
343 .wLength = 0,
344 };
345
346 Pipe_SelectPipe(PIPE_CONTROLPIPE);
347
348 if (!(HIDInterfaceInfo->State.SupportsBootProtocol))
349 return HID_ERROR_LOGICAL;
350
351 if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
352 return ErrorCode;
353
354 HIDInterfaceInfo->State.LargestReportSize = 8;
355 HIDInterfaceInfo->State.UsingBootProtocol = true;
356
357 return HOST_SENDCONTROL_Successful;
358 }
359
360 uint8_t HID_Host_SetIdlePeriod(const uint16_t MS)
361 {
362 USB_ControlRequest = (USB_Request_Header_t)
363 {
364 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE),
365 .bRequest = HID_REQ_SetIdle,
366 .wValue = ((MS << 6) & 0xFF00),
367 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
368 .wLength = 0,
369 };
370
371 Pipe_SelectPipe(PIPE_CONTROLPIPE);
372
373 return USB_Host_SendControlRequest(HIDReportData);
374 }
375
376 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
377 uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
378 {
379 uint8_t ErrorCode;
380
381 uint8_t HIDReportData[HIDInterfaceInfo->State.HIDReportSize];
382
383 USB_ControlRequest = (USB_Request_Header_t)
384 {
385 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE),
386 .bRequest = REQ_GetDescriptor,
387 .wValue = (HID_DTYPE_Report << 8),
388 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
389 .wLength = HIDInterfaceInfo->State.HIDReportSize,
390 };
391
392 Pipe_SelectPipe(PIPE_CONTROLPIPE);
393
394 if ((ErrorCode = USB_Host_SendControlRequest(HIDReportData)) != HOST_SENDCONTROL_Successful)
395 return ErrorCode;
396
397 if (HIDInterfaceInfo->State.UsingBootProtocol)
398 {
399 USB_ControlRequest = (USB_Request_Header_t)
400 {
401 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
402 .bRequest = HID_REQ_SetProtocol,
403 .wValue = 1,
404 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
405 .wLength = 0,
406 };
407
408 if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
409 return ErrorCode;
410
411 HIDInterfaceInfo->State.UsingBootProtocol = false;
412 }
413
414 if (HIDInterfaceInfo->Config.HIDParserData == NULL)
415 return HID_ERROR_LOGICAL;
416
417 if ((ErrorCode = USB_ProcessHIDReport(HIDReportData, HIDInterfaceInfo->State.HIDReportSize,
418 HIDInterfaceInfo->Config.HIDParserData)) != HID_PARSE_Successful)
419 {
420 return HID_ERROR_LOGICAL | ErrorCode;
421 }
422
423 uint8_t LargestReportSizeBits = HIDInterfaceInfo->Config.HIDParserData->LargestReportSizeBits;
424 HIDInterfaceInfo->State.LargestReportSize = (LargestReportSizeBits >> 3) + ((LargestReportSizeBits & 0x07) != 0);
425
426 return 0;
427 }
428 #endif
429
430 #endif
431