]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/CDCClassHost.c
Merge commit '60b30c036397cb5627fa374bb930794b225daa29' as 'lib/lufa'
[qmk_firmware.git] / tmk_core / protocol / lufa / LUFA-git / LUFA / Drivers / USB / Class / Host / CDCClassHost.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_CDC_DRIVER
37 #define  __INCLUDE_FROM_CDC_HOST_C
38 #include "CDCClassHost.h"
39
40 uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
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_Endpoint_t*  NotificationEndpoint = NULL;
47         USB_Descriptor_Interface_t* CDCControlInterface  = NULL;
48
49         memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
50
51         if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
52           return CDC_ENUMERROR_InvalidConfigDescriptor;
53
54         while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint))
55         {
56                 if (!(CDCControlInterface) ||
57                     USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
58                                               DCOMP_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
59                 {
60                         if (NotificationEndpoint)
61                         {
62                                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
63                                                               DCOMP_CDC_Host_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
64                                 {
65                                         return CDC_ENUMERROR_NoCompatibleInterfaceFound;
66                                 }
67
68                                 DataINEndpoint  = NULL;
69                                 DataOUTEndpoint = NULL;
70                         }
71                         else
72                         {
73                                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
74                                                               DCOMP_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
75                                 {
76                                         return CDC_ENUMERROR_NoCompatibleInterfaceFound;
77                                 }
78
79                                 CDCControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
80
81                                 NotificationEndpoint = NULL;
82                         }
83
84                         continue;
85                 }
86
87                 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
88
89                 if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
90                 {
91                         if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
92                           NotificationEndpoint = EndpointData;
93                         else
94                           DataINEndpoint = EndpointData;
95                 }
96                 else
97                 {
98                         DataOUTEndpoint = EndpointData;
99                 }
100         }
101
102         CDCInterfaceInfo->Config.DataINPipe.Size  = le16_to_cpu(DataINEndpoint->EndpointSize);
103         CDCInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
104         CDCInterfaceInfo->Config.DataINPipe.Type  = EP_TYPE_BULK;
105
106         CDCInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
107         CDCInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
108         CDCInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
109
110         CDCInterfaceInfo->Config.NotificationPipe.Size = le16_to_cpu(NotificationEndpoint->EndpointSize);
111         CDCInterfaceInfo->Config.NotificationPipe.EndpointAddress = NotificationEndpoint->EndpointAddress;
112         CDCInterfaceInfo->Config.NotificationPipe.Type = EP_TYPE_INTERRUPT;
113
114         if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.DataINPipe, 1)))
115           return CDC_ENUMERROR_PipeConfigurationFailed;
116
117         if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.DataOUTPipe, 1)))
118           return CDC_ENUMERROR_PipeConfigurationFailed;
119
120         if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.NotificationPipe, 1)))
121           return CDC_ENUMERROR_PipeConfigurationFailed;
122
123         CDCInterfaceInfo->State.ControlInterfaceNumber = CDCControlInterface->InterfaceNumber;
124         CDCInterfaceInfo->State.ControlLineStates.HostToDevice = (CDC_CONTROL_LINE_OUT_RTS | CDC_CONTROL_LINE_OUT_DTR);
125         CDCInterfaceInfo->State.ControlLineStates.DeviceToHost = (CDC_CONTROL_LINE_IN_DCD  | CDC_CONTROL_LINE_IN_DSR);
126         CDCInterfaceInfo->State.IsActive = true;
127
128         return CDC_ENUMERROR_NoError;
129 }
130
131 static uint8_t DCOMP_CDC_Host_NextCDCControlInterface(void* const CurrentDescriptor)
132 {
133         USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
134
135         if (Header->Type == DTYPE_Interface)
136         {
137                 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
138
139                 if ((Interface->Class    == CDC_CSCP_CDCClass)    &&
140                     (Interface->SubClass == CDC_CSCP_ACMSubclass) &&
141                     (Interface->Protocol == CDC_CSCP_ATCommandProtocol))
142                 {
143                         return DESCRIPTOR_SEARCH_Found;
144                 }
145         }
146
147         return DESCRIPTOR_SEARCH_NotFound;
148 }
149
150 static uint8_t DCOMP_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor)
151 {
152         USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
153
154         if (Header->Type == DTYPE_Interface)
155         {
156                 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
157
158                 if ((Interface->Class    == CDC_CSCP_CDCDataClass)   &&
159                     (Interface->SubClass == CDC_CSCP_NoDataSubclass) &&
160                     (Interface->Protocol == CDC_CSCP_NoDataProtocol))
161                 {
162                         return DESCRIPTOR_SEARCH_Found;
163                 }
164         }
165
166         return DESCRIPTOR_SEARCH_NotFound;
167 }
168
169 static uint8_t DCOMP_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor)
170 {
171         USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
172
173         if (Header->Type == DTYPE_Endpoint)
174         {
175                 USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
176
177                 uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
178
179                 if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
180                     !(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
181                 {
182                         return DESCRIPTOR_SEARCH_Found;
183                 }
184         }
185         else if (Header->Type == DTYPE_Interface)
186         {
187                 return DESCRIPTOR_SEARCH_Fail;
188         }
189
190         return DESCRIPTOR_SEARCH_NotFound;
191 }
192
193 void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
194 {
195         if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
196           return;
197
198         Pipe_SelectPipe(CDCInterfaceInfo->Config.NotificationPipe.Address);
199         Pipe_Unfreeze();
200
201         if (Pipe_IsINReceived())
202         {
203                 USB_Request_Header_t Notification;
204                 Pipe_Read_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL);
205
206                 if ((Notification.bRequest      == CDC_NOTIF_SerialState) &&
207                     (Notification.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)))
208                 {
209                         Pipe_Read_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,
210                                             sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
211                                             NULL);
212
213                         Pipe_ClearIN();
214
215                         EVENT_CDC_Host_ControLineStateChanged(CDCInterfaceInfo);
216                 }
217                 else
218                 {
219                         Pipe_ClearIN();
220                 }
221         }
222
223         Pipe_Freeze();
224
225         #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
226         CDC_Host_Flush(CDCInterfaceInfo);
227         #endif
228 }
229
230 uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
231 {
232         USB_ControlRequest = (USB_Request_Header_t)
233         {
234                 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
235                 .bRequest      = CDC_REQ_SetLineEncoding,
236                 .wValue        = 0,
237                 .wIndex        = CDCInterfaceInfo->State.ControlInterfaceNumber,
238                 .wLength       = sizeof(CDCInterfaceInfo->State.LineEncoding),
239         };
240
241         Pipe_SelectPipe(PIPE_CONTROLPIPE);
242
243         return USB_Host_SendControlRequest(&CDCInterfaceInfo->State.LineEncoding);
244 }
245
246 uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
247 {
248         USB_ControlRequest = (USB_Request_Header_t)
249         {
250                 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
251                 .bRequest      = CDC_REQ_SetControlLineState,
252                 .wValue        = CDCInterfaceInfo->State.ControlLineStates.HostToDevice,
253                 .wIndex        = CDCInterfaceInfo->State.ControlInterfaceNumber,
254                 .wLength       = 0,
255         };
256
257         Pipe_SelectPipe(PIPE_CONTROLPIPE);
258
259         return USB_Host_SendControlRequest(NULL);
260 }
261
262 uint8_t CDC_Host_SendBreak(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
263                            const uint8_t Duration)
264 {
265         USB_ControlRequest = (USB_Request_Header_t)
266         {
267                 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
268                 .bRequest      = CDC_REQ_SendBreak,
269                 .wValue        = Duration,
270                 .wIndex        = CDCInterfaceInfo->State.ControlInterfaceNumber,
271                 .wLength       = 0,
272         };
273
274         Pipe_SelectPipe(PIPE_CONTROLPIPE);
275
276         return USB_Host_SendControlRequest(NULL);
277 }
278
279 uint8_t CDC_Host_SendData(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
280                           const void* const Buffer,
281                           const uint16_t Length)
282 {
283         if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
284           return PIPE_READYWAIT_DeviceDisconnected;
285
286         uint8_t ErrorCode;
287
288         Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipe.Address);
289
290         Pipe_Unfreeze();
291         ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NULL);
292         Pipe_Freeze();
293
294         return ErrorCode;
295 }
296
297 uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
298                             const char* const String)
299 {
300         if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
301           return PIPE_READYWAIT_DeviceDisconnected;
302
303         uint8_t ErrorCode;
304
305         Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipe.Address);
306
307         Pipe_Unfreeze();
308         ErrorCode = Pipe_Write_Stream_LE(String, strlen(String), NULL);
309         Pipe_Freeze();
310
311         return ErrorCode;
312 }
313
314 uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
315                           const uint8_t Data)
316 {
317         if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
318           return PIPE_READYWAIT_DeviceDisconnected;
319
320         uint8_t ErrorCode;
321
322         Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipe.Address);
323         Pipe_Unfreeze();
324
325         if (!(Pipe_IsReadWriteAllowed()))
326         {
327                 Pipe_ClearOUT();
328
329                 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
330                   return ErrorCode;
331         }
332
333         Pipe_Write_8(Data);
334         Pipe_Freeze();
335
336         return PIPE_READYWAIT_NoError;
337 }
338
339 uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
340 {
341         if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
342           return 0;
343
344         Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipe.Address);
345         Pipe_Unfreeze();
346
347         if (Pipe_IsINReceived())
348         {
349                 if (!(Pipe_BytesInPipe()))
350                 {
351                         Pipe_ClearIN();
352                         Pipe_Freeze();
353                         return 0;
354                 }
355                 else
356                 {
357                         Pipe_Freeze();
358                         return Pipe_BytesInPipe();
359                 }
360         }
361         else
362         {
363                 Pipe_Freeze();
364
365                 return 0;
366         }
367 }
368
369 int16_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
370 {
371         if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
372           return -1;
373
374         int16_t ReceivedByte = -1;
375
376         Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipe.Address);
377         Pipe_Unfreeze();
378
379         if (Pipe_IsINReceived())
380         {
381                 if (Pipe_BytesInPipe())
382                   ReceivedByte = Pipe_Read_8();
383
384                 if (!(Pipe_BytesInPipe()))
385                   Pipe_ClearIN();
386         }
387
388         Pipe_Freeze();
389
390         return ReceivedByte;
391 }
392
393 uint8_t CDC_Host_Flush(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
394 {
395         if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
396           return PIPE_READYWAIT_DeviceDisconnected;
397
398         uint8_t ErrorCode;
399
400         Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipe.Address);
401         Pipe_Unfreeze();
402
403         if (!(Pipe_BytesInPipe()))
404           return PIPE_READYWAIT_NoError;
405
406         bool BankFull = !(Pipe_IsReadWriteAllowed());
407
408         Pipe_ClearOUT();
409
410         if (BankFull)
411         {
412                 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
413                   return ErrorCode;
414
415                 Pipe_ClearOUT();
416         }
417
418         Pipe_Freeze();
419
420         return PIPE_READYWAIT_NoError;
421 }
422
423 #if defined(FDEV_SETUP_STREAM)
424 void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
425                            FILE* const Stream)
426 {
427         *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar, CDC_Host_getchar, _FDEV_SETUP_RW);
428         fdev_set_udata(Stream, CDCInterfaceInfo);
429 }
430
431 void CDC_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
432                                    FILE* const Stream)
433 {
434         *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar, CDC_Host_getchar_Blocking, _FDEV_SETUP_RW);
435         fdev_set_udata(Stream, CDCInterfaceInfo);
436 }
437
438 static int CDC_Host_putchar(char c,
439                             FILE* Stream)
440 {
441         return CDC_Host_SendByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
442 }
443
444 static int CDC_Host_getchar(FILE* Stream)
445 {
446         int16_t ReceivedByte = CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
447
448         if (ReceivedByte < 0)
449           return _FDEV_EOF;
450
451         return ReceivedByte;
452 }
453
454 static int CDC_Host_getchar_Blocking(FILE* Stream)
455 {
456         int16_t ReceivedByte;
457
458         while ((ReceivedByte = CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream))) < 0)
459         {
460                 if (USB_HostState == HOST_STATE_Unattached)
461                   return _FDEV_EOF;
462
463                 CDC_Host_USBTask((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
464                 USB_USBTask();
465         }
466
467         return ReceivedByte;
468 }
469 #endif
470
471 void CDC_Host_Event_Stub(void)
472 {
473
474 }
475
476 #endif
477