Add missing implementation of O_NONBLOCK for serial writes

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5755 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2013-03-18 16:04:29 +00:00
parent 1a67cb9e1e
commit 730dc3e202
2 changed files with 36 additions and 6 deletions

View File

@ -4366,3 +4366,9 @@
the format statement after the input data stream has been fully
parsed, the %n format specifier will not be handled. Reported by
Lorenz Meier (and also earlier by Kate) (2013-03-17).
* drivers/serial/serial.c: Support for O_NONBLOCK was not supported
in the "upper half" serial driver. This is normally not an issue
because UART TX is almost always available, but it does become an
if the UART uses hardware flow control or if the a "lower half" is
something like the USB CDC/ACM driver that may need to block for
significant amounts of time.

View File

@ -178,7 +178,7 @@ static void uart_pollnotify(FAR uart_dev_t *dev, pollevent_t eventset)
* Name: uart_putxmitchar
************************************************************************************/
static int uart_putxmitchar(FAR uart_dev_t *dev, int ch)
static int uart_putxmitchar(FAR uart_dev_t *dev, int ch, bool oktoblock)
{
irqstate_t flags;
int nexthead;
@ -204,7 +204,13 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch)
dev->xmit.head = nexthead;
return OK;
}
else
/* The buffer is full and no data is available now. Should be block,
* waiting for the the hardware to remove some data from the TX
* buffer?
*/
else if (oktoblock)
{
/* Inform the interrupt level logic that we are waiting. This and
* the following steps must be atomic.
@ -260,6 +266,15 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch)
return -EINTR;
}
}
/* The caller has request that we not block for data. So return the
* EAGAIN error to signal this situation.
*/
else
{
return -EAGAIN;
}
}
/* We won't get here. Some compilers may complain that this code is
@ -307,6 +322,7 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t
FAR struct inode *inode = filep->f_inode;
FAR uart_dev_t *dev = inode->i_private;
ssize_t nread = buflen;
bool oktoblock;
int ret;
/* We may receive console writes through this path from interrupt handlers and
@ -371,6 +387,12 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t
}
#endif
/* Can the following loop block, waiting for space in the TX
* buffer?
*/
oktoblock = ((filep->f_oflags & O_NONBLOCK) == 0);
/* Loop while we still have data to copy to the transmit buffer.
* we add data to the head of the buffer; uart_xmitchars takes the
* data from the end of the buffer.
@ -386,22 +408,24 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t
ret = OK;
if (dev->isconsole && ch == '\n')
{
ret = uart_putxmitchar(dev, '\r');
ret = uart_putxmitchar(dev, '\r', oktoblock);
}
/* Put the character into the transmit buffer */
if (ret == OK)
{
ret = uart_putxmitchar(dev, ch);
ret = uart_putxmitchar(dev, ch, oktoblock);
}
/* uart_putxmitchar() might return an error under one of two
* conditions: (1) The wait for buffer space might have been
* interrupted by a signal (ret should be -EINTR), or (2) if
* interrupted by a signal (ret should be -EINTR), (2) if
* CONFIG_SERIAL_REMOVABLE is defined, then uart_putxmitchar()
* might also return if the serial device was disconnected
* (with -ENOTCONN).
* (with -ENOTCONN), or (3) if O_NONBLOCK is specified, then
* then uart_putxmitchar() might return -EAGAIN if the output
* TX buffer is full.
*/
if (ret < 0)