[PATCH v2 28/28] serial: smh: Implement puts for DM
Sean Anderson
sean.anderson at seco.com
Thu Mar 10 21:50:58 CET 2022
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 at seco.com>
---
Changes in v2:
- New
drivers/serial/serial_semihosting.c | 51 +++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/drivers/serial/serial_semihosting.c b/drivers/serial/serial_semihosting.c
index 706c1aabe1..049dca5428 100644
--- a/drivers/serial/serial_semihosting.c
+++ b/drivers/serial/serial_semihosting.c
@@ -5,9 +5,18 @@
#include <common.h>
#include <dm.h>
+#include <malloc.h>
#include <serial.h>
#include <semihosting.h>
+/**
+ * struct smh_serial_priv - Semihosting serial private data
+ * @outfd: stdout file descriptor (or error)
+ */
+struct smh_serial_priv {
+ int outfd;
+};
+
#if CONFIG_IS_ENABLED(DM_SERIAL)
static int smh_serial_getc(struct udevice *dev)
{
@@ -20,8 +29,40 @@ static int smh_serial_putc(struct udevice *dev, const char ch)
return 0;
}
+static int 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 0;
+ }
+
+ buf = strndup(s, *len);
+ smh_puts(buf);
+ free(buf);
+ return 0;
+ }
+
+ ret = smh_write(priv->outfd, s, *len, &written);
+ *len = written;
+ if (ret)
+ return ret;
+
+ if (written != *len)
+ return -EAGAIN;
+ return 0;
+}
+
static const struct dm_serial_ops smh_serial_ops = {
.putc = smh_serial_putc,
+ .puts = smh_serial_puts,
.getc = smh_serial_getc,
};
@@ -32,10 +73,20 @@ static int smh_serial_bind(struct udevice *dev)
return -ENOENT;
}
+static int smh_serial_probe(struct udevice *dev)
+{
+ struct smh_serial_priv *priv = dev_get_priv(dev);
+
+ priv->outfd = smh_open(":tt", MODE_WRITE);
+ return 0;
+}
+
U_BOOT_DRIVER(smh_serial) = {
.name = "serial_semihosting",
.id = UCLASS_SERIAL,
.bind = smh_serial_bind,
+ .probe = smh_serial_probe,
+ .priv_auto = sizeof(struct smh_serial_priv),
.ops = &smh_serial_ops,
.flags = DM_FLAG_PRE_RELOC,
};
--
2.25.1
More information about the U-Boot
mailing list