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