]> git.gir.st - tmk_keyboard.git/blob - protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/HIDClassHost.c
Squashed 'tmk_core/' changes from b9e0ea0..caca2c0
[tmk_keyboard.git] / protocol / lufa / LUFA-120730 / LUFA / Drivers / USB / Class / Host / HIDClassHost.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2012.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2012 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 "HIDClassHost.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_NextHIDDescriptor) != 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_DIR_MASK) == ENDPOINT_DIR_IN)
92 DataINEndpoint = EndpointData;
93 else
94 DataOUTEndpoint = EndpointData;
95 }
96
97 HIDInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
98 HIDInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
99 HIDInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_INTERRUPT;
100
101 HIDInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
102 HIDInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
103 HIDInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_INTERRUPT;
104
105 if (!(Pipe_ConfigurePipeTable(&HIDInterfaceInfo->Config.DataINPipe, 1)))
106 return false;
107
108 if (!(Pipe_ConfigurePipeTable(&HIDInterfaceInfo->Config.DataOUTPipe, 1)))
109 return false;
110
111 HIDInterfaceInfo->State.InterfaceNumber = HIDInterface->InterfaceNumber;
112 HIDInterfaceInfo->State.HIDReportSize = LE16_TO_CPU(HIDDescriptor->HIDReportLength);
113 HIDInterfaceInfo->State.SupportsBootProtocol = (HIDInterface->SubClass != HID_CSCP_NonBootProtocol);
114 HIDInterfaceInfo->State.LargestReportSize = 8;
115 HIDInterfaceInfo->State.IsActive = true;
116
117 return HID_ENUMERROR_NoError;
118 }
119
120 static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor)
121 {
122 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
123
124 if (Header->Type == DTYPE_Interface)
125 {
126 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
127
128 if (Interface->Class == HID_CSCP_HIDClass)
129 return DESCRIPTOR_SEARCH_Found;
130 }
131
132 return DESCRIPTOR_SEARCH_NotFound;
133 }
134
135 static uint8_t DCOMP_HID_Host_NextHIDDescriptor(void* const CurrentDescriptor)
136 {
137 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
138
139 if (Header->Type == HID_DTYPE_HID)
140 return DESCRIPTOR_SEARCH_Found;
141 else if (Header->Type == DTYPE_Interface)
142 return DESCRIPTOR_SEARCH_Fail;
143 else
144 return DESCRIPTOR_SEARCH_NotFound;
145 }
146
147 static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor)
148 {
149 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
150
151 if (Header->Type == DTYPE_Endpoint)
152 {
153 USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
154
155 if (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
156 return DESCRIPTOR_SEARCH_Found;
157 }
158 else if (Header->Type == DTYPE_Interface)
159 {
160 return DESCRIPTOR_SEARCH_Fail;
161 }
162
163 return DESCRIPTOR_SEARCH_NotFound;
164 }
165
166 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
167 uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
168 const uint8_t ReportID,
169 void* Buffer)
170 {
171 USB_ControlRequest = (USB_Request_Header_t)
172 {
173 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
174 .bRequest = HID_REQ_SetReport,
175 .wValue = ((HID_REPORT_ITEM_In + 1) << 8) | ReportID,
176 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
177 .wLength = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, HID_REPORT_ITEM_In),
178 };
179
180 Pipe_SelectPipe(PIPE_CONTROLPIPE);
181
182 return USB_Host_SendControlRequest(Buffer);
183 }
184 #endif
185
186 uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
187 void* Buffer)
188 {
189 if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
190 return PIPE_READYWAIT_DeviceDisconnected;
191
192 uint8_t ErrorCode;
193
194 Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipe.Address);
195 Pipe_Unfreeze();
196
197 uint16_t ReportSize;
198 uint8_t* BufferPos = Buffer;
199
200 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
201 if (!(HIDInterfaceInfo->State.UsingBootProtocol))
202 {
203 uint8_t ReportID = 0;
204
205 if (HIDInterfaceInfo->Config.HIDParserData->UsingReportIDs)
206 {
207 ReportID = Pipe_Read_8();
208 *(BufferPos++) = ReportID;
209 }
210
211 ReportSize = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, HID_REPORT_ITEM_In);
212 }
213 else
214 #endif
215 {
216 ReportSize = Pipe_BytesInPipe();
217 }
218
219 if ((ErrorCode = Pipe_Read_Stream_LE(BufferPos, ReportSize, NULL)) != PIPE_RWSTREAM_NoError)
220 return ErrorCode;
221
222 Pipe_ClearIN();
223 Pipe_Freeze();
224
225 return PIPE_RWSTREAM_NoError;
226 }
227
228 uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
229 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
230 const uint8_t ReportID,
231 #endif
232 const uint8_t ReportType,
233 void* Buffer,
234 const uint16_t ReportSize)
235 {
236 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
237 if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
238 return false;
239
240 if (HIDInterfaceInfo->State.DeviceUsesOUTPipe && (ReportType == HID_REPORT_ITEM_Out))
241 {
242 uint8_t ErrorCode;
243
244 Pipe_SelectPipe(HIDInterfaceInfo->Config.DataOUTPipe.Address);
245 Pipe_Unfreeze();
246
247 if (ReportID)
248 Pipe_Write_Stream_LE(&ReportID, sizeof(ReportID), NULL);
249
250 if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, ReportSize, NULL)) != PIPE_RWSTREAM_NoError)
251 return ErrorCode;
252
253 Pipe_ClearOUT();
254 Pipe_Freeze();
255
256 return PIPE_RWSTREAM_NoError;
257 }
258 else
259 #endif
260 {
261 USB_ControlRequest = (USB_Request_Header_t)
262 {
263 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
264 .bRequest = HID_REQ_SetReport,
265 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
266 .wValue = ((ReportType + 1) << 8) | ReportID,
267 #else
268 .wValue = ((ReportType + 1) << 8),
269 #endif
270 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
271 .wLength = ReportSize,
272 };
273
274 Pipe_SelectPipe(PIPE_CONTROLPIPE);
275
276 return USB_Host_SendControlRequest(Buffer);
277 }
278 }
279
280 bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
281 {
282 if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
283 return false;
284
285 bool ReportReceived;
286
287 Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipe.Address);
288 Pipe_Unfreeze();
289
290 ReportReceived = Pipe_IsINReceived();
291
292 Pipe_Freeze();
293
294 return ReportReceived;
295 }
296
297 uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
298 {
299 uint8_t ErrorCode;
300
301 if (!(HIDInterfaceInfo->State.SupportsBootProtocol))
302 return HID_ERROR_LOGICAL;
303
304 USB_ControlRequest = (USB_Request_Header_t)
305 {
306 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
307 .bRequest = HID_REQ_SetProtocol,
308 .wValue = 0,
309 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
310 .wLength = 0,
311 };
312
313 Pipe_SelectPipe(PIPE_CONTROLPIPE);
314
315 if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
316 return ErrorCode;
317
318 HIDInterfaceInfo->State.LargestReportSize = 8;
319 HIDInterfaceInfo->State.UsingBootProtocol = true;
320
321 return HOST_SENDCONTROL_Successful;
322 }
323
324 uint8_t HID_Host_SetIdlePeriod(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
325 const uint16_t MS)
326 {
327 USB_ControlRequest = (USB_Request_Header_t)
328 {
329 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
330 .bRequest = HID_REQ_SetIdle,
331 .wValue = ((MS << 6) & 0xFF00),
332 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
333 .wLength = 0,
334 };
335
336 Pipe_SelectPipe(PIPE_CONTROLPIPE);
337
338 return USB_Host_SendControlRequest(NULL);
339 }
340
341 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
342 uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
343 {
344 uint8_t ErrorCode;
345
346 uint8_t HIDReportData[HIDInterfaceInfo->State.HIDReportSize];
347
348 USB_ControlRequest = (USB_Request_Header_t)
349 {
350 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE),
351 .bRequest = REQ_GetDescriptor,
352 .wValue = (HID_DTYPE_Report << 8),
353 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
354 .wLength = HIDInterfaceInfo->State.HIDReportSize,
355 };
356
357 Pipe_SelectPipe(PIPE_CONTROLPIPE);
358
359 if ((ErrorCode = USB_Host_SendControlRequest(HIDReportData)) != HOST_SENDCONTROL_Successful)
360 return ErrorCode;
361
362 if (HIDInterfaceInfo->State.UsingBootProtocol)
363 {
364 USB_ControlRequest = (USB_Request_Header_t)
365 {
366 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
367 .bRequest = HID_REQ_SetProtocol,
368 .wValue = 1,
369 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
370 .wLength = 0,
371 };
372
373 if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
374 return ErrorCode;
375
376 HIDInterfaceInfo->State.UsingBootProtocol = false;
377 }
378
379 if (HIDInterfaceInfo->Config.HIDParserData == NULL)
380 return HID_ERROR_LOGICAL;
381
382 if ((ErrorCode = USB_ProcessHIDReport(HIDReportData, HIDInterfaceInfo->State.HIDReportSize,
383 HIDInterfaceInfo->Config.HIDParserData)) != HID_PARSE_Successful)
384 {
385 return HID_ERROR_LOGICAL | ErrorCode;
386 }
387
388 uint16_t LargestReportSizeBits = HIDInterfaceInfo->Config.HIDParserData->LargestReportSizeBits;
389 HIDInterfaceInfo->State.LargestReportSize = (LargestReportSizeBits >> 3) + ((LargestReportSizeBits & 0x07) != 0);
390
391 return 0;
392 }
393 #endif
394
395 #endif
396
Imprint / Impressum