diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2013-03-18 16:04:29 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2013-03-18 16:04:29 +0000 |
commit | bef7c0ac3dcfd2277e3df45a5767f27187633bb2 (patch) | |
tree | d3a06ff514c73db16cd941d1f8f6c6a03d82ef32 | |
parent | e043d545247953df1980d119fa1a477cbd9f9b18 (diff) | |
download | px4-nuttx-bef7c0ac3dcfd2277e3df45a5767f27187633bb2.tar.gz px4-nuttx-bef7c0ac3dcfd2277e3df45a5767f27187633bb2.tar.bz2 px4-nuttx-bef7c0ac3dcfd2277e3df45a5767f27187633bb2.zip |
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
-rw-r--r-- | nuttx/ChangeLog | 6 | ||||
-rw-r--r-- | nuttx/drivers/serial/serial.c | 36 |
2 files changed, 36 insertions, 6 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index a81b7eb86..10a17a676 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -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. diff --git a/nuttx/drivers/serial/serial.c b/nuttx/drivers/serial/serial.c index e723fb336..912feb255 100644 --- a/nuttx/drivers/serial/serial.c +++ b/nuttx/drivers/serial/serial.c @@ -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) |