From 321c6dcf5d32ee883929fe40ae78de7190fb7846 Mon Sep 17 00:00:00 2001 From: Baptiste Wicht Date: Sat, 24 Sep 2016 19:45:58 +0200 Subject: [PATCH] Cleanup the terminal system --- kernel/include/console.hpp | 50 ++++++++++++++++++++--- kernel/include/stdio.hpp | 26 ++++++++++++ kernel/include/terminal.hpp | 33 ++++++++++++++++ kernel/include/text_console.hpp | 29 ++++++++++++++ kernel/include/vesa_console.hpp | 57 ++++++++++++++++++++++++++- kernel/src/console.cpp | 50 +++++++++++------------ kernel/src/stdio.cpp | 70 ++++++++++++++++----------------- kernel/src/terminal.cpp | 58 ++++++++++++++------------- kernel/src/text_console.cpp | 58 +++++++++++++-------------- 9 files changed, 307 insertions(+), 124 deletions(-) diff --git a/kernel/include/console.hpp b/kernel/include/console.hpp index 7b0feb08..4a77b972 100644 --- a/kernel/include/console.hpp +++ b/kernel/include/console.hpp @@ -16,30 +16,68 @@ namespace stdio { +/*! + * \brief Init the console + */ void init_console(); +/*! + * \brief A console + */ struct console { + /*! + * \brief Init the console + */ void init(); - size_t get_columns() const ; - size_t get_rows() const ; + /*! + * \brief Returns the number of columns of the console + */ + size_t get_columns() const; + /*! + * \brief Returns the number of rows of the console + */ + size_t get_rows() const; + + /*! + * \brief Print the given char to the console + * \param c The character to print + */ void print(char c); + /*! + * \brief Clear the console + */ void wipeout(); + /*! + * \brief Set the active status of the console + * \param active The active status of the console + */ void set_active(bool active); + + /*! + * \brief Save the state of the console + */ void save(); + + /*! + * \brief Restore the state of the console + */ void restore(); private: + /*! + * \brief Move to the next line + */ void next_line(); - size_t current_line = 0; - size_t current_column = 0; + size_t current_line = 0; ///< The current line of the console + size_t current_column = 0; ///< The current column of the console - void* buffer = nullptr; - bool active = false; + void* buffer = nullptr; ///< The buffer to save the state + bool active = false; ///< The active status of the console }; } // end of namespace stdio diff --git a/kernel/include/stdio.hpp b/kernel/include/stdio.hpp index f5034447..411fb4e8 100644 --- a/kernel/include/stdio.hpp +++ b/kernel/include/stdio.hpp @@ -14,14 +14,40 @@ namespace stdio { +/*! + * \brief Initialize the terminals + */ void init_terminals(); + +/*! + * \brief Register the devices into the devfs + */ void register_devices(); + +/*! + * \brief Finalize the terminals + */ void finalize(); +/*! + * \brief Switch the active terminal to the terminal with the given id + * \param id The terminal to activate + */ void switch_terminal(size_t id); +/*! + * \brief Returns the number of terminals + */ size_t terminals_count(); + +/*! + * \brief Returns the active terminal + */ virtual_terminal& get_active_terminal(); + +/*! + * \brief Returns the terminal with the given id + */ virtual_terminal& get_terminal(size_t id); } //end of namespace stdio diff --git a/kernel/include/terminal.hpp b/kernel/include/terminal.hpp index c7d85348..8f1012e3 100644 --- a/kernel/include/terminal.hpp +++ b/kernel/include/terminal.hpp @@ -23,7 +23,13 @@ namespace stdio { constexpr const size_t INPUT_BUFFER_SIZE = 256; +/*! + * \brief A virtual terminal + */ struct virtual_terminal { + /*! + * \brief Construct a new virtual_terminal + */ virtual_terminal(){} virtual_terminal(const virtual_terminal& rhs) = delete; @@ -32,6 +38,10 @@ struct virtual_terminal { virtual_terminal(virtual_terminal&& rhs) = delete; virtual_terminal& operator=(virtual_terminal&& rhs) = delete; + /*! + * \brief Print the given char to the terminal + * \param c The character to print + */ void print(char c); /*! @@ -76,13 +86,36 @@ struct virtual_terminal { */ size_t read_input_raw(size_t ms); + /*! + * \brief Set the canonical mode of the terminal + * \param can The canonical mode of the terminal + */ void set_canonical(bool can); + + /*! + * \brief Set the mouse mode of the terminal + * \param can The mouse mode of the terminal + */ void set_mouse(bool m); + /*! + * \brief Returns true if the terminal is in canonical mode, false otherwise + */ bool is_canonical() const; + /*! + * \brief Returns true if the terminal is in mouse mode, false otherwise + */ + bool is_mouse() const; + + /*! + * \brief Set the active mode of the terminal + */ void set_active(bool); + /*! + * \brief Returns the console linked to this terminal + */ console& get_console(); size_t id; diff --git a/kernel/include/text_console.hpp b/kernel/include/text_console.hpp index 4580a14c..a13230c7 100644 --- a/kernel/include/text_console.hpp +++ b/kernel/include/text_console.hpp @@ -10,12 +10,41 @@ #include +/*! + * \brief A textual console + */ struct text_console { + /*! + * \brief Initialize the console + */ void init(); + + /*! + * \brief Returns the number of lines of the console + */ size_t lines(); + + /*! + * \brief Returns the number of columns of the console + */ size_t columns(); + + /*! + * \brief Clear the text console + */ void clear(); + + /*! + * \brief Scroll up one line + */ void scroll_up(); + + /*! + * \brief Print a char at the given line and column + * \param line The line at which to print the char + * \param column The column at which to print the char + * \param c The char to print + */ void print_char(size_t line, size_t column, char c); }; diff --git a/kernel/include/vesa_console.hpp b/kernel/include/vesa_console.hpp index b87a15dc..be84d033 100644 --- a/kernel/include/vesa_console.hpp +++ b/kernel/include/vesa_console.hpp @@ -10,22 +10,75 @@ #include +/*! + * \brief A VESA console + */ struct vesa_console { + /*! + * \brief Initialize the console + */ void init(); - size_t lines() const ; - size_t columns() const ; + /*! + * \brief Returns the number of lines of the console + */ + size_t lines() const; + /*! + * \brief Returns the number of columns of the console + */ + size_t columns() const; + + /*! + * \brief Clear the vesa console + */ void clear(); + + /*! + * \brief Clear the given vesa console state + * \param buffer The VESA console state + */ void clear(void* buffer); + /*! + * \brief Scroll up one line + */ void scroll_up(); + + /*! + * \brief Scroll up one line on the given vesa console state + * \param buffer The VESA console state + */ void scroll_up(void* buffer); + /*! + * \brief Print a char at the given line and column + * \param line The line at which to print the char + * \param column The column at which to print the char + * \param c The char to print + */ void print_char(size_t line, size_t column, char c); + + /*! + * \brief Print a char at the given line and column on the given vesa console state + * \param buffer The VESA console state + * \param line The line at which to print the char + * \param column The column at which to print the char + * \param c The char to print + */ void print_char(void* buffer, size_t line, size_t column, char c); + /*! + * \brief Save the state of the console + * \param buffer The buffer to save to + * \return the buffer the state was saved to + */ void* save(void* buffer); + + /*! + * \brief Restore the state of the console + * \param buffer The buffer to restore from + */ void restore(void* buffer); }; diff --git a/kernel/src/console.cpp b/kernel/src/console.cpp index 5d8712d3..0bc5deec 100644 --- a/kernel/src/console.cpp +++ b/kernel/src/console.cpp @@ -26,24 +26,24 @@ bool text = true; } //end of anonymous namespace -void stdio::init_console(){ +void stdio::init_console() { text = !vesa::enabled(); - if(text){ + if (text) { t_console.init(); } else { v_console.init(); } } -void stdio::console::init(){ - if(!text){ +void stdio::console::init() { + if (!text) { buffer = vesa::create_buffer(); } } size_t stdio::console::get_rows() const { - if(text){ + if (text) { return t_console.lines(); } else { return v_console.lines(); @@ -51,30 +51,30 @@ size_t stdio::console::get_rows() const { } size_t stdio::console::get_columns() const { - if(text){ + if (text) { return t_console.columns(); } else { return v_console.columns(); } } -void stdio::console::print(char key){ - if(key == '\n'){ +void stdio::console::print(char key) { + if (key == '\n') { next_line(); - } else if(key == '\r'){ + } else if (key == '\r') { // Ignore \r for now - } else if(key == '\b'){ + } else if (key == '\b') { --current_column; print(' '); --current_column; - } else if(key == '\t'){ + } else if (key == '\t') { print(' '); print(' '); } else { - if(text){ + if (text) { t_console.print_char(current_line, current_column, key); } else { - if(active){ + if (active) { v_console.print_char(current_line, current_column, key); } else { v_console.print_char(buffer, current_line, current_column, key); @@ -83,51 +83,51 @@ void stdio::console::print(char key){ ++current_column; - if(current_column == console::get_columns()){ + if (current_column == console::get_columns()) { next_line(); } } } -void stdio::console::wipeout(){ - if(text){ +void stdio::console::wipeout() { + if (text) { t_console.clear(); } else { - if(active){ + if (active) { v_console.clear(); } else { v_console.clear(buffer); } } - current_line = 0; + current_line = 0; current_column = 0; } -void stdio::console::save(){ +void stdio::console::save() { thor_assert(!text, "save/restore of the text console is not yet supported"); buffer = v_console.save(buffer); } -void stdio::console::restore(){ +void stdio::console::restore() { thor_assert(!text, "save/restore of the text console is not yet supported"); v_console.restore(buffer); } -void stdio::console::set_active(bool active){ +void stdio::console::set_active(bool active) { this->active = active; } -void stdio::console::next_line(){ +void stdio::console::next_line() { ++current_line; - if(current_line == console::get_rows()){ - if(text){ + if (current_line == console::get_rows()) { + if (text) { t_console.scroll_up(); } else { - if(active){ + if (active) { v_console.scroll_up(); } else { v_console.scroll_up(buffer); diff --git a/kernel/src/stdio.cpp b/kernel/src/stdio.cpp index 2b267e7c..4be009d4 100644 --- a/kernel/src/stdio.cpp +++ b/kernel/src/stdio.cpp @@ -27,7 +27,7 @@ size_t active_terminal; std::array terminals; -void input_thread(void* data){ +void input_thread(void* data) { auto& terminal = *reinterpret_cast(data); auto pid = scheduler::get_pid(); @@ -35,62 +35,62 @@ void input_thread(void* data){ logging::logf(logging::log_level::TRACE, "stdio: Input Thread for terminal %u started (pid:%u)\n", terminal.id, pid); bool shift = false; - bool alt = false; + bool alt = false; - while(true){ + while (true) { // Wait for some input scheduler::block_process(pid); // Handle keyboard input - while(!terminal.keyboard_buffer.empty()){ + while (!terminal.keyboard_buffer.empty()) { auto key = terminal.keyboard_buffer.pop(); - if(terminal.canonical){ + if (terminal.canonical) { //Key released - if(key & 0x80){ + if (key & 0x80) { key &= ~(0x80); - if(alt && key == keyboard::KEY_F1){ + if (alt && key == keyboard::KEY_F1) { stdio::switch_terminal(0); - } else if(alt && key == keyboard::KEY_F2){ + } else if (alt && key == keyboard::KEY_F2) { stdio::switch_terminal(1); - } else if(alt && key == keyboard::KEY_F3){ + } else if (alt && key == keyboard::KEY_F3) { stdio::switch_terminal(2); } - if(key == keyboard::KEY_LEFT_SHIFT || key == keyboard::KEY_RIGHT_SHIFT){ + if (key == keyboard::KEY_LEFT_SHIFT || key == keyboard::KEY_RIGHT_SHIFT) { shift = false; } - if(key == keyboard::KEY_ALT){ + if (key == keyboard::KEY_ALT) { alt = false; } } //Key pressed else { - if(key == keyboard::KEY_LEFT_SHIFT || key == keyboard::KEY_RIGHT_SHIFT){ + if (key == keyboard::KEY_LEFT_SHIFT || key == keyboard::KEY_RIGHT_SHIFT) { shift = true; - } else if(key == keyboard::KEY_ALT){ + } else if (key == keyboard::KEY_ALT) { alt = true; - } else if(key == keyboard::KEY_BACKSPACE){ - if(!terminal.input_buffer.empty()){ + } else if (key == keyboard::KEY_BACKSPACE) { + if (!terminal.input_buffer.empty()) { terminal.input_buffer.pop_last(); terminal.print('\b'); } } else { auto qwertz_key = shift - ? keyboard::shift_key_to_ascii(key) - : keyboard::key_to_ascii(key); + ? keyboard::shift_key_to_ascii(key) + : keyboard::key_to_ascii(key); - if(qwertz_key){ + if (qwertz_key) { terminal.input_buffer.push(qwertz_key); terminal.print(qwertz_key); - if(qwertz_key == '\n'){ + if (qwertz_key == '\n') { // Transfer current line to the canonical buffer - while(!terminal.input_buffer.empty()){ + while (!terminal.input_buffer.empty()) { terminal.canonical_buffer.push(terminal.input_buffer.pop()); } @@ -112,10 +112,10 @@ void input_thread(void* data){ } // Handle mouse input - while(!terminal.mouse_buffer.empty()){ + while (!terminal.mouse_buffer.empty()) { auto key = terminal.mouse_buffer.pop(); - if(!terminal.canonical && terminal.mouse){ + if (!terminal.canonical && terminal.is_mouse()) { terminal.raw_buffer.push(key); terminal.input_queue.notify_one(); @@ -128,10 +128,10 @@ void input_thread(void* data){ } //end of anonymous namespace -void stdio::init_terminals(){ +void stdio::init_terminals() { size_t id = 0; - for(auto& terminal : terminals){ + for (auto& terminal : terminals) { terminal.id = id++; terminal.active = false; terminal.canonical = true; @@ -140,25 +140,25 @@ void stdio::init_terminals(){ // Initialize the active terminal - active_terminal = 0; + active_terminal = 0; terminals[active_terminal].active = true; terminals[active_terminal].get_console().set_active(true); } -void stdio::register_devices(){ - for(auto& terminal : terminals){ +void stdio::register_devices() { + for (auto& terminal : terminals) { std::string name = std::string("tty") + std::to_string(terminal.id); devfs::register_device("/dev/", name, devfs::device_type::CHAR_DEVICE, tty_driver, &terminal); } } -void stdio::finalize(){ - for(auto& terminal : terminals){ +void stdio::finalize() { + for (auto& terminal : terminals) { auto* user_stack = new char[scheduler::user_stack_size]; auto* kernel_stack = new char[scheduler::kernel_stack_size]; - auto& input_process = scheduler::create_kernel_task_args("tty_input", user_stack, kernel_stack, &input_thread, &terminal); + auto& input_process = scheduler::create_kernel_task_args("tty_input", user_stack, kernel_stack, &input_thread, &terminal); input_process.ppid = 1; input_process.priority = scheduler::DEFAULT_PRIORITY; @@ -172,22 +172,22 @@ void stdio::finalize(){ } } -size_t stdio::terminals_count(){ +size_t stdio::terminals_count() { return MAX_TERMINALS; } -stdio::virtual_terminal& stdio::get_active_terminal(){ +stdio::virtual_terminal& stdio::get_active_terminal() { return terminals[active_terminal]; } -stdio::virtual_terminal& stdio::get_terminal(size_t id){ +stdio::virtual_terminal& stdio::get_terminal(size_t id) { thor_assert(id < MAX_TERMINALS, "Out of bound tty"); return terminals[id]; } -void stdio::switch_terminal(size_t id){ - if(active_terminal != id){ +void stdio::switch_terminal(size_t id) { + if (active_terminal != id) { logging::logf(logging::log_level::TRACE, "stdio: Switch activate virtual terminal %u\n", id); // Effectively switch the terminal diff --git a/kernel/src/terminal.cpp b/kernel/src/terminal.cpp index 83916615..b3ad9b3a 100644 --- a/kernel/src/terminal.cpp +++ b/kernel/src/terminal.cpp @@ -17,12 +17,12 @@ #include "print.hpp" -void stdio::virtual_terminal::print(char key){ +void stdio::virtual_terminal::print(char key) { cons.print(key); } -void stdio::virtual_terminal::send_input(char key){ - if(!input_thread_pid){ +void stdio::virtual_terminal::send_input(char key) { + if (!input_thread_pid) { return; } @@ -34,8 +34,8 @@ void stdio::virtual_terminal::send_input(char key){ scheduler::unblock_process_hint(input_thread_pid); } -void stdio::virtual_terminal::send_mouse_input(std::keycode key){ - if(!input_thread_pid){ +void stdio::virtual_terminal::send_mouse_input(std::keycode key) { + if (!input_thread_pid) { return; } @@ -47,16 +47,16 @@ void stdio::virtual_terminal::send_mouse_input(std::keycode key){ scheduler::unblock_process_hint(input_thread_pid); } -size_t stdio::virtual_terminal::read_input_can(char* buffer, size_t max){ +size_t stdio::virtual_terminal::read_input_can(char* buffer, size_t max) { size_t read = 0; - while(true){ - while(!canonical_buffer.empty()){ + while (true) { + while (!canonical_buffer.empty()) { auto c = canonical_buffer.pop(); buffer[read++] = c; - if(read >= max || c == '\n'){ + if (read >= max || c == '\n') { return read; } } @@ -66,45 +66,45 @@ size_t stdio::virtual_terminal::read_input_can(char* buffer, size_t max){ } // TODO In case of max < read, the timeout is not respected -size_t stdio::virtual_terminal::read_input_can(char* buffer, size_t max, size_t ms){ +size_t stdio::virtual_terminal::read_input_can(char* buffer, size_t max, size_t ms) { size_t read = 0; - while(true){ - while(!canonical_buffer.empty()){ + while (true) { + while (!canonical_buffer.empty()) { auto c = canonical_buffer.pop(); buffer[read++] = c; - if(read >= max || c == '\n'){ + if (read >= max || c == '\n') { return read; } } - if(!ms){ + if (!ms) { return read; } - if(!input_queue.wait_for(ms)){ + if (!input_queue.wait_for(ms)) { return read; } } } -size_t stdio::virtual_terminal::read_input_raw(){ - if(raw_buffer.empty()){ +size_t stdio::virtual_terminal::read_input_raw() { + if (raw_buffer.empty()) { input_queue.wait(); } return raw_buffer.pop(); } -size_t stdio::virtual_terminal::read_input_raw(size_t ms){ - if(raw_buffer.empty()){ - if(!ms){ +size_t stdio::virtual_terminal::read_input_raw(size_t ms) { + if (raw_buffer.empty()) { + if (!ms) { return static_cast(std::keycode::TIMEOUT); } - if(!input_queue.wait_for(ms)){ + if (!input_queue.wait_for(ms)) { return static_cast(std::keycode::TIMEOUT); } } @@ -114,13 +114,13 @@ size_t stdio::virtual_terminal::read_input_raw(size_t ms){ return raw_buffer.pop(); } -void stdio::virtual_terminal::set_canonical(bool can){ +void stdio::virtual_terminal::set_canonical(bool can) { logging::logf(logging::log_level::TRACE, "Switched terminal %u canonical mode from %u to %u\n", id, uint64_t(canonical), uint64_t(can)); canonical = can; } -void stdio::virtual_terminal::set_mouse(bool m){ +void stdio::virtual_terminal::set_mouse(bool m) { logging::logf(logging::log_level::TRACE, "Switched terminal %u mouse handling mode from %u to %u\n", id, uint64_t(mouse), uint64_t(m)); mouse = m; @@ -130,8 +130,12 @@ bool stdio::virtual_terminal::is_canonical() const { return canonical; } -void stdio::virtual_terminal::set_active(bool active){ - if(this->active == active){ +bool stdio::virtual_terminal::is_mouse() const { + return mouse; +} + +void stdio::virtual_terminal::set_active(bool active) { + if (this->active == active) { return; } @@ -139,13 +143,13 @@ void stdio::virtual_terminal::set_active(bool active){ cons.set_active(active); - if(active){ + if (active) { cons.restore(); } else { cons.save(); } } -stdio::console& stdio::virtual_terminal::get_console(){ +stdio::console& stdio::virtual_terminal::get_console() { return cons; } diff --git a/kernel/src/text_console.cpp b/kernel/src/text_console.cpp index 72f8287c..6c9b5575 100644 --- a/kernel/src/text_console.cpp +++ b/kernel/src/text_console.cpp @@ -12,70 +12,70 @@ namespace { enum vga_color { - BLACK = 0, - BLUE = 1, - GREEN = 2, - CYAN = 3, - RED = 4, - MAGENTA = 5, - BROWN = 6, - LIGHT_GREY = 7, - DARK_GREY = 8, - LIGHT_BLUE = 9, - LIGHT_GREEN = 10, - LIGHT_CYAN = 11, - LIGHT_RED = 12, + BLACK = 0, + BLUE = 1, + GREEN = 2, + CYAN = 3, + RED = 4, + MAGENTA = 5, + BROWN = 6, + LIGHT_GREY = 7, + DARK_GREY = 8, + LIGHT_BLUE = 9, + LIGHT_GREEN = 10, + LIGHT_CYAN = 11, + LIGHT_RED = 12, LIGHT_MAGENTA = 13, - LIGHT_BROWN = 14, - WHITE = 15, + LIGHT_BROWN = 14, + WHITE = 15, }; -uint8_t make_color(vga_color fg, vga_color bg){ +uint8_t make_color(vga_color fg, vga_color bg) { return fg | bg << 4; } -uint16_t make_vga_entry(char c, uint8_t color){ - uint16_t c16 = c; +uint16_t make_vga_entry(char c, uint8_t color) { + uint16_t c16 = c; uint16_t color16 = color; return c16 | color16 << 8; } } //end of anonymous namespace -void text_console::init(){ +void text_console::init() { //Nothing special to init } -size_t text_console::lines(){ +size_t text_console::lines() { return 25; } -size_t text_console::columns(){ +size_t text_console::columns() { return 80; } -void text_console::clear(){ - for(int line = 0; line < 25; ++line){ - for(uint64_t column = 0; column < 80; ++column){ +void text_console::clear() { + for (int line = 0; line < 25; ++line) { + for (uint64_t column = 0; column < 80; ++column) { print_char(line, column, ' '); } } } -void text_console::scroll_up(){ +void text_console::scroll_up() { auto vga_buffer_fast = reinterpret_cast(0x0B8000); - auto destination = vga_buffer_fast; - auto source = &vga_buffer_fast[20]; + auto destination = vga_buffer_fast; + auto source = &vga_buffer_fast[20]; std::copy_n(source, 24 * 20, destination); auto vga_buffer = reinterpret_cast(0x0B8000); - for(uint64_t i = 0; i < 80; ++i){ + for (uint64_t i = 0; i < 80; ++i) { vga_buffer[24 * 80 + i] = make_vga_entry(' ', make_color(WHITE, BLACK)); } } -void text_console::print_char(size_t line, size_t column, char c){ +void text_console::print_char(size_t line, size_t column, char c) { uint16_t* vga_buffer = reinterpret_cast(0x0B8000); vga_buffer[line * 80 + column] = make_vga_entry(c, make_color(WHITE, BLACK));