multi_console.c 2.9 KB

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