multi_console.c 2.91 KB
Newer Older
1
/*
2
 * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
3
4
5
6
7
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
8

9
10
11
12
13
#include <drivers/console.h>

console_t *console_list;
uint8_t console_state = CONSOLE_FLAG_BOOT;

14
15
16
IMPORT_SYM(console_t *, __STACKS_START__, stacks_start)
IMPORT_SYM(console_t *, __STACKS_END__, stacks_end)

17
18
19
20
int console_register(console_t *console)
{
	/* Assert that the struct is not on the stack (common mistake). */
	assert((console < stacks_start) || (console >= stacks_end));
21
22
23
24

	/* Check that we won't make a circle in the list. */
	if (console_is_registered(console) == 1)
		return 1;
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

	console->next = console_list;
	console_list = console;

	/* Return 1 for convenient tail-calling from console_xxx_register(). */
	return 1;
}

console_t *console_unregister(console_t *to_be_deleted)
{
	console_t **ptr;

	assert(to_be_deleted != NULL);

	for (ptr = &console_list; *ptr != NULL; ptr = &(*ptr)->next)
		if (*ptr == to_be_deleted) {
			*ptr = (*ptr)->next;
			return to_be_deleted;
		}

	return NULL;
}

int console_is_registered(console_t *to_find)
{
	console_t *console;

	assert(to_find != NULL);

	for (console = console_list; console != NULL; console = console->next)
		if (console == to_find)
			return 1;

	return 0;
}

void console_switch_state(unsigned int new_state)
{
	console_state = new_state;
}

void console_set_scope(console_t *console, unsigned int scope)
{
	assert(console != NULL);

	console->flags = (console->flags & ~CONSOLE_FLAG_SCOPE_MASK) | scope;
}

73
74
75
76
77
78
79
80
81
82
83
84
85
86
static int do_putc(int c, console_t *console)
{
	int ret;

	if ((c == '\n') &&
	    ((console->flags & CONSOLE_FLAG_TRANSLATE_CRLF) != 0)) {
		ret = console->putc('\r', console);
		if (ret < 0)
			return ret;
	}

	return console->putc(c, console);
}

87
88
89
90
91
92
int console_putc(int c)
{
	int err = ERROR_NO_VALID_CONSOLE;
	console_t *console;

	for (console = console_list; console != NULL; console = console->next)
93
		if ((console->flags & console_state) && (console->putc != NULL)) {
94
			int ret = do_putc(c, console);
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
			if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
				err = ret;
		}

	return err;
}

int console_getc(void)
{
	int err = ERROR_NO_VALID_CONSOLE;
	console_t *console;

	do {	/* Keep polling while at least one console works correctly. */
		for (console = console_list; console != NULL;
		     console = console->next)
110
			if ((console->flags & console_state) && (console->getc != NULL)) {
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
				int ret = console->getc(console);
				if (ret >= 0)
					return ret;
				if (err != ERROR_NO_PENDING_CHAR)
					err = ret;
			}
	} while (err == ERROR_NO_PENDING_CHAR);

	return err;
}

int console_flush(void)
{
	int err = ERROR_NO_VALID_CONSOLE;
	console_t *console;

	for (console = console_list; console != NULL; console = console->next)
128
		if ((console->flags & console_state) && (console->flush != NULL)) {
129
130
131
132
133
134
135
			int ret = console->flush(console);
			if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
				err = ret;
		}

	return err;
}