cdc_vcom.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /*
  2. * File : cdc_vcom.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2012, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2012-10-02 Yi Qiu first version
  23. * 2012-12-12 heyuanjie87 change endpoints and function handler
  24. * 2013-06-25 heyuanjie87 remove SOF mechinism
  25. * 2013-07-20 Yi Qiu do more test
  26. */
  27. #include <rtthread.h>
  28. #include <rtservice.h>
  29. #include <rtdevice.h>
  30. #include <rthw.h>
  31. #include "cdc.h"
  32. #ifdef RT_USB_DEVICE_CDC
  33. #define TX_TIMEOUT 100
  34. #define CDC_RX_BUFSIZE 2048
  35. #define CDC_MAX_PACKET_SIZE 64
  36. #define VCOM_DEVICE "vcom"
  37. ALIGN(RT_ALIGN_SIZE)
  38. static rt_uint8_t vcom_thread_stack[512];
  39. static struct rt_thread vcom_thread;
  40. #define VCOM_MQ_MSG_SZ 16
  41. #define VCOM_MQ_MAX_MSG 4
  42. /* internal of the message queue: every message is associated with a pointer,
  43. * so in order to recveive VCOM_MQ_MAX_MSG messages, we have to allocate more
  44. * than VCOM_MQ_MSG_SZ*VCOM_MQ_MAX_MSG memery. */
  45. static rt_uint8_t vcom_tx_thread_mq_pool[(VCOM_MQ_MSG_SZ+sizeof(void*))*VCOM_MQ_MAX_MSG];
  46. static struct rt_messagequeue vcom_tx_thread_mq;
  47. static struct ucdc_line_coding line_coding;
  48. struct vcom
  49. {
  50. struct rt_serial_device serial;
  51. uep_t ep_out;
  52. uep_t ep_in;
  53. uep_t ep_cmd;
  54. rt_bool_t connected;
  55. rt_bool_t in_sending;
  56. struct rt_completion wait;
  57. rt_uint8_t rx_rbp[CDC_RX_BUFSIZE];
  58. struct rt_ringbuffer rx_ringbuffer;
  59. struct serial_ringbuffer vcom_int_rx;
  60. };
  61. struct vcom_tx_msg
  62. {
  63. struct rt_serial_device * serial;
  64. const char *buf;
  65. rt_size_t size;
  66. };
  67. static struct udevice_descriptor dev_desc =
  68. {
  69. USB_DESC_LENGTH_DEVICE, //bLength;
  70. USB_DESC_TYPE_DEVICE, //type;
  71. USB_BCD_VERSION, //bcdUSB;
  72. USB_CLASS_CDC, //bDeviceClass;
  73. 0x00, //bDeviceSubClass;
  74. 0x00, //bDeviceProtocol;
  75. CDC_MAX_PACKET_SIZE, //bMaxPacketSize0;
  76. _VENDOR_ID, //idVendor;
  77. _PRODUCT_ID, //idProduct;
  78. USB_BCD_DEVICE, //bcdDevice;
  79. USB_STRING_MANU_INDEX, //iManufacturer;
  80. USB_STRING_PRODUCT_INDEX, //iProduct;
  81. USB_STRING_SERIAL_INDEX, //iSerialNumber;
  82. USB_DYNAMIC, //bNumConfigurations;
  83. };
  84. static struct usb_qualifier_descriptor dev_qualifier =
  85. {
  86. sizeof(dev_qualifier),
  87. USB_DESC_TYPE_DEVICEQUALIFIER,
  88. 0x0200,
  89. USB_CLASS_CDC,
  90. 0x00,
  91. 64,
  92. 0x01,
  93. 0,
  94. };
  95. /* communcation interface descriptor */
  96. const static struct ucdc_comm_descriptor _comm_desc =
  97. {
  98. #ifdef RT_USB_DEVICE_COMPOSITE
  99. /* Interface Association Descriptor */
  100. USB_DESC_LENGTH_IAD,
  101. USB_DESC_TYPE_IAD,
  102. USB_DYNAMIC,
  103. 0x02,
  104. USB_CDC_CLASS_COMM,
  105. USB_CDC_SUBCLASS_ACM,
  106. USB_CDC_PROTOCOL_V25TER,
  107. 0x00,
  108. #endif
  109. /* Interface Descriptor */
  110. USB_DESC_LENGTH_INTERFACE,
  111. USB_DESC_TYPE_INTERFACE,
  112. USB_DYNAMIC,
  113. 0x00,
  114. 0x01,
  115. USB_CDC_CLASS_COMM,
  116. USB_CDC_SUBCLASS_ACM,
  117. USB_CDC_PROTOCOL_V25TER,
  118. 0x00,
  119. /* Header Functional Descriptor */
  120. 0x05,
  121. USB_CDC_CS_INTERFACE,
  122. USB_CDC_SCS_HEADER,
  123. 0x0110,
  124. /* Call Management Functional Descriptor */
  125. 0x05,
  126. USB_CDC_CS_INTERFACE,
  127. USB_CDC_SCS_CALL_MGMT,
  128. 0x00,
  129. USB_DYNAMIC,
  130. /* Abstract Control Management Functional Descriptor */
  131. 0x04,
  132. USB_CDC_CS_INTERFACE,
  133. USB_CDC_SCS_ACM,
  134. 0x02,
  135. /* Union Functional Descriptor */
  136. 0x05,
  137. USB_CDC_CS_INTERFACE,
  138. USB_CDC_SCS_UNION,
  139. USB_DYNAMIC,
  140. USB_DYNAMIC,
  141. /* Endpoint Descriptor */
  142. USB_DESC_LENGTH_ENDPOINT,
  143. USB_DESC_TYPE_ENDPOINT,
  144. USB_DYNAMIC | USB_DIR_IN,
  145. USB_EP_ATTR_INT,
  146. 0x08,
  147. 0xFF,
  148. };
  149. /* data interface descriptor */
  150. const static struct ucdc_data_descriptor _data_desc =
  151. {
  152. /* interface descriptor */
  153. USB_DESC_LENGTH_INTERFACE,
  154. USB_DESC_TYPE_INTERFACE,
  155. USB_DYNAMIC,
  156. 0x00,
  157. 0x02,
  158. USB_CDC_CLASS_DATA,
  159. 0x00,
  160. 0x00,
  161. 0x00,
  162. /* endpoint, bulk out */
  163. USB_DESC_LENGTH_ENDPOINT,
  164. USB_DESC_TYPE_ENDPOINT,
  165. USB_DYNAMIC | USB_DIR_OUT,
  166. USB_EP_ATTR_BULK,
  167. USB_CDC_BUFSIZE,
  168. 0x00,
  169. /* endpoint, bulk in */
  170. USB_DESC_LENGTH_ENDPOINT,
  171. USB_DESC_TYPE_ENDPOINT,
  172. USB_DYNAMIC | USB_DIR_IN,
  173. USB_EP_ATTR_BULK,
  174. USB_CDC_BUFSIZE,
  175. 0x00,
  176. };
  177. const static char* _ustring[] =
  178. {
  179. "Language",
  180. "RT-Thread Team.",
  181. "RTT Virtual Serial",
  182. "32021919830108",
  183. "Configuration",
  184. "Interface",
  185. };
  186. static void rt_usb_vcom_init(struct ufunction *func);
  187. static void _vcom_reset_state(ufunction_t func)
  188. {
  189. struct vcom* data;
  190. int lvl;
  191. RT_ASSERT(func != RT_NULL)
  192. data = (struct vcom*)func->user_data;
  193. lvl = rt_hw_interrupt_disable();
  194. data->connected = RT_FALSE;
  195. data->in_sending = RT_FALSE;
  196. /*rt_kprintf("reset USB serial\n", cnt);*/
  197. rt_hw_interrupt_enable(lvl);
  198. }
  199. /**
  200. * This function will handle cdc bulk in endpoint request.
  201. *
  202. * @param func the usb function object.
  203. * @param size request size.
  204. *
  205. * @return RT_EOK.
  206. */
  207. static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size)
  208. {
  209. struct vcom *data;
  210. RT_ASSERT(func != RT_NULL);
  211. RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_in_handler %d\n", size));
  212. data = (struct vcom*)func->user_data;
  213. if ((size != 0) && (size % CDC_MAX_PACKET_SIZE == 0))
  214. {
  215. /* don't have data right now. Send a zero-length-packet to
  216. * terminate the transaction.
  217. *
  218. * FIXME: actually, this might not be the right place to send zlp.
  219. * Only the rt_device_write could know how much data is sending. */
  220. data->in_sending = RT_TRUE;
  221. data->ep_in->request.buffer = RT_NULL;
  222. data->ep_in->request.size = 0;
  223. data->ep_in->request.req_type = UIO_REQUEST_WRITE;
  224. rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
  225. return RT_EOK;
  226. }
  227. rt_completion_done(&data->wait);
  228. return RT_EOK;
  229. }
  230. /**
  231. * This function will handle cdc bulk out endpoint request.
  232. *
  233. * @param func the usb function object.
  234. * @param size request size.
  235. *
  236. * @return RT_EOK.
  237. */
  238. static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size)
  239. {
  240. rt_uint32_t level;
  241. struct vcom *data;
  242. RT_ASSERT(func != RT_NULL);
  243. RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_out_handler %d\n", size));
  244. data = (struct vcom*)func->user_data;
  245. /* receive data from USB VCOM */
  246. level = rt_hw_interrupt_disable();
  247. rt_ringbuffer_put(&data->rx_ringbuffer, data->ep_out->buffer, size);
  248. rt_hw_interrupt_enable(level);
  249. /* notify receive data */
  250. rt_hw_serial_isr(&data->serial);
  251. data->ep_out->request.buffer = data->ep_out->buffer;
  252. data->ep_out->request.size = EP_MAXPACKET(data->ep_out);
  253. data->ep_out->request.req_type = UIO_REQUEST_READ_MOST;
  254. rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
  255. return RT_EOK;
  256. }
  257. /**
  258. * This function will handle cdc interrupt in endpoint request.
  259. *
  260. * @param device the usb device object.
  261. * @param size request size.
  262. *
  263. * @return RT_EOK.
  264. */
  265. static rt_err_t _ep_cmd_handler(ufunction_t func, rt_size_t size)
  266. {
  267. RT_ASSERT(func != RT_NULL);
  268. RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_cmd_handler\n"));
  269. return RT_EOK;
  270. }
  271. /**
  272. * This function will handle cdc_get_line_coding request.
  273. *
  274. * @param device the usb device object.
  275. * @param setup the setup request.
  276. *
  277. * @return RT_EOK on successful.
  278. */
  279. static rt_err_t _cdc_get_line_coding(udevice_t device, ureq_t setup)
  280. {
  281. struct ucdc_line_coding data;
  282. rt_uint16_t size;
  283. RT_ASSERT(device != RT_NULL);
  284. RT_ASSERT(setup != RT_NULL);
  285. RT_DEBUG_LOG(RT_DEBUG_USB, ("_cdc_get_line_coding\n"));
  286. data.dwDTERate = 115200;
  287. data.bCharFormat = 0;
  288. data.bDataBits = 8;
  289. data.bParityType = 0;
  290. size = setup->length > 7 ? 7 : setup->length;
  291. rt_usbd_ep0_write(device, (void*)&data, size);
  292. return RT_EOK;
  293. }
  294. static rt_err_t _cdc_set_line_coding_callback(udevice_t device, rt_size_t size)
  295. {
  296. RT_DEBUG_LOG(RT_DEBUG_USB, ("_cdc_set_line_coding_callback\n"));
  297. dcd_ep0_send_status(device->dcd);
  298. return RT_EOK;
  299. }
  300. /**
  301. * This function will handle cdc_set_line_coding request.
  302. *
  303. * @param device the usb device object.
  304. * @param setup the setup request.
  305. *
  306. * @return RT_EOK on successful.
  307. */
  308. static rt_err_t _cdc_set_line_coding(udevice_t device, ureq_t setup)
  309. {
  310. RT_ASSERT(device != RT_NULL);
  311. RT_ASSERT(setup != RT_NULL);
  312. RT_DEBUG_LOG(RT_DEBUG_USB, ("_cdc_set_line_coding\n"));
  313. rt_usbd_ep0_read(device, (void*)&line_coding, sizeof(struct ucdc_line_coding),
  314. _cdc_set_line_coding_callback);
  315. return RT_EOK;
  316. }
  317. /**
  318. * This function will handle cdc interface request.
  319. *
  320. * @param device the usb device object.
  321. * @param setup the setup request.
  322. *
  323. * @return RT_EOK on successful.
  324. */
  325. static rt_err_t _interface_handler(ufunction_t func, ureq_t setup)
  326. {
  327. struct vcom *data;
  328. RT_ASSERT(func != RT_NULL);
  329. RT_ASSERT(func->device != RT_NULL);
  330. RT_ASSERT(setup != RT_NULL);
  331. data = (struct vcom*)func->user_data;
  332. switch(setup->request)
  333. {
  334. case CDC_SEND_ENCAPSULATED_COMMAND:
  335. break;
  336. case CDC_GET_ENCAPSULATED_RESPONSE:
  337. break;
  338. case CDC_SET_COMM_FEATURE:
  339. break;
  340. case CDC_GET_COMM_FEATURE:
  341. break;
  342. case CDC_CLEAR_COMM_FEATURE:
  343. break;
  344. case CDC_SET_LINE_CODING:
  345. _cdc_set_line_coding(func->device, setup);
  346. data->connected = RT_TRUE;
  347. break;
  348. case CDC_GET_LINE_CODING:
  349. _cdc_get_line_coding(func->device, setup);
  350. break;
  351. case CDC_SET_CONTROL_LINE_STATE:
  352. dcd_ep0_send_status(func->device->dcd);
  353. break;
  354. case CDC_SEND_BREAK:
  355. break;
  356. default:
  357. rt_kprintf("unknown cdc request\n",setup->request_type);
  358. return -RT_ERROR;
  359. }
  360. return RT_EOK;
  361. }
  362. /**
  363. * This function will run cdc function, it will be called on handle set configuration request.
  364. *
  365. * @param func the usb function object.
  366. *
  367. * @return RT_EOK on successful.
  368. */
  369. static rt_err_t _function_enable(ufunction_t func)
  370. {
  371. struct vcom *data;
  372. RT_ASSERT(func != RT_NULL);
  373. RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc function enable\n"));
  374. _vcom_reset_state(func);
  375. data = (struct vcom*)func->user_data;
  376. data->ep_out->buffer = rt_malloc(CDC_RX_BUFSIZE);
  377. data->ep_out->request.buffer = data->ep_out->buffer;
  378. data->ep_out->request.size = EP_MAXPACKET(data->ep_out);
  379. data->ep_out->request.req_type = UIO_REQUEST_READ_MOST;
  380. rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
  381. return RT_EOK;
  382. }
  383. /**
  384. * This function will stop cdc function, it will be called on handle set configuration request.
  385. *
  386. * @param func the usb function object.
  387. *
  388. * @return RT_EOK on successful.
  389. */
  390. static rt_err_t _function_disable(ufunction_t func)
  391. {
  392. struct vcom *data;
  393. RT_ASSERT(func != RT_NULL);
  394. RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc function disable\n"));
  395. _vcom_reset_state(func);
  396. data = (struct vcom*)func->user_data;
  397. if(data->ep_out->buffer != RT_NULL)
  398. {
  399. rt_free(data->ep_out->buffer);
  400. data->ep_out->buffer = RT_NULL;
  401. }
  402. return RT_EOK;
  403. }
  404. static struct ufunction_ops ops =
  405. {
  406. _function_enable,
  407. _function_disable,
  408. RT_NULL,
  409. };
  410. /**
  411. * This function will configure cdc descriptor.
  412. *
  413. * @param comm the communication interface number.
  414. * @param data the data interface number.
  415. *
  416. * @return RT_EOK on successful.
  417. */
  418. static rt_err_t _cdc_descriptor_config(ucdc_comm_desc_t comm,
  419. rt_uint8_t cintf_nr, ucdc_data_desc_t data, rt_uint8_t dintf_nr)
  420. {
  421. comm->call_mgmt_desc.data_interface = dintf_nr;
  422. comm->union_desc.master_interface = cintf_nr;
  423. comm->union_desc.slave_interface0 = dintf_nr;
  424. #ifdef RT_USB_DEVICE_COMPOSITE
  425. comm->iad_desc.bFirstInterface = cintf_nr;
  426. #endif
  427. return RT_EOK;
  428. }
  429. /**
  430. * This function will create a cdc function instance.
  431. *
  432. * @param device the usb device object.
  433. *
  434. * @return RT_EOK on successful.
  435. */
  436. ufunction_t rt_usbd_function_cdc_create(udevice_t device)
  437. {
  438. ufunction_t func;
  439. struct vcom* data;
  440. uintf_t intf_comm, intf_data;
  441. ualtsetting_t comm_setting, data_setting;
  442. ucdc_data_desc_t data_desc;
  443. ucdc_comm_desc_t comm_desc;
  444. /* parameter check */
  445. RT_ASSERT(device != RT_NULL);
  446. /* set usb device string description */
  447. rt_usbd_device_set_string(device, _ustring);
  448. /* create a cdc function */
  449. func = rt_usbd_function_new(device, &dev_desc, &ops);
  450. rt_usbd_device_set_qualifier(device, &dev_qualifier);
  451. /* allocate memory for cdc vcom data */
  452. data = (struct vcom*)rt_malloc(sizeof(struct vcom));
  453. rt_memset(data, 0, sizeof(struct vcom));
  454. func->user_data = (void*)data;
  455. /* initilize vcom */
  456. rt_usb_vcom_init(func);
  457. /* create a cdc communication interface and a cdc data interface */
  458. intf_comm = rt_usbd_interface_new(device, _interface_handler);
  459. intf_data = rt_usbd_interface_new(device, _interface_handler);
  460. /* create a communication alternate setting and a data alternate setting */
  461. comm_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_comm_descriptor));
  462. data_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_data_descriptor));
  463. /* config desc in alternate setting */
  464. rt_usbd_altsetting_config_descriptor(comm_setting, &_comm_desc,
  465. (rt_off_t)&((ucdc_comm_desc_t)0)->intf_desc);
  466. rt_usbd_altsetting_config_descriptor(data_setting, &_data_desc, 0);
  467. /* configure the cdc interface descriptor */
  468. _cdc_descriptor_config(comm_setting->desc, intf_comm->intf_num, data_setting->desc, intf_data->intf_num);
  469. /* create a command endpoint */
  470. comm_desc = (ucdc_comm_desc_t)comm_setting->desc;
  471. data->ep_cmd = rt_usbd_endpoint_new(&comm_desc->ep_desc, _ep_cmd_handler);
  472. /* add the command endpoint to the cdc communication interface */
  473. rt_usbd_altsetting_add_endpoint(comm_setting, data->ep_cmd);
  474. /* add the communication alternate setting to the communication interface,
  475. then set default setting of the interface */
  476. rt_usbd_interface_add_altsetting(intf_comm, comm_setting);
  477. rt_usbd_set_altsetting(intf_comm, 0);
  478. /* add the communication interface to the cdc function */
  479. rt_usbd_function_add_interface(func, intf_comm);
  480. /* create a bulk in and a bulk endpoint */
  481. data_desc = (ucdc_data_desc_t)data_setting->desc;
  482. data->ep_out = rt_usbd_endpoint_new(&data_desc->ep_out_desc, _ep_out_handler);
  483. data->ep_in = rt_usbd_endpoint_new(&data_desc->ep_in_desc, _ep_in_handler);
  484. /* add the bulk out and bulk in endpoints to the data alternate setting */
  485. rt_usbd_altsetting_add_endpoint(data_setting, data->ep_in);
  486. rt_usbd_altsetting_add_endpoint(data_setting, data->ep_out);
  487. /* add the data alternate setting to the data interface
  488. then set default setting of the interface */
  489. rt_usbd_interface_add_altsetting(intf_data, data_setting);
  490. rt_usbd_set_altsetting(intf_data, 0);
  491. /* add the cdc data interface to cdc function */
  492. rt_usbd_function_add_interface(func, intf_data);
  493. return func;
  494. }
  495. /**
  496. * UART device in RT-Thread
  497. */
  498. static rt_err_t _vcom_configure(struct rt_serial_device *serial,
  499. struct serial_configure *cfg)
  500. {
  501. return RT_EOK;
  502. }
  503. static rt_err_t _vcom_control(struct rt_serial_device *serial,
  504. int cmd, void *arg)
  505. {
  506. switch (cmd)
  507. {
  508. case RT_DEVICE_CTRL_CLR_INT:
  509. /* disable rx irq */
  510. break;
  511. case RT_DEVICE_CTRL_SET_INT:
  512. /* enable rx irq */
  513. break;
  514. }
  515. return RT_EOK;
  516. }
  517. static int _vcom_getc(struct rt_serial_device *serial)
  518. {
  519. int result;
  520. rt_uint8_t ch;
  521. rt_uint32_t level;
  522. struct ufunction *func;
  523. struct vcom *data;
  524. func = (struct ufunction*)serial->parent.user_data;
  525. data = (struct vcom*)func->user_data;
  526. result = -1;
  527. level = rt_hw_interrupt_disable();
  528. if(rt_ringbuffer_getchar(&data->rx_ringbuffer, &ch) != 0)
  529. {
  530. result = ch;
  531. }
  532. rt_hw_interrupt_enable(level);
  533. return result;
  534. }
  535. static rt_size_t _vcom_tx(struct rt_serial_device *serial,
  536. const char *buf, rt_size_t size)
  537. {
  538. struct vcom_tx_msg msg;
  539. RT_ASSERT(serial != RT_NULL);
  540. RT_ASSERT(buf != RT_NULL);
  541. msg.buf = buf;
  542. msg.serial = serial;
  543. msg.size = size;
  544. if (rt_mq_send(&vcom_tx_thread_mq, (void*)&msg,
  545. sizeof(struct vcom_tx_msg)) != RT_EOK)
  546. {
  547. rt_kprintf("vcom send msg fail\n");
  548. return 0;
  549. }
  550. return size;
  551. }
  552. static const struct rt_uart_ops usb_vcom_ops =
  553. {
  554. _vcom_configure,
  555. _vcom_control,
  556. RT_NULL,
  557. _vcom_getc,
  558. RT_NULL,
  559. //_vcom_tx,
  560. };
  561. /* Vcom Tx Thread */
  562. static void vcom_tx_thread_entry(void* parameter)
  563. {
  564. struct vcom_tx_msg msg;
  565. while (1)
  566. {
  567. if (rt_mq_recv(&vcom_tx_thread_mq, (void*)&msg,
  568. sizeof(struct vcom_tx_msg), RT_WAITING_FOREVER) == RT_EOK)
  569. {
  570. struct ufunction *func;
  571. struct vcom *data;
  572. func = (struct ufunction*)msg.serial->parent.user_data;
  573. data = (struct vcom*)func->user_data;
  574. if (!data->connected)
  575. {
  576. continue;
  577. }
  578. rt_completion_init(&data->wait);
  579. data->ep_in->request.buffer = (void*)msg.buf;
  580. data->ep_in->request.size = msg.size;
  581. data->ep_in->request.req_type = UIO_REQUEST_WRITE;
  582. rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
  583. if (rt_completion_wait(&data->wait, TX_TIMEOUT) != RT_EOK)
  584. {
  585. rt_kprintf("vcom tx timeout\n");
  586. }
  587. }
  588. }
  589. }
  590. static void rt_usb_vcom_init(struct ufunction *func)
  591. {
  592. rt_err_t result = RT_EOK;
  593. struct serial_configure config;
  594. struct vcom *data = (struct vcom*)func->user_data;
  595. /* initialize ring buffer */
  596. rt_ringbuffer_init(&data->rx_ringbuffer, data->rx_rbp, CDC_RX_BUFSIZE);
  597. config.baud_rate = BAUD_RATE_115200;
  598. config.bit_order = BIT_ORDER_LSB;
  599. config.data_bits = DATA_BITS_8;
  600. config.parity = PARITY_NONE;
  601. config.stop_bits = STOP_BITS_1;
  602. config.invert = NRZ_NORMAL;
  603. data->serial.ops = &usb_vcom_ops;
  604. data->serial.int_rx = &data->vcom_int_rx;
  605. data->serial.config = config;
  606. /* register vcom device */
  607. rt_hw_serial_register(&data->serial, VCOM_DEVICE,
  608. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
  609. func);
  610. /* create an vcom message queue */
  611. rt_mq_init(&vcom_tx_thread_mq, "vcomq", vcom_tx_thread_mq_pool, VCOM_MQ_MSG_SZ,
  612. sizeof(vcom_tx_thread_mq_pool), RT_IPC_FLAG_FIFO);
  613. /* init usb device thread */
  614. rt_thread_init(&vcom_thread, "vcom", vcom_tx_thread_entry, RT_NULL,
  615. vcom_thread_stack, 512, 8, 20);
  616. result = rt_thread_startup(&vcom_thread);
  617. RT_ASSERT(result == RT_EOK);
  618. }
  619. #endif