123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- /*
- * Copyright (c) 2018-2023, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <assert.h>
- #include <stddef.h>
- #include <stdlib.h>
- #include <drivers/console.h>
- console_t *console_list;
- static uint8_t console_state = CONSOLE_FLAG_BOOT;
- IMPORT_SYM(console_t *, __STACKS_START__, stacks_start)
- IMPORT_SYM(console_t *, __STACKS_END__, stacks_end)
- int console_register(console_t *console)
- {
- /* Assert that the struct is not on the stack (common mistake). */
- assert((console < stacks_start) || (console >= stacks_end));
- /* Check that we won't make a circle in the list. */
- if (console_is_registered(console) == 1)
- return 1;
- 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;
- }
- 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);
- }
- int console_putc(int c)
- {
- int err = ERROR_NO_VALID_CONSOLE;
- console_t *console;
- for (console = console_list; console != NULL; console = console->next)
- if ((console->flags & console_state) && (console->putc != NULL)) {
- int ret = do_putc(c, console);
- if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
- err = ret;
- }
- return err;
- }
- int putchar(int c)
- {
- if (console_putc(c) == 0)
- return c;
- else
- return EOF;
- }
- #if ENABLE_CONSOLE_GETC
- 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)
- if ((console->flags & console_state) && (console->getc != NULL)) {
- 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;
- }
- #endif
- void console_flush(void)
- {
- console_t *console;
- for (console = console_list; console != NULL; console = console->next)
- if ((console->flags & console_state) && (console->flush != NULL)) {
- console->flush(console);
- }
- }
|