diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/Kconfig | 2 | ||||
-rw-r--r-- | drivers/serial/sandbox.c | 48 | ||||
-rw-r--r-- | drivers/serial/serial-uclass.c | 32 | ||||
-rw-r--r-- | drivers/serial/serial_semihosting.c | 31 |
4 files changed, 101 insertions, 12 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 286c99800f0..dc514c95d33 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -779,6 +779,7 @@ config S5P_SERIAL config SANDBOX_SERIAL bool "Sandbox UART support" depends on SANDBOX + imply SERIAL_PUTS help Select this to enable a seral UART for sandbox. This is required to operate correctly, otherwise you will see no serial output from @@ -833,6 +834,7 @@ config SH_SCIF_CLK_FREQ config SEMIHOSTING_SERIAL bool "Semihosting UART support" depends on SEMIHOSTING && !SERIAL_RX_BUFFER + imply SERIAL_PUTS help Select this to enable a serial UART using semihosting. Special halt instructions will be issued which an external debugger (such as a diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index 0b1756f5c0c..e726e19c46f 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -23,6 +23,19 @@ DECLARE_GLOBAL_DATA_PTR; +static size_t _sandbox_serial_written = 1; +static bool sandbox_serial_enabled = true; + +size_t sandbox_serial_written(void) +{ + return _sandbox_serial_written; +} + +void sandbox_serial_endisable(bool enabled) +{ + sandbox_serial_enabled = enabled; +} + /** * output_ansi_colour() - Output an ANSI colour code * @@ -67,7 +80,7 @@ static int sandbox_serial_remove(struct udevice *dev) return 0; } -static int sandbox_serial_putc(struct udevice *dev, const char ch) +static void sandbox_print_color(struct udevice *dev) { struct sandbox_serial_priv *priv = dev_get_priv(dev); struct sandbox_serial_plat *plat = dev_get_plat(dev); @@ -78,14 +91,44 @@ static int sandbox_serial_putc(struct udevice *dev, const char ch) priv->start_of_line = false; output_ansi_colour(plat->colour); } +} + +static int sandbox_serial_putc(struct udevice *dev, const char ch) +{ + struct sandbox_serial_priv *priv = dev_get_priv(dev); - os_write(1, &ch, 1); if (ch == '\n') priv->start_of_line = true; + if (sandbox_serial_enabled) { + sandbox_print_color(dev); + os_write(1, &ch, 1); + } + _sandbox_serial_written += 1; return 0; } +static ssize_t sandbox_serial_puts(struct udevice *dev, const char *s, + size_t len) +{ + struct sandbox_serial_priv *priv = dev_get_priv(dev); + ssize_t ret; + + if (s[len - 1] == '\n') + priv->start_of_line = true; + + if (sandbox_serial_enabled) { + sandbox_print_color(dev); + ret = os_write(1, s, len); + if (ret < 0) + return ret; + } else { + ret = len; + } + _sandbox_serial_written += ret; + return ret; +} + static int sandbox_serial_pending(struct udevice *dev, bool input) { struct sandbox_serial_priv *priv = dev_get_priv(dev); @@ -212,6 +255,7 @@ static int sandbox_serial_of_to_plat(struct udevice *dev) static const struct dm_serial_ops sandbox_serial_ops = { .putc = sandbox_serial_putc, + .puts = sandbox_serial_puts, .pending = sandbox_serial_pending, .getc = sandbox_serial_getc, .getconfig = sandbox_serial_getconfig, diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 10d6b800e2f..30650e37b0d 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -198,6 +198,22 @@ static void _serial_putc(struct udevice *dev, char ch) } while (err == -EAGAIN); } +static int __serial_puts(struct udevice *dev, const char *str, size_t len) +{ + struct dm_serial_ops *ops = serial_get_ops(dev); + + do { + ssize_t written = ops->puts(dev, str, len); + + if (written < 0) + return written; + str += written; + len -= written; + } while (len); + + return 0; +} + static void _serial_puts(struct udevice *dev, const char *str) { struct dm_serial_ops *ops = serial_get_ops(dev); @@ -210,19 +226,15 @@ static void _serial_puts(struct udevice *dev, const char *str) do { const char *newline = strchrnul(str, '\n'); - size_t len = newline - str + !!*newline; + size_t len = newline - str; - do { - ssize_t written = ops->puts(dev, str, len); + if (__serial_puts(dev, str, len)) + return; - if (written < 0) - return; - str += written; - len -= written; - } while (len); + if (*newline && __serial_puts(dev, "\r\n", 2)) + return; - if (*newline) - _serial_putc(dev, '\r'); + str += len + !!*newline; } while (*str); } diff --git a/drivers/serial/serial_semihosting.c b/drivers/serial/serial_semihosting.c index 62b1b2241b3..4328b3dac5b 100644 --- a/drivers/serial/serial_semihosting.c +++ b/drivers/serial/serial_semihosting.c @@ -5,12 +5,14 @@ #include <common.h> #include <dm.h> +#include <malloc.h> #include <serial.h> #include <semihosting.h> /** * struct smh_serial_priv - Semihosting serial private data * @infd: stdin file descriptor (or error) + * @outfd: stdout file descriptor (or error) */ struct smh_serial_priv { int infd; @@ -36,8 +38,36 @@ static int smh_serial_putc(struct udevice *dev, const char ch) return 0; } +static ssize_t smh_serial_puts(struct udevice *dev, const char *s, size_t len) +{ + int ret; + struct smh_serial_priv *priv = dev_get_priv(dev); + unsigned long written; + + if (priv->outfd < 0) { + char *buf; + + /* Try and avoid a copy if we can */ + if (!s[len + 1]) { + smh_puts(s); + return len; + } + + buf = strndup(s, len); + smh_puts(buf); + free(buf); + return len; + } + + ret = smh_write(priv->outfd, s, len, &written); + if (written) + return written; + return ret; +} + static const struct dm_serial_ops smh_serial_ops = { .putc = smh_serial_putc, + .puts = smh_serial_puts, .getc = smh_serial_getc, }; @@ -53,6 +83,7 @@ static int smh_serial_probe(struct udevice *dev) struct smh_serial_priv *priv = dev_get_priv(dev); priv->infd = smh_open(":tt", MODE_READ); + priv->outfd = smh_open(":tt", MODE_WRITE); return 0; } |