cdcacm: support polling mode in order to work normally in interrupt

Signed-off-by: yangsong8 <yangsong8@xiaomi.com>
This commit is contained in:
yangsong8 2024-08-02 12:02:45 +08:00 committed by Xiang Xiao
parent 7d570182be
commit 6c71276359
1 changed files with 38 additions and 9 deletions

View File

@ -103,7 +103,7 @@ struct cdcacm_dev_s
bool upper; /* True: RX buffer is (nearly) full */
#endif
bool rxenabled; /* true: UART RX "interrupts" enabled */
bool issending;
bool ispolling;
struct cdc_linecoding_s linecoding; /* Buffered line status */
cdcacm_callback_t callback; /* Serial event callback function */
@ -293,6 +293,14 @@ static const struct uart_ops_s g_uartops =
static bool cdcuart_txready(FAR struct uart_dev_s *dev)
{
FAR struct cdcacm_dev_s *priv = dev->priv;
FAR struct usbdev_ep_s *ep = priv->epbulkin;
if (sq_empty(&priv->txfree))
{
priv->ispolling = true;
EP_POLL(ep);
priv->ispolling = false;
}
return !sq_empty(&priv->txfree);
}
@ -337,7 +345,9 @@ static ssize_t cdcuart_sendbuf(FAR struct uart_dev_s *dev,
req->len = nbytes;
req->priv = wrcontainer;
req->flags = USBDEV_REQFLAGS_NULLPKT;
priv->ispolling = true;
ret = EP_SUBMIT(ep, req);
priv->ispolling = false;
if (ret < 0)
{
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_SUBMITFAIL),
@ -372,14 +382,10 @@ static int cdcacm_sndpacket(FAR struct cdcacm_dev_s *priv)
#endif
flags = enter_critical_section();
if (priv->issending)
if (priv->ispolling)
{
goto out;
}
else
{
priv->issending = true;
}
uinfo("head=%d tail=%d nwrq=%d empty=%d\n",
priv->serdev.xmit.head, priv->serdev.xmit.tail,
@ -390,8 +396,6 @@ static int cdcacm_sndpacket(FAR struct cdcacm_dev_s *priv)
uart_xmitchars_dma(&priv->serdev);
}
priv->issending = false;
out:
leave_critical_section(flags);
return OK;
@ -408,6 +412,14 @@ out:
static bool cdcuart_rxavailable(FAR struct uart_dev_s *dev)
{
FAR struct cdcacm_dev_s *priv = dev->priv;
FAR struct usbdev_ep_s *ep = priv->epbulkout;
if (sq_empty(&priv->rxpending))
{
priv->ispolling = true;
EP_POLL(ep);
priv->ispolling = false;
}
return !sq_empty(&priv->rxpending);
}
@ -519,6 +531,11 @@ static int cdcacm_release_rxpending(FAR struct cdcacm_dev_s *priv)
flags = enter_critical_section();
if (priv->ispolling)
{
goto out;
}
/* Cancel any pending failsafe timer */
wd_cancel(&priv->rxfailsafe);
@ -568,6 +585,7 @@ static int cdcacm_release_rxpending(FAR struct cdcacm_dev_s *priv)
cdcacm_rxtimeout, (wdparm_t)priv);
}
out:
leave_critical_section(flags);
return ret;
}
@ -2647,6 +2665,9 @@ static void cdcuart_txint(FAR struct uart_dev_s *dev, bool enable)
static bool cdcuart_txempty(FAR struct uart_dev_s *dev)
{
FAR struct cdcacm_dev_s *priv = (FAR struct cdcacm_dev_s *)dev->priv;
FAR struct usbdev_ep_s *ep = priv->epbulkin;
irqstate_t flags;
bool empty;
usbtrace(CDCACM_CLASSAPI_TXEMPTY, 0);
@ -2658,11 +2679,19 @@ static bool cdcuart_txempty(FAR struct uart_dev_s *dev)
}
#endif
flags = enter_critical_section();
priv->ispolling = true;
EP_POLL(ep);
priv->ispolling = false;
/* When all of the allocated write requests have been returned to the
* txfree, then there is no longer any TX data in flight.
*/
return priv->nwrq >= CONFIG_CDCACM_NWRREQS;
empty = priv->nwrq >= CONFIG_CDCACM_NWRREQS;
leave_critical_section(flags);
return empty;
}
/****************************************************************************