From cb76f1ea75d1258425e3209b9e7fa008abde112f Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 27 Sep 2023 15:44:05 +0300 Subject: [PATCH] Kernel: Add some functionality to disable TTY input/output Userspace programs can call tty_ctrl() to disable/enable tty from handling input and displaying output. This API is probably going to change in the future to ioctl calls but I'm not sure how ioctl is used and what functionality should it have. I decided to create whole new function and syscall for now. Next I will expose framebuffer in /dev/fb0 and then I can start work on graphical environment! :D --- kernel/include/kernel/Process.h | 2 ++ kernel/include/kernel/Terminal/Serial.h | 2 +- kernel/include/kernel/Terminal/TTY.h | 13 ++++++- kernel/include/kernel/Terminal/VirtualTTY.h | 2 +- kernel/kernel/Process.cpp | 13 +++++++ kernel/kernel/Syscall.cpp | 3 ++ kernel/kernel/Terminal/Serial.cpp | 2 +- kernel/kernel/Terminal/TTY.cpp | 39 +++++++++++++++++++++ kernel/kernel/Terminal/VirtualTTY.cpp | 2 +- libc/CMakeLists.txt | 1 + libc/include/sys/banan-os.h | 25 +++++++++++++ libc/include/sys/syscall.h | 1 + libc/sys/banan-os.cpp | 8 +++++ 13 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 libc/include/sys/banan-os.h create mode 100644 libc/sys/banan-os.cpp diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 62e6de54ce..f91cd54f5f 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 41cb7dd074..b53310aab7 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 f98268c64d..0cb81befcd 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 ac9879ee54..3f3fdbf458 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 47149c5b22..76c6a333f4 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 f48f0ee53b..68bcd57554 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 fd2109a7ca..ec71c97b11 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 44d475e438..e2c50884f0 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 d8896c5407..a5fe142b7f 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 48f3f62836..76c4f766fd 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 0000000000..9db8b93c45 --- /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 dd8052e24d..a0f97ea154 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 0000000000..cc471928e6 --- /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); +}