From: Simon Glass <sjg@chromium.org>
A single character may result in a stall waiting for user input, which
means that it may request that a string be output. So when the pager is
active we never actually use the devices' putc() methods. Add a special
case so they don't go to wrack and ruin.
As before, the pager is only supported with CONFIG_CONSOLE_MUX enabled.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
common/console.c | 22 +++++++++++++++-------
test/common/pager.c | 40 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+), 7 deletions(-)
@@ -322,14 +322,22 @@ static int console_tstc(int file)
return 0;
}
+static void console_puts_pager(int file, const char *s);
+
static void console_putc_pager(int file, const char c)
{
- int i;
- struct stdio_dev *dev;
+ if (IS_ENABLED(CONFIG_CONSOLE_PAGER) && gd_pager()) {
+ char str[2] = {c, '\0'};
- for_each_console_dev(i, file, dev) {
- if (dev->putc != NULL)
- dev->putc(dev, c);
+ console_puts_pager(file, str);
+ } else {
+ int i;
+ struct stdio_dev *dev;
+
+ for_each_console_dev(i, file, dev) {
+ if (dev->putc != NULL)
+ dev->putc(dev, c);
+ }
}
}
@@ -757,8 +765,8 @@ void putc(const char c)
return pre_console_putc(c);
if (gd->flags & GD_FLG_DEVINIT) {
- /* Send to the standard output */
- fputc(stdout, c);
+ /* Send to the standard output through pager system */
+ console_putc_pager(stdout, c);
} else {
/* Send directly to the handler */
pre_console_putc(c);
@@ -425,3 +425,43 @@ static int pager_test_bypass_mode(struct unit_test_state *uts)
return 0;
}
COMMON_TEST(pager_test_bypass_mode, 0);
+
+/* Test that single character output via putc goes through pager */
+static int pager_test_putc(struct unit_test_state *uts)
+{
+ struct pager *pag;
+ const char *result;
+
+ /* Init pager */
+ ut_assertok(pager_init(&pag, 20, 1024));
+ pager_set_bypass(pag, true);
+
+ /*
+ * Test that individual characters can be posted via pager API
+ * This verifies that console_putc_pager() routes through the pager
+ * system
+ */
+ result = pager_post(pag, true, "A");
+ ut_asserteq_ptr("A", result); /* Bypass mode returns original pointer */
+
+ result = pager_post(pag, true, "\n");
+ ut_asserteq_ptr("\n", result);
+
+ result = pager_post(pag, true, "B");
+ ut_asserteq_ptr("B", result);
+
+ /* Disable bypass to test normal functionality with single chars */
+ pager_set_bypass(pag, false);
+
+ result = pager_post(pag, true, "X");
+ ut_assertnonnull(result);
+ ut_asserteq_str("X", result);
+
+ result = pager_next(pag, true, 0);
+ ut_assertnull(result);
+
+ pager_uninit(pag);
+
+ return 0;
+}
+COMMON_TEST(pager_test_putc, 0);