blob: 1210226a15671db1729aaaba441ca7b269f74cb9 [file] [log] [blame]
Julius Werner91b48c92018-11-27 22:10:56 -08001/*
Yann Gautier03bd4812022-12-09 14:30:55 +01002 * Copyright (c) 2018-2023, ARM Limited and Contributors. All rights reserved.
Julius Werner91b48c92018-11-27 22:10:56 -08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Julius Werner91b48c92018-11-27 22:10:56 -08007#include <assert.h>
Claus Pedersen885e2682022-09-12 22:42:58 +00008#include <stddef.h>
Claus Pedersene0b68262022-09-12 23:47:10 +00009#include <stdlib.h>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +000010
Julius Werner91b48c92018-11-27 22:10:56 -080011#include <drivers/console.h>
12
13console_t *console_list;
Maheedhar Bollapalli51df71c2024-04-24 18:25:49 +053014static uint32_t console_state = CONSOLE_FLAG_BOOT;
Julius Werner91b48c92018-11-27 22:10:56 -080015
Ambroise Vincentbde28362019-02-14 09:48:21 +000016IMPORT_SYM(console_t *, __STACKS_START__, stacks_start)
17IMPORT_SYM(console_t *, __STACKS_END__, stacks_end)
18
Julius Werner91b48c92018-11-27 22:10:56 -080019int console_register(console_t *console)
20{
Julius Werner91b48c92018-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 Vincent71892ca2019-04-18 11:36:42 +010023
24 /* Check that we won't make a circle in the list. */
Maheedhar Bollapalli9ded5e82024-04-25 11:14:22 +053025 if (console_is_registered(console) == 1) {
Ambroise Vincent71892ca2019-04-18 11:36:42 +010026 return 1;
Maheedhar Bollapalli9ded5e82024-04-25 11:14:22 +053027 }
Julius Werner91b48c92018-11-27 22:10:56 -080028
29 console->next = console_list;
30 console_list = console;
31
32 /* Return 1 for convenient tail-calling from console_xxx_register(). */
33 return 1;
34}
35
36console_t *console_unregister(console_t *to_be_deleted)
37{
38 console_t **ptr;
39
40 assert(to_be_deleted != NULL);
41
42 for (ptr = &console_list; *ptr != NULL; ptr = &(*ptr)->next)
43 if (*ptr == to_be_deleted) {
44 *ptr = (*ptr)->next;
45 return to_be_deleted;
46 }
47
48 return NULL;
49}
50
51int console_is_registered(console_t *to_find)
52{
53 console_t *console;
54
55 assert(to_find != NULL);
56
Maheedhar Bollapalli9ded5e82024-04-25 11:14:22 +053057 for (console = console_list; console != NULL; console = console->next) {
58 if (console == to_find) {
Julius Werner91b48c92018-11-27 22:10:56 -080059 return 1;
Maheedhar Bollapalli9ded5e82024-04-25 11:14:22 +053060 }
61 }
Julius Werner91b48c92018-11-27 22:10:56 -080062
63 return 0;
64}
65
66void console_switch_state(unsigned int new_state)
67{
68 console_state = new_state;
69}
70
71void console_set_scope(console_t *console, unsigned int scope)
72{
73 assert(console != NULL);
74
75 console->flags = (console->flags & ~CONSOLE_FLAG_SCOPE_MASK) | scope;
76}
77
Masahiro Yamadaf51df472019-07-23 12:32:58 +090078static int do_putc(int c, console_t *console)
79{
80 int ret;
81
Nithin G97eefd92024-04-23 17:54:08 +053082 if ((c == (int)'\n') &&
83 ((console->flags & CONSOLE_FLAG_TRANSLATE_CRLF) != 0U)) {
Masahiro Yamadaf51df472019-07-23 12:32:58 +090084 ret = console->putc('\r', console);
85 if (ret < 0)
86 return ret;
87 }
88
89 return console->putc(c, console);
90}
91
Julius Werner91b48c92018-11-27 22:10:56 -080092int console_putc(int c)
93{
94 int err = ERROR_NO_VALID_CONSOLE;
95 console_t *console;
96
Maheedhar Bollapalli9ded5e82024-04-25 11:14:22 +053097 for (console = console_list; console != NULL; console = console->next) {
Maheedhar Bollapalli5bbe4fd2024-04-24 13:16:11 +053098 if (((console->flags & console_state) != 0U) && (console->putc != NULL)) {
Masahiro Yamadaf51df472019-07-23 12:32:58 +090099 int ret = do_putc(c, console);
Maheedhar Bollapalli9ded5e82024-04-25 11:14:22 +0530100 if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err)) {
Julius Werner91b48c92018-11-27 22:10:56 -0800101 err = ret;
Maheedhar Bollapalli9ded5e82024-04-25 11:14:22 +0530102 }
Julius Werner91b48c92018-11-27 22:10:56 -0800103 }
Maheedhar Bollapalli9ded5e82024-04-25 11:14:22 +0530104 }
Julius Werner91b48c92018-11-27 22:10:56 -0800105 return err;
106}
107
Claus Pedersene0b68262022-09-12 23:47:10 +0000108int putchar(int c)
109{
Maheedhar Bollapalli9ded5e82024-04-25 11:14:22 +0530110 if (console_putc(c) == 0) {
Claus Pedersene0b68262022-09-12 23:47:10 +0000111 return c;
Maheedhar Bollapalli9ded5e82024-04-25 11:14:22 +0530112 } else {
Claus Pedersene0b68262022-09-12 23:47:10 +0000113 return EOF;
Maheedhar Bollapalli9ded5e82024-04-25 11:14:22 +0530114 }
Claus Pedersene0b68262022-09-12 23:47:10 +0000115}
116
Sandrine Bailleux85bebe12023-10-11 08:38:00 +0200117#if ENABLE_CONSOLE_GETC
Julius Werner91b48c92018-11-27 22:10:56 -0800118int console_getc(void)
119{
120 int err = ERROR_NO_VALID_CONSOLE;
121 console_t *console;
122
123 do { /* Keep polling while at least one console works correctly. */
124 for (console = console_list; console != NULL;
125 console = console->next)
Maheedhar Bollapalli5bbe4fd2024-04-24 13:16:11 +0530126 if (((console->flags & console_state) != 0U) && (console->getc != NULL)) {
Julius Werner91b48c92018-11-27 22:10:56 -0800127 int ret = console->getc(console);
Maheedhar Bollapalli9ded5e82024-04-25 11:14:22 +0530128 if (ret >= 0) {
Julius Werner91b48c92018-11-27 22:10:56 -0800129 return ret;
Maheedhar Bollapalli9ded5e82024-04-25 11:14:22 +0530130 }
131 if (err != ERROR_NO_PENDING_CHAR) {
Julius Werner91b48c92018-11-27 22:10:56 -0800132 err = ret;
Maheedhar Bollapalli9ded5e82024-04-25 11:14:22 +0530133 }
Julius Werner91b48c92018-11-27 22:10:56 -0800134 }
135 } while (err == ERROR_NO_PENDING_CHAR);
136
137 return err;
138}
Sandrine Bailleux85bebe12023-10-11 08:38:00 +0200139#endif
Julius Werner91b48c92018-11-27 22:10:56 -0800140
Jimmy Brisson831b0e92020-08-05 13:44:05 -0500141void console_flush(void)
Julius Werner91b48c92018-11-27 22:10:56 -0800142{
Julius Werner91b48c92018-11-27 22:10:56 -0800143 console_t *console;
144
145 for (console = console_list; console != NULL; console = console->next)
Maheedhar Bollapalli5bbe4fd2024-04-24 13:16:11 +0530146 if (((console->flags & console_state) != 0U) && (console->flush != NULL)) {
Jimmy Brisson831b0e92020-08-05 13:44:05 -0500147 console->flush(console);
Julius Werner91b48c92018-11-27 22:10:56 -0800148 }
Julius Werner91b48c92018-11-27 22:10:56 -0800149}