blob: e962fff3734002235539576d51beb43cc8d69653 [file] [log] [blame]
Julius Werner03020da2018-11-27 22:10:56 -08001/*
Yann Gautier0d5ca3d2022-12-09 14:30:55 +01002 * Copyright (c) 2018-2023, ARM Limited and Contributors. All rights reserved.
Julius Werner03020da2018-11-27 22:10:56 -08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Julius Werner03020da2018-11-27 22:10:56 -08007#include <assert.h>
Claus Pedersen785e66c2022-09-12 22:42:58 +00008#include <stddef.h>
Claus Pedersen63f75862022-09-12 23:47:10 +00009#include <stdlib.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010
Julius Werner03020da2018-11-27 22:10:56 -080011#include <drivers/console.h>
12
13console_t *console_list;
Yann Gautier0d5ca3d2022-12-09 14:30:55 +010014static uint8_t console_state = CONSOLE_FLAG_BOOT;
Julius Werner03020da2018-11-27 22:10:56 -080015
Ambroise Vincenta88a35d2019-02-14 09:48:21 +000016IMPORT_SYM(console_t *, __STACKS_START__, stacks_start)
17IMPORT_SYM(console_t *, __STACKS_END__, stacks_end)
18
Julius Werner03020da2018-11-27 22:10:56 -080019int console_register(console_t *console)
20{
Julius Werner03020da2018-11-27 22:10:56 -080021 /* Assert that the struct is not on the stack (common mistake). */
22 assert((console < stacks_start) || (console >= stacks_end));
Ambroise Vincent29d5c382019-04-18 11:36:42 +010023
24 /* Check that we won't make a circle in the list. */
25 if (console_is_registered(console) == 1)
26 return 1;
Julius Werner03020da2018-11-27 22:10:56 -080027
28 console->next = console_list;
29 console_list = console;
30
31 /* Return 1 for convenient tail-calling from console_xxx_register(). */
32 return 1;
33}
34
35console_t *console_unregister(console_t *to_be_deleted)
36{
37 console_t **ptr;
38
39 assert(to_be_deleted != NULL);
40
41 for (ptr = &console_list; *ptr != NULL; ptr = &(*ptr)->next)
42 if (*ptr == to_be_deleted) {
43 *ptr = (*ptr)->next;
44 return to_be_deleted;
45 }
46
47 return NULL;
48}
49
50int console_is_registered(console_t *to_find)
51{
52 console_t *console;
53
54 assert(to_find != NULL);
55
56 for (console = console_list; console != NULL; console = console->next)
57 if (console == to_find)
58 return 1;
59
60 return 0;
61}
62
63void console_switch_state(unsigned int new_state)
64{
65 console_state = new_state;
66}
67
68void console_set_scope(console_t *console, unsigned int scope)
69{
70 assert(console != NULL);
71
72 console->flags = (console->flags & ~CONSOLE_FLAG_SCOPE_MASK) | scope;
73}
74
Masahiro Yamada269a8ad2019-07-23 12:32:58 +090075static int do_putc(int c, console_t *console)
76{
77 int ret;
78
79 if ((c == '\n') &&
80 ((console->flags & CONSOLE_FLAG_TRANSLATE_CRLF) != 0)) {
81 ret = console->putc('\r', console);
82 if (ret < 0)
83 return ret;
84 }
85
86 return console->putc(c, console);
87}
88
Julius Werner03020da2018-11-27 22:10:56 -080089int console_putc(int c)
90{
91 int err = ERROR_NO_VALID_CONSOLE;
92 console_t *console;
93
94 for (console = console_list; console != NULL; console = console->next)
Zelaleme8dadb12020-02-05 14:12:39 -060095 if ((console->flags & console_state) && (console->putc != NULL)) {
Masahiro Yamada269a8ad2019-07-23 12:32:58 +090096 int ret = do_putc(c, console);
Julius Werner03020da2018-11-27 22:10:56 -080097 if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
98 err = ret;
99 }
Julius Werner03020da2018-11-27 22:10:56 -0800100 return err;
101}
102
Claus Pedersen63f75862022-09-12 23:47:10 +0000103int putchar(int c)
104{
105 if (console_putc(c) == 0)
106 return c;
107 else
108 return EOF;
109}
110
Sandrine Bailleuxf57e2032023-10-11 08:38:00 +0200111#if ENABLE_CONSOLE_GETC
Julius Werner03020da2018-11-27 22:10:56 -0800112int console_getc(void)
113{
114 int err = ERROR_NO_VALID_CONSOLE;
115 console_t *console;
116
117 do { /* Keep polling while at least one console works correctly. */
118 for (console = console_list; console != NULL;
119 console = console->next)
Zelaleme8dadb12020-02-05 14:12:39 -0600120 if ((console->flags & console_state) && (console->getc != NULL)) {
Julius Werner03020da2018-11-27 22:10:56 -0800121 int ret = console->getc(console);
122 if (ret >= 0)
123 return ret;
124 if (err != ERROR_NO_PENDING_CHAR)
125 err = ret;
126 }
127 } while (err == ERROR_NO_PENDING_CHAR);
128
129 return err;
130}
Sandrine Bailleuxf57e2032023-10-11 08:38:00 +0200131#endif
Julius Werner03020da2018-11-27 22:10:56 -0800132
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500133void console_flush(void)
Julius Werner03020da2018-11-27 22:10:56 -0800134{
Julius Werner03020da2018-11-27 22:10:56 -0800135 console_t *console;
136
137 for (console = console_list; console != NULL; console = console->next)
Zelaleme8dadb12020-02-05 14:12:39 -0600138 if ((console->flags & console_state) && (console->flush != NULL)) {
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500139 console->flush(console);
Julius Werner03020da2018-11-27 22:10:56 -0800140 }
Julius Werner03020da2018-11-27 22:10:56 -0800141}