9 #include "../usb/usbapi.h"
17 #define INT_IN_EP 0x81
18 #define BULK_OUT_EP 0x05
19 #define BULK_IN_EP 0x82
21 #define MAX_PACKET_SIZE 64
23 #define LE_WORD(x) ((x)&0xFF),((x)>>8)
26 #define CS_INTERFACE 0x24
27 #define CS_ENDPOINT 0x25
29 #define SET_LINE_CODING 0x20
30 #define GET_LINE_CODING 0x21
31 #define SET_CONTROL_LINE_STATE 0x22
34 // Data structure for GET_LINE_CODING / SET_LINE_CODING class requests
45 static TLineCoding LineCoding = {115200, 0, 0, 8};
46 static U8 abBulkBuf [64];
47 static U8 abClassReqData [8];
48 static xQueueHandle xRXQueue = NULL;
49 static xQueueHandle xTXQueue = NULL;
50 static int usbSerialInitialized = FALSE;
55 static const U8 abDescriptors [] =
62 LE_WORD(0x0200), // bcdUSB
64 0x00, // bDeviceSubClass
65 0x00, // bDeviceProtocol
66 MAX_PACKET_SIZE0, // bMaxPacketSize
67 LE_WORD(0xFFFF), // idVendor
68 LE_WORD(0x0005), // idProduct
69 LE_WORD(0x0100), // bcdDevice
70 0x01, // iManufacturer
72 0x03, // iSerialNumber
73 0x01, // bNumConfigurations
76 // Configuration descriptor
80 LE_WORD(67), // wTotalLength
81 0x02, // bNumInterfaces
82 0x01, // bConfigurationValue
83 0x00, // iConfiguration
88 // Control class interface
92 0x00, // bInterfaceNumber
93 0x00, // bAlternateSetting
94 0x01, // bNumEndPoints
95 0x02, // bInterfaceClass
96 0x02, // bInterfaceSubClass
97 0x01, // bInterfaceProtocol, linux requires value of 1 for the cdc_acm module
101 // Header functional descriptor
109 // Call management functional descriptor
114 0x01, // bmCapabilities = device handles call management
115 0x01, // bDataInterface
118 // ACM functional descriptor
123 0x02, // bmCapabilities
126 // Union functional descriptor
131 0x00, // bMasterInterface
132 0x01, // bSlaveInterface0
139 INT_IN_EP, // bEndpointAddress
140 0x03, // bmAttributes = intr
141 LE_WORD(8), // wMaxPacketSize
145 // Data class interface descriptor
149 0x01, // bInterfaceNumber
150 0x00, // bAlternateSetting
151 0x02, // bNumEndPoints
152 0x0A, // bInterfaceClass = data
153 0x00, // bInterfaceSubClass
154 0x00, // bInterfaceProtocol
162 BULK_OUT_EP, // bEndpointAddress
163 0x02, // bmAttributes = bulk
164 LE_WORD(MAX_PACKET_SIZE), // wMaxPacketSize
172 BULK_IN_EP, // bEndpointAddress
173 0x02, // bmAttributes = bulk
174 LE_WORD(MAX_PACKET_SIZE), // wMaxPacketSize
178 // String descriptors
186 'L', 0, 'P', 0, 'C', 0, 'U', 0, 'S', 0, 'B', 0,
190 'U', 0, 'S', 0, 'B', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0,
194 'D', 0, 'E', 0, 'A', 0, 'D', 0, 'C', 0, '0', 0, 'D', 0, 'E', 0,
203 // Local function to handle incoming bulk data. This needs to copy the incoming data to the VCOM RX queue.
205 static int usbserBulkOut (U8 bEP, U8 bEPStatus __attribute__ ((unused)))
209 portBASE_TYPE xTaskWokenByPost = pdFALSE;
211 iLen = usbHardwareEndpointRead (bEP, abBulkBuf, sizeof (abBulkBuf));
213 for (i = 0; i < iLen; i++)
214 xTaskWokenByPost = xQueueSendFromISR (xRXQueue, &abBulkBuf [i], xTaskWokenByPost);
216 return xTaskWokenByPost;
220 // Local function to handle outgoing bulk data. This needs to copy any user data in the VCOM TX queue to the bulk endpoint.
222 static int usbserBulkIn (U8 bEP, U8 bEPStatus __attribute__ ((unused)))
225 portBASE_TYPE xTaskWoken = pdFALSE;
227 for (i = 0; i < MAX_PACKET_SIZE; i++)
228 if (!xQueueReceiveFromISR (xTXQueue, &abBulkBuf [i], &xTaskWoken))
232 usbHardwareEndpointWrite (bEP, abBulkBuf, i);
238 // Local function to handle the USB-CDC class requests
240 static BOOL usbserHandleClassRequest (TSetupPacket *pSetup, int *piLen, U8 **ppbData)
242 switch (pSetup->bRequest)
244 case SET_LINE_CODING:
246 memcpy ((U8 *) &LineCoding, *ppbData, 7);
251 case GET_LINE_CODING:
253 *ppbData = (U8 *) &LineCoding;
258 case SET_CONTROL_LINE_STATE:
269 // Writes one character to VCOM port
271 signed portBASE_TYPE usbserPutChar (signed portCHAR cOutChar, portTickType xBlockTime)
273 if (!usbSerialInitialized)
276 return xQueueSend (xTXQueue, &cOutChar, xBlockTime);
279 signed portBASE_TYPE usbserPutString (const signed portCHAR * const pcString, portTickType xBlockTime)
281 signed portCHAR *pxNext;
283 if (!usbSerialInitialized)
286 pxNext = (signed portCHAR *) pcString;
290 if (!usbserPutChar (*pxNext, xBlockTime))
300 // Reads one character from VCOM port
302 signed portBASE_TYPE usbserGetChar (signed portCHAR *pcRxedChar, portTickType xBlockTime)
304 if (!usbSerialInitialized)
307 if (xQueueReceive (xRXQueue, pcRxedChar, xBlockTime))
313 void usbserGetRxQueue (xQueueHandle *qh)
321 void usbserInit (void)
323 portENTER_CRITICAL ();
324 usbRegisterHandlers ();
325 usbRegisterDescriptors (abDescriptors);
326 usbRegisterRequestHandler (REQTYPE_TYPE_CLASS, usbserHandleClassRequest, abClassReqData);
327 usbHardwareRegisterEPIntHandler (INT_IN_EP, NULL);
328 usbHardwareRegisterEPIntHandler (BULK_IN_EP, usbserBulkIn);
329 usbHardwareRegisterEPIntHandler (BULK_OUT_EP, usbserBulkOut);
330 usbHardwareNakIntEnable (INACK_BI);
331 usbSetupInterruptHandler ();
332 xRXQueue = xQueueCreate (256, (unsigned portBASE_TYPE) sizeof (signed portCHAR));
333 xTXQueue = xQueueCreate (256, (unsigned portBASE_TYPE) sizeof (signed portCHAR));
334 usbSerialInitialized = TRUE;
335 portEXIT_CRITICAL ();
337 usbHardwareConnect (TRUE);