@@ -2131,12 +2131,177 @@ static void cdcuart_detach(FAR struct uart_dev_s *dev)
21312131
21322132static 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