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