This is an automated email from the ASF dual-hosted git repository. lupyuen pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push: new a0a61ff345 driver/serial/cdcacm: Get the status of rx or tx buf by ioctl a0a61ff345 is described below commit a0a61ff345df9f5f693a90cf24321df09b384377 Author: yangsong8 <yangso...@xiaomi.com> AuthorDate: Fri Mar 21 14:35:55 2025 +0800 driver/serial/cdcacm: Get the status of rx or tx buf by ioctl In cdcacm, USB req buf is directly used as serial buf, so the getting buf status operation in ioctl is different from the original serial. Signed-off-by: yangsong8 <yangso...@xiaomi.com> --- drivers/usbdev/cdcacm.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 168 insertions(+), 3 deletions(-) diff --git a/drivers/usbdev/cdcacm.c b/drivers/usbdev/cdcacm.c index 815a854e2a..8a84a81d67 100644 --- a/drivers/usbdev/cdcacm.c +++ b/drivers/usbdev/cdcacm.c @@ -2131,12 +2131,177 @@ static void cdcuart_detach(FAR struct uart_dev_s *dev) static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { - struct inode *inode = filep->f_inode; - struct cdcacm_dev_s *priv = inode->i_private; - int ret = OK; + FAR struct inode *inode = filep->f_inode; + FAR struct cdcacm_dev_s *priv = inode->i_private; + FAR struct uart_dev_s *serdev = &priv->serdev; + int ret = OK; switch (cmd) { + /* Get the number of bytes that may be read from the RX buffer + * (without waiting) + */ + + case FIONREAD: + { + FAR struct cdcacm_rdreq_s *rdcontainer; + FAR sq_entry_t *entry; + int count; + + irqstate_t flags = enter_critical_section(); + + /* Determine the number of bytes available in the RX buffer */ + + count = serdev->recv.head - serdev->recv.tail; + + sq_for_every(&priv->rxpending, entry) + { + rdcontainer = (FAR struct cdcacm_rdreq_s *)entry; + count += rdcontainer->req->xfrd; + } + + leave_critical_section(flags); + + *(FAR int *)((uintptr_t)arg) = count; + } + break; + + /* Get the number of bytes that have been written to the TX + * buffer. + */ + + case FIONWRITE: + { + FAR struct cdcacm_wrreq_s *wrcontainer; + FAR sq_entry_t *entry; + int count; + int i; + + irqstate_t flags = enter_critical_section(); + + /* Determine the number of bytes waiting in the TX buffer */ + + count = serdev->xmit.head - serdev->xmit.tail; + + if (priv->nwrq < (CONFIG_CDCACM_NWRREQS - 1)) + { + for (i = 0; i < CONFIG_CDCACM_NWRREQS; i++) + { + sq_for_every(&priv->txfree, entry) + { + wrcontainer = (FAR struct cdcacm_wrreq_s *)entry; + if (&priv->wrreqs[i] == wrcontainer) + { + continue; + } + else if (&priv->wrreqs[i] != priv->wrcontainer) + { + count += priv->wrreqs[i].req->len; + } + } + } + } + + leave_critical_section(flags); + + *(FAR int *)((uintptr_t)arg) = count; + } + break; + + /* Get the number of free bytes in the TX buffer */ + + case FIONSPACE: + { + FAR sq_entry_t *entry; + int count = 0; + + irqstate_t flags = enter_critical_section(); + + /* Determine the number of bytes free in the TX buffer */ + + if (serdev->xmit.head == 0) + { + count = serdev->xmit.size - 1; + } + + sq_for_every(&priv->txfree, entry) + { + count += serdev->xmit.size - 1; + } + + leave_critical_section(flags); + + *(FAR int *)((uintptr_t)arg) = count; + } + break; + + case TCFLSH: + { + /* Empty the tx/rx buffers */ + + irqstate_t flags = enter_critical_section(); + + if (arg == TCIFLUSH || arg == TCIOFLUSH) + { + FAR struct cdcacm_rdreq_s *rdcontainer; + + if (priv->rdcontainer) + { + sq_addlast((FAR sq_entry_t *)priv->rdcontainer, + &priv->rxpending); + priv->rdcontainer = NULL; + } + + while (!sq_empty(&priv->rxpending)) + { + rdcontainer = (FAR struct cdcacm_rdreq_s *) + sq_remfirst(&priv->rxpending); + ret = cdcacm_requeue_rdrequest(priv, rdcontainer); + } + + serdev->recv.head = 0; + serdev->recv.tail = 0; + +#ifdef CONFIG_SERIAL_IFLOWCONTROL + /* De-activate RX flow control. */ + + uart_rxflowcontrol(serdev, 0, false); +#endif + } + + if (arg == TCOFLUSH || arg == TCIOFLUSH) + { + if (priv->wrcontainer) + { + serdev->xmit.head = 0; + serdev->xmit.tail = 0; + + /* Inform any waiters there is space available. */ + + uart_datasent(serdev); + } + else if(priv->nwrq > 0) + { + priv->wrcontainer = (FAR struct cdcacm_wrreq_s *) + sq_remfirst(&priv->txfree); + serdev->xmit.buffer = + (FAR char *)priv->wrcontainer->req->buf; + priv->nwrq--; + serdev->xmit.head = 0; + serdev->xmit.tail = 0; + + uart_datasent(serdev); + } + else + { + ret = -EBUSY; + } + } + + leave_critical_section(flags); + } + break; + /* CAICO_REGISTERCB * Register a callback for serial event notification. Argument: * cdcacm_callback_t. See cdcacm_callback_t type definition below.