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:
parent
1a67cb9e1e
commit
730dc3e202
@ -4366,3 +4366,9 @@
|
|||||||
the format statement after the input data stream has been fully
|
the format statement after the input data stream has been fully
|
||||||
parsed, the %n format specifier will not be handled. Reported by
|
parsed, the %n format specifier will not be handled. Reported by
|
||||||
Lorenz Meier (and also earlier by Kate) (2013-03-17).
|
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.
|
||||||
|
@ -178,7 +178,7 @@ static void uart_pollnotify(FAR uart_dev_t *dev, pollevent_t eventset)
|
|||||||
* Name: uart_putxmitchar
|
* 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;
|
irqstate_t flags;
|
||||||
int nexthead;
|
int nexthead;
|
||||||
@ -204,7 +204,13 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch)
|
|||||||
dev->xmit.head = nexthead;
|
dev->xmit.head = nexthead;
|
||||||
return OK;
|
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
|
/* Inform the interrupt level logic that we are waiting. This and
|
||||||
* the following steps must be atomic.
|
* the following steps must be atomic.
|
||||||
@ -260,6 +266,15 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch)
|
|||||||
return -EINTR;
|
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
|
/* 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 struct inode *inode = filep->f_inode;
|
||||||
FAR uart_dev_t *dev = inode->i_private;
|
FAR uart_dev_t *dev = inode->i_private;
|
||||||
ssize_t nread = buflen;
|
ssize_t nread = buflen;
|
||||||
|
bool oktoblock;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* We may receive console writes through this path from interrupt handlers and
|
/* 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
|
#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.
|
/* 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
|
* we add data to the head of the buffer; uart_xmitchars takes the
|
||||||
* data from the end of the buffer.
|
* 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;
|
ret = OK;
|
||||||
if (dev->isconsole && ch == '\n')
|
if (dev->isconsole && ch == '\n')
|
||||||
{
|
{
|
||||||
ret = uart_putxmitchar(dev, '\r');
|
ret = uart_putxmitchar(dev, '\r', oktoblock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put the character into the transmit buffer */
|
/* Put the character into the transmit buffer */
|
||||||
|
|
||||||
if (ret == OK)
|
if (ret == OK)
|
||||||
{
|
{
|
||||||
ret = uart_putxmitchar(dev, ch);
|
ret = uart_putxmitchar(dev, ch, oktoblock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* uart_putxmitchar() might return an error under one of two
|
/* uart_putxmitchar() might return an error under one of two
|
||||||
* conditions: (1) The wait for buffer space might have been
|
* 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()
|
* CONFIG_SERIAL_REMOVABLE is defined, then uart_putxmitchar()
|
||||||
* might also return if the serial device was disconnected
|
* 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)
|
if (ret < 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user