blob: a68a018e7b73849eba26a2c3e0d7f435fcf6eae1 [file] [log] [blame]
Julius Werner03020da2018-11-27 22:10:56 -08001/*
Zelaleme8dadb12020-02-05 14:12:39 -06002 * Copyright (c) 2018-2020, 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>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00009
Julius Werner03020da2018-11-27 22:10:56 -080010#include <drivers/console.h>
11
12console_t *console_list;
13uint8_t console_state = CONSOLE_FLAG_BOOT;
14
Ambroise Vincenta88a35d2019-02-14 09:48:21 +000015IMPORT_SYM(console_t *, __STACKS_START__, stacks_start)
16IMPORT_SYM(console_t *, __STACKS_END__, stacks_end)
17
Julius Werner03020da2018-11-27 22:10:56 -080018int console_register(console_t *console)
19{
Julius Werner03020da2018-11-27 22:10:56 -080020 /* Assert that the struct is not on the stack (common mistake). */
21 assert((console < stacks_start) || (console >= stacks_end));
Ambroise Vincent29d5c382019-04-18 11:36:42 +010022
23 /* Check that we won't make a circle in the list. */
24 if (console_is_registered(console) == 1)
25 return 1;
Julius Werner03020da2018-11-27 22:10:56 -080026
27 console->next = console_list;
28 console_list = console;
29
30 /* Return 1 for convenient tail-calling from console_xxx_register(). */
31 return 1;
32}
33
34console_t *console_unregister(console_t *to_be_deleted)
35{
36 console_t **ptr;
37
38 assert(to_be_deleted != NULL);
39
40 for (ptr = &console_list; *ptr != NULL; ptr = &(*ptr)->next)
41 if (*ptr == to_be_deleted) {
42 *ptr = (*ptr)->next;
43 return to_be_deleted;
44 }
45
46 return NULL;
47}
48
49int console_is_registered(console_t *to_find)
50{
51 console_t *console;
52
53 assert(to_find != NULL);
54
55 for (console = console_list; console != NULL; console = console->next)
56 if (console == to_find)
57 return 1;
58
59 return 0;
60}
61
62void console_switch_state(unsigned int new_state)
63{
64 console_state = new_state;
65}
66
67void console_set_scope(console_t *console, unsigned int scope)
68{
69 assert(console != NULL);
70
71 console->flags = (console->flags & ~CONSOLE_FLAG_SCOPE_MASK) | scope;
72}
73
Masahiro Yamada269a8ad2019-07-23 12:32:58 +090074static int do_putc(int c, console_t *console)
75{
76 int ret;
77
78 if ((c == '\n') &&
79 ((console->flags & CONSOLE_FLAG_TRANSLATE_CRLF) != 0)) {
80 ret = console->putc('\r', console);
81 if (ret < 0)
82 return ret;
83 }
84
85 return console->putc(c, console);
86}
87
Julius Werner03020da2018-11-27 22:10:56 -080088int console_putc(int c)
89{
90 int err = ERROR_NO_VALID_CONSOLE;
91 console_t *console;
92
93 for (console = console_list; console != NULL; console = console->next)
Zelaleme8dadb12020-02-05 14:12:39 -060094 if ((console->flags & console_state) && (console->putc != NULL)) {
Masahiro Yamada269a8ad2019-07-23 12:32:58 +090095 int ret = do_putc(c, console);
Julius Werner03020da2018-11-27 22:10:56 -080096 if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
97 err = ret;
98 }
99
100 return err;
101}
102
103int console_getc(void)
104{
105 int err = ERROR_NO_VALID_CONSOLE;
106 console_t *console;
107
108 do { /* Keep polling while at least one console works correctly. */
109 for (console = console_list; console != NULL;
110 console = console->next)
Zelaleme8dadb12020-02-05 14:12:39 -0600111 if ((console->flags & console_state) && (console->getc != NULL)) {
Julius Werner03020da2018-11-27 22:10:56 -0800112 int ret = console->getc(console);
113 if (ret >= 0)
114 return ret;
115 if (err != ERROR_NO_PENDING_CHAR)
116 err = ret;
117 }
118 } while (err == ERROR_NO_PENDING_CHAR);
119
120 return err;
121}
122
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500123void console_flush(void)
Julius Werner03020da2018-11-27 22:10:56 -0800124{
Julius Werner03020da2018-11-27 22:10:56 -0800125 console_t *console;
126
127 for (console = console_list; console != NULL; console = console->next)
Zelaleme8dadb12020-02-05 14:12:39 -0600128 if ((console->flags & console_state) && (console->flush != NULL)) {
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500129 console->flush(console);
Julius Werner03020da2018-11-27 22:10:56 -0800130 }
Julius Werner03020da2018-11-27 22:10:56 -0800131}