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