cdc_vcom.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  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 class handler
  24. */
  25. #include <rtthread.h>
  26. #include <rtdevice.h>
  27. #include <rthw.h>
  28. #include "cdc.h"
  29. #ifdef RT_USB_DEVICE_CDC
  30. #define CDC_RX_BUFSIZE 2048
  31. #define CDC_TX_BUFSIZE 2048
  32. static rt_uint8_t rx_rbp[CDC_RX_BUFSIZE];
  33. static rt_uint8_t tx_rbp[CDC_TX_BUFSIZE];
  34. static struct rt_ringbuffer rx_ringbuffer;
  35. static struct rt_ringbuffer tx_ringbuffer;
  36. static struct serial_ringbuffer vcom_int_rx;
  37. static struct rt_serial_device vcom_serial;
  38. #define CDC_MaxPacketSize 64
  39. ALIGN(RT_ALIGN_SIZE)
  40. static rt_uint8_t rx_buf[CDC_RX_BUFSIZE];
  41. ALIGN(RT_ALIGN_SIZE)
  42. static rt_uint8_t tx_buf[CDC_TX_BUFSIZE];
  43. volatile static rt_bool_t vcom_connected = RT_FALSE;
  44. volatile static rt_bool_t vcom_in_sending = RT_FALSE;
  45. static struct udevice_descriptor dev_desc =
  46. {
  47. USB_DESC_LENGTH_DEVICE, //bLength;
  48. USB_DESC_TYPE_DEVICE, //type;
  49. USB_BCD_VERSION, //bcdUSB;
  50. USB_CLASS_CDC, //bDeviceClass;
  51. 0x00, //bDeviceSubClass;
  52. 0x00, //bDeviceProtocol;
  53. CDC_MaxPacketSize, //bMaxPacketSize0;
  54. _VENDOR_ID, //idVendor;
  55. _PRODUCT_ID, //idProduct;
  56. USB_BCD_DEVICE, //bcdDevice;
  57. USB_STRING_MANU_INDEX, //iManufacturer;
  58. USB_STRING_PRODUCT_INDEX, //iProduct;
  59. USB_STRING_SERIAL_INDEX, //iSerialNumber;
  60. USB_DYNAMIC, //bNumConfigurations;
  61. };
  62. /* communcation interface descriptor */
  63. const static struct ucdc_comm_descriptor _comm_desc =
  64. {
  65. #ifdef RT_USB_DEVICE_COMPOSITE
  66. /* Interface Association Descriptor */
  67. USB_DESC_LENGTH_IAD,
  68. USB_DESC_TYPE_IAD,
  69. USB_DYNAMIC,
  70. 0x02,
  71. USB_CDC_CLASS_COMM,
  72. USB_CDC_SUBCLASS_ACM,
  73. USB_CDC_PROTOCOL_V25TER,
  74. 0x00,
  75. #endif
  76. /* Interface Descriptor */
  77. USB_DESC_LENGTH_INTERFACE,
  78. USB_DESC_TYPE_INTERFACE,
  79. USB_DYNAMIC,
  80. 0x00,
  81. 0x01,
  82. USB_CDC_CLASS_COMM,
  83. USB_CDC_SUBCLASS_ACM,
  84. USB_CDC_PROTOCOL_V25TER,
  85. 0x00,
  86. /* Header Functional Descriptor */
  87. 0x05,
  88. USB_CDC_CS_INTERFACE,
  89. USB_CDC_SCS_HEADER,
  90. 0x0110,
  91. /* Call Management Functional Descriptor */
  92. 0x05,
  93. USB_CDC_CS_INTERFACE,
  94. USB_CDC_SCS_CALL_MGMT,
  95. 0x00,
  96. USB_DYNAMIC,
  97. /* Abstract Control Management Functional Descriptor */
  98. 0x04,
  99. USB_CDC_CS_INTERFACE,
  100. USB_CDC_SCS_ACM,
  101. 0x02,
  102. /* Union Functional Descriptor */
  103. 0x05,
  104. USB_CDC_CS_INTERFACE,
  105. USB_CDC_SCS_UNION,
  106. USB_DYNAMIC,
  107. USB_DYNAMIC,
  108. /* Endpoint Descriptor */
  109. USB_DESC_LENGTH_ENDPOINT,
  110. USB_DESC_TYPE_ENDPOINT,
  111. USB_DYNAMIC | USB_DIR_IN,
  112. USB_EP_ATTR_INT,
  113. 0x08,
  114. 0xFF,
  115. };
  116. /* data interface descriptor */
  117. const static struct ucdc_data_descriptor _data_desc =
  118. {
  119. /* interface descriptor */
  120. USB_DESC_LENGTH_INTERFACE,
  121. USB_DESC_TYPE_INTERFACE,
  122. USB_DYNAMIC,
  123. 0x00,
  124. 0x02,
  125. USB_CDC_CLASS_DATA,
  126. 0x00,
  127. 0x00,
  128. 0x00,
  129. /* endpoint, bulk out */
  130. USB_DESC_LENGTH_ENDPOINT,
  131. USB_DESC_TYPE_ENDPOINT,
  132. USB_DYNAMIC | USB_DIR_OUT,
  133. USB_EP_ATTR_BULK,
  134. USB_CDC_BUFSIZE,
  135. 0x00,
  136. /* endpoint, bulk in */
  137. USB_DESC_LENGTH_ENDPOINT,
  138. USB_DESC_TYPE_ENDPOINT,
  139. USB_DYNAMIC | USB_DIR_IN,
  140. USB_EP_ATTR_BULK,
  141. USB_CDC_BUFSIZE,
  142. 0x00,
  143. };
  144. const static char* _ustring[] =
  145. {
  146. "Language",
  147. "RT-Thread Team.",
  148. "RTT Virtual Serial",
  149. "1.1.0",
  150. "Configuration",
  151. "Interface",
  152. };
  153. static void _vcom_reset_state(void)
  154. {
  155. int lvl = rt_hw_interrupt_disable();
  156. tx_ringbuffer.read_mirror = tx_ringbuffer.read_index = 0;
  157. tx_ringbuffer.write_mirror = tx_ringbuffer.write_index = 0;
  158. vcom_connected = RT_FALSE;
  159. vcom_in_sending = RT_FALSE;
  160. /*rt_kprintf("reset USB serial\n", cnt);*/
  161. rt_hw_interrupt_enable(lvl);
  162. }
  163. /**
  164. * This function will handle cdc bulk in endpoint request.
  165. *
  166. * @param device the usb device object.
  167. * @param size request size.
  168. *
  169. * @return RT_EOK.
  170. */
  171. static rt_err_t _ep_in_handler(udevice_t device, uclass_t cls, rt_size_t size)
  172. {
  173. rt_uint32_t level;
  174. rt_uint32_t remain;
  175. cdc_eps_t eps;
  176. eps = (cdc_eps_t)cls->eps;
  177. level = rt_hw_interrupt_disable();
  178. remain = rt_ringbuffer_data_len(&tx_ringbuffer);
  179. if (remain != 0)
  180. {
  181. /* although vcom_in_sending is set in SOF handler in the very
  182. * beginning, we have to guarantee the state is right when start
  183. * sending. There is at least one extreme case where we have finished the
  184. * last IN transaction but the vcom_in_sending is RT_FALSE.
  185. *
  186. * Ok, what the extreme case is: pour data into vcom in loop. Open
  187. * terminal on the PC, you will see the data. Then close it. So the
  188. * data will be sent to the PC in the back. When the buffer of the PC
  189. * driver is full. It will not send IN packet to the board and you will
  190. * have no chance to clear vcom_in_sending in this function. The data
  191. * will fill into the ringbuffer until it is full, and we will reset
  192. * the state machine and clear vcom_in_sending. When you open the
  193. * terminal on the PC again. The IN packet will appear on the line and
  194. * we will, eventually, reach here with vcom_in_sending is clear.
  195. */
  196. vcom_in_sending = RT_TRUE;
  197. rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, remain);
  198. rt_hw_interrupt_enable(level);
  199. /* send data to host */
  200. dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, remain);
  201. return RT_EOK;
  202. }
  203. if (size != 0 &&
  204. (size % CDC_MaxPacketSize) == 0)
  205. {
  206. /* don't have data right now. Send a zero-length-packet to
  207. * terminate the transaction.
  208. *
  209. * FIXME: actually, this might not be the right place to send zlp.
  210. * Only the rt_device_write could know how much data is sending. */
  211. vcom_in_sending = RT_TRUE;
  212. rt_hw_interrupt_enable(level);
  213. dcd_ep_write(device->dcd, eps->ep_in, RT_NULL, 0);
  214. return RT_EOK;
  215. }
  216. else
  217. {
  218. vcom_in_sending = RT_FALSE;
  219. rt_hw_interrupt_enable(level);
  220. return RT_EOK;
  221. }
  222. }
  223. /**
  224. * This function will handle cdc bulk out endpoint request.
  225. *
  226. * @param device the usb device object.
  227. * @param size request size.
  228. *
  229. * @return RT_EOK.
  230. */
  231. static rt_err_t _ep_out_handler(udevice_t device, uclass_t cls, rt_size_t size)
  232. {
  233. rt_uint32_t level;
  234. cdc_eps_t eps;
  235. RT_ASSERT(device != RT_NULL);
  236. eps = (cdc_eps_t)cls->eps;
  237. /* receive data from USB VCOM */
  238. level = rt_hw_interrupt_disable();
  239. rt_ringbuffer_put(&rx_ringbuffer, eps->ep_out->buffer, size);
  240. rt_hw_interrupt_enable(level);
  241. /* notify receive data */
  242. rt_hw_serial_isr(&vcom_serial);
  243. dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
  244. eps->ep_out->ep_desc->wMaxPacketSize);
  245. return RT_EOK;
  246. }
  247. /**
  248. * This function will handle cdc interrupt in endpoint request.
  249. *
  250. * @param device the usb device object.
  251. * @param size request size.
  252. *
  253. * @return RT_EOK.
  254. */
  255. static rt_err_t _ep_cmd_handler(udevice_t device, uclass_t cls, rt_size_t size)
  256. {
  257. RT_ASSERT(device != RT_NULL);
  258. RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_cmd_handler\n"));
  259. return RT_EOK;
  260. }
  261. /**
  262. * This function will handle cdc_get_line_coding request.
  263. *
  264. * @param device the usb device object.
  265. * @param setup the setup request.
  266. *
  267. * @return RT_EOK on successful.
  268. */
  269. static rt_err_t _cdc_get_line_coding(udevice_t device, ureq_t setup)
  270. {
  271. struct ucdc_line_coding data;
  272. rt_uint16_t size;
  273. RT_ASSERT(device != RT_NULL);
  274. RT_ASSERT(setup != RT_NULL);
  275. data.dwDTERate = 115200;
  276. data.bCharFormat = 0;
  277. data.bDataBits = 8;
  278. data.bParityType = 0;
  279. size = setup->length > 7 ? 7 : setup->length;
  280. dcd_ep_write(device->dcd, 0, (void*)&data, size);
  281. return RT_EOK;
  282. }
  283. /**
  284. * This function will handle cdc_set_line_coding request.
  285. *
  286. * @param device the usb device object.
  287. * @param setup the setup request.
  288. *
  289. * @return RT_EOK on successful.
  290. */
  291. static rt_err_t _cdc_set_line_coding(udevice_t device, ureq_t setup)
  292. {
  293. struct ucdc_line_coding data;
  294. rt_err_t ret;
  295. RT_ASSERT(device != RT_NULL);
  296. RT_ASSERT(setup != RT_NULL);
  297. rt_completion_init(&device->dcd->completion);
  298. dcd_ep_read(device->dcd, 0, (void*)&data, setup->length);
  299. ret = rt_completion_wait(&device->dcd->completion, 100);
  300. if(ret != RT_EOK)
  301. {
  302. rt_kprintf("_cdc_set_line_coding timeout\n");
  303. }
  304. return RT_EOK;
  305. }
  306. /**
  307. * This function will handle cdc interface request.
  308. *
  309. * @param device the usb device object.
  310. * @param setup the setup request.
  311. *
  312. * @return RT_EOK on successful.
  313. */
  314. static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup)
  315. {
  316. RT_ASSERT(device != RT_NULL);
  317. RT_ASSERT(setup != RT_NULL);
  318. switch(setup->request)
  319. {
  320. case CDC_SEND_ENCAPSULATED_COMMAND:
  321. break;
  322. case CDC_GET_ENCAPSULATED_RESPONSE:
  323. break;
  324. case CDC_SET_COMM_FEATURE:
  325. break;
  326. case CDC_GET_COMM_FEATURE:
  327. break;
  328. case CDC_CLEAR_COMM_FEATURE:
  329. break;
  330. case CDC_SET_LINE_CODING:
  331. _cdc_set_line_coding(device, setup);
  332. vcom_connected = RT_TRUE;
  333. break;
  334. case CDC_GET_LINE_CODING:
  335. _cdc_get_line_coding(device, setup);
  336. break;
  337. case CDC_SET_CONTROL_LINE_STATE:
  338. dcd_send_status(device->dcd);
  339. break;
  340. case CDC_SEND_BREAK:
  341. break;
  342. default:
  343. rt_kprintf("unknown cdc request\n",setup->request_type);
  344. return -RT_ERROR;
  345. }
  346. return RT_EOK;
  347. }
  348. /**
  349. * This function will run cdc class, it will be called on handle set configuration request.
  350. *
  351. * @param device the usb device object.
  352. *
  353. * @return RT_EOK on successful.
  354. */
  355. static rt_err_t _class_run(udevice_t device, uclass_t cls)
  356. {
  357. cdc_eps_t eps;
  358. RT_ASSERT(device != RT_NULL);
  359. RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc class run\n"));
  360. eps = (cdc_eps_t)cls->eps;
  361. eps->ep_in->buffer = tx_buf;
  362. eps->ep_out->buffer = rx_buf;
  363. _vcom_reset_state();
  364. dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
  365. eps->ep_out->ep_desc->wMaxPacketSize);
  366. return RT_EOK;
  367. }
  368. /**
  369. * This function will stop cdc class, it will be called on handle set configuration request.
  370. *
  371. * @param device the usb device object.
  372. *
  373. * @return RT_EOK on successful.
  374. */
  375. static rt_err_t _class_stop(udevice_t device, uclass_t cls)
  376. {
  377. RT_ASSERT(device != RT_NULL);
  378. RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc class stop\n"));
  379. _vcom_reset_state();
  380. return RT_EOK;
  381. }
  382. /**
  383. * This function will handle system sof event.
  384. *
  385. * @param device the usb device object.
  386. *
  387. * @return RT_EOK on successful.
  388. */
  389. static rt_err_t _class_sof_handler(udevice_t device, uclass_t cls)
  390. {
  391. rt_uint32_t level;
  392. rt_size_t size;
  393. cdc_eps_t eps;
  394. if (vcom_connected != RT_TRUE)
  395. return -RT_ERROR;
  396. if (vcom_in_sending)
  397. {
  398. return RT_EOK;
  399. }
  400. eps = (cdc_eps_t)cls->eps;
  401. size = rt_ringbuffer_data_len(&tx_ringbuffer);
  402. if (size == 0)
  403. return -RT_EFULL;
  404. level = rt_hw_interrupt_disable();
  405. rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, size);
  406. rt_hw_interrupt_enable(level);
  407. /* send data to host */
  408. vcom_in_sending = RT_TRUE;
  409. dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, size);
  410. return RT_EOK;
  411. }
  412. static struct uclass_ops ops =
  413. {
  414. _class_run,
  415. _class_stop,
  416. _class_sof_handler,
  417. };
  418. /**
  419. * This function will configure cdc descriptor.
  420. *
  421. * @param comm the communication interface number.
  422. * @param data the data interface number.
  423. *
  424. * @return RT_EOK on successful.
  425. */
  426. static rt_err_t _cdc_descriptor_config(ucdc_comm_desc_t comm, rt_uint8_t cintf_nr, ucdc_data_desc_t data, rt_uint8_t dintf_nr)
  427. {
  428. comm->call_mgmt_desc.data_interface = dintf_nr;
  429. comm->union_desc.master_interface = cintf_nr;
  430. comm->union_desc.slave_interface0 = dintf_nr;
  431. #ifdef RT_USB_DEVICE_COMPOSITE
  432. comm->iad_desc.bFirstInterface = cintf_nr;
  433. #endif
  434. return RT_EOK;
  435. }
  436. /**
  437. * This function will create a cdc class instance.
  438. *
  439. * @param device the usb device object.
  440. *
  441. * @return RT_EOK on successful.
  442. */
  443. uclass_t rt_usbd_class_cdc_create(udevice_t device)
  444. {
  445. uclass_t cdc;
  446. cdc_eps_t eps;
  447. uintf_t intf_comm, intf_data;
  448. ualtsetting_t comm_setting, data_setting;
  449. ucdc_data_desc_t data_desc;
  450. ucdc_comm_desc_t comm_desc;
  451. /* parameter check */
  452. RT_ASSERT(device != RT_NULL);
  453. /* set usb device string description */
  454. rt_usbd_device_set_string(device, _ustring);
  455. /* create a cdc class */
  456. cdc = rt_usbd_class_create(device, &dev_desc, &ops);
  457. /* create a cdc class endpoints collection */
  458. eps = rt_malloc(sizeof(struct cdc_eps));
  459. cdc->eps = (void*)eps;
  460. /* create a cdc communication interface and a cdc data interface */
  461. intf_comm = rt_usbd_interface_create(device, _interface_handler);
  462. intf_data = rt_usbd_interface_create(device, _interface_handler);
  463. /* create a communication alternate setting and a data alternate setting */
  464. comm_setting = rt_usbd_altsetting_create(sizeof(struct ucdc_comm_descriptor));
  465. data_setting = rt_usbd_altsetting_create(sizeof(struct ucdc_data_descriptor));
  466. /* config desc in alternate setting */
  467. rt_usbd_altsetting_config_descriptor(comm_setting, &_comm_desc,
  468. (rt_off_t)&((ucdc_comm_desc_t)0)->intf_desc);
  469. rt_usbd_altsetting_config_descriptor(data_setting, &_data_desc, 0);
  470. /* configure the cdc interface descriptor */
  471. _cdc_descriptor_config(comm_setting->desc, intf_comm->intf_num, data_setting->desc, intf_data->intf_num);
  472. /* create a bulk in and a bulk endpoint */
  473. data_desc = (ucdc_data_desc_t)data_setting->desc;
  474. eps->ep_out = rt_usbd_endpoint_create(&data_desc->ep_out_desc, _ep_out_handler);
  475. eps->ep_in = rt_usbd_endpoint_create(&data_desc->ep_in_desc, _ep_in_handler);
  476. /* add the bulk out and bulk in endpoints to the data alternate setting */
  477. rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_in);
  478. rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_out);
  479. /* add the data alternate setting to the data interface
  480. then set default setting of the interface */
  481. rt_usbd_interface_add_altsetting(intf_data, data_setting);
  482. rt_usbd_set_altsetting(intf_data, 0);
  483. /* add the cdc data interface to cdc class */
  484. rt_usbd_class_add_interface(cdc, intf_data);
  485. /* create a command endpoint */
  486. comm_desc = (ucdc_comm_desc_t)comm_setting->desc;
  487. eps->ep_cmd = rt_usbd_endpoint_create(&comm_desc->ep_desc, _ep_cmd_handler);
  488. /* add the command endpoint to the cdc communication interface */
  489. rt_usbd_altsetting_add_endpoint(comm_setting, eps->ep_cmd);
  490. /* add the communication alternate setting to the communication interface,
  491. then set default setting of the interface */
  492. rt_usbd_interface_add_altsetting(intf_comm, comm_setting);
  493. rt_usbd_set_altsetting(intf_comm, 0);
  494. /* add the communication interface to the cdc class */
  495. rt_usbd_class_add_interface(cdc, intf_comm);
  496. return cdc;
  497. }
  498. /**
  499. * UART device in RT-Thread
  500. */
  501. static rt_err_t _vcom_configure(struct rt_serial_device *serial,
  502. struct serial_configure *cfg)
  503. {
  504. return RT_EOK;
  505. }
  506. static rt_err_t _vcom_control(struct rt_serial_device *serial,
  507. int cmd, void *arg)
  508. {
  509. switch (cmd)
  510. {
  511. case RT_DEVICE_CTRL_CLR_INT:
  512. /* disable rx irq */
  513. break;
  514. case RT_DEVICE_CTRL_SET_INT:
  515. /* enable rx irq */
  516. break;
  517. }
  518. return RT_EOK;
  519. }
  520. static int _vcom_putc(struct rt_serial_device *serial, char c)
  521. {
  522. rt_uint32_t level;
  523. int cnt;
  524. if (vcom_connected != RT_TRUE)
  525. {
  526. return 0;
  527. }
  528. /* if the buffer is full, there is a chance that the host would pull some
  529. * data out soon. But we cannot rely on that and if we wait to long, just
  530. * return. */
  531. for (cnt = 500;
  532. rt_ringbuffer_space_len(&tx_ringbuffer) == 0 && cnt;
  533. cnt--)
  534. {
  535. /*rt_kprintf("wait for %d\n", cnt);*/
  536. if (vcom_connected != RT_TRUE)
  537. return 0;
  538. }
  539. if (cnt == 0)
  540. {
  541. /* OK, we believe that the connection is lost. So don't send any more
  542. * data and act as the USB cable is not plugged in. Reset the VCOM
  543. * state machine */
  544. _vcom_reset_state();
  545. return 0;
  546. }
  547. level = rt_hw_interrupt_disable();
  548. if (rt_ringbuffer_space_len(&tx_ringbuffer))
  549. {
  550. rt_ringbuffer_putchar(&tx_ringbuffer, c);
  551. }
  552. rt_hw_interrupt_enable(level);
  553. return 1;
  554. }
  555. static int _vcom_getc(struct rt_serial_device *serial)
  556. {
  557. int result;
  558. rt_uint8_t ch;
  559. rt_uint32_t level;
  560. result = -1;
  561. level = rt_hw_interrupt_disable();
  562. if (rt_ringbuffer_data_len(&rx_ringbuffer))
  563. {
  564. rt_ringbuffer_getchar(&rx_ringbuffer, &ch);
  565. result = ch;
  566. }
  567. rt_hw_interrupt_enable(level);
  568. return result;
  569. }
  570. static const struct rt_uart_ops usb_vcom_ops =
  571. {
  572. _vcom_configure,
  573. _vcom_control,
  574. _vcom_putc,
  575. _vcom_getc,
  576. };
  577. void rt_usb_vcom_init(void)
  578. {
  579. struct serial_configure config;
  580. /* initialize ring buffer */
  581. rt_ringbuffer_init(&rx_ringbuffer, rx_rbp, CDC_RX_BUFSIZE);
  582. rt_ringbuffer_init(&tx_ringbuffer, tx_rbp, CDC_TX_BUFSIZE);
  583. config.baud_rate = BAUD_RATE_115200;
  584. config.bit_order = BIT_ORDER_LSB;
  585. config.data_bits = DATA_BITS_8;
  586. config.parity = PARITY_NONE;
  587. config.stop_bits = STOP_BITS_1;
  588. config.invert = NRZ_NORMAL;
  589. vcom_serial.ops = &usb_vcom_ops;
  590. vcom_serial.int_rx = &vcom_int_rx;
  591. vcom_serial.config = config;
  592. /* register vcom device */
  593. rt_hw_serial_register(&vcom_serial, "vcom",
  594. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
  595. RT_NULL);
  596. }
  597. #endif