forked from Imagelibrary/rtems
termios: Fix input canonical mode
Canonical input processing was broken by
667501a314 as shown by test case
termios09.
Update #3800.
This commit is contained in:
@@ -1337,23 +1337,16 @@ rtems_status_code rtems_termios_register_isig_handler(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Type returned by all input processing (iproc) methods
|
* @brief Type returned by all input processing (iproc) methods
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/**
|
/**
|
||||||
* This indicates that the input character was processed
|
* This indicates that the input processing can continue.
|
||||||
* and the results were placed into the buffer.
|
|
||||||
*/
|
*/
|
||||||
RTEMS_TERMIOS_IPROC_IN_BUFFER,
|
RTEMS_TERMIOS_IPROC_CONTINUE,
|
||||||
/**
|
/**
|
||||||
* This indicates that the input character was processed
|
* This indicates that the input processing is done.
|
||||||
* and the result did not go into the buffer.
|
|
||||||
*/
|
*/
|
||||||
RTEMS_TERMIOS_IPROC_WAS_PROCESSED,
|
RTEMS_TERMIOS_IPROC_DONE,
|
||||||
/**
|
|
||||||
* This indicates that the input character was not processed and
|
|
||||||
* subsequent processing is required.
|
|
||||||
*/
|
|
||||||
RTEMS_TERMIOS_IPROC_WAS_NOT_PROCESSED,
|
|
||||||
/**
|
/**
|
||||||
* This indicates that the character was processed and determined
|
* This indicates that the character was processed and determined
|
||||||
* to be one that requires a signal to be raised (e.g. VINTR or
|
* to be one that requires a signal to be raised (e.g. VINTR or
|
||||||
@@ -1361,7 +1354,7 @@ typedef enum {
|
|||||||
* occur. There is no further processing of this character required and
|
* occur. There is no further processing of this character required and
|
||||||
* the pending read() operation should be interrupted.
|
* the pending read() operation should be interrupted.
|
||||||
*/
|
*/
|
||||||
RTEMS_TERMIOS_IPROC_INTERRUPT_READ
|
RTEMS_TERMIOS_IPROC_INTERRUPT
|
||||||
} rtems_termios_iproc_status_code;
|
} rtems_termios_iproc_status_code;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1379,12 +1372,10 @@ iproc (unsigned char c, struct rtems_termios_tty *tty)
|
|||||||
rtems_termios_isig_status_code rc;
|
rtems_termios_isig_status_code rc;
|
||||||
rc = (*termios_isig_handler)(c, tty);
|
rc = (*termios_isig_handler)(c, tty);
|
||||||
if (rc == RTEMS_TERMIOS_ISIG_INTERRUPT_READ) {
|
if (rc == RTEMS_TERMIOS_ISIG_INTERRUPT_READ) {
|
||||||
return RTEMS_TERMIOS_IPROC_INTERRUPT_READ;
|
return RTEMS_TERMIOS_IPROC_INTERRUPT;
|
||||||
}
|
}
|
||||||
if (rc == RTEMS_TERMIOS_ISIG_WAS_PROCESSED) {
|
|
||||||
return RTEMS_TERMIOS_IPROC_IN_BUFFER;
|
return RTEMS_TERMIOS_IPROC_CONTINUE;
|
||||||
}
|
|
||||||
_Assert(rc == RTEMS_TERMIOS_ISIG_WAS_NOT_PROCESSED);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1394,25 +1385,25 @@ iproc (unsigned char c, struct rtems_termios_tty *tty)
|
|||||||
if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {
|
if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {
|
||||||
if (c == tty->termios.c_cc[VERASE]) {
|
if (c == tty->termios.c_cc[VERASE]) {
|
||||||
erase (tty, 0);
|
erase (tty, 0);
|
||||||
return RTEMS_TERMIOS_IPROC_WAS_PROCESSED;
|
return RTEMS_TERMIOS_IPROC_CONTINUE;
|
||||||
}
|
}
|
||||||
else if (c == tty->termios.c_cc[VKILL]) {
|
else if (c == tty->termios.c_cc[VKILL]) {
|
||||||
erase (tty, 1);
|
erase (tty, 1);
|
||||||
return RTEMS_TERMIOS_IPROC_WAS_PROCESSED;
|
return RTEMS_TERMIOS_IPROC_CONTINUE;
|
||||||
}
|
}
|
||||||
else if (c == tty->termios.c_cc[VEOF]) {
|
else if (c == tty->termios.c_cc[VEOF]) {
|
||||||
return RTEMS_TERMIOS_IPROC_IN_BUFFER;
|
return RTEMS_TERMIOS_IPROC_DONE;
|
||||||
} else if (c == '\n') {
|
} else if (c == '\n') {
|
||||||
if (tty->termios.c_lflag & (ECHO | ECHONL))
|
if (tty->termios.c_lflag & (ECHO | ECHONL))
|
||||||
echo (c, tty);
|
echo (c, tty);
|
||||||
tty->cbuf[tty->ccount++] = c;
|
tty->cbuf[tty->ccount++] = c;
|
||||||
return RTEMS_TERMIOS_IPROC_IN_BUFFER;
|
return RTEMS_TERMIOS_IPROC_DONE;
|
||||||
} else if ((c == tty->termios.c_cc[VEOL]) ||
|
} else if ((c == tty->termios.c_cc[VEOL]) ||
|
||||||
(c == tty->termios.c_cc[VEOL2])) {
|
(c == tty->termios.c_cc[VEOL2])) {
|
||||||
if (tty->termios.c_lflag & ECHO)
|
if (tty->termios.c_lflag & ECHO)
|
||||||
echo (c, tty);
|
echo (c, tty);
|
||||||
tty->cbuf[tty->ccount++] = c;
|
tty->cbuf[tty->ccount++] = c;
|
||||||
return RTEMS_TERMIOS_IPROC_IN_BUFFER;
|
return RTEMS_TERMIOS_IPROC_DONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1425,9 +1416,8 @@ iproc (unsigned char c, struct rtems_termios_tty *tty)
|
|||||||
if (tty->termios.c_lflag & ECHO)
|
if (tty->termios.c_lflag & ECHO)
|
||||||
echo (c, tty);
|
echo (c, tty);
|
||||||
tty->cbuf[tty->ccount++] = c;
|
tty->cbuf[tty->ccount++] = c;
|
||||||
return RTEMS_TERMIOS_IPROC_IN_BUFFER;
|
|
||||||
}
|
}
|
||||||
return RTEMS_TERMIOS_IPROC_WAS_NOT_PROCESSED;
|
return RTEMS_TERMIOS_IPROC_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1456,7 +1446,7 @@ static rtems_termios_iproc_status_code
|
|||||||
siprocPoll (unsigned char c, rtems_termios_tty *tty)
|
siprocPoll (unsigned char c, rtems_termios_tty *tty)
|
||||||
{
|
{
|
||||||
if (c == '\r' && (tty->termios.c_iflag & IGNCR) != 0) {
|
if (c == '\r' && (tty->termios.c_iflag & IGNCR) != 0) {
|
||||||
return RTEMS_TERMIOS_IPROC_WAS_NOT_PROCESSED;
|
return RTEMS_TERMIOS_IPROC_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1476,7 +1466,6 @@ fillBufferPoll (struct rtems_termios_tty *tty)
|
|||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
rtems_termios_iproc_status_code rc;
|
rtems_termios_iproc_status_code rc;
|
||||||
rtems_termios_iproc_status_code retval = RTEMS_TERMIOS_IPROC_WAS_PROCESSED;
|
|
||||||
|
|
||||||
if (tty->termios.c_lflag & ICANON) {
|
if (tty->termios.c_lflag & ICANON) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -1485,12 +1474,8 @@ fillBufferPoll (struct rtems_termios_tty *tty)
|
|||||||
rtems_task_wake_after (1);
|
rtems_task_wake_after (1);
|
||||||
} else {
|
} else {
|
||||||
rc = siprocPoll (n, tty);
|
rc = siprocPoll (n, tty);
|
||||||
if (rc == RTEMS_TERMIOS_IPROC_IN_BUFFER) {
|
if (rc != RTEMS_TERMIOS_IPROC_CONTINUE) {
|
||||||
break;
|
return rc;
|
||||||
}
|
|
||||||
if (rc == RTEMS_TERMIOS_IPROC_INTERRUPT_READ) {
|
|
||||||
retval = RTEMS_TERMIOS_IPROC_INTERRUPT_READ;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1519,9 +1504,8 @@ fillBufferPoll (struct rtems_termios_tty *tty)
|
|||||||
rtems_task_wake_after (1);
|
rtems_task_wake_after (1);
|
||||||
} else {
|
} else {
|
||||||
rc = siprocPoll (n, tty);
|
rc = siprocPoll (n, tty);
|
||||||
if (rc == RTEMS_TERMIOS_IPROC_INTERRUPT_READ) {
|
if (rc != RTEMS_TERMIOS_IPROC_CONTINUE) {
|
||||||
retval = RTEMS_TERMIOS_IPROC_INTERRUPT_READ;
|
return rc;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (tty->ccount >= tty->termios.c_cc[VMIN])
|
if (tty->ccount >= tty->termios.c_cc[VMIN])
|
||||||
break;
|
break;
|
||||||
@@ -1530,7 +1514,7 @@ fillBufferPoll (struct rtems_termios_tty *tty)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return retval;
|
return RTEMS_TERMIOS_IPROC_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1587,20 +1571,17 @@ fillBufferQueue (struct rtems_termios_tty *tty)
|
|||||||
/* continue processing new character */
|
/* continue processing new character */
|
||||||
if (tty->termios.c_lflag & ICANON) {
|
if (tty->termios.c_lflag & ICANON) {
|
||||||
rc = siproc (c, tty);
|
rc = siproc (c, tty);
|
||||||
/* If the read() should be interrupted, return */
|
if (rc != RTEMS_TERMIOS_IPROC_CONTINUE) {
|
||||||
if (rc == RTEMS_TERMIOS_IPROC_INTERRUPT_READ) {
|
return rc;
|
||||||
return RTEMS_TERMIOS_IPROC_INTERRUPT_READ;
|
|
||||||
}
|
|
||||||
/* In canonical mode, input is made available line by line */
|
|
||||||
if (rc == RTEMS_TERMIOS_IPROC_IN_BUFFER) {
|
|
||||||
return RTEMS_TERMIOS_IPROC_IN_BUFFER;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = siproc (c, tty);
|
rc = siproc (c, tty);
|
||||||
/* If the read() should be interrupted, return */
|
|
||||||
if (rc == RTEMS_TERMIOS_IPROC_INTERRUPT_READ) {
|
/* in non-canonical mode only stop on interrupt */
|
||||||
return RTEMS_TERMIOS_IPROC_INTERRUPT_READ;
|
if (rc == RTEMS_TERMIOS_IPROC_INTERRUPT) {
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tty->ccount >= tty->termios.c_cc[VMIN])
|
if (tty->ccount >= tty->termios.c_cc[VMIN])
|
||||||
wait = false;
|
wait = false;
|
||||||
}
|
}
|
||||||
@@ -1635,7 +1616,7 @@ fillBufferQueue (struct rtems_termios_tty *tty)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return RTEMS_TERMIOS_IPROC_WAS_PROCESSED;
|
return RTEMS_TERMIOS_IPROC_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static rtems_status_code
|
static rtems_status_code
|
||||||
@@ -1647,7 +1628,7 @@ rtems_termios_read_tty (
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
rtems_termios_iproc_status_code rc = RTEMS_TERMIOS_IPROC_WAS_PROCESSED;
|
rtems_termios_iproc_status_code rc;
|
||||||
|
|
||||||
count = initial_count;
|
count = initial_count;
|
||||||
|
|
||||||
@@ -1658,6 +1639,8 @@ rtems_termios_read_tty (
|
|||||||
rc = fillBufferPoll (tty);
|
rc = fillBufferPoll (tty);
|
||||||
else
|
else
|
||||||
rc = fillBufferQueue (tty);
|
rc = fillBufferQueue (tty);
|
||||||
|
} else {
|
||||||
|
rc = RTEMS_TERMIOS_IPROC_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1675,7 +1658,7 @@ rtems_termios_read_tty (
|
|||||||
* was interrupted. The isig handler can do nothing, have POSIX behavior
|
* was interrupted. The isig handler can do nothing, have POSIX behavior
|
||||||
* and cause a signal, or a user defined action.
|
* and cause a signal, or a user defined action.
|
||||||
*/
|
*/
|
||||||
if (rc == RTEMS_TERMIOS_IPROC_INTERRUPT_READ) {
|
if (rc == RTEMS_TERMIOS_IPROC_INTERRUPT) {
|
||||||
return RTEMS_INTERRUPTED;
|
return RTEMS_INTERRUPTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user