initial usb
[rapper.git] / new_cmsis / usb / cdcuser.c
1 /*----------------------------------------------------------------------------\r
2  *      U S B  -  K e r n e l\r
3  *----------------------------------------------------------------------------\r
4  *      Name:    cdcuser.c\r
5  *      Purpose: USB Communication Device Class User module\r
6  *      Version: V1.10\r
7  *----------------------------------------------------------------------------\r
8 *      This software is supplied "AS IS" without any warranties, express,\r
9  *      implied or statutory, including but not limited to the implied\r
10  *      warranties of fitness for purpose, satisfactory quality and\r
11  *      noninfringement. Keil extends you a royalty-free right to reproduce\r
12  *      and distribute executable files created using this software for use\r
13  *      on NXP Semiconductors LPC microcontroller devices only. Nothing else\r
14  *      gives you the right to use this software.\r
15  *\r
16  * Copyright (c) 2009 Keil - An ARM Company. All rights reserved.\r
17  *---------------------------------------------------------------------------*/\r
18 \r
19 #include "lpc_types.h"\r
20 \r
21 #include "usb.h"\r
22 #include "usbhw.h"\r
23 #include "usbcfg.h"\r
24 #include "usbcore.h"\r
25 #include "cdc.h"\r
26 #include "cdcuser.h"\r
27 #include "serial.h"\r
28 \r
29 \r
30 unsigned char BulkBufIn  [USB_CDC_BUFSIZE];            // Buffer to store USB IN  packet\r
31 unsigned char BulkBufOut [USB_CDC_BUFSIZE];            // Buffer to store USB OUT packet\r
32 unsigned char NotificationBuf [10];\r
33 \r
34 CDC_LINE_CODING CDC_LineCoding  = {9600, 0, 0, 8};\r
35 unsigned short  CDC_SerialState = 0x0000;\r
36 unsigned short  CDC_DepInEmpty  = 1;                   // Data IN EP is empty\r
37 \r
38 /*----------------------------------------------------------------------------\r
39   We need a buffer for incomming data on USB port because USB receives\r
40   much faster than  UART transmits\r
41  *---------------------------------------------------------------------------*/\r
42 /* Buffer masks */\r
43 #define CDC_BUF_SIZE               (64)               // Output buffer in bytes (power 2)\r
44                                                        // large enough for file transfer\r
45 #define CDC_BUF_MASK               (CDC_BUF_SIZE-1ul)\r
46 \r
47 /* Buffer read / write macros */\r
48 #define CDC_BUF_RESET(cdcBuf)      (cdcBuf.rdIdx = cdcBuf.wrIdx = 0)\r
49 #define CDC_BUF_WR(cdcBuf, dataIn) (cdcBuf.data[CDC_BUF_MASK & cdcBuf.wrIdx++] = (dataIn))\r
50 #define CDC_BUF_RD(cdcBuf)         (cdcBuf.data[CDC_BUF_MASK & cdcBuf.rdIdx++])\r
51 #define CDC_BUF_EMPTY(cdcBuf)      (cdcBuf.rdIdx == cdcBuf.wrIdx)\r
52 #define CDC_BUF_FULL(cdcBuf)       (cdcBuf.rdIdx == cdcBuf.wrIdx+1)\r
53 #define CDC_BUF_COUNT(cdcBuf)      (CDC_BUF_MASK & (cdcBuf.wrIdx - cdcBuf.rdIdx))\r
54 \r
55 \r
56 // CDC output buffer\r
57 typedef struct __CDC_BUF_T {\r
58   unsigned char data[CDC_BUF_SIZE];\r
59   unsigned int wrIdx;\r
60   unsigned int rdIdx;\r
61 } CDC_BUF_T;\r
62 \r
63 CDC_BUF_T  CDC_OutBuf;                                 // buffer for all CDC Out data\r
64 \r
65 /*----------------------------------------------------------------------------\r
66   read data from CDC_OutBuf\r
67  *---------------------------------------------------------------------------*/\r
68 int CDC_RdOutBuf (char *buffer, const int *length) {\r
69   int bytesToRead, bytesRead;\r
70 \r
71   /* Read *length bytes, block if *bytes are not avaialable     */\r
72   bytesToRead = *length;\r
73   bytesToRead = (bytesToRead < (*length)) ? bytesToRead : (*length);\r
74   bytesRead = bytesToRead;\r
75 \r
76 \r
77   // ... add code to check for underrun\r
78 \r
79   while (bytesToRead--) {\r
80     *buffer++ = CDC_BUF_RD(CDC_OutBuf);\r
81   }\r
82   return (bytesRead);\r
83 }\r
84 \r
85 /*----------------------------------------------------------------------------\r
86   write data to CDC_OutBuf\r
87  *---------------------------------------------------------------------------*/\r
88 int CDC_WrOutBuf (const char *buffer, int *length) {\r
89   int bytesToWrite, bytesWritten;\r
90 \r
91   // Write *length bytes\r
92   bytesToWrite = *length;\r
93   bytesWritten = bytesToWrite;\r
94 \r
95 \r
96   // ... add code to check for overwrite\r
97 \r
98   while (bytesToWrite) {\r
99       CDC_BUF_WR(CDC_OutBuf, *buffer++);           // Copy Data to buffer\r
100       bytesToWrite--;\r
101   }\r
102 \r
103   return (bytesWritten);\r
104 }\r
105 \r
106 /*----------------------------------------------------------------------------\r
107   check if character(s) are available at CDC_OutBuf\r
108  *---------------------------------------------------------------------------*/\r
109 int CDC_OutBufAvailChar (int *availChar) {\r
110 \r
111   *availChar = CDC_BUF_COUNT(CDC_OutBuf);\r
112 \r
113   return (0);\r
114 }\r
115 /* end Buffer handling */\r
116 \r
117 \r
118 /*----------------------------------------------------------------------------\r
119   CDC Initialisation\r
120   Initializes the data structures and serial port\r
121   Parameters:   None\r
122   Return Value: None\r
123  *---------------------------------------------------------------------------*/\r
124 void CDC_Init (char portNum ) {\r
125 \r
126   if ( portNum == 0 )\r
127   {\r
128         ser_OpenPort (0);\r
129         ser_InitPort0 (CDC_LineCoding.dwDTERate,\r
130                 CDC_LineCoding.bDataBits,\r
131                 CDC_LineCoding.bParityType,\r
132                 CDC_LineCoding.bCharFormat);\r
133   }\r
134   else\r
135   {\r
136         ser_OpenPort (1);\r
137         ser_InitPort1 (CDC_LineCoding.dwDTERate,\r
138                 CDC_LineCoding.bDataBits,\r
139                 CDC_LineCoding.bParityType,\r
140                 CDC_LineCoding.bCharFormat);\r
141   }\r
142   CDC_DepInEmpty  = 1;\r
143   CDC_SerialState = CDC_GetSerialState();\r
144 \r
145   CDC_BUF_RESET(CDC_OutBuf);\r
146 }\r
147 \r
148 \r
149 /*----------------------------------------------------------------------------\r
150   CDC SendEncapsulatedCommand Request Callback\r
151   Called automatically on CDC SEND_ENCAPSULATED_COMMAND Request\r
152   Parameters:   None                          (global SetupPacket and EP0Buf)\r
153   Return Value: TRUE - Success, FALSE - Error\r
154  *---------------------------------------------------------------------------*/\r
155 uint32_t CDC_SendEncapsulatedCommand (void) {\r
156 \r
157   return (TRUE);\r
158 }\r
159 \r
160 \r
161 /*----------------------------------------------------------------------------\r
162   CDC GetEncapsulatedResponse Request Callback\r
163   Called automatically on CDC Get_ENCAPSULATED_RESPONSE Request\r
164   Parameters:   None                          (global SetupPacket and EP0Buf)\r
165   Return Value: TRUE - Success, FALSE - Error\r
166  *---------------------------------------------------------------------------*/\r
167 uint32_t CDC_GetEncapsulatedResponse (void) {\r
168 \r
169   /* ... add code to handle request */\r
170   return (TRUE);\r
171 }\r
172 \r
173 \r
174 /*----------------------------------------------------------------------------\r
175   CDC SetCommFeature Request Callback\r
176   Called automatically on CDC Set_COMM_FATURE Request\r
177   Parameters:   FeatureSelector\r
178   Return Value: TRUE - Success, FALSE - Error\r
179  *---------------------------------------------------------------------------*/\r
180 uint32_t CDC_SetCommFeature (unsigned short wFeatureSelector) {\r
181 \r
182   /* ... add code to handle request */\r
183   return (TRUE);\r
184 }\r
185 \r
186 \r
187 /*----------------------------------------------------------------------------\r
188   CDC GetCommFeature Request Callback\r
189   Called automatically on CDC Get_COMM_FATURE Request\r
190   Parameters:   FeatureSelector\r
191   Return Value: TRUE - Success, FALSE - Error\r
192  *---------------------------------------------------------------------------*/\r
193 uint32_t CDC_GetCommFeature (unsigned short wFeatureSelector) {\r
194 \r
195   /* ... add code to handle request */\r
196   return (TRUE);\r
197 }\r
198 \r
199 \r
200 /*----------------------------------------------------------------------------\r
201   CDC ClearCommFeature Request Callback\r
202   Called automatically on CDC CLEAR_COMM_FATURE Request\r
203   Parameters:   FeatureSelector\r
204   Return Value: TRUE - Success, FALSE - Error\r
205  *---------------------------------------------------------------------------*/\r
206 uint32_t CDC_ClearCommFeature (unsigned short wFeatureSelector) {\r
207 \r
208   /* ... add code to handle request */\r
209   return (TRUE);\r
210 }\r
211 \r
212 \r
213 /*----------------------------------------------------------------------------\r
214   CDC SetLineCoding Request Callback\r
215   Called automatically on CDC SET_LINE_CODING Request\r
216   Parameters:   none                    (global SetupPacket and EP0Buf)\r
217   Return Value: TRUE - Success, FALSE - Error\r
218  *---------------------------------------------------------------------------*/\r
219 uint32_t CDC_SetLineCoding (void) {\r
220 \r
221   CDC_LineCoding.dwDTERate   =   (EP0Buf[0] <<  0)\r
222                                | (EP0Buf[1] <<  8)\r
223                                | (EP0Buf[2] << 16)\r
224                                | (EP0Buf[3] << 24);\r
225   CDC_LineCoding.bCharFormat =  EP0Buf[4];\r
226   CDC_LineCoding.bParityType =  EP0Buf[5];\r
227   CDC_LineCoding.bDataBits   =  EP0Buf[6];\r
228 \r
229 #if PORT_NUM\r
230   ser_ClosePort(1);\r
231   ser_OpenPort (1);\r
232   ser_InitPort1 (CDC_LineCoding.dwDTERate,\r
233                 CDC_LineCoding.bDataBits,\r
234                 CDC_LineCoding.bParityType,\r
235                 CDC_LineCoding.bCharFormat);\r
236 #else\r
237   ser_ClosePort(0);\r
238   ser_OpenPort (0);\r
239   ser_InitPort0 (CDC_LineCoding.dwDTERate,\r
240                 CDC_LineCoding.bDataBits,\r
241                 CDC_LineCoding.bParityType,\r
242                 CDC_LineCoding.bCharFormat);\r
243 #endif\r
244   return (TRUE);\r
245 }\r
246 \r
247 \r
248 /*----------------------------------------------------------------------------\r
249   CDC GetLineCoding Request Callback\r
250   Called automatically on CDC GET_LINE_CODING Request\r
251   Parameters:   None                         (global SetupPacket and EP0Buf)\r
252   Return Value: TRUE - Success, FALSE - Error\r
253  *---------------------------------------------------------------------------*/\r
254 uint32_t CDC_GetLineCoding (void) {\r
255 \r
256   EP0Buf[0] = (CDC_LineCoding.dwDTERate >>  0) & 0xFF;\r
257   EP0Buf[1] = (CDC_LineCoding.dwDTERate >>  8) & 0xFF;\r
258   EP0Buf[2] = (CDC_LineCoding.dwDTERate >> 16) & 0xFF;\r
259   EP0Buf[3] = (CDC_LineCoding.dwDTERate >> 24) & 0xFF;\r
260   EP0Buf[4] =  CDC_LineCoding.bCharFormat;\r
261   EP0Buf[5] =  CDC_LineCoding.bParityType;\r
262   EP0Buf[6] =  CDC_LineCoding.bDataBits;\r
263 \r
264   return (TRUE);\r
265 }\r
266 \r
267 \r
268 /*----------------------------------------------------------------------------\r
269   CDC SetControlLineState Request Callback\r
270   Called automatically on CDC SET_CONTROL_LINE_STATE Request\r
271   Parameters:   ControlSignalBitmap\r
272   Return Value: TRUE - Success, FALSE - Error\r
273  *---------------------------------------------------------------------------*/\r
274 uint32_t CDC_SetControlLineState (unsigned short wControlSignalBitmap) {\r
275 \r
276   /* ... add code to handle request */\r
277   return (TRUE);\r
278 }\r
279 \r
280 \r
281 /*----------------------------------------------------------------------------\r
282   CDC SendBreak Request Callback\r
283   Called automatically on CDC Set_COMM_FATURE Request\r
284   Parameters:   0xFFFF  start of Break\r
285                 0x0000  stop  of Break\r
286                 0x####  Duration of Break\r
287   Return Value: TRUE - Success, FALSE - Error\r
288  *---------------------------------------------------------------------------*/\r
289 uint32_t CDC_SendBreak (unsigned short wDurationOfBreak) {\r
290 \r
291   /* ... add code to handle request */\r
292   return (TRUE);\r
293 }\r
294 \r
295 \r
296 /*----------------------------------------------------------------------------\r
297   CDC_BulkIn call on DataIn Request\r
298   Parameters:   none\r
299   Return Value: none\r
300  *---------------------------------------------------------------------------*/\r
301 void CDC_BulkIn(void) {\r
302   int numBytesRead, numBytesAvail;\r
303 \r
304   ser_AvailChar (&numBytesAvail);\r
305 \r
306   // ... add code to check for overwrite\r
307 \r
308   numBytesRead = ser_Read ((char *)&BulkBufIn[0], &numBytesAvail);\r
309 \r
310   // send over USB\r
311   if (numBytesRead > 0) {\r
312         USB_WriteEP (CDC_DEP_IN, &BulkBufIn[0], numBytesRead);\r
313   }\r
314   else {\r
315     CDC_DepInEmpty = 1;\r
316   }\r
317 }\r
318 \r
319 \r
320 /*----------------------------------------------------------------------------\r
321   CDC_BulkOut call on DataOut Request\r
322   Parameters:   none\r
323   Return Value: none\r
324  *---------------------------------------------------------------------------*/\r
325 void CDC_BulkOut(void) {\r
326   int numBytesRead;\r
327 \r
328   // get data from USB into intermediate buffer\r
329   numBytesRead = USB_ReadEP(CDC_DEP_OUT, &BulkBufOut[0]);\r
330 \r
331   // ... add code to check for overwrite\r
332 \r
333   // store data in a buffer to transmit it over serial interface\r
334   CDC_WrOutBuf ((char *)&BulkBufOut[0], &numBytesRead);\r
335 \r
336 }\r
337 \r
338 \r
339 /*----------------------------------------------------------------------------\r
340   Get the SERIAL_STATE as defined in usbcdc11.pdf, 6.3.5, Table 69.\r
341   Parameters:   none\r
342   Return Value: SerialState as defined in usbcdc11.pdf\r
343  *---------------------------------------------------------------------------*/\r
344 unsigned short CDC_GetSerialState (void) {\r
345   unsigned short temp;\r
346 \r
347   CDC_SerialState = 0;\r
348   ser_LineState (&temp);\r
349 \r
350   if (temp & 0x8000)  CDC_SerialState |= CDC_SERIAL_STATE_RX_CARRIER;\r
351   if (temp & 0x2000)  CDC_SerialState |= CDC_SERIAL_STATE_TX_CARRIER;\r
352   if (temp & 0x0010)  CDC_SerialState |= CDC_SERIAL_STATE_BREAK;\r
353   if (temp & 0x4000)  CDC_SerialState |= CDC_SERIAL_STATE_RING;\r
354   if (temp & 0x0008)  CDC_SerialState |= CDC_SERIAL_STATE_FRAMING;\r
355   if (temp & 0x0004)  CDC_SerialState |= CDC_SERIAL_STATE_PARITY;\r
356   if (temp & 0x0002)  CDC_SerialState |= CDC_SERIAL_STATE_OVERRUN;\r
357 \r
358   return (CDC_SerialState);\r
359 }\r
360 \r
361 \r
362 /*----------------------------------------------------------------------------\r
363   Send the SERIAL_STATE notification as defined in usbcdc11.pdf, 6.3.5.\r
364  *---------------------------------------------------------------------------*/\r
365 void CDC_NotificationIn (void) {\r
366 \r
367   NotificationBuf[0] = 0xA1;                           // bmRequestType\r
368   NotificationBuf[1] = CDC_NOTIFICATION_SERIAL_STATE;  // bNotification (SERIAL_STATE)\r
369   NotificationBuf[2] = 0x00;                           // wValue\r
370   NotificationBuf[3] = 0x00;\r
371   NotificationBuf[4] = 0x00;                           // wIndex (Interface #, LSB first)\r
372   NotificationBuf[5] = 0x00;\r
373   NotificationBuf[6] = 0x02;                           // wLength (Data length = 2 bytes, LSB first)\r
374   NotificationBuf[7] = 0x00;\r
375   NotificationBuf[8] = (CDC_SerialState >>  0) & 0xFF; // UART State Bitmap (16bits, LSB first)\r
376   NotificationBuf[9] = (CDC_SerialState >>  8) & 0xFF;\r
377 \r
378   USB_WriteEP (CDC_CEP_IN, &NotificationBuf[0], 10);   // send notification\r
379 }\r