summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-03-18 16:04:29 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-03-18 16:04:29 +0000
commitbef7c0ac3dcfd2277e3df45a5767f27187633bb2 (patch)
treed3a06ff514c73db16cd941d1f8f6c6a03d82ef32 /nuttx
parente043d545247953df1980d119fa1a477cbd9f9b18 (diff)
downloadpx4-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
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/ChangeLog6
-rw-r--r--nuttx/drivers/serial/serial.c36
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)