[PATCH 8/8] termios: Make write POSIX compatible
Sebastian Huber
sebastian.huber at embedded-brains.de
Thu Feb 23 14:45:40 UTC 2017
Currenlty only blocking read/write operations are implemented. A
blocking write must transfer at least one character. It should not wait
for the device for the second character and so on.
---
cpukit/libcsupport/src/termios.c | 89 +++++++++++++++++++++++++---------------
1 file changed, 56 insertions(+), 33 deletions(-)
diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c
index d185398..e1bdd0b 100644
--- a/cpukit/libcsupport/src/termios.c
+++ b/cpukit/libcsupport/src/termios.c
@@ -1020,20 +1020,24 @@ startXmit (
/*
* Send characters to device-specific code
*/
-static void
-doTransmit (const char *buf, size_t len, rtems_termios_tty *tty)
+static size_t
+doTransmit (const char *buf, size_t len, rtems_termios_tty *tty,
+ bool wait, bool nextWait)
{
unsigned int newHead;
rtems_termios_device_context *ctx = tty->device_context;
rtems_interrupt_lock_context lock_context;
rtems_status_code sc;
+ size_t todo;
if (tty->handler.mode == TERMIOS_POLLED) {
(*tty->handler.write)(ctx, buf, len);
- return;
+ return len;
}
- while (len) {
+ todo = len;
+
+ while (todo > 0) {
size_t nToCopy;
size_t nAvail;
@@ -1043,18 +1047,27 @@ doTransmit (const char *buf, size_t len, rtems_termios_tty *tty)
newHead -= tty->rawOutBuf.Size;
rtems_termios_device_lock_acquire (ctx, &lock_context);
- while (newHead == tty->rawOutBuf.Tail) {
- tty->rawOutBufState = rob_wait;
- rtems_termios_device_lock_release (ctx, &lock_context);
- sc = rtems_semaphore_obtain(
- tty->rawOutBuf.Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
- if (sc != RTEMS_SUCCESSFUL)
- rtems_fatal_error_occurred (sc);
- rtems_termios_device_lock_acquire (ctx, &lock_context);
+ if (newHead == tty->rawOutBuf.Tail) {
+ if (wait) {
+ do {
+ tty->rawOutBufState = rob_wait;
+ rtems_termios_device_lock_release (ctx, &lock_context);
+ sc = rtems_semaphore_obtain(
+ tty->rawOutBuf.Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ rtems_termios_device_lock_acquire (ctx, &lock_context);
+ } while (newHead == tty->rawOutBuf.Tail);
+
+ wait = nextWait;
+ } else {
+ rtems_termios_device_lock_release (ctx, &lock_context);
+ return len - todo;
+ }
}
/* Determine free space up to current tail or end of ring buffer */
- nToCopy = len;
+ nToCopy = todo;
if (tty->rawOutBuf.Tail > tty->rawOutBuf.Head) {
/* Available space is contiguous from Head to Tail */
nAvail = tty->rawOutBuf.Tail - tty->rawOutBuf.Head - 1;
@@ -1086,22 +1099,24 @@ doTransmit (const char *buf, size_t len, rtems_termios_tty *tty)
rtems_termios_device_lock_release (ctx, &lock_context);
buf += nToCopy;
- len -= nToCopy;
+ todo -= nToCopy;
}
+
+ return len;
}
void
rtems_termios_puts (
const void *_buf, size_t len, struct rtems_termios_tty *tty)
{
- doTransmit (_buf, len, tty);
+ doTransmit (_buf, len, tty, true, true);
}
/*
* Handle output processing
*/
-static void
-oproc (unsigned char c, struct rtems_termios_tty *tty)
+static bool
+oproc (unsigned char c, rtems_termios_tty *tty, bool wait)
{
char buf[8];
size_t len;
@@ -1129,7 +1144,7 @@ oproc (unsigned char c, struct rtems_termios_tty *tty)
case '\r':
if ((tty->termios.c_oflag & ONOCR) && (oldColumn == 0))
- return;
+ return true;
if (tty->termios.c_oflag & OCRNL) {
buf[0] = '\n';
if (tty->termios.c_oflag & ONLRET)
@@ -1170,26 +1185,34 @@ oproc (unsigned char c, struct rtems_termios_tty *tty)
}
tty->column = oldColumn + columnAdj;
- doTransmit (buf, len, tty);
+ return doTransmit (buf, len, tty, wait, true) > 0;
}
static uint32_t
-rtems_termios_write_tty (struct rtems_termios_tty *tty, const char *buffer,
- uint32_t initial_count)
+rtems_termios_write_tty (rtems_termios_tty *tty, const char *buf, uint32_t len)
{
if (tty->termios.c_oflag & OPOST) {
- uint32_t count;
+ uint32_t todo;
+ bool wait;
- count = initial_count;
+ todo = len;
+ wait = true;
- while (count--)
- oproc (*buffer++, tty);
+ while (todo > 0) {
+ if (!oproc (*buf, tty, wait)) {
+ break;
+ }
+
+ ++buf;
+ --todo;
+ wait = false;
+ }
+
+ return len - todo;
} else {
- doTransmit (buffer, initial_count, tty);
+ return doTransmit (buf, len, tty, true, false);
}
-
- return initial_count;
}
rtems_status_code
@@ -1224,10 +1247,10 @@ echo (unsigned char c, struct rtems_termios_tty *tty)
echobuf[0] = '^';
echobuf[1] = c ^ 0x40;
- doTransmit (echobuf, 2, tty);
+ doTransmit (echobuf, 2, tty, true, true);
tty->column += 2;
} else {
- oproc (c, tty);
+ oproc (c, tty, true);
}
}
@@ -1284,18 +1307,18 @@ erase (struct rtems_termios_tty *tty, int lineFlag)
* Back up over the tab
*/
while (tty->column > col) {
- doTransmit ("\b", 1, tty);
+ doTransmit ("\b", 1, tty, true, true);
tty->column--;
}
}
else {
if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
- doTransmit ("\b \b", 3, tty);
+ doTransmit ("\b \b", 3, tty, true, true);
if (tty->column)
tty->column--;
}
if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
- doTransmit ("\b \b", 3, tty);
+ doTransmit ("\b \b", 3, tty, true, true);
if (tty->column)
tty->column--;
}
--
1.8.4.5
More information about the devel
mailing list