serial: smh: Implement puts for DM
authorSean Anderson <sean.anderson@seco.com>
Mon, 4 Apr 2022 18:18:00 +0000 (14:18 -0400)
committerTom Rini <trini@konsulko.com>
Thu, 14 Apr 2022 19:39:15 +0000 (15:39 -0400)
This adds an implementation of puts for DM. The implementation is not as
clean as for the non-DM puts because we have to handle non-nul-terminated
string. We also handle short writes (though these are probably very
unusual).

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
drivers/serial/Kconfig
drivers/serial/serial_semihosting.c

index 6b189f8..dc514c9 100644 (file)
@@ -834,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
index 62b1b22..4328b3d 100644 (file)
@@ -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;
 }