blob: 1ec81c3c6156f7af830d02d041312393e050f8f0 [file] [log] [blame]
Julius Werner03020da2018-11-27 22:10:56 -08001/*
Joel Hutton698d8352019-01-15 15:40:18 +00002 * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
Julius Werner03020da2018-11-27 22:10:56 -08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#if MULTI_CONSOLE_API
8
9#include <assert.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;
14uint8_t console_state = CONSOLE_FLAG_BOOT;
15
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
75int console_putc(int c)
76{
77 int err = ERROR_NO_VALID_CONSOLE;
78 console_t *console;
79
80 for (console = console_list; console != NULL; console = console->next)
Joel Hutton698d8352019-01-15 15:40:18 +000081 if ((console->flags & console_state) && console->putc) {
Julius Werner03020da2018-11-27 22:10:56 -080082 int ret = console->putc(c, console);
83 if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
84 err = ret;
85 }
86
87 return err;
88}
89
90int console_getc(void)
91{
92 int err = ERROR_NO_VALID_CONSOLE;
93 console_t *console;
94
95 do { /* Keep polling while at least one console works correctly. */
96 for (console = console_list; console != NULL;
97 console = console->next)
Joel Hutton698d8352019-01-15 15:40:18 +000098 if ((console->flags & console_state) && console->getc) {
Julius Werner03020da2018-11-27 22:10:56 -080099 int ret = console->getc(console);
100 if (ret >= 0)
101 return ret;
102 if (err != ERROR_NO_PENDING_CHAR)
103 err = ret;
104 }
105 } while (err == ERROR_NO_PENDING_CHAR);
106
107 return err;
108}
109
110int console_flush(void)
111{
112 int err = ERROR_NO_VALID_CONSOLE;
113 console_t *console;
114
115 for (console = console_list; console != NULL; console = console->next)
Joel Hutton698d8352019-01-15 15:40:18 +0000116 if ((console->flags & console_state) && console->flush) {
Julius Werner03020da2018-11-27 22:10:56 -0800117 int ret = console->flush(console);
118 if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
119 err = ret;
120 }
121
122 return err;
123}
124
125#endif /* MULTI_CONSOLE_API */