]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c
Merge commit '657d9f23fe47fb88cf221adb23095082f191ba6a'
[max/tmk_keyboard.git] / tmk_core / protocol / lufa / LUFA-git / LUFA / Drivers / USB / Class / Host / AndroidAccessoryClassHost.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_AOA_DRIVER
37 #define  __INCLUDE_FROM_ANDROIDACCESSORY_HOST_C
38 #include "AndroidAccessoryClassHost.h"
39
40 bool AOA_Host_ValidateAccessoryDevice(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
41                                       const USB_Descriptor_Device_t* const DeviceDescriptor,
42                                       bool* const NeedModeSwitch)
43 {
44         (void)AOAInterfaceInfo;
45
46         if (DeviceDescriptor->Header.Type != DTYPE_Device)
47           return false;
48
49         *NeedModeSwitch = ((DeviceDescriptor->ProductID != ANDROID_ACCESSORY_PRODUCT_ID) &&
50                            (DeviceDescriptor->ProductID != ANDROID_ACCESSORY_ADB_PRODUCT_ID));
51
52         return true;
53 }
54
55 uint8_t AOA_Host_ConfigurePipes(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
56                                 uint16_t ConfigDescriptorSize,
57                                 void* ConfigDescriptorData)
58 {
59         USB_Descriptor_Endpoint_t*  DataINEndpoint  = NULL;
60         USB_Descriptor_Endpoint_t*  DataOUTEndpoint = NULL;
61         USB_Descriptor_Interface_t* AOAInterface    = NULL;
62
63         memset(&AOAInterfaceInfo->State, 0x00, sizeof(AOAInterfaceInfo->State));
64
65         if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
66           return AOA_ENUMERROR_InvalidConfigDescriptor;
67
68         if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
69                                       DCOMP_AOA_Host_NextAndroidAccessoryInterface) != DESCRIPTOR_SEARCH_COMP_Found)
70         {
71                 return AOA_ENUMERROR_NoCompatibleInterfaceFound;
72         }
73
74         AOAInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
75
76         while (!(DataINEndpoint) || !(DataOUTEndpoint))
77         {
78                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
79                                               DCOMP_AOA_Host_NextInterfaceBulkEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
80                 {
81                         return AOA_ENUMERROR_NoCompatibleInterfaceFound;
82                 }
83
84                 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
85
86                 if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
87                   DataINEndpoint  = EndpointData;
88                 else
89                   DataOUTEndpoint = EndpointData;
90         }
91
92         AOAInterfaceInfo->Config.DataINPipe.Size  = le16_to_cpu(DataINEndpoint->EndpointSize);
93         AOAInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
94         AOAInterfaceInfo->Config.DataINPipe.Type  = EP_TYPE_BULK;
95
96         AOAInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
97         AOAInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
98         AOAInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
99
100         if (!(Pipe_ConfigurePipeTable(&AOAInterfaceInfo->Config.DataINPipe, 1)))
101           return AOA_ENUMERROR_PipeConfigurationFailed;
102
103         if (!(Pipe_ConfigurePipeTable(&AOAInterfaceInfo->Config.DataOUTPipe, 1)))
104           return AOA_ENUMERROR_PipeConfigurationFailed;
105
106         AOAInterfaceInfo->State.IsActive        = true;
107         AOAInterfaceInfo->State.InterfaceNumber = AOAInterface->InterfaceNumber;
108
109         return AOA_ENUMERROR_NoError;
110 }
111
112 static uint8_t DCOMP_AOA_Host_NextAndroidAccessoryInterface(void* const CurrentDescriptor)
113 {
114         USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
115
116         if (Header->Type == DTYPE_Interface)
117         {
118                 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
119
120                 if ((Interface->Class    == AOA_CSCP_AOADataClass)    &&
121                     (Interface->SubClass == AOA_CSCP_AOADataSubclass) &&
122                     (Interface->Protocol == AOA_CSCP_AOADataProtocol))
123                 {
124                         return DESCRIPTOR_SEARCH_Found;
125                 }
126         }
127
128         return DESCRIPTOR_SEARCH_NotFound;
129 }
130
131 static uint8_t DCOMP_AOA_Host_NextInterfaceBulkEndpoint(void* const CurrentDescriptor)
132 {
133         USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
134
135         if (Header->Type == DTYPE_Endpoint)
136         {
137                 USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
138
139                 uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
140
141                 if ((EndpointType == EP_TYPE_BULK) && (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress))))
142                   return DESCRIPTOR_SEARCH_Found;
143         }
144         else if (Header->Type == DTYPE_Interface)
145         {
146                 return DESCRIPTOR_SEARCH_Fail;
147         }
148
149         return DESCRIPTOR_SEARCH_NotFound;
150 }
151
152 void AOA_Host_USBTask(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
153 {
154         if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
155           return;
156
157         #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
158         AOA_Host_Flush(AOAInterfaceInfo);
159         #endif
160 }
161
162 uint8_t AOA_Host_StartAccessoryMode(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
163 {
164         uint8_t ErrorCode;
165
166         uint16_t AccessoryProtocol;
167         if ((ErrorCode = AOA_Host_GetAccessoryProtocol(&AccessoryProtocol)) != HOST_WAITERROR_Successful)
168           return ErrorCode;
169
170         if ((AccessoryProtocol != CPU_TO_LE16(AOA_PROTOCOL_AccessoryV1)) && (AccessoryProtocol != CPU_TO_LE16(AOA_PROTOCOL_AccessoryV2)))
171           return AOA_ERROR_LOGICAL_CMD_FAILED;
172
173         for (uint8_t PropertyIndex = 0; PropertyIndex < AOA_STRING_TOTAL_STRINGS; PropertyIndex++)
174         {
175                 if ((ErrorCode = AOA_Host_SendPropertyString(AOAInterfaceInfo, PropertyIndex)) != HOST_WAITERROR_Successful)
176                   return ErrorCode;
177         }
178
179         USB_ControlRequest = (USB_Request_Header_t)
180         {
181                 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR | REQREC_DEVICE),
182                 .bRequest      = AOA_REQ_StartAccessoryMode,
183                 .wValue        = 0,
184                 .wIndex        = 0,
185                 .wLength       = 0,
186         };
187
188         Pipe_SelectPipe(PIPE_CONTROLPIPE);
189         return USB_Host_SendControlRequest(NULL);
190 }
191
192 static uint8_t AOA_Host_GetAccessoryProtocol(uint16_t* const Protocol)
193 {
194         USB_ControlRequest = (USB_Request_Header_t)
195         {
196                 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_DEVICE),
197                 .bRequest      = AOA_REQ_GetAccessoryProtocol,
198                 .wValue        = 0,
199                 .wIndex        = 0,
200                 .wLength       = sizeof(uint16_t),
201         };
202
203         Pipe_SelectPipe(PIPE_CONTROLPIPE);
204         return USB_Host_SendControlRequest(Protocol);
205 }
206
207 static uint8_t AOA_Host_SendPropertyString(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
208                                            const uint8_t StringIndex)
209 {
210         const char* String = AOAInterfaceInfo->Config.PropertyStrings[StringIndex];
211
212         if (String == NULL)
213           String = "";
214
215         USB_ControlRequest = (USB_Request_Header_t)
216         {
217                 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR | REQREC_DEVICE),
218                 .bRequest      = AOA_REQ_SendString,
219                 .wValue        = 0,
220                 .wIndex        = StringIndex,
221                 .wLength       = (strlen(String) + 1),
222         };
223
224         Pipe_SelectPipe(PIPE_CONTROLPIPE);
225         return USB_Host_SendControlRequest((char*)String);
226 }
227
228 uint8_t AOA_Host_SendData(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
229                           const void* const Buffer,
230                           const uint16_t Length)
231 {
232         if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
233           return PIPE_READYWAIT_DeviceDisconnected;
234
235         uint8_t ErrorCode;
236
237         Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipe.Address);
238
239         Pipe_Unfreeze();
240         ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NULL);
241         Pipe_Freeze();
242
243         return ErrorCode;
244 }
245
246 uint8_t AOA_Host_SendString(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
247                             const char* const String)
248 {
249         if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
250           return PIPE_READYWAIT_DeviceDisconnected;
251
252         uint8_t ErrorCode;
253
254         Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipe.Address);
255
256         Pipe_Unfreeze();
257         ErrorCode = Pipe_Write_Stream_LE(String, strlen(String), NULL);
258         Pipe_Freeze();
259
260         return ErrorCode;
261 }
262
263 uint8_t AOA_Host_SendByte(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
264                           const uint8_t Data)
265 {
266         if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
267           return PIPE_READYWAIT_DeviceDisconnected;
268
269         uint8_t ErrorCode;
270
271         Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipe.Address);
272         Pipe_Unfreeze();
273
274         if (!(Pipe_IsReadWriteAllowed()))
275         {
276                 Pipe_ClearOUT();
277
278                 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
279                   return ErrorCode;
280         }
281
282         Pipe_Write_8(Data);
283         Pipe_Freeze();
284
285         return PIPE_READYWAIT_NoError;
286 }
287
288 uint16_t AOA_Host_BytesReceived(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
289 {
290         if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
291           return 0;
292
293         Pipe_SelectPipe(AOAInterfaceInfo->Config.DataINPipe.Address);
294         Pipe_Unfreeze();
295
296         if (Pipe_IsINReceived())
297         {
298                 if (!(Pipe_BytesInPipe()))
299                 {
300                         Pipe_ClearIN();
301                         Pipe_Freeze();
302                         return 0;
303                 }
304                 else
305                 {
306                         Pipe_Freeze();
307                         return Pipe_BytesInPipe();
308                 }
309         }
310         else
311         {
312                 Pipe_Freeze();
313
314                 return 0;
315         }
316 }
317
318 int16_t AOA_Host_ReceiveByte(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
319 {
320         if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
321           return -1;
322
323         int16_t ReceivedByte = -1;
324
325         Pipe_SelectPipe(AOAInterfaceInfo->Config.DataINPipe.Address);
326         Pipe_Unfreeze();
327
328         if (Pipe_IsINReceived())
329         {
330                 if (Pipe_BytesInPipe())
331                   ReceivedByte = Pipe_Read_8();
332
333                 if (!(Pipe_BytesInPipe()))
334                   Pipe_ClearIN();
335         }
336
337         Pipe_Freeze();
338
339         return ReceivedByte;
340 }
341
342 uint8_t AOA_Host_Flush(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
343 {
344         if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
345           return PIPE_READYWAIT_DeviceDisconnected;
346
347         uint8_t ErrorCode;
348
349         Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipe.Address);
350         Pipe_Unfreeze();
351
352         if (!(Pipe_BytesInPipe()))
353           return PIPE_READYWAIT_NoError;
354
355         bool BankFull = !(Pipe_IsReadWriteAllowed());
356
357         Pipe_ClearOUT();
358
359         if (BankFull)
360         {
361                 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
362                   return ErrorCode;
363
364                 Pipe_ClearOUT();
365         }
366
367         Pipe_Freeze();
368
369         return PIPE_READYWAIT_NoError;
370 }
371
372 #if defined(FDEV_SETUP_STREAM)
373 void AOA_Host_CreateStream(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
374                            FILE* const Stream)
375 {
376         *Stream = (FILE)FDEV_SETUP_STREAM(AOA_Host_putchar, AOA_Host_getchar, _FDEV_SETUP_RW);
377         fdev_set_udata(Stream, AOAInterfaceInfo);
378 }
379
380 void AOA_Host_CreateBlockingStream(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
381                                    FILE* const Stream)
382 {
383         *Stream = (FILE)FDEV_SETUP_STREAM(AOA_Host_putchar, AOA_Host_getchar_Blocking, _FDEV_SETUP_RW);
384         fdev_set_udata(Stream, AOAInterfaceInfo);
385 }
386
387 static int AOA_Host_putchar(char c,
388                             FILE* Stream)
389 {
390         return AOA_Host_SendByte((USB_ClassInfo_AOA_Host_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
391 }
392
393 static int AOA_Host_getchar(FILE* Stream)
394 {
395         int16_t ReceivedByte = AOA_Host_ReceiveByte((USB_ClassInfo_AOA_Host_t*)fdev_get_udata(Stream));
396
397         if (ReceivedByte < 0)
398           return _FDEV_EOF;
399
400         return ReceivedByte;
401 }
402
403 static int AOA_Host_getchar_Blocking(FILE* Stream)
404 {
405         int16_t ReceivedByte;
406
407         while ((ReceivedByte = AOA_Host_ReceiveByte((USB_ClassInfo_AOA_Host_t*)fdev_get_udata(Stream))) < 0)
408         {
409                 if (USB_HostState == HOST_STATE_Unattached)
410                   return _FDEV_EOF;
411
412                 AOA_Host_USBTask((USB_ClassInfo_AOA_Host_t*)fdev_get_udata(Stream));
413                 USB_USBTask();
414         }
415
416         return ReceivedByte;
417 }
418 #endif
419
420 #endif
421
422