From: Simon Glass <simon.glass@canonical.com>
Add an optional putsn() method to struct stdio_dev to allow devices to
provide optimised length-based output. The field is added
unconditionally but only used when CONFIG_CONSOLE_PUTSN is enabled.
Add console_putsn_pager() and fputsn() to route length-based output
through console devices. If a device provides a putsn method, it is
used; otherwise, the output falls back to calling putc in a loop.
Co-developed-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---
common/console.c | 31 ++++++++++++++++++++++++-------
include/stdio_dev.h | 12 ++++++++++++
2 files changed, 36 insertions(+), 7 deletions(-)
@@ -271,6 +271,7 @@ static int console_tstc(int file)
}
static void console_puts_pager(int file, const char *s);
+static void console_putsn_pager(int file, const char *s, int len);
static void console_putc_pager(int file, const char c)
{
@@ -355,18 +356,28 @@ static void console_puts(int file, bool use_pager, const char *s)
}
}
+static void console_putsn_pager(int file, const char *s, int len)
+{
+ struct stdio_dev *dev;
+ int i;
+
+ for_each_console_dev(i, file, dev) {
+ if (dev->putsn)
+ dev->putsn(dev, s, len);
+ else if (dev->puts)
+ dev->puts(dev, s);
+ else
+ while (len--)
+ dev->putc(dev, *s++);
+ }
+}
+
static void console_puts_pager(int file, const char *s)
{
if (IS_ENABLED(CONFIG_CONSOLE_PAGER) && gd_pager()) {
console_puts(file, true, s);
} else {
- struct stdio_dev *dev;
- int i;
-
- for_each_console_dev(i, file, dev) {
- if (dev->puts != NULL)
- dev->puts(dev, s);
- }
+ console_putsn_pager(file, s, strlen(s));
}
}
@@ -629,6 +640,12 @@ void fputs(int file, const char *s)
console_puts_pager(file, s);
}
+void fputsn(int file, const char *s, int len)
+{
+ if ((unsigned int)file < MAX_FILES)
+ console_putsn_pager(file, s, len);
+}
+
#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
void fflush(int file)
{
@@ -38,6 +38,18 @@ struct stdio_dev {
void (*putc)(struct stdio_dev *dev, const char c);
/* To put a string (accelerator) */
void (*puts)(struct stdio_dev *dev, const char *s);
+ /**
+ * putsn() - Output a string with specified length
+ *
+ * This outputs exactly @len characters from @s, regardless of any nul
+ * characters that may be present. This is an optional accelerator - if
+ * NULL, the console will fall back to calling putc() in a loop.
+ *
+ * @dev: Device to output to
+ * @s: String to output (need not be nul-terminated)
+ * @len: Number of characters to output
+ */
+ void (*putsn)(struct stdio_dev *dev, const char *s, int len);
#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
/* To flush output queue */
void (*flush)(struct stdio_dev *dev);