Skip to content

Commit a0a61ff

Browse files
yangsong8-a1lupyuen
authored andcommitted
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 <[email protected]>
1 parent a99c183 commit a0a61ff

File tree

1 file changed

+168
-3
lines changed

1 file changed

+168
-3
lines changed

drivers/usbdev/cdcacm.c

Lines changed: 168 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,12 +2131,177 @@ static void cdcuart_detach(FAR struct uart_dev_s *dev)
21312131

21322132
static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
21332133
{
2134-
struct inode *inode = filep->f_inode;
2135-
struct cdcacm_dev_s *priv = inode->i_private;
2136-
int ret = OK;
2134+
FAR struct inode *inode = filep->f_inode;
2135+
FAR struct cdcacm_dev_s *priv = inode->i_private;
2136+
FAR struct uart_dev_s *serdev = &priv->serdev;
2137+
int ret = OK;
21372138

21382139
switch (cmd)
21392140
{
2141+
/* Get the number of bytes that may be read from the RX buffer
2142+
* (without waiting)
2143+
*/
2144+
2145+
case FIONREAD:
2146+
{
2147+
FAR struct cdcacm_rdreq_s *rdcontainer;
2148+
FAR sq_entry_t *entry;
2149+
int count;
2150+
2151+
irqstate_t flags = enter_critical_section();
2152+
2153+
/* Determine the number of bytes available in the RX buffer */
2154+
2155+
count = serdev->recv.head - serdev->recv.tail;
2156+
2157+
sq_for_every(&priv->rxpending, entry)
2158+
{
2159+
rdcontainer = (FAR struct cdcacm_rdreq_s *)entry;
2160+
count += rdcontainer->req->xfrd;
2161+
}
2162+
2163+
leave_critical_section(flags);
2164+
2165+
*(FAR int *)((uintptr_t)arg) = count;
2166+
}
2167+
break;
2168+
2169+
/* Get the number of bytes that have been written to the TX
2170+
* buffer.
2171+
*/
2172+
2173+
case FIONWRITE:
2174+
{
2175+
FAR struct cdcacm_wrreq_s *wrcontainer;
2176+
FAR sq_entry_t *entry;
2177+
int count;
2178+
int i;
2179+
2180+
irqstate_t flags = enter_critical_section();
2181+
2182+
/* Determine the number of bytes waiting in the TX buffer */
2183+
2184+
count = serdev->xmit.head - serdev->xmit.tail;
2185+
2186+
if (priv->nwrq < (CONFIG_CDCACM_NWRREQS - 1))
2187+
{
2188+
for (i = 0; i < CONFIG_CDCACM_NWRREQS; i++)
2189+
{
2190+
sq_for_every(&priv->txfree, entry)
2191+
{
2192+
wrcontainer = (FAR struct cdcacm_wrreq_s *)entry;
2193+
if (&priv->wrreqs[i] == wrcontainer)
2194+
{
2195+
continue;
2196+
}
2197+
else if (&priv->wrreqs[i] != priv->wrcontainer)
2198+
{
2199+
count += priv->wrreqs[i].req->len;
2200+
}
2201+
}
2202+
}
2203+
}
2204+
2205+
leave_critical_section(flags);
2206+
2207+
*(FAR int *)((uintptr_t)arg) = count;
2208+
}
2209+
break;
2210+
2211+
/* Get the number of free bytes in the TX buffer */
2212+
2213+
case FIONSPACE:
2214+
{
2215+
FAR sq_entry_t *entry;
2216+
int count = 0;
2217+
2218+
irqstate_t flags = enter_critical_section();
2219+
2220+
/* Determine the number of bytes free in the TX buffer */
2221+
2222+
if (serdev->xmit.head == 0)
2223+
{
2224+
count = serdev->xmit.size - 1;
2225+
}
2226+
2227+
sq_for_every(&priv->txfree, entry)
2228+
{
2229+
count += serdev->xmit.size - 1;
2230+
}
2231+
2232+
leave_critical_section(flags);
2233+
2234+
*(FAR int *)((uintptr_t)arg) = count;
2235+
}
2236+
break;
2237+
2238+
case TCFLSH:
2239+
{
2240+
/* Empty the tx/rx buffers */
2241+
2242+
irqstate_t flags = enter_critical_section();
2243+
2244+
if (arg == TCIFLUSH || arg == TCIOFLUSH)
2245+
{
2246+
FAR struct cdcacm_rdreq_s *rdcontainer;
2247+
2248+
if (priv->rdcontainer)
2249+
{
2250+
sq_addlast((FAR sq_entry_t *)priv->rdcontainer,
2251+
&priv->rxpending);
2252+
priv->rdcontainer = NULL;
2253+
}
2254+
2255+
while (!sq_empty(&priv->rxpending))
2256+
{
2257+
rdcontainer = (FAR struct cdcacm_rdreq_s *)
2258+
sq_remfirst(&priv->rxpending);
2259+
ret = cdcacm_requeue_rdrequest(priv, rdcontainer);
2260+
}
2261+
2262+
serdev->recv.head = 0;
2263+
serdev->recv.tail = 0;
2264+
2265+
#ifdef CONFIG_SERIAL_IFLOWCONTROL
2266+
/* De-activate RX flow control. */
2267+
2268+
uart_rxflowcontrol(serdev, 0, false);
2269+
#endif
2270+
}
2271+
2272+
if (arg == TCOFLUSH || arg == TCIOFLUSH)
2273+
{
2274+
if (priv->wrcontainer)
2275+
{
2276+
serdev->xmit.head = 0;
2277+
serdev->xmit.tail = 0;
2278+
2279+
/* Inform any waiters there is space available. */
2280+
2281+
uart_datasent(serdev);
2282+
}
2283+
else if(priv->nwrq > 0)
2284+
{
2285+
priv->wrcontainer = (FAR struct cdcacm_wrreq_s *)
2286+
sq_remfirst(&priv->txfree);
2287+
serdev->xmit.buffer =
2288+
(FAR char *)priv->wrcontainer->req->buf;
2289+
priv->nwrq--;
2290+
serdev->xmit.head = 0;
2291+
serdev->xmit.tail = 0;
2292+
2293+
uart_datasent(serdev);
2294+
}
2295+
else
2296+
{
2297+
ret = -EBUSY;
2298+
}
2299+
}
2300+
2301+
leave_critical_section(flags);
2302+
}
2303+
break;
2304+
21402305
/* CAICO_REGISTERCB
21412306
* Register a callback for serial event notification. Argument:
21422307
* cdcacm_callback_t. See cdcacm_callback_t type definition below.

0 commit comments

Comments
 (0)