xref: /nrf52832-nimble/rt-thread/components/drivers/usb/usbdevice/class/cdc_vcom.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero  *
4*10465441SEvalZero  * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero  *
6*10465441SEvalZero  * Change Logs:
7*10465441SEvalZero  * Date           Author       Notes
8*10465441SEvalZero  * 2012-10-02     Yi Qiu       first version
9*10465441SEvalZero  * 2012-12-12     heyuanjie87  change endpoints and function handler
10*10465441SEvalZero  * 2013-06-25     heyuanjie87  remove SOF mechinism
11*10465441SEvalZero  * 2013-07-20     Yi Qiu       do more test
12*10465441SEvalZero  * 2016-02-01     Urey         Fix some error
13*10465441SEvalZero  */
14*10465441SEvalZero 
15*10465441SEvalZero #include <rthw.h>
16*10465441SEvalZero #include <rtthread.h>
17*10465441SEvalZero #include <rtservice.h>
18*10465441SEvalZero #include <rtdevice.h>
19*10465441SEvalZero #include <drivers/serial.h>
20*10465441SEvalZero #include "drivers/usb_device.h"
21*10465441SEvalZero #include "cdc.h"
22*10465441SEvalZero 
23*10465441SEvalZero #ifdef RT_USB_DEVICE_CDC
24*10465441SEvalZero 
25*10465441SEvalZero #ifdef RT_VCOM_TX_TIMEOUT
26*10465441SEvalZero #define VCOM_TX_TIMEOUT      RT_VCOM_TX_TIMEOUT
27*10465441SEvalZero #else /*!RT_VCOM_TX_TIMEOUT*/
28*10465441SEvalZero #define VCOM_TX_TIMEOUT      1000
29*10465441SEvalZero #endif /*RT_VCOM_TX_TIMEOUT*/
30*10465441SEvalZero 
31*10465441SEvalZero #define CDC_RX_BUFSIZE          128
32*10465441SEvalZero #define CDC_MAX_PACKET_SIZE     64
33*10465441SEvalZero #define VCOM_DEVICE             "vcom"
34*10465441SEvalZero 
35*10465441SEvalZero #ifdef RT_VCOM_TASK_STK_SIZE
36*10465441SEvalZero #define VCOM_TASK_STK_SIZE      RT_VCOM_TASK_STK_SIZE
37*10465441SEvalZero #else /*!RT_VCOM_TASK_STK_SIZE*/
38*10465441SEvalZero #define VCOM_TASK_STK_SIZE      512
39*10465441SEvalZero #endif /*RT_VCOM_TASK_STK_SIZE*/
40*10465441SEvalZero 
41*10465441SEvalZero #ifdef RT_VCOM_TX_USE_DMA
42*10465441SEvalZero #define VCOM_TX_USE_DMA
43*10465441SEvalZero #endif /*RT_VCOM_TX_USE_DMA*/
44*10465441SEvalZero 
45*10465441SEvalZero #ifdef RT_VCOM_SERNO
46*10465441SEvalZero #define _SER_NO RT_VCOM_SERNO
47*10465441SEvalZero #else /*!RT_VCOM_SERNO*/
48*10465441SEvalZero #define _SER_NO  "32021919830108"
49*10465441SEvalZero #endif /*RT_VCOM_SERNO*/
50*10465441SEvalZero 
51*10465441SEvalZero #ifdef RT_VCOM_SER_LEN
52*10465441SEvalZero #define _SER_NO_LEN RT_VCOM_SER_LEN
53*10465441SEvalZero #else /*!RT_VCOM_SER_LEN*/
54*10465441SEvalZero #define _SER_NO_LEN 14 /*rt_strlen("32021919830108")*/
55*10465441SEvalZero #endif /*RT_VCOM_SER_LEN*/
56*10465441SEvalZero 
57*10465441SEvalZero ALIGN(RT_ALIGN_SIZE)
58*10465441SEvalZero static rt_uint8_t vcom_thread_stack[VCOM_TASK_STK_SIZE];
59*10465441SEvalZero static struct rt_thread vcom_thread;
60*10465441SEvalZero static struct ucdc_line_coding line_coding;
61*10465441SEvalZero 
62*10465441SEvalZero #define CDC_TX_BUFSIZE    1024
63*10465441SEvalZero #define CDC_BULKIN_MAXSIZE (CDC_TX_BUFSIZE / 8)
64*10465441SEvalZero 
65*10465441SEvalZero #define CDC_TX_HAS_DATE   0x01
66*10465441SEvalZero 
67*10465441SEvalZero struct vcom
68*10465441SEvalZero {
69*10465441SEvalZero     struct rt_serial_device serial;
70*10465441SEvalZero     uep_t ep_out;
71*10465441SEvalZero     uep_t ep_in;
72*10465441SEvalZero     uep_t ep_cmd;
73*10465441SEvalZero     rt_bool_t connected;
74*10465441SEvalZero     rt_bool_t in_sending;
75*10465441SEvalZero     struct rt_completion wait;
76*10465441SEvalZero     rt_uint8_t rx_rbp[CDC_RX_BUFSIZE];
77*10465441SEvalZero     struct rt_ringbuffer rx_ringbuffer;
78*10465441SEvalZero     rt_uint8_t tx_rbp[CDC_TX_BUFSIZE];
79*10465441SEvalZero     struct rt_ringbuffer tx_ringbuffer;
80*10465441SEvalZero     struct rt_event  tx_event;
81*10465441SEvalZero };
82*10465441SEvalZero 
83*10465441SEvalZero struct vcom_tx_msg
84*10465441SEvalZero {
85*10465441SEvalZero     struct rt_serial_device * serial;
86*10465441SEvalZero     const char *buf;
87*10465441SEvalZero     rt_size_t size;
88*10465441SEvalZero };
89*10465441SEvalZero 
90*10465441SEvalZero ALIGN(4)
91*10465441SEvalZero static struct udevice_descriptor dev_desc =
92*10465441SEvalZero {
93*10465441SEvalZero     USB_DESC_LENGTH_DEVICE,     //bLength;
94*10465441SEvalZero     USB_DESC_TYPE_DEVICE,       //type;
95*10465441SEvalZero     USB_BCD_VERSION,            //bcdUSB;
96*10465441SEvalZero     USB_CLASS_CDC,              //bDeviceClass;
97*10465441SEvalZero     0x00,                       //bDeviceSubClass;
98*10465441SEvalZero     0x00,                       //bDeviceProtocol;
99*10465441SEvalZero     CDC_MAX_PACKET_SIZE,          //bMaxPacketSize0;
100*10465441SEvalZero     _VENDOR_ID,                 //idVendor;
101*10465441SEvalZero     _PRODUCT_ID,                //idProduct;
102*10465441SEvalZero     USB_BCD_DEVICE,             //bcdDevice;
103*10465441SEvalZero     USB_STRING_MANU_INDEX,      //iManufacturer;
104*10465441SEvalZero     USB_STRING_PRODUCT_INDEX,   //iProduct;
105*10465441SEvalZero     USB_STRING_SERIAL_INDEX,    //iSerialNumber;
106*10465441SEvalZero     USB_DYNAMIC,                //bNumConfigurations;
107*10465441SEvalZero };
108*10465441SEvalZero 
109*10465441SEvalZero //FS and HS needed
110*10465441SEvalZero ALIGN(4)
111*10465441SEvalZero static struct usb_qualifier_descriptor dev_qualifier =
112*10465441SEvalZero {
113*10465441SEvalZero     sizeof(dev_qualifier),          //bLength
114*10465441SEvalZero     USB_DESC_TYPE_DEVICEQUALIFIER,  //bDescriptorType
115*10465441SEvalZero     0x0200,                         //bcdUSB
116*10465441SEvalZero     USB_CLASS_CDC,                  //bDeviceClass
117*10465441SEvalZero     0x00,                           //bDeviceSubClass
118*10465441SEvalZero     0x00,                           //bDeviceProtocol
119*10465441SEvalZero     64,                             //bMaxPacketSize0
120*10465441SEvalZero     0x01,                           //bNumConfigurations
121*10465441SEvalZero     0,
122*10465441SEvalZero };
123*10465441SEvalZero 
124*10465441SEvalZero /* communcation interface descriptor */
125*10465441SEvalZero ALIGN(4)
126*10465441SEvalZero const static struct ucdc_comm_descriptor _comm_desc =
127*10465441SEvalZero {
128*10465441SEvalZero #ifdef RT_USB_DEVICE_COMPOSITE
129*10465441SEvalZero     /* Interface Association Descriptor */
130*10465441SEvalZero     {
131*10465441SEvalZero         USB_DESC_LENGTH_IAD,
132*10465441SEvalZero         USB_DESC_TYPE_IAD,
133*10465441SEvalZero         USB_DYNAMIC,
134*10465441SEvalZero         0x02,
135*10465441SEvalZero         USB_CDC_CLASS_COMM,
136*10465441SEvalZero         USB_CDC_SUBCLASS_ACM,
137*10465441SEvalZero         USB_CDC_PROTOCOL_V25TER,
138*10465441SEvalZero         0x00,
139*10465441SEvalZero     },
140*10465441SEvalZero #endif
141*10465441SEvalZero     /* Interface Descriptor */
142*10465441SEvalZero     {
143*10465441SEvalZero         USB_DESC_LENGTH_INTERFACE,
144*10465441SEvalZero         USB_DESC_TYPE_INTERFACE,
145*10465441SEvalZero         USB_DYNAMIC,
146*10465441SEvalZero         0x00,
147*10465441SEvalZero         0x01,
148*10465441SEvalZero         USB_CDC_CLASS_COMM,
149*10465441SEvalZero         USB_CDC_SUBCLASS_ACM,
150*10465441SEvalZero         USB_CDC_PROTOCOL_V25TER,
151*10465441SEvalZero         0x00,
152*10465441SEvalZero     },
153*10465441SEvalZero     /* Header Functional Descriptor */
154*10465441SEvalZero     {
155*10465441SEvalZero         0x05,
156*10465441SEvalZero         USB_CDC_CS_INTERFACE,
157*10465441SEvalZero         USB_CDC_SCS_HEADER,
158*10465441SEvalZero         0x0110,
159*10465441SEvalZero     },
160*10465441SEvalZero     /* Call Management Functional Descriptor */
161*10465441SEvalZero     {
162*10465441SEvalZero         0x05,
163*10465441SEvalZero         USB_CDC_CS_INTERFACE,
164*10465441SEvalZero         USB_CDC_SCS_CALL_MGMT,
165*10465441SEvalZero         0x00,
166*10465441SEvalZero         USB_DYNAMIC,
167*10465441SEvalZero     },
168*10465441SEvalZero     /* Abstract Control Management Functional Descriptor */
169*10465441SEvalZero     {
170*10465441SEvalZero         0x04,
171*10465441SEvalZero         USB_CDC_CS_INTERFACE,
172*10465441SEvalZero         USB_CDC_SCS_ACM,
173*10465441SEvalZero         0x02,
174*10465441SEvalZero     },
175*10465441SEvalZero     /* Union Functional Descriptor */
176*10465441SEvalZero     {
177*10465441SEvalZero         0x05,
178*10465441SEvalZero         USB_CDC_CS_INTERFACE,
179*10465441SEvalZero         USB_CDC_SCS_UNION,
180*10465441SEvalZero         USB_DYNAMIC,
181*10465441SEvalZero         USB_DYNAMIC,
182*10465441SEvalZero     },
183*10465441SEvalZero     /* Endpoint Descriptor */
184*10465441SEvalZero     {
185*10465441SEvalZero         USB_DESC_LENGTH_ENDPOINT,
186*10465441SEvalZero         USB_DESC_TYPE_ENDPOINT,
187*10465441SEvalZero         USB_DYNAMIC | USB_DIR_IN,
188*10465441SEvalZero         USB_EP_ATTR_INT,
189*10465441SEvalZero         0x08,
190*10465441SEvalZero         0xFF,
191*10465441SEvalZero     },
192*10465441SEvalZero };
193*10465441SEvalZero 
194*10465441SEvalZero /* data interface descriptor */
195*10465441SEvalZero ALIGN(4)
196*10465441SEvalZero const static struct ucdc_data_descriptor _data_desc =
197*10465441SEvalZero {
198*10465441SEvalZero     /* interface descriptor */
199*10465441SEvalZero     {
200*10465441SEvalZero         USB_DESC_LENGTH_INTERFACE,
201*10465441SEvalZero         USB_DESC_TYPE_INTERFACE,
202*10465441SEvalZero         USB_DYNAMIC,
203*10465441SEvalZero         0x00,
204*10465441SEvalZero         0x02,
205*10465441SEvalZero         USB_CDC_CLASS_DATA,
206*10465441SEvalZero         0x00,
207*10465441SEvalZero         0x00,
208*10465441SEvalZero         0x00,
209*10465441SEvalZero     },
210*10465441SEvalZero     /* endpoint, bulk out */
211*10465441SEvalZero     {
212*10465441SEvalZero         USB_DESC_LENGTH_ENDPOINT,
213*10465441SEvalZero         USB_DESC_TYPE_ENDPOINT,
214*10465441SEvalZero         USB_DYNAMIC | USB_DIR_OUT,
215*10465441SEvalZero         USB_EP_ATTR_BULK,
216*10465441SEvalZero         USB_CDC_BUFSIZE,
217*10465441SEvalZero         0x00,
218*10465441SEvalZero     },
219*10465441SEvalZero     /* endpoint, bulk in */
220*10465441SEvalZero     {
221*10465441SEvalZero         USB_DESC_LENGTH_ENDPOINT,
222*10465441SEvalZero         USB_DESC_TYPE_ENDPOINT,
223*10465441SEvalZero         USB_DYNAMIC | USB_DIR_IN,
224*10465441SEvalZero         USB_EP_ATTR_BULK,
225*10465441SEvalZero         USB_CDC_BUFSIZE,
226*10465441SEvalZero         0x00,
227*10465441SEvalZero     },
228*10465441SEvalZero };
229*10465441SEvalZero ALIGN(4)
230*10465441SEvalZero static char serno[_SER_NO_LEN + 1] = {'\0'};
231*10465441SEvalZero RT_WEAK rt_err_t vcom_get_stored_serno(char *serno, int size);
232*10465441SEvalZero 
vcom_get_stored_serno(char * serno,int size)233*10465441SEvalZero rt_err_t vcom_get_stored_serno(char *serno, int size)
234*10465441SEvalZero {
235*10465441SEvalZero     return RT_ERROR;
236*10465441SEvalZero }
237*10465441SEvalZero ALIGN(4)
238*10465441SEvalZero const static char* _ustring[] =
239*10465441SEvalZero {
240*10465441SEvalZero     "Language",
241*10465441SEvalZero     "RT-Thread Team.",
242*10465441SEvalZero     "RTT Virtual Serial",
243*10465441SEvalZero     serno,
244*10465441SEvalZero     "Configuration",
245*10465441SEvalZero     "Interface",
246*10465441SEvalZero };
247*10465441SEvalZero static void rt_usb_vcom_init(struct ufunction *func);
248*10465441SEvalZero 
_vcom_reset_state(ufunction_t func)249*10465441SEvalZero static void _vcom_reset_state(ufunction_t func)
250*10465441SEvalZero {
251*10465441SEvalZero     struct vcom* data;
252*10465441SEvalZero     int lvl;
253*10465441SEvalZero 
254*10465441SEvalZero     RT_ASSERT(func != RT_NULL)
255*10465441SEvalZero 
256*10465441SEvalZero     data = (struct vcom*)func->user_data;
257*10465441SEvalZero 
258*10465441SEvalZero     lvl = rt_hw_interrupt_disable();
259*10465441SEvalZero     data->connected = RT_FALSE;
260*10465441SEvalZero     data->in_sending = RT_FALSE;
261*10465441SEvalZero     /*rt_kprintf("reset USB serial\n", cnt);*/
262*10465441SEvalZero     rt_hw_interrupt_enable(lvl);
263*10465441SEvalZero }
264*10465441SEvalZero 
265*10465441SEvalZero /**
266*10465441SEvalZero  * This function will handle cdc bulk in endpoint request.
267*10465441SEvalZero  *
268*10465441SEvalZero  * @param func the usb function object.
269*10465441SEvalZero  * @param size request size.
270*10465441SEvalZero  *
271*10465441SEvalZero  * @return RT_EOK.
272*10465441SEvalZero  */
_ep_in_handler(ufunction_t func,rt_size_t size)273*10465441SEvalZero static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size)
274*10465441SEvalZero {
275*10465441SEvalZero     struct vcom *data;
276*10465441SEvalZero     rt_size_t request_size;
277*10465441SEvalZero 
278*10465441SEvalZero     RT_ASSERT(func != RT_NULL);
279*10465441SEvalZero 
280*10465441SEvalZero     data = (struct vcom*)func->user_data;
281*10465441SEvalZero     request_size = data->ep_in->request.size;
282*10465441SEvalZero     RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_in_handler %d\n", request_size));
283*10465441SEvalZero     if ((request_size != 0) && ((request_size % EP_MAXPACKET(data->ep_in)) == 0))
284*10465441SEvalZero     {
285*10465441SEvalZero         /* don't have data right now. Send a zero-length-packet to
286*10465441SEvalZero          * terminate the transaction.
287*10465441SEvalZero          *
288*10465441SEvalZero          * FIXME: actually, this might not be the right place to send zlp.
289*10465441SEvalZero          * Only the rt_device_write could know how much data is sending. */
290*10465441SEvalZero         data->in_sending = RT_TRUE;
291*10465441SEvalZero 
292*10465441SEvalZero         data->ep_in->request.buffer = RT_NULL;
293*10465441SEvalZero         data->ep_in->request.size = 0;
294*10465441SEvalZero         data->ep_in->request.req_type = UIO_REQUEST_WRITE;
295*10465441SEvalZero         rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
296*10465441SEvalZero 
297*10465441SEvalZero         return RT_EOK;
298*10465441SEvalZero     }
299*10465441SEvalZero 
300*10465441SEvalZero     rt_completion_done(&data->wait);
301*10465441SEvalZero 
302*10465441SEvalZero     return RT_EOK;
303*10465441SEvalZero }
304*10465441SEvalZero 
305*10465441SEvalZero /**
306*10465441SEvalZero  * This function will handle cdc bulk out endpoint request.
307*10465441SEvalZero  *
308*10465441SEvalZero  * @param func the usb function object.
309*10465441SEvalZero  * @param size request size.
310*10465441SEvalZero  *
311*10465441SEvalZero  * @return RT_EOK.
312*10465441SEvalZero  */
_ep_out_handler(ufunction_t func,rt_size_t size)313*10465441SEvalZero static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size)
314*10465441SEvalZero {
315*10465441SEvalZero     rt_uint32_t level;
316*10465441SEvalZero     struct vcom *data;
317*10465441SEvalZero 
318*10465441SEvalZero     RT_ASSERT(func != RT_NULL);
319*10465441SEvalZero 
320*10465441SEvalZero     RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_out_handler %d\n", size));
321*10465441SEvalZero 
322*10465441SEvalZero     data = (struct vcom*)func->user_data;
323*10465441SEvalZero     /* ensure serial is active */
324*10465441SEvalZero     if((data->serial.parent.flag & RT_DEVICE_FLAG_ACTIVATED)
325*10465441SEvalZero         && (data->serial.parent.open_flag & RT_DEVICE_OFLAG_OPEN))
326*10465441SEvalZero     {
327*10465441SEvalZero         /* receive data from USB VCOM */
328*10465441SEvalZero         level = rt_hw_interrupt_disable();
329*10465441SEvalZero 
330*10465441SEvalZero         rt_ringbuffer_put(&data->rx_ringbuffer, data->ep_out->buffer, size);
331*10465441SEvalZero         rt_hw_interrupt_enable(level);
332*10465441SEvalZero 
333*10465441SEvalZero         /* notify receive data */
334*10465441SEvalZero         rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_RX_IND);
335*10465441SEvalZero     }
336*10465441SEvalZero 
337*10465441SEvalZero     data->ep_out->request.buffer = data->ep_out->buffer;
338*10465441SEvalZero     data->ep_out->request.size = EP_MAXPACKET(data->ep_out);
339*10465441SEvalZero     data->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
340*10465441SEvalZero     rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
341*10465441SEvalZero 
342*10465441SEvalZero     return RT_EOK;
343*10465441SEvalZero }
344*10465441SEvalZero 
345*10465441SEvalZero /**
346*10465441SEvalZero  * This function will handle cdc interrupt in endpoint request.
347*10465441SEvalZero  *
348*10465441SEvalZero  * @param device the usb device object.
349*10465441SEvalZero  * @param size request size.
350*10465441SEvalZero  *
351*10465441SEvalZero  * @return RT_EOK.
352*10465441SEvalZero  */
_ep_cmd_handler(ufunction_t func,rt_size_t size)353*10465441SEvalZero static rt_err_t _ep_cmd_handler(ufunction_t func, rt_size_t size)
354*10465441SEvalZero {
355*10465441SEvalZero     RT_ASSERT(func != RT_NULL);
356*10465441SEvalZero 
357*10465441SEvalZero     RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_cmd_handler\n"));
358*10465441SEvalZero 
359*10465441SEvalZero     return RT_EOK;
360*10465441SEvalZero }
361*10465441SEvalZero 
362*10465441SEvalZero /**
363*10465441SEvalZero  * This function will handle cdc_get_line_coding request.
364*10465441SEvalZero  *
365*10465441SEvalZero  * @param device the usb device object.
366*10465441SEvalZero  * @param setup the setup request.
367*10465441SEvalZero  *
368*10465441SEvalZero  * @return RT_EOK on successful.
369*10465441SEvalZero  */
_cdc_get_line_coding(udevice_t device,ureq_t setup)370*10465441SEvalZero static rt_err_t _cdc_get_line_coding(udevice_t device, ureq_t setup)
371*10465441SEvalZero {
372*10465441SEvalZero     struct ucdc_line_coding data;
373*10465441SEvalZero     rt_uint16_t size;
374*10465441SEvalZero 
375*10465441SEvalZero     RT_ASSERT(device != RT_NULL);
376*10465441SEvalZero     RT_ASSERT(setup != RT_NULL);
377*10465441SEvalZero 
378*10465441SEvalZero     RT_DEBUG_LOG(RT_DEBUG_USB, ("_cdc_get_line_coding\n"));
379*10465441SEvalZero 
380*10465441SEvalZero     data.dwDTERate = 115200;
381*10465441SEvalZero     data.bCharFormat = 0;
382*10465441SEvalZero     data.bDataBits = 8;
383*10465441SEvalZero     data.bParityType = 0;
384*10465441SEvalZero     size = setup->wLength > 7 ? 7 : setup->wLength;
385*10465441SEvalZero 
386*10465441SEvalZero     rt_usbd_ep0_write(device, (void*)&data, size);
387*10465441SEvalZero 
388*10465441SEvalZero     return RT_EOK;
389*10465441SEvalZero }
390*10465441SEvalZero 
_cdc_set_line_coding_callback(udevice_t device,rt_size_t size)391*10465441SEvalZero static rt_err_t _cdc_set_line_coding_callback(udevice_t device, rt_size_t size)
392*10465441SEvalZero {
393*10465441SEvalZero     RT_DEBUG_LOG(RT_DEBUG_USB, ("_cdc_set_line_coding_callback\n"));
394*10465441SEvalZero 
395*10465441SEvalZero     dcd_ep0_send_status(device->dcd);
396*10465441SEvalZero 
397*10465441SEvalZero     return RT_EOK;
398*10465441SEvalZero }
399*10465441SEvalZero 
400*10465441SEvalZero /**
401*10465441SEvalZero  * This function will handle cdc_set_line_coding request.
402*10465441SEvalZero  *
403*10465441SEvalZero  * @param device the usb device object.
404*10465441SEvalZero  * @param setup the setup request.
405*10465441SEvalZero  *
406*10465441SEvalZero  * @return RT_EOK on successful.
407*10465441SEvalZero  */
_cdc_set_line_coding(udevice_t device,ureq_t setup)408*10465441SEvalZero static rt_err_t _cdc_set_line_coding(udevice_t device, ureq_t setup)
409*10465441SEvalZero {
410*10465441SEvalZero     RT_ASSERT(device != RT_NULL);
411*10465441SEvalZero     RT_ASSERT(setup != RT_NULL);
412*10465441SEvalZero 
413*10465441SEvalZero     RT_DEBUG_LOG(RT_DEBUG_USB, ("_cdc_set_line_coding\n"));
414*10465441SEvalZero 
415*10465441SEvalZero     rt_usbd_ep0_read(device, (void*)&line_coding, sizeof(struct ucdc_line_coding),
416*10465441SEvalZero         _cdc_set_line_coding_callback);
417*10465441SEvalZero 
418*10465441SEvalZero     return RT_EOK;
419*10465441SEvalZero }
420*10465441SEvalZero 
421*10465441SEvalZero /**
422*10465441SEvalZero  * This function will handle cdc interface request.
423*10465441SEvalZero  *
424*10465441SEvalZero  * @param device the usb device object.
425*10465441SEvalZero  * @param setup the setup request.
426*10465441SEvalZero  *
427*10465441SEvalZero  * @return RT_EOK on successful.
428*10465441SEvalZero  */
_interface_handler(ufunction_t func,ureq_t setup)429*10465441SEvalZero static rt_err_t _interface_handler(ufunction_t func, ureq_t setup)
430*10465441SEvalZero {
431*10465441SEvalZero     struct vcom *data;
432*10465441SEvalZero 
433*10465441SEvalZero     RT_ASSERT(func != RT_NULL);
434*10465441SEvalZero     RT_ASSERT(func->device != RT_NULL);
435*10465441SEvalZero     RT_ASSERT(setup != RT_NULL);
436*10465441SEvalZero 
437*10465441SEvalZero     data = (struct vcom*)func->user_data;
438*10465441SEvalZero 
439*10465441SEvalZero     switch(setup->bRequest)
440*10465441SEvalZero     {
441*10465441SEvalZero     case CDC_SEND_ENCAPSULATED_COMMAND:
442*10465441SEvalZero         break;
443*10465441SEvalZero     case CDC_GET_ENCAPSULATED_RESPONSE:
444*10465441SEvalZero         break;
445*10465441SEvalZero     case CDC_SET_COMM_FEATURE:
446*10465441SEvalZero         break;
447*10465441SEvalZero     case CDC_GET_COMM_FEATURE:
448*10465441SEvalZero         break;
449*10465441SEvalZero     case CDC_CLEAR_COMM_FEATURE:
450*10465441SEvalZero         break;
451*10465441SEvalZero     case CDC_SET_LINE_CODING:
452*10465441SEvalZero         _cdc_set_line_coding(func->device, setup);
453*10465441SEvalZero         break;
454*10465441SEvalZero     case CDC_GET_LINE_CODING:
455*10465441SEvalZero         _cdc_get_line_coding(func->device, setup);
456*10465441SEvalZero         break;
457*10465441SEvalZero     case CDC_SET_CONTROL_LINE_STATE:
458*10465441SEvalZero         data->connected = (setup->wValue & 0x01) > 0?RT_TRUE:RT_FALSE;
459*10465441SEvalZero         RT_DEBUG_LOG(RT_DEBUG_USB, ("vcom state:%d \n", data->connected));
460*10465441SEvalZero         dcd_ep0_send_status(func->device->dcd);
461*10465441SEvalZero         break;
462*10465441SEvalZero     case CDC_SEND_BREAK:
463*10465441SEvalZero         break;
464*10465441SEvalZero     default:
465*10465441SEvalZero         rt_kprintf("unknown cdc request\n",setup->request_type);
466*10465441SEvalZero         return -RT_ERROR;
467*10465441SEvalZero     }
468*10465441SEvalZero 
469*10465441SEvalZero     return RT_EOK;
470*10465441SEvalZero }
471*10465441SEvalZero 
472*10465441SEvalZero /**
473*10465441SEvalZero  * This function will run cdc function, it will be called on handle set configuration request.
474*10465441SEvalZero  *
475*10465441SEvalZero  * @param func the usb function object.
476*10465441SEvalZero  *
477*10465441SEvalZero  * @return RT_EOK on successful.
478*10465441SEvalZero  */
_function_enable(ufunction_t func)479*10465441SEvalZero static rt_err_t _function_enable(ufunction_t func)
480*10465441SEvalZero {
481*10465441SEvalZero     struct vcom *data;
482*10465441SEvalZero 
483*10465441SEvalZero     RT_ASSERT(func != RT_NULL);
484*10465441SEvalZero 
485*10465441SEvalZero     RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc function enable\n"));
486*10465441SEvalZero 
487*10465441SEvalZero     _vcom_reset_state(func);
488*10465441SEvalZero 
489*10465441SEvalZero     data = (struct vcom*)func->user_data;
490*10465441SEvalZero     data->ep_out->buffer = rt_malloc(CDC_RX_BUFSIZE);
491*10465441SEvalZero 
492*10465441SEvalZero     data->ep_out->request.buffer = data->ep_out->buffer;
493*10465441SEvalZero     data->ep_out->request.size = EP_MAXPACKET(data->ep_out);
494*10465441SEvalZero 
495*10465441SEvalZero     data->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
496*10465441SEvalZero     rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
497*10465441SEvalZero 
498*10465441SEvalZero     return RT_EOK;
499*10465441SEvalZero }
500*10465441SEvalZero 
501*10465441SEvalZero /**
502*10465441SEvalZero  * This function will stop cdc function, it will be called on handle set configuration request.
503*10465441SEvalZero  *
504*10465441SEvalZero  * @param func the usb function object.
505*10465441SEvalZero  *
506*10465441SEvalZero  * @return RT_EOK on successful.
507*10465441SEvalZero  */
_function_disable(ufunction_t func)508*10465441SEvalZero static rt_err_t _function_disable(ufunction_t func)
509*10465441SEvalZero {
510*10465441SEvalZero     struct vcom *data;
511*10465441SEvalZero 
512*10465441SEvalZero     RT_ASSERT(func != RT_NULL);
513*10465441SEvalZero 
514*10465441SEvalZero     RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc function disable\n"));
515*10465441SEvalZero 
516*10465441SEvalZero     _vcom_reset_state(func);
517*10465441SEvalZero 
518*10465441SEvalZero     data = (struct vcom*)func->user_data;
519*10465441SEvalZero     if(data->ep_out->buffer != RT_NULL)
520*10465441SEvalZero     {
521*10465441SEvalZero         rt_free(data->ep_out->buffer);
522*10465441SEvalZero         data->ep_out->buffer = RT_NULL;
523*10465441SEvalZero     }
524*10465441SEvalZero 
525*10465441SEvalZero     return RT_EOK;
526*10465441SEvalZero }
527*10465441SEvalZero 
528*10465441SEvalZero static struct ufunction_ops ops =
529*10465441SEvalZero {
530*10465441SEvalZero     _function_enable,
531*10465441SEvalZero     _function_disable,
532*10465441SEvalZero     RT_NULL,
533*10465441SEvalZero };
534*10465441SEvalZero 
535*10465441SEvalZero /**
536*10465441SEvalZero  * This function will configure cdc descriptor.
537*10465441SEvalZero  *
538*10465441SEvalZero  * @param comm the communication interface number.
539*10465441SEvalZero  * @param data the data interface number.
540*10465441SEvalZero  *
541*10465441SEvalZero  * @return RT_EOK on successful.
542*10465441SEvalZero  */
_cdc_descriptor_config(ucdc_comm_desc_t comm,rt_uint8_t cintf_nr,ucdc_data_desc_t data,rt_uint8_t dintf_nr)543*10465441SEvalZero static rt_err_t _cdc_descriptor_config(ucdc_comm_desc_t comm,
544*10465441SEvalZero     rt_uint8_t cintf_nr, ucdc_data_desc_t data, rt_uint8_t dintf_nr)
545*10465441SEvalZero {
546*10465441SEvalZero     comm->call_mgmt_desc.data_interface = dintf_nr;
547*10465441SEvalZero     comm->union_desc.master_interface = cintf_nr;
548*10465441SEvalZero     comm->union_desc.slave_interface0 = dintf_nr;
549*10465441SEvalZero #ifdef RT_USB_DEVICE_COMPOSITE
550*10465441SEvalZero     comm->iad_desc.bFirstInterface = cintf_nr;
551*10465441SEvalZero #endif
552*10465441SEvalZero 
553*10465441SEvalZero     return RT_EOK;
554*10465441SEvalZero }
555*10465441SEvalZero 
556*10465441SEvalZero /**
557*10465441SEvalZero  * This function will create a cdc function instance.
558*10465441SEvalZero  *
559*10465441SEvalZero  * @param device the usb device object.
560*10465441SEvalZero  *
561*10465441SEvalZero  * @return RT_EOK on successful.
562*10465441SEvalZero  */
rt_usbd_function_cdc_create(udevice_t device)563*10465441SEvalZero ufunction_t rt_usbd_function_cdc_create(udevice_t device)
564*10465441SEvalZero {
565*10465441SEvalZero     ufunction_t func;
566*10465441SEvalZero     struct vcom* data;
567*10465441SEvalZero     uintf_t intf_comm, intf_data;
568*10465441SEvalZero     ualtsetting_t comm_setting, data_setting;
569*10465441SEvalZero     ucdc_data_desc_t data_desc;
570*10465441SEvalZero     ucdc_comm_desc_t comm_desc;
571*10465441SEvalZero 
572*10465441SEvalZero     /* parameter check */
573*10465441SEvalZero     RT_ASSERT(device != RT_NULL);
574*10465441SEvalZero 
575*10465441SEvalZero     rt_memset(serno, 0, _SER_NO_LEN + 1);
576*10465441SEvalZero     if(vcom_get_stored_serno(serno, _SER_NO_LEN) != RT_EOK)
577*10465441SEvalZero     {
578*10465441SEvalZero         rt_memset(serno, 0, _SER_NO_LEN + 1);
579*10465441SEvalZero         rt_memcpy(serno, _SER_NO, rt_strlen(_SER_NO));
580*10465441SEvalZero     }
581*10465441SEvalZero     /* set usb device string description */
582*10465441SEvalZero     rt_usbd_device_set_string(device, _ustring);
583*10465441SEvalZero 
584*10465441SEvalZero     /* create a cdc function */
585*10465441SEvalZero     func = rt_usbd_function_new(device, &dev_desc, &ops);
586*10465441SEvalZero     //not support HS
587*10465441SEvalZero     //rt_usbd_device_set_qualifier(device, &dev_qualifier);
588*10465441SEvalZero 
589*10465441SEvalZero     /* allocate memory for cdc vcom data */
590*10465441SEvalZero     data = (struct vcom*)rt_malloc(sizeof(struct vcom));
591*10465441SEvalZero     rt_memset(data, 0, sizeof(struct vcom));
592*10465441SEvalZero     func->user_data = (void*)data;
593*10465441SEvalZero 
594*10465441SEvalZero     /* initilize vcom */
595*10465441SEvalZero     rt_usb_vcom_init(func);
596*10465441SEvalZero 
597*10465441SEvalZero     /* create a cdc communication interface and a cdc data interface */
598*10465441SEvalZero     intf_comm = rt_usbd_interface_new(device, _interface_handler);
599*10465441SEvalZero     intf_data = rt_usbd_interface_new(device, _interface_handler);
600*10465441SEvalZero 
601*10465441SEvalZero     /* create a communication alternate setting and a data alternate setting */
602*10465441SEvalZero     comm_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_comm_descriptor));
603*10465441SEvalZero     data_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_data_descriptor));
604*10465441SEvalZero 
605*10465441SEvalZero     /* config desc in alternate setting */
606*10465441SEvalZero     rt_usbd_altsetting_config_descriptor(comm_setting, &_comm_desc,
607*10465441SEvalZero                                          (rt_off_t)&((ucdc_comm_desc_t)0)->intf_desc);
608*10465441SEvalZero     rt_usbd_altsetting_config_descriptor(data_setting, &_data_desc, 0);
609*10465441SEvalZero     /* configure the cdc interface descriptor */
610*10465441SEvalZero     _cdc_descriptor_config(comm_setting->desc, intf_comm->intf_num, data_setting->desc, intf_data->intf_num);
611*10465441SEvalZero 
612*10465441SEvalZero     /* create a command endpoint */
613*10465441SEvalZero     comm_desc = (ucdc_comm_desc_t)comm_setting->desc;
614*10465441SEvalZero     data->ep_cmd = rt_usbd_endpoint_new(&comm_desc->ep_desc, _ep_cmd_handler);
615*10465441SEvalZero 
616*10465441SEvalZero     /* add the command endpoint to the cdc communication interface */
617*10465441SEvalZero     rt_usbd_altsetting_add_endpoint(comm_setting, data->ep_cmd);
618*10465441SEvalZero 
619*10465441SEvalZero     /* add the communication alternate setting to the communication interface,
620*10465441SEvalZero        then set default setting of the interface */
621*10465441SEvalZero     rt_usbd_interface_add_altsetting(intf_comm, comm_setting);
622*10465441SEvalZero     rt_usbd_set_altsetting(intf_comm, 0);
623*10465441SEvalZero 
624*10465441SEvalZero     /* add the communication interface to the cdc function */
625*10465441SEvalZero     rt_usbd_function_add_interface(func, intf_comm);
626*10465441SEvalZero 
627*10465441SEvalZero     /* create a bulk in and a bulk endpoint */
628*10465441SEvalZero     data_desc = (ucdc_data_desc_t)data_setting->desc;
629*10465441SEvalZero     data->ep_out = rt_usbd_endpoint_new(&data_desc->ep_out_desc, _ep_out_handler);
630*10465441SEvalZero     data->ep_in = rt_usbd_endpoint_new(&data_desc->ep_in_desc, _ep_in_handler);
631*10465441SEvalZero 
632*10465441SEvalZero     /* add the bulk out and bulk in endpoints to the data alternate setting */
633*10465441SEvalZero     rt_usbd_altsetting_add_endpoint(data_setting, data->ep_in);
634*10465441SEvalZero     rt_usbd_altsetting_add_endpoint(data_setting, data->ep_out);
635*10465441SEvalZero 
636*10465441SEvalZero     /* add the data alternate setting to the data interface
637*10465441SEvalZero             then set default setting of the interface */
638*10465441SEvalZero     rt_usbd_interface_add_altsetting(intf_data, data_setting);
639*10465441SEvalZero     rt_usbd_set_altsetting(intf_data, 0);
640*10465441SEvalZero 
641*10465441SEvalZero     /* add the cdc data interface to cdc function */
642*10465441SEvalZero     rt_usbd_function_add_interface(func, intf_data);
643*10465441SEvalZero 
644*10465441SEvalZero     return func;
645*10465441SEvalZero }
646*10465441SEvalZero 
647*10465441SEvalZero /**
648*10465441SEvalZero * UART device in RT-Thread
649*10465441SEvalZero */
_vcom_configure(struct rt_serial_device * serial,struct serial_configure * cfg)650*10465441SEvalZero static rt_err_t _vcom_configure(struct rt_serial_device *serial,
651*10465441SEvalZero                                 struct serial_configure *cfg)
652*10465441SEvalZero {
653*10465441SEvalZero     return RT_EOK;
654*10465441SEvalZero }
655*10465441SEvalZero 
_vcom_control(struct rt_serial_device * serial,int cmd,void * arg)656*10465441SEvalZero static rt_err_t _vcom_control(struct rt_serial_device *serial,
657*10465441SEvalZero                               int cmd, void *arg)
658*10465441SEvalZero {
659*10465441SEvalZero     switch (cmd)
660*10465441SEvalZero     {
661*10465441SEvalZero     case RT_DEVICE_CTRL_CLR_INT:
662*10465441SEvalZero         /* disable rx irq */
663*10465441SEvalZero         break;
664*10465441SEvalZero     case RT_DEVICE_CTRL_SET_INT:
665*10465441SEvalZero         /* enable rx irq */
666*10465441SEvalZero         break;
667*10465441SEvalZero     }
668*10465441SEvalZero 
669*10465441SEvalZero     return RT_EOK;
670*10465441SEvalZero }
671*10465441SEvalZero 
_vcom_getc(struct rt_serial_device * serial)672*10465441SEvalZero static int _vcom_getc(struct rt_serial_device *serial)
673*10465441SEvalZero {
674*10465441SEvalZero     int result;
675*10465441SEvalZero     rt_uint8_t ch;
676*10465441SEvalZero     rt_uint32_t level;
677*10465441SEvalZero     struct ufunction *func;
678*10465441SEvalZero     struct vcom *data;
679*10465441SEvalZero 
680*10465441SEvalZero     func = (struct ufunction*)serial->parent.user_data;
681*10465441SEvalZero     data = (struct vcom*)func->user_data;
682*10465441SEvalZero 
683*10465441SEvalZero     result = -1;
684*10465441SEvalZero 
685*10465441SEvalZero     level = rt_hw_interrupt_disable();
686*10465441SEvalZero 
687*10465441SEvalZero     if(rt_ringbuffer_getchar(&data->rx_ringbuffer, &ch) != 0)
688*10465441SEvalZero     {
689*10465441SEvalZero         result = ch;
690*10465441SEvalZero     }
691*10465441SEvalZero 
692*10465441SEvalZero     rt_hw_interrupt_enable(level);
693*10465441SEvalZero 
694*10465441SEvalZero     return result;
695*10465441SEvalZero }
_vcom_tx(struct rt_serial_device * serial,rt_uint8_t * buf,rt_size_t size,int direction)696*10465441SEvalZero static rt_size_t _vcom_tx(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size,int direction)
697*10465441SEvalZero {
698*10465441SEvalZero     rt_uint32_t level;
699*10465441SEvalZero 
700*10465441SEvalZero     struct ufunction *func;
701*10465441SEvalZero     struct vcom *data;
702*10465441SEvalZero     rt_uint32_t baksize;
703*10465441SEvalZero     rt_size_t ptr = 0;
704*10465441SEvalZero     int empty = 0;
705*10465441SEvalZero     rt_uint8_t crlf[2] = {'\r', '\n',};
706*10465441SEvalZero 
707*10465441SEvalZero     func = (struct ufunction*)serial->parent.user_data;
708*10465441SEvalZero     data = (struct vcom*)func->user_data;
709*10465441SEvalZero 
710*10465441SEvalZero     size = (size >= CDC_BULKIN_MAXSIZE) ? CDC_BULKIN_MAXSIZE : size;
711*10465441SEvalZero     baksize = size;
712*10465441SEvalZero 
713*10465441SEvalZero     RT_ASSERT(serial != RT_NULL);
714*10465441SEvalZero     RT_ASSERT(buf != RT_NULL);
715*10465441SEvalZero 
716*10465441SEvalZero     RT_DEBUG_LOG(RT_DEBUG_USB, ("%s\n",__func__));
717*10465441SEvalZero 
718*10465441SEvalZero     if (data->connected)
719*10465441SEvalZero     {
720*10465441SEvalZero         size = 0;
721*10465441SEvalZero         if((serial->parent.open_flag & RT_DEVICE_FLAG_STREAM))
722*10465441SEvalZero         {
723*10465441SEvalZero             empty = 0;
724*10465441SEvalZero             while(ptr < baksize)
725*10465441SEvalZero             {
726*10465441SEvalZero                 while(ptr < baksize && buf[ptr] != '\n')
727*10465441SEvalZero                 {
728*10465441SEvalZero                     ptr++;
729*10465441SEvalZero                 }
730*10465441SEvalZero                 if(ptr < baksize)
731*10465441SEvalZero                 {
732*10465441SEvalZero                     level = rt_hw_interrupt_disable();
733*10465441SEvalZero                     size += rt_ringbuffer_put_force(&data->tx_ringbuffer, (const rt_uint8_t *)&buf[size], ptr - size);
734*10465441SEvalZero                     rt_hw_interrupt_enable(level);
735*10465441SEvalZero 
736*10465441SEvalZero                     /* no data was be ignored */
737*10465441SEvalZero                     if(size == ptr)
738*10465441SEvalZero                     {
739*10465441SEvalZero                         level = rt_hw_interrupt_disable();
740*10465441SEvalZero                         if(rt_ringbuffer_space_len(&data->tx_ringbuffer) >= 2)
741*10465441SEvalZero                         {
742*10465441SEvalZero                             rt_ringbuffer_put_force(&data->tx_ringbuffer, crlf, 2);
743*10465441SEvalZero                             size++;
744*10465441SEvalZero                         }
745*10465441SEvalZero                         rt_hw_interrupt_enable(level);
746*10465441SEvalZero                     }
747*10465441SEvalZero                     else
748*10465441SEvalZero                     {
749*10465441SEvalZero                         empty = 1;
750*10465441SEvalZero                         break;
751*10465441SEvalZero                     }
752*10465441SEvalZero 
753*10465441SEvalZero                     /* ring buffer is full */
754*10465441SEvalZero                     if(size == ptr)
755*10465441SEvalZero                     {
756*10465441SEvalZero                         empty = 1;
757*10465441SEvalZero                         break;
758*10465441SEvalZero                     }
759*10465441SEvalZero                     ptr++;
760*10465441SEvalZero                 }
761*10465441SEvalZero                 else
762*10465441SEvalZero                 {
763*10465441SEvalZero                     break;
764*10465441SEvalZero                 }
765*10465441SEvalZero             }
766*10465441SEvalZero         }
767*10465441SEvalZero 
768*10465441SEvalZero         if(size < baksize && !empty)
769*10465441SEvalZero         {
770*10465441SEvalZero             level = rt_hw_interrupt_disable();
771*10465441SEvalZero             size += rt_ringbuffer_put_force(&data->tx_ringbuffer, (rt_uint8_t *)&buf[size], baksize - size);
772*10465441SEvalZero             rt_hw_interrupt_enable(level);
773*10465441SEvalZero         }
774*10465441SEvalZero 
775*10465441SEvalZero         if(size)
776*10465441SEvalZero         {
777*10465441SEvalZero             rt_event_send(&data->tx_event, CDC_TX_HAS_DATE);
778*10465441SEvalZero         }
779*10465441SEvalZero     }
780*10465441SEvalZero     else
781*10465441SEvalZero     {
782*10465441SEvalZero         /* recover dataqueue resources */
783*10465441SEvalZero         rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DMADONE);
784*10465441SEvalZero     }
785*10465441SEvalZero 
786*10465441SEvalZero     return size;
787*10465441SEvalZero }
_vcom_putc(struct rt_serial_device * serial,char c)788*10465441SEvalZero static int _vcom_putc(struct rt_serial_device *serial, char c)
789*10465441SEvalZero {
790*10465441SEvalZero     rt_uint32_t level;
791*10465441SEvalZero     struct ufunction *func;
792*10465441SEvalZero     struct vcom *data;
793*10465441SEvalZero 
794*10465441SEvalZero     func = (struct ufunction*)serial->parent.user_data;
795*10465441SEvalZero     data = (struct vcom*)func->user_data;
796*10465441SEvalZero 
797*10465441SEvalZero     RT_ASSERT(serial != RT_NULL);
798*10465441SEvalZero 
799*10465441SEvalZero     if (data->connected)
800*10465441SEvalZero     {
801*10465441SEvalZero         if(c == '\n' && (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM))
802*10465441SEvalZero         {
803*10465441SEvalZero             level = rt_hw_interrupt_disable();
804*10465441SEvalZero             rt_ringbuffer_putchar_force(&data->tx_ringbuffer, '\r');
805*10465441SEvalZero             rt_hw_interrupt_enable(level);
806*10465441SEvalZero             rt_event_send(&data->tx_event, CDC_TX_HAS_DATE);
807*10465441SEvalZero         }
808*10465441SEvalZero         level = rt_hw_interrupt_disable();
809*10465441SEvalZero         rt_ringbuffer_putchar_force(&data->tx_ringbuffer, c);
810*10465441SEvalZero         rt_hw_interrupt_enable(level);
811*10465441SEvalZero         rt_event_send(&data->tx_event, CDC_TX_HAS_DATE);
812*10465441SEvalZero     }
813*10465441SEvalZero 
814*10465441SEvalZero     return 1;
815*10465441SEvalZero }
816*10465441SEvalZero 
817*10465441SEvalZero static const struct rt_uart_ops usb_vcom_ops =
818*10465441SEvalZero {
819*10465441SEvalZero     _vcom_configure,
820*10465441SEvalZero     _vcom_control,
821*10465441SEvalZero     _vcom_putc,
822*10465441SEvalZero     _vcom_getc,
823*10465441SEvalZero     _vcom_tx
824*10465441SEvalZero };
825*10465441SEvalZero 
826*10465441SEvalZero /* Vcom Tx Thread */
vcom_tx_thread_entry(void * parameter)827*10465441SEvalZero static void vcom_tx_thread_entry(void* parameter)
828*10465441SEvalZero {
829*10465441SEvalZero     rt_uint32_t level;
830*10465441SEvalZero     rt_uint32_t res;
831*10465441SEvalZero     struct ufunction *func = (struct ufunction *)parameter;
832*10465441SEvalZero     struct vcom *data = (struct vcom*)func->user_data;
833*10465441SEvalZero     rt_uint8_t ch[CDC_BULKIN_MAXSIZE];
834*10465441SEvalZero 
835*10465441SEvalZero     while (1)
836*10465441SEvalZero     {
837*10465441SEvalZero         if
838*10465441SEvalZero         (
839*10465441SEvalZero             (rt_event_recv(&data->tx_event, CDC_TX_HAS_DATE,
840*10465441SEvalZero                     RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
841*10465441SEvalZero                     RT_WAITING_FOREVER, &res) != RT_EOK) ||
842*10465441SEvalZero                                  (!(res & CDC_TX_HAS_DATE))
843*10465441SEvalZero         )
844*10465441SEvalZero         {
845*10465441SEvalZero             continue;
846*10465441SEvalZero         }
847*10465441SEvalZero         if(!(res & CDC_TX_HAS_DATE))
848*10465441SEvalZero         {
849*10465441SEvalZero             continue;
850*10465441SEvalZero         }
851*10465441SEvalZero         while(rt_ringbuffer_data_len(&data->tx_ringbuffer))
852*10465441SEvalZero         {
853*10465441SEvalZero             level = rt_hw_interrupt_disable();
854*10465441SEvalZero             res = rt_ringbuffer_get(&data->tx_ringbuffer, ch, CDC_BULKIN_MAXSIZE);
855*10465441SEvalZero             rt_hw_interrupt_enable(level);
856*10465441SEvalZero 
857*10465441SEvalZero             if(!res)
858*10465441SEvalZero             {
859*10465441SEvalZero                 continue;
860*10465441SEvalZero             }
861*10465441SEvalZero             if (!data->connected)
862*10465441SEvalZero             {
863*10465441SEvalZero                 if(data->serial.parent.open_flag &
864*10465441SEvalZero #ifndef VCOM_TX_USE_DMA
865*10465441SEvalZero                          RT_DEVICE_FLAG_INT_TX
866*10465441SEvalZero #else
867*10465441SEvalZero                          RT_DEVICE_FLAG_DMA_TX
868*10465441SEvalZero #endif
869*10465441SEvalZero                 )
870*10465441SEvalZero                 {
871*10465441SEvalZero                 /* drop msg */
872*10465441SEvalZero #ifndef VCOM_TX_USE_DMA
873*10465441SEvalZero                     rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DONE);
874*10465441SEvalZero #else
875*10465441SEvalZero                     rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DMADONE);
876*10465441SEvalZero #endif
877*10465441SEvalZero                 }
878*10465441SEvalZero                 continue;
879*10465441SEvalZero             }
880*10465441SEvalZero             rt_completion_init(&data->wait);
881*10465441SEvalZero             data->ep_in->request.buffer     = ch;
882*10465441SEvalZero             data->ep_in->request.size       = res;
883*10465441SEvalZero 
884*10465441SEvalZero             data->ep_in->request.req_type   = UIO_REQUEST_WRITE;
885*10465441SEvalZero 
886*10465441SEvalZero             rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
887*10465441SEvalZero 
888*10465441SEvalZero             if (rt_completion_wait(&data->wait, VCOM_TX_TIMEOUT) != RT_EOK)
889*10465441SEvalZero             {
890*10465441SEvalZero                 RT_DEBUG_LOG(RT_DEBUG_USB, ("vcom tx timeout\n"));
891*10465441SEvalZero             }
892*10465441SEvalZero             if(data->serial.parent.open_flag &
893*10465441SEvalZero #ifndef VCOM_TX_USE_DMA
894*10465441SEvalZero                          RT_DEVICE_FLAG_INT_TX
895*10465441SEvalZero #else
896*10465441SEvalZero                          RT_DEVICE_FLAG_DMA_TX
897*10465441SEvalZero #endif
898*10465441SEvalZero             )
899*10465441SEvalZero             {
900*10465441SEvalZero #ifndef VCOM_TX_USE_DMA
901*10465441SEvalZero                 rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DONE);
902*10465441SEvalZero #else
903*10465441SEvalZero                 rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DMADONE);
904*10465441SEvalZero #endif
905*10465441SEvalZero             }
906*10465441SEvalZero         }
907*10465441SEvalZero 
908*10465441SEvalZero     }
909*10465441SEvalZero }
910*10465441SEvalZero 
rt_usb_vcom_init(struct ufunction * func)911*10465441SEvalZero static void rt_usb_vcom_init(struct ufunction *func)
912*10465441SEvalZero {
913*10465441SEvalZero     rt_err_t result = RT_EOK;
914*10465441SEvalZero     struct serial_configure config;
915*10465441SEvalZero     struct vcom *data = (struct vcom*)func->user_data;
916*10465441SEvalZero 
917*10465441SEvalZero     /* initialize ring buffer */
918*10465441SEvalZero     rt_ringbuffer_init(&data->rx_ringbuffer, data->rx_rbp, CDC_RX_BUFSIZE);
919*10465441SEvalZero     rt_ringbuffer_init(&data->tx_ringbuffer, data->tx_rbp, CDC_TX_BUFSIZE);
920*10465441SEvalZero 
921*10465441SEvalZero     rt_event_init(&data->tx_event, "vcom", RT_IPC_FLAG_FIFO);
922*10465441SEvalZero 
923*10465441SEvalZero     config.baud_rate    = BAUD_RATE_115200;
924*10465441SEvalZero     config.data_bits    = DATA_BITS_8;
925*10465441SEvalZero     config.stop_bits    = STOP_BITS_1;
926*10465441SEvalZero     config.parity       = PARITY_NONE;
927*10465441SEvalZero     config.bit_order    = BIT_ORDER_LSB;
928*10465441SEvalZero     config.invert       = NRZ_NORMAL;
929*10465441SEvalZero     config.bufsz        = CDC_RX_BUFSIZE;
930*10465441SEvalZero 
931*10465441SEvalZero     data->serial.ops        = &usb_vcom_ops;
932*10465441SEvalZero     data->serial.serial_rx  = RT_NULL;
933*10465441SEvalZero     data->serial.config     = config;
934*10465441SEvalZero 
935*10465441SEvalZero     /* register vcom device */
936*10465441SEvalZero     rt_hw_serial_register(&data->serial, VCOM_DEVICE,
937*10465441SEvalZero #ifndef VCOM_TX_USE_DMA
938*10465441SEvalZero                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
939*10465441SEvalZero #else
940*10465441SEvalZero                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_TX,
941*10465441SEvalZero #endif
942*10465441SEvalZero                           func);
943*10465441SEvalZero 
944*10465441SEvalZero     /* init usb device thread */
945*10465441SEvalZero     rt_thread_init(&vcom_thread, "vcom",
946*10465441SEvalZero                    vcom_tx_thread_entry, func,
947*10465441SEvalZero                    vcom_thread_stack, VCOM_TASK_STK_SIZE,
948*10465441SEvalZero                    16, 20);
949*10465441SEvalZero     result = rt_thread_startup(&vcom_thread);
950*10465441SEvalZero     RT_ASSERT(result == RT_EOK);
951*10465441SEvalZero }
952*10465441SEvalZero struct udclass vcom_class =
953*10465441SEvalZero {
954*10465441SEvalZero     .rt_usbd_function_create = rt_usbd_function_cdc_create
955*10465441SEvalZero };
956*10465441SEvalZero 
rt_usbd_vcom_class_register(void)957*10465441SEvalZero int rt_usbd_vcom_class_register(void)
958*10465441SEvalZero {
959*10465441SEvalZero     rt_usbd_class_register(&vcom_class);
960*10465441SEvalZero     return 0;
961*10465441SEvalZero }
962*10465441SEvalZero INIT_PREV_EXPORT(rt_usbd_vcom_class_register);
963*10465441SEvalZero 
964*10465441SEvalZero #endif
965