drivers/serial/pty.c, serial.c, usbdev/cdcacm.c, include/nuttx/fs/ioctl.h: Fix FIONWRITE and add FIONSPACE. All implementations of FIONWRITE were wrong. FIONWRITE should return the number of bytes waiting in the outgoing send queue, not the free space. Rather, FIONSPACE should return the free space in the send queue.

This commit is contained in:
Gregory Nutt 2016-07-25 14:06:32 -06:00
parent 899a8aa2f0
commit e0b4a10dfa
5 changed files with 118 additions and 9 deletions

View File

@ -785,11 +785,18 @@ int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
case FIONREAD:
case FIONWRITE: /* Number of bytes waiting in send queue */
case FIONREAD: /* Number of bytes available for reading */
{
int count;
/* Determine the number of bytes available in the buffer */
/* Determine the number of bytes written to the buffer. This is,
* of course, also the number of bytes that may be read from the
* buffer.
*
* d_rdndx - index to remove next byte from the buffer
* d_wrndx - Index to next location to add a byte to the buffer.
*/
if (dev->d_wrndx < dev->d_rdndx)
{
@ -805,11 +812,17 @@ int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
case FIONWRITE:
/* Free space in buffer */
case FIONSPACE:
{
int count;
/* Determine the number of bytes free in the buffer */
/* Determine the number of bytes free in the buffer.
*
* d_rdndx - index to remove next byte from the buffer
* d_wrndx - Index to next location to add a byte to the buffer.
*/
if (dev->d_wrndx < dev->d_rdndx)
{

View File

@ -774,17 +774,48 @@ static int pty_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
#endif
/* Get the number of bytes that are immediately available for reading
* from the source pipe.
*/
case FIONREAD:
{
ret = file_ioctl(&dev->pd_src, cmd, arg);
}
break;
/* Get the number of bytes waiting in the sink pipe (FIONWRITE) or the
* number of unused bytes in the sink pipe (FIONSPACE).
*/
case FIONWRITE:
case FIONSPACE:
{
ret = file_ioctl(&dev->pd_sink, cmd, arg);
}
break;
/* Any unrecognized IOCTL commands will be passed to the contained
* pipe driver.
*
* REVISIT: We know for a fact that the pipe driver only supports
* FIONREAD, FIONWRITE, FIONSPACE and PIPEIOC_POLICY. The first two
* are handled above and PIPEIOC_POLICY should not be managed by
* applications -- it can break the PTY!
*/
default:
{
#if 0
ret = file_ioctl(&dev->pd_src, cmd, arg);
if (ret >= 0 || ret == -ENOTTY)
{
ret = file_ioctl(&dev->pd_sink, cmd, arg);
}
#else
ret = ENOTTY;
#endif
}
break;
}

View File

@ -910,12 +910,16 @@ static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
switch (cmd)
{
/* Get the number of bytes that may be read from the RX buffer
* (without waiting)
*/
case FIONREAD:
{
int count;
irqstate_t flags = enter_critical_section();
/* Determine the number of bytes available in the buffer */
/* Determine the number of bytes available in the RX buffer */
if (dev->recv.tail <= dev->recv.head)
{
@ -933,12 +937,39 @@ static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
/* Get the number of bytes that have been written to the TX buffer. */
case FIONWRITE:
{
int count;
irqstate_t flags = enter_critical_section();
/* Determine the number of bytes free in the buffer */
/* Determine the number of bytes waiting in the TX buffer */
if (dev->xmit.head < dev->xmit.tail)
{
count = dev->xmit.head - dev->xmit.tail;
}
else
{
count = dev->xmit.size - (dev->xmit.tail - dev->xmit.head);
}
leave_critical_section(flags);
*(FAR int *)((uintptr_t)arg) = count;
ret = 0;
}
break;
/* Get the number of free bytes in the TX buffer */
case FIONSPACE:
{
int count;
irqstate_t flags = enter_critical_section();
/* Determine the number of bytes free in the TX buffer */
if (dev->xmit.head < dev->xmit.tail)
{

View File

@ -1982,12 +1982,16 @@ static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
break;
#endif
/* Get the number of bytes that may be read from the RX buffer (without
* waiting)
*/
case FIONREAD:
{
int count;
irqstate_t flags = enter_critical_section();
/* Determine the number of bytes available in the buffer. */
/* Determine the number of bytes available in the RX buffer. */
if (serdev->recv.tail <= serdev->recv.head)
{
@ -2005,12 +2009,39 @@ static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
/* Get the number of bytes that have been written to the TX buffer. */
case FIONWRITE:
{
int count;
irqstate_t flags = enter_critical_section();
/* Determine the number of bytes free in the buffer. */
/* Determine the number of bytes waiting in the TX buffer. */
if (serdev->xmit.tail <= serdev->xmit.head)
{
count = serdev->xmit.head - serdev->xmit.tail;
}
else
{
count = serdev->xmit.size - (serdev->xmit.tail - serdev->xmit.head);
}
leave_critical_section(flags);
*(int *)arg = count;
ret = 0;
}
break;
/* Get the number of free bytes in the TX buffer */
case FIONSPACE:
{
int count;
irqstate_t flags = enter_critical_section();
/* Determine the number of bytes free in the TX buffer */
if (serdev->xmit.head < serdev->xmit.tail)
{

View File

@ -137,7 +137,10 @@
* OUT: Bytes readable from this fd
*/
#define FIONWRITE _FIOC(0x0006) /* IN: Location to return value (int *)
* OUT: Bytes writable to this fd
* OUT: Number bytes in send queue
*/
#define FIONSPACE _FIOC(0x0007) /* IN: Location to return value (int *)
* OUT: Free space in send queue.
*/
/* NuttX file system ioctl definitions **************************************/