diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 62e6de54c..f91cd54f5 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -118,6 +118,8 @@ namespace Kernel BAN::ErrorOr sys_mmap(const sys_mmap_t*); BAN::ErrorOr sys_munmap(void* addr, size_t len); + BAN::ErrorOr sys_tty_ctrl(int fildes, int command, int flags); + BAN::ErrorOr sys_signal(int, void (*)(int)); BAN::ErrorOr sys_raise(int signal); static BAN::ErrorOr sys_kill(pid_t pid, int signal); diff --git a/kernel/include/kernel/Terminal/Serial.h b/kernel/include/kernel/Terminal/Serial.h index 41cb7dd07..b53310aab 100644 --- a/kernel/include/kernel/Terminal/Serial.h +++ b/kernel/include/kernel/Terminal/Serial.h @@ -41,7 +41,7 @@ namespace Kernel virtual uint32_t width() const override; virtual uint32_t height() const override; - virtual void putchar(uint8_t) override; + virtual void putchar_impl(uint8_t) override; virtual void update() override; diff --git a/kernel/include/kernel/Terminal/TTY.h b/kernel/include/kernel/Terminal/TTY.h index f98268c64..0cb81befc 100644 --- a/kernel/include/kernel/Terminal/TTY.h +++ b/kernel/include/kernel/Terminal/TTY.h @@ -21,6 +21,8 @@ namespace Kernel void set_foreground_pgrp(pid_t pgrp) { m_foreground_pgrp = pgrp; } pid_t foreground_pgrp() const { return m_foreground_pgrp; } + BAN::ErrorOr tty_ctrl(int command, int flags); + // for kprint static void putchar_current(uint8_t ch); static bool is_initialized(); @@ -35,7 +37,8 @@ namespace Kernel virtual uint32_t height() const = 0; virtual uint32_t width() const = 0; - virtual void putchar(uint8_t ch) = 0; + void putchar(uint8_t ch); + virtual void putchar_impl(uint8_t ch) = 0; bool has_data() const; @@ -62,6 +65,14 @@ namespace Kernel private: pid_t m_foreground_pgrp { 0 }; + struct tty_ctrl_t + { + bool draw_graphics { true }; + bool receive_input { true }; + Semaphore semaphore; + }; + tty_ctrl_t m_tty_ctrl; + struct Buffer { BAN::Array buffer; diff --git a/kernel/include/kernel/Terminal/VirtualTTY.h b/kernel/include/kernel/Terminal/VirtualTTY.h index ac9879ee5..3f3fdbf45 100644 --- a/kernel/include/kernel/Terminal/VirtualTTY.h +++ b/kernel/include/kernel/Terminal/VirtualTTY.h @@ -21,7 +21,7 @@ namespace Kernel virtual uint32_t height() const override { return m_height; } virtual uint32_t width() const override { return m_width; } - virtual void putchar(uint8_t ch) override; + virtual void putchar_impl(uint8_t ch) override; protected: virtual BAN::StringView name() const override { return m_name; } diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 47149c5b2..76c6a333f 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -883,6 +883,19 @@ namespace Kernel return 0; } + BAN::ErrorOr Process::sys_tty_ctrl(int fildes, int command, int flags) + { + LockGuard _(m_lock); + + auto inode = TRY(m_open_file_descriptors.inode_of(fildes)); + if (!inode->is_tty()) + return BAN::Error::from_errno(ENOTTY); + + TRY(((TTY*)inode.ptr())->tty_ctrl(command, flags)); + + return 0; + } + BAN::ErrorOr Process::sys_termid(char* buffer) { LockGuard _(m_lock); diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index f48f0ee53..68bcd5755 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -193,6 +193,9 @@ namespace Kernel case SYS_MUNMAP: ret = Process::current().sys_munmap((void*)arg1, (size_t)arg2); break; + case SYS_TTY_CTRL: + ret = Process::current().sys_tty_ctrl((int)arg1, (int)arg2, (int)arg3); + break; default: dwarnln("Unknown syscall {}", syscall); break; diff --git a/kernel/kernel/Terminal/Serial.cpp b/kernel/kernel/Terminal/Serial.cpp index fd2109a7c..ec71c97b1 100644 --- a/kernel/kernel/Terminal/Serial.cpp +++ b/kernel/kernel/Terminal/Serial.cpp @@ -286,7 +286,7 @@ namespace Kernel return m_serial.height(); } - void SerialTTY::putchar(uint8_t ch) + void SerialTTY::putchar_impl(uint8_t ch) { m_serial.putchar(ch); } diff --git a/kernel/kernel/Terminal/TTY.cpp b/kernel/kernel/Terminal/TTY.cpp index 44d475e43..e2c50884f 100644 --- a/kernel/kernel/Terminal/TTY.cpp +++ b/kernel/kernel/Terminal/TTY.cpp @@ -10,6 +10,7 @@ #include #include +#include #include namespace Kernel @@ -42,6 +43,35 @@ namespace Kernel MUST(((RamSymlinkInode*)inode.ptr())->set_link_target(name())); } + BAN::ErrorOr TTY::tty_ctrl(int command, int flags) + { + if (flags & ~(TTY_FLAG_ENABLE_INPUT | TTY_FLAG_ENABLE_OUTPUT)) + return BAN::Error::from_errno(EINVAL); + + switch (command) + { + case TTY_CMD_SET: + if ((flags & TTY_FLAG_ENABLE_INPUT) && !m_tty_ctrl.receive_input) + { + m_tty_ctrl.receive_input = true; + m_tty_ctrl.semaphore.unblock(); + } + if (flags & TTY_FLAG_ENABLE_OUTPUT) + m_tty_ctrl.draw_graphics = true; + break; + case TTY_CMD_UNSET: + if ((flags & TTY_FLAG_ENABLE_INPUT) && m_tty_ctrl.receive_input) + m_tty_ctrl.receive_input = false; + if (flags & TTY_FLAG_ENABLE_OUTPUT) + m_tty_ctrl.draw_graphics = false; + break; + default: + return BAN::Error::from_errno(EINVAL); + } + + return {}; + } + void TTY::initialize_devices() { static bool initialized = false; @@ -53,6 +83,9 @@ namespace Kernel auto inode = MUST(VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, "/dev/input0"sv, O_RDONLY)).inode; while (true) { + while (!TTY::current()->m_tty_ctrl.receive_input) + TTY::current()->m_tty_ctrl.semaphore.block(); + Input::KeyEvent event; size_t read = MUST(inode->read(0, &event, sizeof(event))); ASSERT(read == sizeof(event)); @@ -251,6 +284,12 @@ namespace Kernel } } + void TTY::putchar(uint8_t ch) + { + if (m_tty_ctrl.draw_graphics) + putchar_impl(ch); + } + BAN::ErrorOr TTY::read_impl(off_t, void* buffer, size_t count) { LockGuard _(m_lock); diff --git a/kernel/kernel/Terminal/VirtualTTY.cpp b/kernel/kernel/Terminal/VirtualTTY.cpp index d8896c540..a5fe142b7 100644 --- a/kernel/kernel/Terminal/VirtualTTY.cpp +++ b/kernel/kernel/Terminal/VirtualTTY.cpp @@ -304,7 +304,7 @@ namespace Kernel m_terminal_driver->putchar_at(codepoint, x, y, m_foreground, m_background); } - void VirtualTTY::putchar(uint8_t ch) + void VirtualTTY::putchar_impl(uint8_t ch) { ASSERT(m_lock.is_locked()); diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 48f3f6283..76c4f766f 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -14,6 +14,7 @@ set(LIBC_SOURCES stdio.cpp stdlib.cpp string.cpp + sys/banan-os.cpp sys/mman.cpp sys/stat.cpp sys/wait.cpp diff --git a/libc/include/sys/banan-os.h b/libc/include/sys/banan-os.h new file mode 100644 index 000000000..9db8b93c4 --- /dev/null +++ b/libc/include/sys/banan-os.h @@ -0,0 +1,25 @@ +#ifndef _SYS_BANAN_OS_H +#define _SYS_BANAN_OS_H 1 + +#include + +__BEGIN_DECLS + +#define TTY_CMD_SET 0x01 +#define TTY_CMD_UNSET 0x02 + +#define TTY_FLAG_ENABLE_OUTPUT 1 +#define TTY_FLAG_ENABLE_INPUT 2 + +/* +fildes: refers to valid tty device +command: one of TTY_CMD_* definitions +flags: bitwise or of TTY_FLAG_* definitions + +return value: 0 on success, -1 on failure and errno set to the error +*/ +int tty_ctrl(int fildes, int command, int flags); + +__END_DECLS + +#endif diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h index dd8052e24..a0f97ea15 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -53,6 +53,7 @@ __BEGIN_DECLS #define SYS_SYNC 50 #define SYS_MMAP 51 #define SYS_MUNMAP 52 +#define SYS_TTY_CTRL 53 __END_DECLS diff --git a/libc/sys/banan-os.cpp b/libc/sys/banan-os.cpp new file mode 100644 index 000000000..cc471928e --- /dev/null +++ b/libc/sys/banan-os.cpp @@ -0,0 +1,8 @@ +#include +#include +#include + +int tty_ctrl(int fildes, int command, int flags) +{ + return syscall(SYS_TTY_CTRL, fildes, command, flags); +}