blob: c678de09895feb5ab731ab8de41f49742e106b93 [file] [log] [blame]
Julius Werner03020da2018-11-27 22:10:56 -08001/*
2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#if MULTI_CONSOLE_API
8
9#include <assert.h>
10#include <drivers/console.h>
11
12console_t *console_list;
13uint8_t console_state = CONSOLE_FLAG_BOOT;
14
15int console_register(console_t *console)
16{
17 IMPORT_SYM(console_t *, __STACKS_START__, stacks_start)
18 IMPORT_SYM(console_t *, __STACKS_END__, stacks_end)
19
20 /* Assert that the struct is not on the stack (common mistake). */
21 assert((console < stacks_start) || (console >= stacks_end));
22 /* Assert that we won't make a circle in the list. */
23 assert(!console_is_registered(console));
24
25 console->next = console_list;
26 console_list = console;
27
28 /* Return 1 for convenient tail-calling from console_xxx_register(). */
29 return 1;
30}
31
32console_t *console_unregister(console_t *to_be_deleted)
33{
34 console_t **ptr;
35
36 assert(to_be_deleted != NULL);
37
38 for (ptr = &console_list; *ptr != NULL; ptr = &(*ptr)->next)
39 if (*ptr == to_be_deleted) {
40 *ptr = (*ptr)->next;
41 return to_be_deleted;
42 }
43
44 return NULL;
45}
46
47int console_is_registered(console_t *to_find)
48{
49 console_t *console;
50
51 assert(to_find != NULL);
52
53 for (console = console_list; console != NULL; console = console->next)
54 if (console == to_find)
55 return 1;
56
57 return 0;
58}
59
60void console_switch_state(unsigned int new_state)
61{
62 console_state = new_state;
63}
64
65void console_set_scope(console_t *console, unsigned int scope)
66{
67 assert(console != NULL);
68
69 console->flags = (console->flags & ~CONSOLE_FLAG_SCOPE_MASK) | scope;
70}
71
72int console_putc(int c)
73{
74 int err = ERROR_NO_VALID_CONSOLE;
75 console_t *console;
76
77 for (console = console_list; console != NULL; console = console->next)
78 if (console->flags & console_state) {
79 int ret = console->putc(c, console);
80 if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
81 err = ret;
82 }
83
84 return err;
85}
86
87int console_getc(void)
88{
89 int err = ERROR_NO_VALID_CONSOLE;
90 console_t *console;
91
92 do { /* Keep polling while at least one console works correctly. */
93 for (console = console_list; console != NULL;
94 console = console->next)
95 if (console->flags & console_state) {
96 int ret = console->getc(console);
97 if (ret >= 0)
98 return ret;
99 if (err != ERROR_NO_PENDING_CHAR)
100 err = ret;
101 }
102 } while (err == ERROR_NO_PENDING_CHAR);
103
104 return err;
105}
106
107int console_flush(void)
108{
109 int err = ERROR_NO_VALID_CONSOLE;
110 console_t *console;
111
112 for (console = console_list; console != NULL; console = console->next)
113 if (console->flags & console_state) {
114 int ret = console->flush(console);
115 if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
116 err = ret;
117 }
118
119 return err;
120}
121
122#endif /* MULTI_CONSOLE_API */