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