Update copyright year on all source files.
[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 "../../HighLevel/USBMode.h"
33 #if defined(USB_CAN_BE_HOST)
34
35 #define __INCLUDE_FROM_HID_DRIVER
36 #define __INCLUDE_FROM_HID_HOST_C
37 #include "HID.h"
38
39 uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
40 uint16_t ConfigDescriptorSize,
41 void* ConfigDescriptorData)
42 {
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;
47
48 memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State));
49
50 if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
51 return HID_ENUMERROR_InvalidConfigDescriptor;
52
53 while (!(DataINEndpoint) || !(DataOUTEndpoint))
54 {
55 if (!(HIDInterface) ||
56 USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
57 DCOMP_HID_Host_NextHIDInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
58 {
59 if (DataINEndpoint || DataOUTEndpoint)
60 break;
61
62 do
63 {
64 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
65 DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
66 {
67 return HID_ENUMERROR_NoCompatibleInterfaceFound;
68 }
69
70 HIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
71 } while (HIDInterfaceInfo->Config.HIDInterfaceProtocol &&
72 (HIDInterface->Protocol != HIDInterfaceInfo->Config.HIDInterfaceProtocol));
73
74 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
75 DCOMP_HID_Host_NextHID) != DESCRIPTOR_SEARCH_COMP_Found)
76 {
77 return HID_ENUMERROR_NoCompatibleInterfaceFound;
78 }
79
80 HIDDescriptor = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_HID_Descriptor_HID_t);
81
82 DataINEndpoint = NULL;
83 DataOUTEndpoint = NULL;
84
85 continue;
86 }
87
88 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
89
90 if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
91 DataINEndpoint = EndpointData;
92 else
93 DataOUTEndpoint = EndpointData;
94 }
95
96 for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
97 {
98 uint16_t Size;
99 uint8_t Type;
100 uint8_t Token;
101 uint8_t EndpointAddress;
102 uint8_t InterruptPeriod;
103 bool DoubleBanked;
104
105 if (PipeNum == HIDInterfaceInfo->Config.DataINPipeNumber)
106 {
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;
113
114 HIDInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
115 }
116 else if (PipeNum == HIDInterfaceInfo->Config.DataOUTPipeNumber)
117 {
118 if (DataOUTEndpoint == NULL)
119 continue;
120
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;
127
128 HIDInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
129 HIDInterfaceInfo->State.DeviceUsesOUTPipe = true;
130 }
131 else
132 {
133 continue;
134 }
135
136 if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size,
137 DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE)))
138 {
139 return HID_ENUMERROR_PipeConfigurationFailed;
140 }
141
142 if (InterruptPeriod)
143 Pipe_SetInterruptPeriod(InterruptPeriod);
144 }
145
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;
151
152 return HID_ENUMERROR_NoError;
153 }
154
155 static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor)
156 {
157 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
158
159 if (Header->Type == DTYPE_Interface)
160 {
161 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
162
163 if (Interface->Class == HID_CSCP_HIDClass)
164 return DESCRIPTOR_SEARCH_Found;
165 }
166
167 return DESCRIPTOR_SEARCH_NotFound;
168 }
169
170 static uint8_t DCOMP_HID_Host_NextHID(void* const CurrentDescriptor)
171 {
172 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
173
174 if (Header->Type == HID_DTYPE_HID)
175 return DESCRIPTOR_SEARCH_Found;
176 else if (Header->Type == DTYPE_Interface)
177 return DESCRIPTOR_SEARCH_Fail;
178 else
179 return DESCRIPTOR_SEARCH_NotFound;
180 }
181
182 static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor)
183 {
184 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
185
186 if (Header->Type == DTYPE_Endpoint)
187 {
188 USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
189
190 if (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
191 return DESCRIPTOR_SEARCH_Found;
192 }
193 else if (Header->Type == DTYPE_Interface)
194 {
195 return DESCRIPTOR_SEARCH_Fail;
196 }
197
198 return DESCRIPTOR_SEARCH_NotFound;
199 }
200
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,
204 void* Buffer)
205 {
206 USB_ControlRequest = (USB_Request_Header_t)
207 {
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),
213 };
214
215 Pipe_SelectPipe(PIPE_CONTROLPIPE);
216
217 return USB_Host_SendControlRequest(Buffer);
218 }
219 #endif
220
221 uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
222 void* Buffer)
223 {
224 if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
225 return PIPE_READYWAIT_DeviceDisconnected;
226
227 uint8_t ErrorCode;
228
229 Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipeNumber);
230 Pipe_Unfreeze();
231
232 uint16_t ReportSize;
233 uint8_t* BufferPos = Buffer;
234
235 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
236 if (!(HIDInterfaceInfo->State.UsingBootProtocol))
237 {
238 uint8_t ReportID = 0;
239
240 if (HIDInterfaceInfo->Config.HIDParserData->UsingReportIDs)
241 {
242 ReportID = Pipe_Read_Byte();
243 *(BufferPos++) = ReportID;
244 }
245
246 ReportSize = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, HID_REPORT_ITEM_In);
247 }
248 else
249 #endif
250 {
251 ReportSize = Pipe_BytesInPipe();
252 }
253
254 if ((ErrorCode = Pipe_Read_Stream_LE(BufferPos, ReportSize, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
255 return ErrorCode;
256
257 Pipe_ClearIN();
258 Pipe_Freeze();
259
260 return PIPE_RWSTREAM_NoError;
261 }
262
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,
266 #endif
267 const uint8_t ReportType,
268 void* Buffer,
269 const uint16_t ReportSize)
270 {
271 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
272 if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
273 return false;
274
275 if (HIDInterfaceInfo->State.DeviceUsesOUTPipe && (ReportType == HID_REPORT_ITEM_Out))
276 {
277 uint8_t ErrorCode;
278
279 Pipe_SelectPipe(HIDInterfaceInfo->Config.DataOUTPipeNumber);
280 Pipe_Unfreeze();
281
282 if (ReportID)
283 Pipe_Write_Stream_LE(&ReportID, sizeof(ReportID), NO_STREAM_CALLBACK);
284
285 if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, ReportSize, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
286 return ErrorCode;
287
288 Pipe_ClearOUT();
289 Pipe_Freeze();
290
291 return PIPE_RWSTREAM_NoError;
292 }
293 else
294 #endif
295 {
296 USB_ControlRequest = (USB_Request_Header_t)
297 {
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,
302 #else
303 .wValue = ((ReportType + 1) << 8),
304 #endif
305 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
306 .wLength = ReportSize,
307 };
308
309 Pipe_SelectPipe(PIPE_CONTROLPIPE);
310
311 return USB_Host_SendControlRequest(Buffer);
312 }
313 }
314
315 bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
316 {
317 if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
318 return false;
319
320 bool ReportReceived;
321
322 Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipeNumber);
323 Pipe_Unfreeze();
324
325 ReportReceived = Pipe_IsINReceived();
326
327 Pipe_Freeze();
328
329 return ReportReceived;
330 }
331
332 uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
333 {
334 uint8_t ErrorCode;
335
336 USB_ControlRequest = (USB_Request_Header_t)
337 {
338 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
339 .bRequest = HID_REQ_SetProtocol,
340 .wValue = 0,
341 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
342 .wLength = 0,
343 };
344
345 Pipe_SelectPipe(PIPE_CONTROLPIPE);
346
347 if (!(HIDInterfaceInfo->State.SupportsBootProtocol))
348 return HID_ERROR_LOGICAL;
349
350 if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
351 return ErrorCode;
352
353 HIDInterfaceInfo->State.LargestReportSize = 8;
354 HIDInterfaceInfo->State.UsingBootProtocol = true;
355
356 return HOST_SENDCONTROL_Successful;
357 }
358
359 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
360 uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
361 {
362 uint8_t ErrorCode;
363
364 uint8_t HIDReportData[HIDInterfaceInfo->State.HIDReportSize];
365
366 USB_ControlRequest = (USB_Request_Header_t)
367 {
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,
373 };
374
375 Pipe_SelectPipe(PIPE_CONTROLPIPE);
376
377 if ((ErrorCode = USB_Host_SendControlRequest(HIDReportData)) != HOST_SENDCONTROL_Successful)
378 return ErrorCode;
379
380 if (HIDInterfaceInfo->State.UsingBootProtocol)
381 {
382 USB_ControlRequest = (USB_Request_Header_t)
383 {
384 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
385 .bRequest = HID_REQ_SetProtocol,
386 .wValue = 1,
387 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
388 .wLength = 0,
389 };
390
391 if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
392 return ErrorCode;
393
394 HIDInterfaceInfo->State.UsingBootProtocol = false;
395 }
396
397 if (HIDInterfaceInfo->Config.HIDParserData == NULL)
398 return HID_ERROR_LOGICAL;
399
400 if ((ErrorCode = USB_ProcessHIDReport(HIDReportData, HIDInterfaceInfo->State.HIDReportSize,
401 HIDInterfaceInfo->Config.HIDParserData)) != HID_PARSE_Successful)
402 {
403 return HID_ERROR_LOGICAL | ErrorCode;
404 }
405
406 uint8_t LargestReportSizeBits = HIDInterfaceInfo->Config.HIDParserData->LargestReportSizeBits;
407 HIDInterfaceInfo->State.LargestReportSize = (LargestReportSizeBits >> 3) + ((LargestReportSizeBits & 0x07) != 0);
408
409 return 0;
410 }
411 #endif
412
413 #endif
414