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