b0593f0f425bce1927c9631f36f976c75ef95ef9
[pub/USBasp.git] / LUFA / Drivers / USB / Class / Host / HID.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2010.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2010 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_CLASS_HOST_C
36 #define __INCLUDE_FROM_HID_DRIVER
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_Interface_t* CurrentHIDInterface;
44
45 USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
46 USB_Descriptor_Endpoint_t* DataOUTEndpoint = 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 do
54 {
55 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
56 DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
57 {
58 return HID_ENUMERROR_NoCompatibleInterfaceFound;
59 }
60
61 CurrentHIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
62 } while (HIDInterfaceInfo->Config.HIDInterfaceProtocol &&
63 (CurrentHIDInterface->Protocol != HIDInterfaceInfo->Config.HIDInterfaceProtocol));
64
65 HIDInterfaceInfo->State.InterfaceNumber = CurrentHIDInterface->InterfaceNumber;
66 HIDInterfaceInfo->State.SupportsBootProtocol = (CurrentHIDInterface->SubClass != HID_BOOTP_NonBootProtocol);
67
68 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
69 DCOMP_HID_Host_NextHID) != DESCRIPTOR_SEARCH_COMP_Found)
70 {
71 return HID_ENUMERROR_NoCompatibleInterfaceFound;
72 }
73
74 HIDInterfaceInfo->State.HIDReportSize = DESCRIPTOR_PCAST(ConfigDescriptorData,
75 USB_HID_Descriptor_HID_t)->HIDReportLength;
76
77 while (!(DataINEndpoint) || !(DataOUTEndpoint))
78 {
79 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
80 DCOMP_HID_Host_NextHIDInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
81 {
82 if (DataINEndpoint || DataOUTEndpoint)
83 break;
84
85 do
86 {
87 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
88 DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
89 {
90 return HID_ENUMERROR_NoCompatibleInterfaceFound;
91 }
92
93 CurrentHIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
94 } while (HIDInterfaceInfo->Config.HIDInterfaceProtocol &&
95 (CurrentHIDInterface->Protocol != HIDInterfaceInfo->Config.HIDInterfaceProtocol));
96
97 HIDInterfaceInfo->State.InterfaceNumber = CurrentHIDInterface->InterfaceNumber;
98 HIDInterfaceInfo->State.SupportsBootProtocol = (CurrentHIDInterface->SubClass != HID_BOOTP_NonBootProtocol);
99
100 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
101 DCOMP_HID_Host_NextHID) != DESCRIPTOR_SEARCH_COMP_Found)
102 {
103 return HID_ENUMERROR_NoCompatibleInterfaceFound;
104 }
105
106 HIDInterfaceInfo->State.HIDReportSize = DESCRIPTOR_PCAST(ConfigDescriptorData,
107 USB_HID_Descriptor_HID_t)->HIDReportLength;
108
109 DataINEndpoint = NULL;
110 DataOUTEndpoint = NULL;
111
112 continue;
113 }
114
115 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
116
117 if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
118 DataINEndpoint = EndpointData;
119 else
120 DataOUTEndpoint = EndpointData;
121 }
122
123 for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
124 {
125 if (PipeNum == HIDInterfaceInfo->Config.DataINPipeNumber)
126 {
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);
131
132 HIDInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
133 }
134 else if (PipeNum == HIDInterfaceInfo->Config.DataOUTPipeNumber)
135 {
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);
140
141 HIDInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
142 HIDInterfaceInfo->State.DeviceUsesOUTPipe = true;
143 }
144 }
145
146 HIDInterfaceInfo->State.LargestReportSize = 8;
147 HIDInterfaceInfo->State.IsActive = true;
148
149 return HID_ENUMERROR_NoError;
150 }
151
152 static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor)
153 {
154 if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
155 {
156 USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
157 USB_Descriptor_Interface_t);
158
159 if (CurrentInterface->Class == HID_INTERFACE_CLASS)
160 return DESCRIPTOR_SEARCH_Found;
161 }
162
163 return DESCRIPTOR_SEARCH_NotFound;
164 }
165
166 static uint8_t DCOMP_HID_Host_NextHID(void* const CurrentDescriptor)
167 {
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;
172 else
173 return DESCRIPTOR_SEARCH_NotFound;
174 }
175
176 static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor)
177 {
178 if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
179 {
180 USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
181 USB_Descriptor_Endpoint_t);
182
183 if (!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress)))
184 return DESCRIPTOR_SEARCH_Found;
185 }
186 else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
187 {
188 return DESCRIPTOR_SEARCH_Fail;
189 }
190
191 return DESCRIPTOR_SEARCH_NotFound;
192 }
193
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,
197 void* Buffer)
198 {
199 USB_ControlRequest = (USB_Request_Header_t)
200 {
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),
206 };
207
208 Pipe_SelectPipe(PIPE_CONTROLPIPE);
209
210 return USB_Host_SendControlRequest(Buffer);
211 }
212 #endif
213
214 uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
215 void* Buffer)
216 {
217 if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
218 return PIPE_READYWAIT_DeviceDisconnected;
219
220 uint8_t ErrorCode;
221
222 Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipeNumber);
223 Pipe_Unfreeze();
224
225 uint16_t ReportSize;
226 uint8_t* BufferPos = Buffer;
227
228 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
229 if (!(HIDInterfaceInfo->State.UsingBootProtocol))
230 {
231 uint8_t ReportID = 0;
232
233 if (HIDInterfaceInfo->Config.HIDParserData->UsingReportIDs)
234 {
235 ReportID = Pipe_Read_Byte();
236 *(BufferPos++) = ReportID;
237 }
238
239 ReportSize = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, HID_REPORT_ITEM_In);
240 }
241 else
242 #endif
243 {
244 ReportSize = Pipe_BytesInPipe();
245 }
246
247 if ((ErrorCode = Pipe_Read_Stream_LE(BufferPos, ReportSize, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
248 return ErrorCode;
249
250 Pipe_ClearIN();
251 Pipe_Freeze();
252
253 return PIPE_RWSTREAM_NoError;
254 }
255
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,
259 #endif
260 const uint8_t ReportType,
261 void* Buffer,
262 const uint16_t ReportSize)
263 {
264 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
265 if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
266 return false;
267
268 if (HIDInterfaceInfo->State.DeviceUsesOUTPipe && (ReportType == HID_REPORT_ITEM_Out))
269 {
270 uint8_t ErrorCode;
271
272 Pipe_SelectPipe(HIDInterfaceInfo->Config.DataOUTPipeNumber);
273 Pipe_Unfreeze();
274
275 if (ReportID)
276 Pipe_Write_Stream_LE(&ReportID, sizeof(ReportID), NO_STREAM_CALLBACK);
277
278 if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, ReportSize, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
279 return ErrorCode;
280
281 Pipe_ClearOUT();
282 Pipe_Freeze();
283
284 return PIPE_RWSTREAM_NoError;
285 }
286 else
287 #endif
288 {
289 USB_ControlRequest = (USB_Request_Header_t)
290 {
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,
295 #else
296 .wValue = ((ReportType + 1) << 8),
297 #endif
298 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
299 .wLength = ReportSize,
300 };
301
302 Pipe_SelectPipe(PIPE_CONTROLPIPE);
303
304 return USB_Host_SendControlRequest(Buffer);
305 }
306 }
307
308 bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
309 {
310 if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
311 return false;
312
313 bool ReportReceived;
314
315 Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipeNumber);
316 Pipe_Unfreeze();
317
318 ReportReceived = Pipe_IsINReceived();
319
320 Pipe_Freeze();
321
322 return ReportReceived;
323 }
324
325 uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
326 {
327 uint8_t ErrorCode;
328
329 USB_ControlRequest = (USB_Request_Header_t)
330 {
331 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
332 .bRequest = HID_REQ_SetProtocol,
333 .wValue = 0,
334 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
335 .wLength = 0,
336 };
337
338 Pipe_SelectPipe(PIPE_CONTROLPIPE);
339
340 if (!(HIDInterfaceInfo->State.SupportsBootProtocol))
341 return HID_ERROR_LOGICAL;
342
343 if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
344 return ErrorCode;
345
346 HIDInterfaceInfo->State.LargestReportSize = 8;
347 HIDInterfaceInfo->State.UsingBootProtocol = true;
348
349 return HOST_SENDCONTROL_Successful;
350 }
351
352 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
353 uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
354 {
355 uint8_t ErrorCode;
356
357 uint8_t HIDReportData[HIDInterfaceInfo->State.HIDReportSize];
358
359 USB_ControlRequest = (USB_Request_Header_t)
360 {
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,
366 };
367
368 Pipe_SelectPipe(PIPE_CONTROLPIPE);
369
370 if ((ErrorCode = USB_Host_SendControlRequest(HIDReportData)) != HOST_SENDCONTROL_Successful)
371 return ErrorCode;
372
373 if (HIDInterfaceInfo->State.UsingBootProtocol)
374 {
375 USB_ControlRequest = (USB_Request_Header_t)
376 {
377 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
378 .bRequest = HID_REQ_SetProtocol,
379 .wValue = 1,
380 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
381 .wLength = 0,
382 };
383
384 if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
385 return ErrorCode;
386
387 HIDInterfaceInfo->State.UsingBootProtocol = false;
388 }
389
390 if (HIDInterfaceInfo->Config.HIDParserData == NULL)
391 return HID_ERROR_LOGICAL;
392
393 if ((ErrorCode = USB_ProcessHIDReport(HIDReportData, HIDInterfaceInfo->State.HIDReportSize,
394 HIDInterfaceInfo->Config.HIDParserData)) != HID_PARSE_Successful)
395 {
396 return HID_ERROR_LOGICAL | ErrorCode;
397 }
398
399 uint8_t LargestReportSizeBits = HIDInterfaceInfo->Config.HIDParserData->LargestReportSizeBits;
400 HIDInterfaceInfo->State.LargestReportSize = (LargestReportSizeBits >> 3) + ((LargestReportSizeBits & 0x07) != 0);
401
402 return 0;
403 }
404 #endif
405
406 #endif