diff options
Diffstat (limited to 'cpukit/libcsupport/src/termios.c')
-rw-r--r-- | cpukit/libcsupport/src/termios.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c index 17fa5ef91e..823a2cbe60 100644 --- a/cpukit/libcsupport/src/termios.c +++ b/cpukit/libcsupport/src/termios.c @@ -509,6 +509,73 @@ termios_set_flowctrl(struct rtems_termios_tty *tty) } } +static bool +rtems_termios_can_read (const struct rtems_termios_tty *tty) +{ + if (tty->cindex == tty->ccount) { + if (tty->device.outputUsesInterrupts == TERMIOS_IRQ_DRIVEN) { + return tty->rawInBuf.Head != tty->rawInBuf.Tail; + } else { + return true; + } + } else { + return tty->cindex < tty->ccount; + } +} + +static bool +rtems_termios_can_write (const struct rtems_termios_tty *tty) +{ + /* + * Termios has no non-blocking writes. In case the raw output buffer is + * full, we wait for the interrupt or poll. + */ + return true; +} + +static void +rtems_termios_select_wakeup (struct termios *tty, void *arg) +{ + rtems_id task_id = (rtems_id) arg; + rtems_status_code sc = rtems_event_send (task_id, RTEMS_IOCTL_SELECT_EVENT); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); +} + +static int +rtems_termios_select (struct rtems_termios_tty *tty, + const rtems_ioctl_select_request *request) +{ + int rv = 0; + + rtems_interrupt_level level; + rtems_interrupt_disable(level); + switch (request->kind) { + case RTEMS_IOCTL_SELECT_READ: + if (rtems_termios_can_read (tty)) { + rv = 1; + } else { + tty->tty_rcvwakeup = 0; + tty->tty_rcv.sw_pfn = rtems_termios_select_wakeup; + tty->tty_rcv.sw_arg = (void *) request->request_task_id; + } + break; + case RTEMS_IOCTL_SELECT_WRITE: + if (rtems_termios_can_write (tty)) { + rv = 1; + } else { + tty->tty_snd.sw_pfn = rtems_termios_select_wakeup; + tty->tty_snd.sw_arg = (void *) request->request_task_id; + } + break; + default: + break; + } + rtems_interrupt_enable(level); + + return rv; +} + rtems_status_code rtems_termios_ioctl (void *arg) { @@ -532,6 +599,10 @@ rtems_termios_ioctl (void *arg) } break; + case RTEMS_IOCTL_SELECT: + args->ioctl_return = rtems_termios_select (tty, args->buffer); + break; + case RTEMS_IO_GET_ATTRIBUTES: *(struct termios *)args->buffer = tty->termios; break; |