1 /* 2 * Copyright (c) 2018, 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 int console_register(console_t *console) 17 { 18 IMPORT_SYM(console_t *, __STACKS_START__, stacks_start) 19 IMPORT_SYM(console_t *, __STACKS_END__, stacks_end) 20 21 /* Assert that the struct is not on the stack (common mistake). */ 22 assert((console < stacks_start) || (console >= stacks_end)); 23 /* Assert that we won't make a circle in the list. */ 24 assert(!console_is_registered(console)); 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 int console_putc(int c) 74 { 75 int err = ERROR_NO_VALID_CONSOLE; 76 console_t *console; 77 78 for (console = console_list; console != NULL; console = console->next) 79 if (console->flags & console_state) { 80 int ret = console->putc(c, console); 81 if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err)) 82 err = ret; 83 } 84 85 return err; 86 } 87 88 int console_getc(void) 89 { 90 int err = ERROR_NO_VALID_CONSOLE; 91 console_t *console; 92 93 do { /* Keep polling while at least one console works correctly. */ 94 for (console = console_list; console != NULL; 95 console = console->next) 96 if (console->flags & console_state) { 97 int ret = console->getc(console); 98 if (ret >= 0) 99 return ret; 100 if (err != ERROR_NO_PENDING_CHAR) 101 err = ret; 102 } 103 } while (err == ERROR_NO_PENDING_CHAR); 104 105 return err; 106 } 107 108 int console_flush(void) 109 { 110 int err = ERROR_NO_VALID_CONSOLE; 111 console_t *console; 112 113 for (console = console_list; console != NULL; console = console->next) 114 if (console->flags & console_state) { 115 int ret = console->flush(console); 116 if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err)) 117 err = ret; 118 } 119 120 return err; 121 } 122 123 #endif /* MULTI_CONSOLE_API */ 124