Statistics
| Branch: | Tag: | Revision:

root / LUFA / Drivers / USB / Class / Device / CDC.c @ 978b99e5

History | View | Annotate | Download (10.8 KB)

1
/*
2
             LUFA Library
3
     Copyright (C) Dean Camera, 2011.
4

5
  dean [at] fourwalledcubicle [dot] com
6
           www.lufa-lib.org
7
*/
8

    
9
/*
10
  Copyright 2011  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_DEVICE)
35

    
36
#define  __INCLUDE_FROM_CDC_DRIVER
37
#define  __INCLUDE_FROM_CDC_DEVICE_C
38
#include "CDC.h"
39

    
40
void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
41
{
42
        if (!(Endpoint_IsSETUPReceived()))
43
          return;
44

    
45
        if (USB_ControlRequest.wIndex != CDCInterfaceInfo->Config.ControlInterfaceNumber)
46
          return;
47

    
48
        switch (USB_ControlRequest.bRequest)
49
        {
50
                case CDC_REQ_GetLineEncoding:
51
                        if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
52
                        {
53
                                Endpoint_ClearSETUP();
54
                                Endpoint_Write_32_LE(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS);
55
                                Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.CharFormat);
56
                                Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.ParityType);
57
                                Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.DataBits);
58
                                Endpoint_ClearIN();
59
                                Endpoint_ClearStatusStage();
60
                        }
61

    
62
                        break;
63
                case CDC_REQ_SetLineEncoding:
64
                        if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
65
                        {
66
                                Endpoint_ClearSETUP();
67
                                CDCInterfaceInfo->State.LineEncoding.BaudRateBPS = Endpoint_Read_32_LE();
68
                                CDCInterfaceInfo->State.LineEncoding.CharFormat  = Endpoint_Read_8();
69
                                CDCInterfaceInfo->State.LineEncoding.ParityType  = Endpoint_Read_8();
70
                                CDCInterfaceInfo->State.LineEncoding.DataBits    = Endpoint_Read_8();
71
                                Endpoint_ClearOUT();
72
                                Endpoint_ClearStatusStage();
73

    
74
                                EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo);
75
                        }
76

    
77
                        break;
78
                case CDC_REQ_SetControlLineState:
79
                        if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
80
                        {
81
                                Endpoint_ClearSETUP();
82
                                Endpoint_ClearStatusStage();
83

    
84
                                CDCInterfaceInfo->State.ControlLineStates.HostToDevice = USB_ControlRequest.wValue;
85

    
86
                                EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo);
87
                        }
88

    
89
                        break;
90
                case CDC_REQ_SendBreak:
91
                        if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
92
                        {
93
                                Endpoint_ClearSETUP();
94
                                Endpoint_ClearStatusStage();
95

    
96
                                EVENT_CDC_Device_BreakSent(CDCInterfaceInfo, (uint8_t)USB_ControlRequest.wValue);
97
                        }
98

    
99
                        break;
100
        }
101
}
102

    
103
bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
104
{
105
        memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
106

    
107
        for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++)
108
        {
109
                uint16_t Size;
110
                uint8_t  Type;
111
                uint8_t  Direction;
112
                bool     DoubleBanked;
113

    
114
                if (EndpointNum == CDCInterfaceInfo->Config.DataINEndpointNumber)
115
                {
116
                        Size         = CDCInterfaceInfo->Config.DataINEndpointSize;
117
                        Direction    = ENDPOINT_DIR_IN;
118
                        Type         = EP_TYPE_BULK;
119
                        DoubleBanked = CDCInterfaceInfo->Config.DataINEndpointDoubleBank;
120
                }
121
                else if (EndpointNum == CDCInterfaceInfo->Config.DataOUTEndpointNumber)
122
                {
123
                        Size         = CDCInterfaceInfo->Config.DataOUTEndpointSize;
124
                        Direction    = ENDPOINT_DIR_OUT;
125
                        Type         = EP_TYPE_BULK;
126
                        DoubleBanked = CDCInterfaceInfo->Config.DataOUTEndpointDoubleBank;
127
                }
128
                else if (EndpointNum == CDCInterfaceInfo->Config.NotificationEndpointNumber)
129
                {
130
                        Size         = CDCInterfaceInfo->Config.NotificationEndpointSize;
131
                        Direction    = ENDPOINT_DIR_IN;
132
                        Type         = EP_TYPE_INTERRUPT;
133
                        DoubleBanked = CDCInterfaceInfo->Config.NotificationEndpointDoubleBank;
134
                }
135
                else
136
                {
137
                        continue;
138
                }
139

    
140
                if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size,
141
                                                 DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
142
                {
143
                        return false;
144
                }
145
        }
146

    
147
        return true;
148
}
149

    
150
void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
151
{
152
        if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
153
          return;
154

    
155
        #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
156
        CDC_Device_Flush(CDCInterfaceInfo);
157
        #endif
158
}
159

    
160
uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
161
                              const char* const String)
162
{
163
        if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
164
          return ENDPOINT_RWSTREAM_DeviceDisconnected;
165

    
166
        Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
167
        return Endpoint_Write_Stream_LE(String, strlen(String), NULL);
168
}
169

    
170
uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
171
                            const char* const Buffer,
172
                            const uint16_t Length)
173
{
174
        if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
175
          return ENDPOINT_RWSTREAM_DeviceDisconnected;
176

    
177
        Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
178
        return Endpoint_Write_Stream_LE(Buffer, Length, NULL);
179
}
180

    
181
uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
182
                            const uint8_t Data)
183
{
184
        if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
185
          return ENDPOINT_RWSTREAM_DeviceDisconnected;
186

    
187
        Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
188

    
189
        if (!(Endpoint_IsReadWriteAllowed()))
190
        {
191
                Endpoint_ClearIN();
192

    
193
                uint8_t ErrorCode;
194

    
195
                if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
196
                  return ErrorCode;
197
        }
198

    
199
        Endpoint_Write_8(Data);
200
        return ENDPOINT_READYWAIT_NoError;
201
}
202

    
203
uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
204
{
205
        if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
206
          return ENDPOINT_RWSTREAM_DeviceDisconnected;
207

    
208
        uint8_t ErrorCode;
209

    
210
        Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
211

    
212
        if (!(Endpoint_BytesInEndpoint()))
213
          return ENDPOINT_READYWAIT_NoError;
214

    
215
        bool BankFull = !(Endpoint_IsReadWriteAllowed());
216

    
217
        Endpoint_ClearIN();
218

    
219
        if (BankFull)
220
        {
221
                if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
222
                  return ErrorCode;
223

    
224
                Endpoint_ClearIN();
225
        }
226

    
227
        return ENDPOINT_READYWAIT_NoError;
228
}
229

    
230
uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
231
{
232
        if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
233
          return 0;
234

    
235
        Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);
236

    
237
        if (Endpoint_IsOUTReceived())
238
        {
239
                if (!(Endpoint_BytesInEndpoint()))
240
                {
241
                        Endpoint_ClearOUT();
242
                        return 0;
243
                }
244
                else
245
                {
246
                        return Endpoint_BytesInEndpoint();
247
                }
248
        }
249
        else
250
        {
251
                return 0;
252
        }
253
}
254

    
255
int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
256
{
257
        if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
258
          return -1;
259

    
260
        int16_t ReceivedByte = -1;
261

    
262
        Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);
263

    
264
        if (Endpoint_IsOUTReceived())
265
        {
266
                if (Endpoint_BytesInEndpoint())
267
                  ReceivedByte = Endpoint_Read_8();
268

    
269
                if (!(Endpoint_BytesInEndpoint()))
270
                  Endpoint_ClearOUT();
271
        }
272

    
273
        return ReceivedByte;
274
}
275

    
276
void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
277
{
278
        if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
279
          return;
280

    
281
        Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.NotificationEndpointNumber);
282

    
283
        USB_Request_Header_t Notification = (USB_Request_Header_t)
284
                {
285
                        .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
286
                        .bRequest      = CDC_NOTIF_SerialState,
287
                        .wValue        = CPU_TO_LE16(0),
288
                        .wIndex        = CPU_TO_LE16(0),
289
                        .wLength       = CPU_TO_LE16(sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost)),
290
                };
291

    
292
        Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL);
293
        Endpoint_Write_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,
294
                                 sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
295
                                 NULL);
296
        Endpoint_ClearIN();
297
}
298

    
299
#if defined(FDEV_SETUP_STREAM)
300
void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
301
                             FILE* const Stream)
302
{
303
        *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar, _FDEV_SETUP_RW);
304
        fdev_set_udata(Stream, CDCInterfaceInfo);
305
}
306

    
307
void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
308
                                     FILE* const Stream)
309
{
310
        *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar_Blocking, _FDEV_SETUP_RW);
311
        fdev_set_udata(Stream, CDCInterfaceInfo);
312
}
313

    
314
static int CDC_Device_putchar(char c,
315
                              FILE* Stream)
316
{
317
        return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
318
}
319

    
320
static int CDC_Device_getchar(FILE* Stream)
321
{
322
        int16_t ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
323

    
324
        if (ReceivedByte < 0)
325
          return _FDEV_EOF;
326

    
327
        return ReceivedByte;
328
}
329

    
330
static int CDC_Device_getchar_Blocking(FILE* Stream)
331
{
332
        int16_t ReceivedByte;
333

    
334
        while ((ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))) < 0)
335
        {
336
                if (USB_DeviceState == DEVICE_STATE_Unattached)
337
                  return _FDEV_EOF;
338

    
339
                CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
340
                USB_USBTask();
341
        }
342

    
343
        return ReceivedByte;
344
}
345
#endif
346

    
347
void CDC_Device_Event_Stub(void)
348
{
349

    
350
}
351

    
352
#endif
353