v0.1 board believed to be reading Vbat, Pressure, and X/Y/Z correctly now,
[fw/openalt] / usbser / usbser.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <string.h>
4
5 #include "FreeRTOS.h"
6 #include "task.h"
7 #include "queue.h"
8
9 #include "../usb/usbapi.h"
10 #include "usbser.h"
11
12 //
13 //
14 //
15 #define EOF (-1)
16
17 #define INT_IN_EP     0x81
18 #define BULK_OUT_EP   0x05
19 #define BULK_IN_EP    0x82
20
21 #define MAX_PACKET_SIZE 64
22
23 #define LE_WORD(x)    ((x)&0xFF),((x)>>8)
24
25 // CDC definitions
26 #define CS_INTERFACE      0x24
27 #define CS_ENDPOINT       0x25
28
29 #define SET_LINE_CODING         0x20
30 #define GET_LINE_CODING         0x21
31 #define SET_CONTROL_LINE_STATE  0x22
32
33 //
34 //  Data structure for GET_LINE_CODING / SET_LINE_CODING class requests
35 //
36 typedef struct 
37 {
38   U32   dwDTERate;
39   U8    bCharFormat;
40   U8    bParityType;
41   U8    bDataBits;
42
43 TLineCoding;
44
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;
51
52 //
53 //
54 //
55 static const U8 abDescriptors [] = 
56 {
57   //
58   //  Device descriptor
59   //
60   0x12,
61   DESC_DEVICE,
62   LE_WORD(0x0200),      // bcdUSB
63   0x02,                 // bDeviceClass
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
71   0x02,                 // iProduct
72   0x03,                 // iSerialNumber
73   0x01,                 // bNumConfigurations
74
75   //
76   //  Configuration descriptor
77   //
78   0x09,
79   DESC_CONFIGURATION,
80   LE_WORD(67),          // wTotalLength
81   0x02,                 // bNumInterfaces
82   0x01,                 // bConfigurationValue
83   0x00,                 // iConfiguration
84   0xC0,                 // bmAttributes
85   0x32,                 // bMaxPower
86
87   //
88   //  Control class interface
89   //
90   0x09,
91   DESC_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
98   0x00,                 // iInterface
99
100   //
101   //  Header functional descriptor
102   //
103   0x05,
104   CS_INTERFACE,
105   0x00,
106   LE_WORD(0x0110),
107
108   //
109   //  Call management functional descriptor
110   //
111   0x05,
112   CS_INTERFACE,
113   0x01,
114   0x01,                 // bmCapabilities = device handles call management
115   0x01,                 // bDataInterface
116
117   //
118   //  ACM functional descriptor
119   //
120   0x04,
121   CS_INTERFACE,
122   0x02,
123   0x02,                 // bmCapabilities
124
125   //
126   //  Union functional descriptor
127   //
128   0x05,
129   CS_INTERFACE,
130   0x06,
131   0x00,                 // bMasterInterface
132   0x01,                 // bSlaveInterface0
133
134   //
135   //  Notification EP
136   //
137   0x07,
138   DESC_ENDPOINT,
139   INT_IN_EP,            // bEndpointAddress
140   0x03,                 // bmAttributes = intr
141   LE_WORD(8),           // wMaxPacketSize
142   0x0A,                 // bInterval
143
144   //
145   //  Data class interface descriptor
146   //
147   0x09,
148   DESC_INTERFACE,
149   0x01,                 // bInterfaceNumber
150   0x00,                 // bAlternateSetting
151   0x02,                 // bNumEndPoints
152   0x0A,                 // bInterfaceClass = data
153   0x00,                 // bInterfaceSubClass
154   0x00,                 // bInterfaceProtocol
155   0x00,                 // iInterface
156
157   //
158   //  Data EP OUT
159   //
160   0x07,
161   DESC_ENDPOINT,
162   BULK_OUT_EP,              // bEndpointAddress
163   0x02,                     // bmAttributes = bulk
164   LE_WORD(MAX_PACKET_SIZE), // wMaxPacketSize
165   0x00,                     // bInterval
166
167   //
168   //  Data EP in
169   //
170   0x07,
171   DESC_ENDPOINT,
172   BULK_IN_EP,               // bEndpointAddress
173   0x02,                     // bmAttributes = bulk
174   LE_WORD(MAX_PACKET_SIZE), // wMaxPacketSize
175   0x00,                     // bInterval
176
177   //
178   //  String descriptors
179   //
180   0x04,
181   DESC_STRING,
182   LE_WORD(0x0409),
183
184   0x0E,
185   DESC_STRING,
186   'L', 0, 'P', 0, 'C', 0, 'U', 0, 'S', 0, 'B', 0,
187
188   0x14,
189   DESC_STRING,
190   'U', 0, 'S', 0, 'B', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0,
191
192   0x12,
193   DESC_STRING,
194   'D', 0, 'E', 0, 'A', 0, 'D', 0, 'C', 0, '0', 0, 'D', 0, 'E', 0,
195
196   //
197   //  Terminating zero
198   //
199   0
200 };
201
202 //
203 //  Local function to handle incoming bulk data.  This needs to copy the incoming data to the VCOM RX queue.
204 //
205 static int usbserBulkOut (U8 bEP, U8 bEPStatus __attribute__ ((unused)))
206 {
207   int i;
208   int iLen;
209   portBASE_TYPE xTaskWokenByPost = pdFALSE;
210
211   iLen = usbHardwareEndpointRead (bEP, abBulkBuf, sizeof (abBulkBuf));
212
213   for (i = 0; i < iLen; i++) 
214     xTaskWokenByPost = xQueueSendFromISR (xRXQueue, &abBulkBuf [i], xTaskWokenByPost);
215
216   return xTaskWokenByPost;
217 }
218
219 //
220 //  Local function to handle outgoing bulk data.  This needs to copy any user data in the VCOM TX queue to the bulk endpoint.
221 //
222 static int usbserBulkIn (U8 bEP, U8 bEPStatus __attribute__ ((unused)))
223 {
224   int i;
225   portBASE_TYPE xTaskWoken = pdFALSE;
226   
227   for (i = 0; i < MAX_PACKET_SIZE; i++)
228     if (!xQueueReceiveFromISR (xTXQueue, &abBulkBuf [i], &xTaskWoken))
229       break;
230
231   if (i > 0)
232     usbHardwareEndpointWrite (bEP, abBulkBuf, i);
233
234   return xTaskWoken;
235 }
236
237 //
238 //  Local function to handle the USB-CDC class requests
239 //
240 static BOOL usbserHandleClassRequest (TSetupPacket *pSetup, int *piLen, U8 **ppbData)
241 {
242   switch (pSetup->bRequest) 
243   {
244     case SET_LINE_CODING:
245       {
246         memcpy ((U8 *) &LineCoding, *ppbData, 7);
247         *piLen = 7;
248       }
249       break;
250
251     case GET_LINE_CODING:
252       {
253         *ppbData = (U8 *) &LineCoding;
254         *piLen = 7;
255       }
256       break;
257
258     case SET_CONTROL_LINE_STATE:
259       break;
260
261     default:
262       return FALSE;
263   }
264
265   return TRUE;
266 }
267
268 //
269 //  Writes one character to VCOM port
270 //
271 signed portBASE_TYPE usbserPutChar (signed portCHAR cOutChar, portTickType xBlockTime)
272 {
273   if (!usbSerialInitialized)
274     return pdFALSE;
275
276   return xQueueSend (xTXQueue, &cOutChar, xBlockTime);
277 }
278
279 signed portBASE_TYPE usbserPutString (const signed portCHAR * const pcString, portTickType xBlockTime)
280 {
281   signed portCHAR *pxNext;
282
283   if (!usbSerialInitialized)
284     return pdFALSE;
285
286   pxNext = (signed portCHAR *) pcString;
287
288   while (*pxNext)
289   {
290     if (!usbserPutChar (*pxNext, xBlockTime))
291       return pdFALSE;
292
293     pxNext++;
294   }
295
296   return pdTRUE;
297 }
298
299 //
300 //  Reads one character from VCOM port
301 //
302 signed portBASE_TYPE usbserGetChar (signed portCHAR *pcRxedChar, portTickType xBlockTime)
303 {
304   if (!usbSerialInitialized)
305     return pdFALSE;
306
307   if (xQueueReceive (xRXQueue, pcRxedChar, xBlockTime))
308     return pdTRUE;
309   else
310     return pdFALSE;
311 }
312
313 void usbserGetRxQueue (xQueueHandle *qh)
314 {
315   *qh = xRXQueue;
316 }
317
318 //
319 //
320 //
321 void usbserInit (void)
322 {
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 ();
336
337   usbHardwareConnect (TRUE);
338 }