1 | // SPDX-License-Identifier: GPL-3.0-or-later |
2 | |
3 | #pragma once |
4 | |
5 | #include <ansi_colors.h> |
6 | #include <mos/io/io.hpp> |
7 | #include <mos/lib/structures/list.hpp> |
8 | #include <mos/lib/structures/ring_buffer.hpp> |
9 | #include <mos/lib/sync/spinlock.hpp> |
10 | #include <mos/mos_global.h> |
11 | #include <mos/tasks/wait.hpp> |
12 | #include <mos/types.hpp> |
13 | |
14 | typedef enum |
15 | { |
16 | CONSOLE_CAP_COLOR = 1 << 0, |
17 | CONSOLE_CAP_CLEAR = 1 << 1, |
18 | CONSOLE_CAP_GET_SIZE = 1 << 2, |
19 | CONSOLE_CAP_CURSOR_HIDE = 1 << 3, |
20 | CONSOLE_CAP_CURSOR_MOVE = 1 << 4, |
21 | CONSOLE_CAP_READ = 1 << 6, ///< console supports read |
22 | } console_caps; |
23 | |
24 | MOS_ENUM_OPERATORS(console_caps) |
25 | |
26 | template<size_t buf_size> |
27 | struct Buffer |
28 | { |
29 | u8 buf[buf_size] __aligned(buf_size) = { 0 }; |
30 | const size_t size = buf_size; |
31 | }; |
32 | |
33 | struct Console // : public io_t |
34 | { |
35 | as_linked_list; |
36 | io_t io; |
37 | const char *name = "<unnamed>" ; |
38 | console_caps caps; |
39 | waitlist_t waitlist; // waitlist for read |
40 | |
41 | template<size_t buf_size> |
42 | Console(const char *name, console_caps caps, Buffer<buf_size> *read_buf, standard_color_t default_fg, standard_color_t default_bg) |
43 | : name(name), caps(caps), fg(default_fg), bg(default_bg), default_fg(default_fg), default_bg(default_bg) |
44 | { |
45 | reader.buf = read_buf->buf; |
46 | reader.size = read_buf->size; |
47 | waitlist_init(list: &waitlist); |
48 | } |
49 | |
50 | virtual ~Console() = default; |
51 | |
52 | struct |
53 | { |
54 | spinlock_t lock; |
55 | ring_buffer_pos_t pos; |
56 | u8 *buf = nullptr; |
57 | size_t size = 0; |
58 | } reader; |
59 | |
60 | struct |
61 | { |
62 | spinlock_t lock; |
63 | } writer; |
64 | |
65 | standard_color_t fg, bg; |
66 | standard_color_t default_fg = White, default_bg = Black; |
67 | |
68 | public: |
69 | size_t write(const char *data, size_t size) |
70 | { |
71 | spinlock_acquire(&writer.lock); |
72 | size_t ret = do_write(data, size); |
73 | spinlock_release(&writer.lock); |
74 | return ret; |
75 | } |
76 | |
77 | size_t write_color(const char *data, size_t size, standard_color_t fg, standard_color_t bg) |
78 | { |
79 | spinlock_acquire(&writer.lock); |
80 | if (caps & CONSOLE_CAP_COLOR) |
81 | { |
82 | if (this->fg != fg || this->bg != bg) |
83 | { |
84 | set_color(fg, bg); |
85 | this->fg = fg; |
86 | this->bg = bg; |
87 | } |
88 | } |
89 | |
90 | size_t ret = do_write(data, size); |
91 | spinlock_release(&writer.lock); |
92 | return ret; |
93 | } |
94 | |
95 | void putc(u8 c); |
96 | |
97 | public: |
98 | virtual bool () |
99 | { |
100 | return true; |
101 | } |
102 | |
103 | virtual bool get_size(u32 *width, u32 *height) = 0; |
104 | virtual bool set_color(standard_color_t fg, standard_color_t bg) = 0; |
105 | virtual bool clear() = 0; |
106 | |
107 | public: // TODO: make protected |
108 | virtual size_t do_write(const char *data, size_t size) = 0; |
109 | }; |
110 | |
111 | extern list_head consoles; |
112 | |
113 | void console_register(Console *con); |
114 | Console *console_get(const char *name); |
115 | Console *console_get_by_prefix(const char *prefix); |
116 | |