usbh_serial.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. /*
  2. * Copyright (c) 2025, sakumisu
  3. * Copyright (c) 2025, MDLZCOOL
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. */
  7. #include "usbh_core.h"
  8. #include "usbh_serial.h"
  9. #undef USB_DBG_TAG
  10. #define USB_DBG_TAG "usbh_serial"
  11. #include "usb_log.h"
  12. #define DEV_FORMAT_VENDOR "/dev/ttyUSB%d"
  13. #define DEV_FORMAT_CDC_ACM "/dev/ttyACM%d"
  14. #define CONFIG_USBHOST_MAX_SERIAL_CLASS 4
  15. static struct usbh_serial g_serial_class[CONFIG_USBHOST_MAX_SERIAL_CLASS];
  16. static uint32_t g_devinuse = 0;
  17. static uint32_t g_cdcacm_devinuse = 0;
  18. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_serial_iobuffer[CONFIG_USBHOST_MAX_SERIAL_CLASS][USB_ALIGN_UP((USBH_SERIAL_INT_NOCACHE_OFFSET + USBH_SERIAL_INT_NOCACHE_SIZE), CONFIG_USB_ALIGN_SIZE)];
  19. /* refer to cherryrb */
  20. static int usbh_serial_ringbuffer_init(usbh_serial_ringbuf_t *rb, void *pool, uint32_t size)
  21. {
  22. if (NULL == rb) {
  23. return -1;
  24. }
  25. if (NULL == pool) {
  26. return -1;
  27. }
  28. if ((size < 2) || (size & (size - 1))) {
  29. return -1;
  30. }
  31. rb->in = 0;
  32. rb->out = 0;
  33. rb->mask = size - 1;
  34. rb->pool = pool;
  35. return 0;
  36. }
  37. static void usbh_serial_ringbuffer_reset(usbh_serial_ringbuf_t *rb)
  38. {
  39. rb->in = 0;
  40. rb->out = 0;
  41. }
  42. static uint32_t usbh_serial_ringbuffer_get_used(usbh_serial_ringbuf_t *rb)
  43. {
  44. return rb->in - rb->out;
  45. }
  46. static uint32_t usbh_serial_ringbuffer_write(usbh_serial_ringbuf_t *rb, void *data, uint32_t size)
  47. {
  48. uint32_t unused;
  49. uint32_t offset;
  50. uint32_t remain;
  51. unused = (rb->mask + 1) - (rb->in - rb->out);
  52. if (size > unused) {
  53. size = unused;
  54. }
  55. offset = rb->in & rb->mask;
  56. remain = rb->mask + 1 - offset;
  57. remain = remain > size ? size : remain;
  58. memcpy(((uint8_t *)(rb->pool)) + offset, data, remain);
  59. memcpy(rb->pool, (uint8_t *)data + remain, size - remain);
  60. rb->in += size;
  61. return size;
  62. }
  63. static uint32_t usbh_serial_ringbuffer_peek(usbh_serial_ringbuf_t *rb, void *data, uint32_t size)
  64. {
  65. uint32_t used;
  66. uint32_t offset;
  67. uint32_t remain;
  68. used = rb->in - rb->out;
  69. if (size > used) {
  70. size = used;
  71. }
  72. offset = rb->out & rb->mask;
  73. remain = rb->mask + 1 - offset;
  74. remain = remain > size ? size : remain;
  75. memcpy(data, ((uint8_t *)(rb->pool)) + offset, remain);
  76. memcpy((uint8_t *)data + remain, rb->pool, size - remain);
  77. return size;
  78. }
  79. static uint32_t usbh_serial_ringbuffer_read(usbh_serial_ringbuf_t *rb, void *data, uint32_t size)
  80. {
  81. size = usbh_serial_ringbuffer_peek(rb, data, size);
  82. rb->out += size;
  83. return size;
  84. }
  85. static struct usbh_serial *usbh_serial_alloc(bool is_cdcacm)
  86. {
  87. uint8_t devno;
  88. uint8_t devno2;
  89. for (devno = 0; devno < CONFIG_USBHOST_MAX_SERIAL_CLASS; devno++) {
  90. if ((g_devinuse & (1U << devno)) == 0) {
  91. g_devinuse |= (1U << devno);
  92. memset(&g_serial_class[devno], 0, sizeof(struct usbh_serial));
  93. g_serial_class[devno].minor = devno;
  94. g_serial_class[devno].cdc_minor = -1;
  95. g_serial_class[devno].iobuffer = g_serial_iobuffer[devno];
  96. g_serial_class[devno].rx_complete_sem = usb_osal_sem_create(0);
  97. if (is_cdcacm) {
  98. for (devno2 = 0; devno2 < CONFIG_USBHOST_MAX_SERIAL_CLASS; devno2++) {
  99. if ((g_cdcacm_devinuse & (1U << devno2)) == 0) {
  100. g_cdcacm_devinuse |= (1U << devno2);
  101. g_serial_class[devno].cdc_minor = devno2;
  102. return &g_serial_class[devno];
  103. }
  104. }
  105. g_devinuse &= ~(1U << devno);
  106. return NULL;
  107. } else {
  108. return &g_serial_class[devno];
  109. }
  110. }
  111. }
  112. return NULL;
  113. }
  114. static void usbh_serial_free(struct usbh_serial *serial)
  115. {
  116. uint8_t devno = serial->minor;
  117. if (devno < 32) {
  118. g_devinuse &= ~(1U << devno);
  119. }
  120. if (serial->cdc_minor >= 0) {
  121. g_cdcacm_devinuse &= ~(1U << serial->cdc_minor);
  122. }
  123. if (g_serial_class[devno].rx_complete_sem) {
  124. usb_osal_sem_delete(g_serial_class[devno].rx_complete_sem);
  125. }
  126. }
  127. static void usbh_serial_callback(void *arg, int nbytes)
  128. {
  129. struct usbh_serial *serial = (struct usbh_serial *)arg;
  130. int ret;
  131. if (nbytes < 0) {
  132. if (nbytes != -USB_ERR_SHUTDOWN) {
  133. USB_LOG_ERR("serial transfer error: %d\n", nbytes);
  134. }
  135. serial->rx_errorcode = nbytes;
  136. usb_osal_sem_give(serial->rx_complete_sem);
  137. return;
  138. }
  139. if (nbytes < serial->driver->ignore_rx_header) {
  140. USB_LOG_ERR("serial rx short packet: %d\n", nbytes);
  141. serial->rx_errorcode = -USB_ERR_IO;
  142. usb_osal_sem_give(serial->rx_complete_sem);
  143. return;
  144. }
  145. if (nbytes >= serial->driver->ignore_rx_header) {
  146. /* resubmit the read urb */
  147. usbh_bulk_urb_fill(&serial->bulkin_urb, serial->hport, serial->bulkin, &serial->iobuffer[serial->rx_buf_index ? USBH_SERIAL_RX_NOCACHE_OFFSET : USBH_SERIAL_RX2_NOCACHE_OFFSET], serial->bulkin->wMaxPacketSize,
  148. 0, usbh_serial_callback, serial);
  149. ret = usbh_submit_urb(&serial->bulkin_urb);
  150. if (ret < 0) {
  151. USB_LOG_ERR("serial submit failed: %d\n", ret);
  152. serial->rx_errorcode = ret;
  153. usb_osal_sem_give(serial->rx_complete_sem);
  154. return;
  155. }
  156. usbh_serial_ringbuffer_write(&serial->rx_rb,
  157. &serial->iobuffer[(serial->rx_buf_index ? USBH_SERIAL_RX2_NOCACHE_OFFSET : USBH_SERIAL_RX_NOCACHE_OFFSET) + serial->driver->ignore_rx_header],
  158. (nbytes - serial->driver->ignore_rx_header));
  159. if (serial->rx_complete_callback) {
  160. serial->rx_complete_callback(serial, nbytes - serial->driver->ignore_rx_header);
  161. }
  162. serial->rx_buf_index ^= 1;
  163. serial->rx_errorcode = 0;
  164. usb_osal_sem_give(serial->rx_complete_sem);
  165. }
  166. }
  167. struct usbh_serial *usbh_serial_probe(struct usbh_hubport *hport, uint8_t intf,
  168. const struct usbh_serial_driver *driver)
  169. {
  170. struct usb_endpoint_descriptor *ep_desc;
  171. struct usbh_serial *serial;
  172. bool is_cdcacm = false;
  173. int ret;
  174. if (strcmp(driver->driver_name, "cdc_acm") == 0) {
  175. is_cdcacm = true;
  176. }
  177. serial = usbh_serial_alloc(is_cdcacm);
  178. if (serial == NULL) {
  179. USB_LOG_ERR("Fail to alloc serial class\r\n");
  180. return NULL;
  181. }
  182. serial->hport = hport;
  183. serial->intf = intf;
  184. serial->driver = driver;
  185. if (driver->attach) {
  186. ret = driver->attach(serial);
  187. if (ret < 0) {
  188. USB_LOG_ERR("Serial attach failed: %d\r\n", ret);
  189. usbh_serial_free(serial);
  190. return NULL;
  191. }
  192. }
  193. if (is_cdcacm) {
  194. intf = intf + 1; /* data interface */
  195. }
  196. for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
  197. ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
  198. if (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_BULK) {
  199. if (ep_desc->bEndpointAddress & 0x80) {
  200. USBH_EP_INIT(serial->bulkin, ep_desc);
  201. } else {
  202. USBH_EP_INIT(serial->bulkout, ep_desc);
  203. }
  204. }
  205. }
  206. if (is_cdcacm) {
  207. intf = intf - 1; /* data interface */
  208. }
  209. if (!serial->bulkin || !serial->bulkout) {
  210. USB_LOG_ERR("Serial bulk in/out endpoint not found\r\n");
  211. usbh_serial_free(serial);
  212. return NULL;
  213. }
  214. if (is_cdcacm) {
  215. snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT_CDC_ACM, serial->cdc_minor);
  216. } else {
  217. snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT_VENDOR, serial->minor);
  218. }
  219. hport->config.intf[intf].priv = serial;
  220. USB_LOG_INFO("Register Serial Class: %s (%s)\r\n", hport->config.intf[intf].devname, driver->driver_name);
  221. usbh_serial_run(serial);
  222. return serial;
  223. }
  224. void usbh_serial_remove(struct usbh_serial *serial)
  225. {
  226. if (!serial || !serial->hport)
  227. return;
  228. usbh_serial_close(serial);
  229. if (serial->driver && serial->driver->detach) {
  230. serial->driver->detach(serial);
  231. }
  232. if (serial->hport->config.intf[serial->intf].priv) {
  233. usb_osal_thread_schedule_other();
  234. USB_LOG_INFO("Unregister Serial Class: %s (%s)\r\n", serial->hport->config.intf[serial->intf].devname, serial->driver->driver_name);
  235. usbh_serial_stop(serial);
  236. }
  237. usbh_serial_free(serial);
  238. }
  239. struct usbh_serial *usbh_serial_open(const char *devname, uint32_t open_flags)
  240. {
  241. struct usbh_serial *serial;
  242. int ret;
  243. serial = usbh_find_class_instance(devname);
  244. if (!serial) {
  245. return NULL;
  246. }
  247. if (serial->ref_count != 0) {
  248. USB_LOG_ERR("Device busy: %s\r\n", devname);
  249. return NULL;
  250. }
  251. if (serial && serial->driver && serial->driver->open) {
  252. ret = serial->driver->open(serial);
  253. if (ret < 0) {
  254. return NULL;
  255. }
  256. }
  257. usbh_serial_ringbuffer_init(&serial->rx_rb, serial->rx_rb_pool, CONFIG_USBHOST_SERIAL_RX_SIZE);
  258. serial->ref_count++;
  259. serial->open_flags = open_flags;
  260. return serial;
  261. }
  262. int usbh_serial_close(struct usbh_serial *serial)
  263. {
  264. if (!serial || !serial->hport) {
  265. return -USB_ERR_INVAL;
  266. }
  267. if (serial->ref_count == 0) {
  268. return 0;
  269. }
  270. if (serial->bulkin) {
  271. usbh_kill_urb(&serial->bulkin_urb);
  272. }
  273. if (serial->bulkout) {
  274. usbh_kill_urb(&serial->bulkout_urb);
  275. }
  276. if (serial && serial->driver && serial->driver->set_flow_control && serial->rtscts) {
  277. serial->driver->set_flow_control(serial, false);
  278. }
  279. if (serial && serial->driver && serial->driver->close) {
  280. serial->driver->close(serial);
  281. }
  282. serial->ref_count--;
  283. serial->rtscts = false;
  284. return 0;
  285. }
  286. static int usbh_serial_tiocmset(struct usbh_serial *serial, uint32_t set, uint32_t clear)
  287. {
  288. int ret;
  289. uint16_t line_state;
  290. bool dtr;
  291. bool rts;
  292. if (!serial || !serial->hport || !serial->hport->connected) {
  293. return -USB_ERR_INVAL;
  294. }
  295. if (serial->ref_count == 0) {
  296. return -USB_ERR_NODEV;
  297. }
  298. line_state = serial->line_state;
  299. clear &= ~set; /* 'set' takes precedence over 'clear' */
  300. if (set & USBH_SERIAL_TIOCM_DTR) {
  301. line_state |= USBH_SERIAL_TIOCM_DTR;
  302. }
  303. if (set & USBH_SERIAL_TIOCM_RTS) {
  304. line_state |= USBH_SERIAL_TIOCM_RTS;
  305. }
  306. if (clear & USBH_SERIAL_TIOCM_DTR) {
  307. line_state &= ~USBH_SERIAL_TIOCM_DTR;
  308. }
  309. if (clear & USBH_SERIAL_TIOCM_RTS) {
  310. line_state &= ~USBH_SERIAL_TIOCM_RTS;
  311. }
  312. dtr = (line_state & USBH_SERIAL_TIOCM_DTR) ? true : false;
  313. rts = (line_state & USBH_SERIAL_TIOCM_RTS) ? true : false;
  314. if (serial && serial->driver && serial->driver->set_line_state) {
  315. ret = serial->driver->set_line_state(serial, dtr, rts);
  316. } else {
  317. return -USB_ERR_NOTSUPP;
  318. }
  319. serial->line_state = line_state;
  320. return ret;
  321. }
  322. int usbh_serial_control(struct usbh_serial *serial, int cmd, void *arg)
  323. {
  324. int ret;
  325. if (!serial || !serial->hport || !serial->hport->connected) {
  326. return -USB_ERR_INVAL;
  327. }
  328. if (serial->ref_count == 0) {
  329. return -USB_ERR_NODEV;
  330. }
  331. switch (cmd) {
  332. case USBH_SERIAL_CMD_SET_ATTR: {
  333. struct usbh_serial_termios *termios = (struct usbh_serial_termios *)arg;
  334. struct cdc_line_coding line_coding;
  335. line_coding.dwDTERate = termios->baudrate;
  336. line_coding.bCharFormat = termios->stopbits;
  337. line_coding.bParityType = termios->parity;
  338. line_coding.bDataBits = termios->databits;
  339. if (serial->bulkin) {
  340. usbh_kill_urb(&serial->bulkin_urb);
  341. }
  342. if (serial->bulkout) {
  343. usbh_kill_urb(&serial->bulkout_urb);
  344. }
  345. if (serial && serial->driver && serial->driver->set_line_coding) {
  346. ret = serial->driver->set_line_coding(serial, &line_coding);
  347. if (ret < 0) {
  348. return ret;
  349. }
  350. } else {
  351. return -USB_ERR_NOTSUPP;
  352. }
  353. memcpy(&serial->line_coding, &line_coding, sizeof(struct cdc_line_coding));
  354. if (serial && serial->driver && serial->driver->set_flow_control) {
  355. ret = serial->driver->set_flow_control(serial, termios->rtscts);
  356. }
  357. serial->rtscts = termios->rtscts;
  358. serial->rx_timeout_ms = termios->rx_timeout;
  359. ret = usbh_serial_tiocmset(serial, USBH_SERIAL_TIOCM_DTR | USBH_SERIAL_TIOCM_RTS, 0);
  360. if (ret < 0) {
  361. return ret;
  362. }
  363. usbh_serial_ringbuffer_reset(&serial->rx_rb);
  364. usb_osal_sem_reset(serial->rx_complete_sem);
  365. serial->rx_buf_index = 0;
  366. usbh_bulk_urb_fill(&serial->bulkin_urb, serial->hport, serial->bulkin, &serial->iobuffer[serial->rx_buf_index ? USBH_SERIAL_RX2_NOCACHE_OFFSET : USBH_SERIAL_RX_NOCACHE_OFFSET], serial->bulkin->wMaxPacketSize,
  367. 0, usbh_serial_callback, serial);
  368. ret = usbh_submit_urb(&serial->bulkin_urb);
  369. return ret;
  370. } break;
  371. case USBH_SERIAL_CMD_GET_ATTR: {
  372. struct usbh_serial_termios *termios = (struct usbh_serial_termios *)arg;
  373. struct cdc_line_coding line_coding;
  374. if (serial && serial->driver && serial->driver->get_line_coding) {
  375. return serial->driver->get_line_coding(serial, &line_coding);
  376. } else {
  377. memcpy(&line_coding, &serial->line_coding, sizeof(struct cdc_line_coding));
  378. }
  379. termios->baudrate = line_coding.dwDTERate;
  380. termios->stopbits = line_coding.bCharFormat;
  381. termios->parity = line_coding.bParityType;
  382. termios->databits = line_coding.bDataBits;
  383. termios->rtscts = serial->rtscts;
  384. termios->rx_timeout = serial->rx_timeout_ms;
  385. return 0;
  386. } break;
  387. case USBH_SERIAL_CMD_IOCMBIS: {
  388. uint32_t flags = *(uint32_t *)arg;
  389. return usbh_serial_tiocmset(serial, flags, 0);
  390. } break;
  391. case USBH_SERIAL_CMD_IOCMBIC: {
  392. uint32_t flags = *(uint32_t *)arg;
  393. return usbh_serial_tiocmset(serial, 0, flags);
  394. } break;
  395. case USBH_SERIAL_CMD_TIOCMSET: {
  396. uint32_t flags = *(uint32_t *)arg;
  397. uint32_t set = 0;
  398. uint32_t clear = 0;
  399. set |= (flags & USBH_SERIAL_TIOCM_DTR) ? USBH_SERIAL_TIOCM_DTR : 0;
  400. set |= (flags & USBH_SERIAL_TIOCM_RTS) ? USBH_SERIAL_TIOCM_RTS : 0;
  401. clear |= !(flags & USBH_SERIAL_TIOCM_DTR) ? USBH_SERIAL_TIOCM_DTR : 0;
  402. clear |= !(flags & USBH_SERIAL_TIOCM_RTS) ? USBH_SERIAL_TIOCM_RTS : 0;
  403. return usbh_serial_tiocmset(serial, set, clear);
  404. } break;
  405. case USBH_SERIAL_CMD_TIOCMGET: {
  406. uint32_t *flags = (uint32_t *)arg;
  407. int status;
  408. if (serial && serial->driver && serial->driver->get_modem_status) {
  409. status = serial->driver->get_modem_status(serial);
  410. if (status < 0) {
  411. return status;
  412. }
  413. } else {
  414. return -USB_ERR_NOTSUPP;
  415. }
  416. *flags = status;
  417. } break;
  418. default:
  419. break;
  420. }
  421. return -USB_ERR_NOTSUPP;
  422. }
  423. int usbh_serial_write(struct usbh_serial *serial, const void *buffer, uint32_t buflen)
  424. {
  425. int ret;
  426. struct usbh_urb *urb;
  427. if (!serial || !serial->hport || !serial->hport->connected || !serial->bulkout) {
  428. return -USB_ERR_INVAL;
  429. }
  430. if (serial->ref_count == 0) {
  431. return -USB_ERR_NODEV;
  432. }
  433. urb = &serial->bulkout_urb;
  434. usbh_bulk_urb_fill(urb, serial->hport, serial->bulkout, (uint8_t *)buffer, serial->line_coding.dwDTERate ? MIN(buflen, serial->bulkout->wMaxPacketSize) : buflen, 0xffffffff, NULL, NULL);
  435. ret = usbh_submit_urb(urb);
  436. if (ret == 0) {
  437. ret = urb->actual_length;
  438. }
  439. return ret;
  440. }
  441. int usbh_serial_read(struct usbh_serial *serial, void *buffer, uint32_t buflen)
  442. {
  443. int ret;
  444. if (!serial || !serial->hport || !serial->hport->connected || !serial->bulkin || !serial->line_coding.dwDTERate) {
  445. return -USB_ERR_INVAL;
  446. }
  447. if (serial->ref_count == 0) {
  448. return -USB_ERR_NODEV;
  449. }
  450. if (serial->open_flags & USBH_SERIAL_O_NONBLOCK) {
  451. return usbh_serial_ringbuffer_read(&serial->rx_rb, buffer, buflen);
  452. } else {
  453. if (usbh_serial_ringbuffer_get_used(&serial->rx_rb) == 0) {
  454. ret = usb_osal_sem_take(serial->rx_complete_sem, serial->rx_timeout_ms == 0 ? USB_OSAL_WAITING_FOREVER : serial->rx_timeout_ms);
  455. if (ret < 0) {
  456. return ret;
  457. }
  458. if (serial->rx_errorcode < 0) {
  459. return serial->rx_errorcode;
  460. }
  461. }
  462. return usbh_serial_ringbuffer_read(&serial->rx_rb, buffer, buflen);
  463. }
  464. }
  465. int usbh_serial_cdc_write_async(struct usbh_serial *serial, uint8_t *buffer, uint32_t buflen, usbh_complete_callback_t complete, void *arg)
  466. {
  467. struct usbh_urb *urb;
  468. if (!serial || !serial->hport || !serial->hport->connected || !serial->bulkout || !complete || serial->line_coding.dwDTERate) {
  469. return -USB_ERR_INVAL;
  470. }
  471. if (serial->ref_count > 0) {
  472. return -USB_ERR_NODEV;
  473. }
  474. urb = &serial->bulkout_urb;
  475. usbh_bulk_urb_fill(urb, serial->hport, serial->bulkout, buffer, buflen,
  476. 0, complete, serial);
  477. return usbh_submit_urb(urb);
  478. }
  479. int usbh_serial_cdc_read_async(struct usbh_serial *serial, uint8_t *buffer, uint32_t buflen, usbh_complete_callback_t complete, void *arg)
  480. {
  481. struct usbh_urb *urb;
  482. if (!serial || !serial->hport || !serial->hport->connected || !serial->bulkin || !complete || serial->line_coding.dwDTERate) {
  483. return -USB_ERR_INVAL;
  484. }
  485. if (serial->ref_count > 0) {
  486. return -USB_ERR_NODEV;
  487. }
  488. if (buflen % serial->bulkin->wMaxPacketSize) {
  489. return -USB_ERR_INVAL;
  490. }
  491. urb = &serial->bulkin_urb;
  492. usbh_bulk_urb_fill(urb, serial->hport, serial->bulkin, buffer, MIN(buflen, serial->bulkin->wMaxPacketSize),
  493. 0, complete, serial);
  494. return usbh_submit_urb(urb);
  495. }
  496. void usbh_serial_help(void)
  497. {
  498. USB_LOG_RAW("USB host serial test\r\n"
  499. "Usage: usbh_serial <ttypath> [options]...\r\n"
  500. "\r\n"
  501. "-b <baud> set serial baudrate\r\n"
  502. "-t <dtr> <rts> set rts and dtr\r\n"
  503. "-w string write string\r\n"
  504. "-r read data and dump\r\n"
  505. "-x close serial device\r\n"
  506. "\r\n");
  507. }
  508. static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_serial_testbuffer[512];
  509. int usbh_serial(int argc, char **argv)
  510. {
  511. static struct usbh_serial *serial;
  512. int ret;
  513. if (argc < 3) {
  514. usbh_serial_help();
  515. return 0;
  516. }
  517. if (serial) {
  518. if (!serial->hport || !serial->hport->connected) {
  519. serial = NULL;
  520. }
  521. }
  522. if (!serial) {
  523. serial = usbh_serial_open(argv[1], USBH_SERIAL_O_RDWR | USBH_SERIAL_O_NONBLOCK);
  524. if (!serial) {
  525. USB_LOG_ERR("Fail to open serial device: %s\r\n", argv[1]);
  526. return -USB_ERR_INVAL;
  527. }
  528. }
  529. if (strncmp(argv[2], "-b", 2) == 0 && argc >= 4) {
  530. struct usbh_serial_termios termios;
  531. memset(&termios, 0, sizeof(termios));
  532. termios.baudrate = atoi(argv[3]);
  533. termios.stopbits = 0;
  534. termios.parity = 0;
  535. termios.databits = 8;
  536. termios.rtscts = false;
  537. termios.rx_timeout = 0;
  538. usbh_serial_control(serial, USBH_SERIAL_CMD_SET_ATTR, &termios);
  539. } else if (strncmp(argv[2], "-t", 2) == 0 && argc >= 5) {
  540. uint32_t flags;
  541. flags = atoi(argv[3]) ? USBH_SERIAL_TIOCM_DTR : 0;
  542. flags |= atoi(argv[4]) ? USBH_SERIAL_TIOCM_RTS : 0;
  543. usbh_serial_control(serial, USBH_SERIAL_CMD_TIOCMSET, &flags);
  544. USB_LOG_INFO("Set DTR: %d, RTS: %d\r\n", atoi(argv[3]), atoi(argv[4]));
  545. } else if (strncmp(argv[2], "-w", 2) == 0 && argc >= 4) {
  546. memcpy(g_serial_testbuffer, argv[3], MIN(strlen(argv[3]), sizeof(g_serial_testbuffer)));
  547. uint32_t len = snprintf((char *)g_serial_testbuffer, sizeof(g_serial_testbuffer), "%s\r\n", argv[3]);
  548. ret = usbh_serial_write(serial, g_serial_testbuffer, len);
  549. if (ret >= 0) {
  550. USB_LOG_INFO("Write %d bytes\r\n", ret);
  551. } else {
  552. USB_LOG_ERR("Write failed: %d\r\n", ret);
  553. }
  554. } else if (strncmp(argv[2], "-r", 2) == 0) {
  555. ret = usbh_serial_read(serial, g_serial_testbuffer, sizeof(g_serial_testbuffer));
  556. if (ret >= 0) {
  557. usb_hexdump(g_serial_testbuffer, ret);
  558. USB_LOG_INFO("Read %d bytes\r\n", ret);
  559. } else {
  560. USB_LOG_ERR("Read failed: %d\r\n", ret);
  561. }
  562. } else if (strncmp(argv[2], "-x", 2) == 0) {
  563. usbh_serial_close(serial);
  564. serial = NULL;
  565. } else {
  566. usbh_serial_help();
  567. }
  568. return 0;
  569. }
  570. __WEAK void usbh_serial_run(struct usbh_serial *serial)
  571. {
  572. (void)serial;
  573. }
  574. __WEAK void usbh_serial_stop(struct usbh_serial *serial)
  575. {
  576. (void)serial;
  577. }
  578. static int usbh_cdc_data_connect(struct usbh_hubport *hport, uint8_t intf)
  579. {
  580. (void)hport;
  581. (void)intf;
  582. return 0;
  583. }
  584. static int usbh_cdc_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
  585. {
  586. (void)hport;
  587. (void)intf;
  588. return 0;
  589. }
  590. const struct usbh_class_driver cdc_data_class_driver = {
  591. .driver_name = "cdc_data",
  592. .connect = usbh_cdc_data_connect,
  593. .disconnect = usbh_cdc_data_disconnect
  594. };
  595. CLASS_INFO_DEFINE const struct usbh_class_info cdc_data_class_info = {
  596. .match_flags = USB_CLASS_MATCH_INTF_CLASS,
  597. .bInterfaceClass = USB_DEVICE_CLASS_CDC_DATA,
  598. .bInterfaceSubClass = 0x00,
  599. .bInterfaceProtocol = 0x00,
  600. .id_table = NULL,
  601. .class_driver = &cdc_data_class_driver
  602. };