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