From 6203020bfd7985eae9c7f6de02247d937fdd28af Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Tue, 23 Oct 2018 21:15:46 +0300 Subject: [PATCH] subsys: console: Switch to POSIX-like read/write interface Tty device gets only read/write calls, but console retains getchar/putchar for convenience. Signed-off-by: Paul Sokolovsky --- include/console.h | 58 +++++++++++++++++++++++++++------- subsys/console/getchar.c | 31 ++++++++++++++++--- subsys/console/tty.c | 67 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 136 insertions(+), 20 deletions(-) diff --git a/include/console.h b/include/console.h index ce3425be2e4..88e3df7c314 100644 --- a/include/console.h +++ b/include/console.h @@ -7,6 +7,7 @@ #ifndef ZEPHYR_INCLUDE_CONSOLE_H_ #define ZEPHYR_INCLUDE_CONSOLE_H_ +#include #include #include @@ -79,24 +80,31 @@ static inline void tty_set_tx_timeout(struct tty_serial *tty, s32_t timeout) } /** - * @brief Input a character from a tty device. + * @brief Read data from a tty device. * * @param tty tty device structure - * @return >=0, an input character - * <0, an error (e.g. -EAGAIN if timeout expired) + * @param buf buffer to read data to + * @param size maximum number of bytes to read + * @return >0, number of actually read bytes (can be less than size param) + * =0, for EOF-like condition (e.g., break signalled) + * <0, in case of error (e.g. -EAGAIN if timeout expired). errno + * variable is also set. */ -int tty_getchar(struct tty_serial *tty); +ssize_t tty_read(struct tty_serial *tty, void *buf, size_t size); /** - * @brief Output a character from to tty device. + * @brief Write data to tty device. * * @param tty tty device structure - * @param c character to output - * @return 0 if ok, <0 if error + * @param buf buffer containg data + * @param size maximum number of bytes to write + * @return =>0, number of actually written bytes (can be less than size param) + * <0, in case of error (e.g. -EAGAIN if timeout expired). errno + * variable is also set. */ -int tty_putchar(struct tty_serial *tty, u8_t c); +ssize_t tty_write(struct tty_serial *tty, const void *buf, size_t size); -/** @brief Initialize console_getchar()/putchar() calls. +/** @brief Initialize console device. * * This function should be called once to initialize pull-style * access to console via console_getchar() function and buffered @@ -108,6 +116,31 @@ int tty_putchar(struct tty_serial *tty, u8_t c); */ void console_init(void); +/** + * @brief Read data from console. + * + * @param dummy ignored, present to follow read() prototype + * @param buf buffer to read data to + * @param size maximum number of bytes to read + * @return >0, number of actually read bytes (can be less than size param) + * =0, in case of EOF + * <0, in case of error (e.g. -EAGAIN if timeout expired). errno + * variable is also set. + */ +ssize_t console_read(void *dummy, void *buf, size_t size); + +/** + * @brief Write data to console. + * + * @param dummy ignored, present to follow write() prototype + * @param buf buffer to write data to + * @param size maximum number of bytes to write + * @return =>0, number of actually written bytes (can be less than size param) + * <0, in case of error (e.g. -EAGAIN if timeout expired). errno + * variable is also set. + */ +ssize_t console_write(void *dummy, const void *buf, size_t size); + /** @brief Get next char from console input buffer. * * Return next input character from console. If no characters available, @@ -118,16 +151,17 @@ void console_init(void); * Zephyr callback-based console input processing, shell subsystem, * or console_getline(). * - * @return A character read, including control characters. + * @return 0-255: a character read, including control characters. + * <0: error occured. */ -u8_t console_getchar(void); +int console_getchar(void); /** @brief Output a char to console (buffered). * * Puts a character into console output buffer. It will be sent * to a console asynchronously, e.g. using an IRQ handler. * - * @return -1 on output buffer overflow, otherwise 0. + * @return <0 on error, otherwise 0. */ int console_putchar(char c); diff --git a/subsys/console/getchar.c b/subsys/console/getchar.c index 6b313563be5..aa4d9085ee2 100644 --- a/subsys/console/getchar.c +++ b/subsys/console/getchar.c @@ -13,15 +13,36 @@ static struct tty_serial console_serial; static u8_t console_rxbuf[CONFIG_CONSOLE_GETCHAR_BUFSIZE]; static u8_t console_txbuf[CONFIG_CONSOLE_PUTCHAR_BUFSIZE]; -int console_putchar(char c) +ssize_t console_write(void *dummy, const void *buf, size_t size) { - return tty_putchar(&console_serial, (u8_t)c); + ARG_UNUSED(dummy); + + return tty_write(&console_serial, buf, size); } -u8_t console_getchar(void) +ssize_t console_read(void *dummy, void *buf, size_t size) { - /* Console works in blocking mode, so we don't expect an error here */ - return (u8_t)tty_getchar(&console_serial); + ARG_UNUSED(dummy); + + return tty_read(&console_serial, buf, size); +} + +int console_putchar(char c) +{ + return tty_write(&console_serial, &c, 1); +} + +int console_getchar(void) +{ + u8_t c; + int res; + + res = tty_read(&console_serial, &c, 1); + if (res < 0) { + return res; + } + + return c; } void console_init(void) diff --git a/subsys/console/tty.c b/subsys/console/tty.c index d4fd5d48b6c..31b475a909d 100644 --- a/subsys/console/tty.c +++ b/subsys/console/tty.c @@ -69,7 +69,7 @@ static int tty_irq_input_hook(struct tty_serial *tty, u8_t c) return 1; } -int tty_putchar(struct tty_serial *tty, u8_t c) +static int tty_putchar(struct tty_serial *tty, u8_t c) { unsigned int key; int tx_next; @@ -87,7 +87,7 @@ int tty_putchar(struct tty_serial *tty, u8_t c) } if (tx_next == tty->tx_get) { irq_unlock(key); - return -1; + return -ENOSPC; } tty->tx_ringbuf[tty->tx_put] = c; @@ -98,7 +98,37 @@ int tty_putchar(struct tty_serial *tty, u8_t c) return 0; } -int tty_getchar(struct tty_serial *tty) +ssize_t tty_write(struct tty_serial *tty, const void *buf, size_t size) +{ + const u8_t *p = buf; + size_t out_size = 0; + int res = 0; + + while (size--) { + res = tty_putchar(tty, *p++); + if (res < 0) { + /* If we didn't transmit anything, return the error. */ + if (out_size == 0) { + errno = -res; + return res; + } + + /* + * Otherwise, return how much we transmitted. If error + * was transient (like EAGAIN), on next call user might + * not even get it. And if it's non-transient, they'll + * get it on the next call. + */ + return out_size; + } + + out_size++; + } + + return out_size; +} + +static int tty_getchar(struct tty_serial *tty) { unsigned int key; u8_t c; @@ -119,6 +149,37 @@ int tty_getchar(struct tty_serial *tty) return c; } +ssize_t tty_read(struct tty_serial *tty, void *buf, size_t size) +{ + u8_t *p = buf; + size_t out_size = 0; + int res = 0; + + while (size--) { + res = tty_getchar(tty); + if (res < 0) { + /* If we didn't transmit anything, return the error. */ + if (out_size == 0) { + errno = -res; + return res; + } + + /* + * Otherwise, return how much we transmitted. If error + * was transient (like EAGAIN), on next call user might + * not even get it. And if it's non-transient, they'll + * get it on the next call. + */ + return out_size; + } + + *p++ = (u8_t)res; + out_size++; + } + + return out_size; +} + void tty_init(struct tty_serial *tty, struct device *uart_dev, u8_t *rxbuf, u16_t rxbuf_sz, u8_t *txbuf, u16_t txbuf_sz)