Kernel: Start work on making tty a file

TTY is now a file that you can read from/write to. I still have
to port shell to use this new interface
This commit is contained in:
Bananymous
2023-04-05 00:56:09 +03:00
parent 783842bac2
commit 7f95444bb5
17 changed files with 718 additions and 491 deletions

View File

@@ -0,0 +1,113 @@
#pragma once
#include <BAN/Array.h>
#include <kernel/Device.h>
#include <kernel/Input/KeyEvent.h>
#include <kernel/SpinLock.h>
#include <kernel/Terminal/TerminalDriver.h>
#include <kernel/Terminal/termios.h>
#include <kernel/Semaphore.h>
namespace Kernel
{
class TTY : public CharacterDevice
{
public:
TTY(TerminalDriver*);
void clear();
void putchar(uint8_t ch);
void set_cursor_position(uint32_t x, uint32_t y);
void set_font(const Kernel::Font&);
uint32_t height() const { return m_height; }
uint32_t width() const { return m_width; }
// for kprint
static void putchar_current(uint8_t ch);
static bool is_initialized();
virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override;
virtual BAN::ErrorOr<size_t> write(size_t, const void*, size_t) override;
private:
void reset_ansi();
void handle_ansi_csi(uint8_t ch);
void handle_ansi_csi_color();
void putchar_at(uint32_t codepoint, uint32_t x, uint32_t y);
void render_from_buffer(uint32_t x, uint32_t y);
void on_key(Input::KeyEvent);
private:
enum class State
{
Normal,
WaitingAnsiEscape,
WaitingAnsiCSI,
WaitingUTF8,
};
struct AnsiState
{
int32_t nums[2] { -1, -1 };
int32_t index { 0 };
};
struct UTF8State
{
uint32_t codepoint { 0 };
uint8_t bytes_missing { 0 };
};
struct Cell
{
TerminalDriver::Color foreground { TerminalColor::BRIGHT_WHITE };
TerminalDriver::Color background { TerminalColor::BLACK };
uint32_t codepoint { ' ' };
};
private:
Kernel::SpinLock m_lock;
State m_state { State::Normal };
AnsiState m_ansi_state { };
UTF8State m_utf8_state { };
uint32_t m_width { 0 };
uint32_t m_height { 0 };
uint32_t m_row { 0 };
uint32_t m_column { 0 };
Cell* m_buffer { nullptr };
TerminalDriver::Color m_foreground { TerminalColor::BRIGHT_WHITE };
TerminalDriver::Color m_background { TerminalColor::BLACK };
termios m_termios;
struct Buffer
{
BAN::Array<uint8_t, 1024> buffer;
size_t bytes { 0 };
bool flush { false };
Semaphore semaphore;
};
Buffer m_output;
TerminalDriver* m_terminal_driver { nullptr };
public:
virtual Mode mode() const override { return { Mode::IFCHR | Mode::IRUSR }; }
virtual uid_t uid() const override { return 0; }
virtual gid_t gid() const override { return 0; }
virtual dev_t rdev() const override { return m_rdev; }
virtual BAN::StringView name() const { return m_name; }
private:
const dev_t m_rdev;
const BAN::String m_name;
};
}

View File

@@ -0,0 +1,61 @@
#pragma once
#include <kernel/Font.h>
#include <stdint.h>
class TerminalDriver
{
public:
struct Color
{
constexpr Color(uint32_t rgb)
: rgb(rgb)
{ }
constexpr Color(uint8_t r, uint8_t g, uint8_t b)
: rgb(((uint32_t)r << 16) | ((uint32_t)g << 8) | b)
{ }
uint8_t red() const { return (rgb >> 0x10) & 0xFF; }
uint8_t green() const { return (rgb >> 0x08) & 0xFF; }
uint8_t blue() const { return (rgb >> 0x00) & 0xFF; }
uint32_t rgb;
};
public:
TerminalDriver() : m_font(MUST(Kernel::Font::prefs())) {}
virtual ~TerminalDriver() {}
virtual uint32_t width() const = 0;
virtual uint32_t height() const = 0;
virtual void putchar_at(uint16_t, uint32_t, uint32_t, Color, Color) = 0;
virtual void clear(Color) = 0;
virtual void set_cursor_position(uint32_t, uint32_t) = 0;
void set_font(const Kernel::Font& font) { m_font = font; };
const Kernel::Font& font() const { return m_font; }
private:
Kernel::Font m_font;
};
namespace TerminalColor
{
static constexpr TerminalDriver::Color BLACK = 0x000000;
static constexpr TerminalDriver::Color BLUE = 0x0000AA;
static constexpr TerminalDriver::Color GREEN = 0x00AA00;
static constexpr TerminalDriver::Color CYAN = 0x00AAAA;
static constexpr TerminalDriver::Color RED = 0xAA0000;
static constexpr TerminalDriver::Color MAGENTA = 0xAA00AA;
static constexpr TerminalDriver::Color YELLOW = 0xAA5500;
static constexpr TerminalDriver::Color WHITE = 0xAAAAAA;
static constexpr TerminalDriver::Color BRIGHT_BLACK = 0x555555;
static constexpr TerminalDriver::Color BRIGHT_BLUE = 0x5555FF;
static constexpr TerminalDriver::Color BRIGHT_GREEN = 0x55FF55;
static constexpr TerminalDriver::Color BRIGHT_CYAN = 0x55FFFF;
static constexpr TerminalDriver::Color BRIGHT_RED = 0xFF5555;
static constexpr TerminalDriver::Color BRIGHT_MAGENTA = 0xFF55FF;
static constexpr TerminalDriver::Color BRIGHT_YELLOW = 0xFFFF55;
static constexpr TerminalDriver::Color BRIGHT_WHITE = 0xFFFFFF;
}

View File

@@ -0,0 +1,38 @@
#pragma once
#include <kernel/Terminal/TerminalDriver.h>
class VesaTerminalDriver final : public TerminalDriver
{
public:
static VesaTerminalDriver* create();
~VesaTerminalDriver();
virtual uint32_t width() const override { return m_width / font().width(); }
virtual uint32_t height() const override { return m_height / font().height(); }
virtual void putchar_at(uint16_t, uint32_t, uint32_t, Color, Color) override;
virtual void clear(Color) override;
virtual void set_cursor_position(uint32_t, uint32_t) override;
private:
VesaTerminalDriver(uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp, uintptr_t address)
: m_width(width)
, m_height(height)
, m_pitch(pitch)
, m_bpp(bpp)
, m_address(address)
{ }
void set_pixel(uint32_t, Color);
private:
uint32_t m_width = 0;
uint32_t m_height = 0;
uint32_t m_pitch = 0;
uint8_t m_bpp = 0;
uintptr_t m_address = 0;
static constexpr Color s_cursor_color = TerminalColor::BRIGHT_WHITE;
};

View File

@@ -0,0 +1,12 @@
#pragma once
namespace Kernel
{
struct termios
{
bool canonical { true };
bool echo { true };
};
}