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 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 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 650 static rt_err_t _vcom_configure(struct rt_serial_device *serial, 651 struct serial_configure *cfg) 652 { 653 return RT_EOK; 654 } 655 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 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 } 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 } 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 */ 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 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 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