cdc_vcom.c 27 KB

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