From 396ad681ba974609e2ad0c172e0fe751e1bc3628 Mon Sep 17 00:00:00 2001 From: EnderIce2 Date: Sun, 13 Oct 2024 13:00:22 +0300 Subject: [PATCH] tty: Fix kcon & tty implementation; Add stub ptmx --- core/console.cpp | 97 ------------ core/driver/daemon.cpp | 230 ++++++++++++++++++++++++++-- exec/spawn.cpp | 4 + include/driver.hpp | 1 + include/filesystem/mounts.hpp | 76 ---------- include/kcon.hpp | 17 ++- include/task.hpp | 1 + include/tty.hpp | 130 ++++++++++++++++ kernel.cpp | 1 - kernel.h | 2 +- kernel_vfs.cpp | 1 - storage/devices/tty/ptmx.cpp | 90 ----------- storage/devices/tty/pty.cpp | 69 --------- tasking/process.cpp | 5 + tty/ptmx.cpp | 66 ++++++++ tty/pty.cpp | 95 ++++++++++++ tty/teletype.cpp | 141 ++++++++++++++++++ {core => tty}/vt.cpp | 273 +++++++++++++++++++++++++++------- 18 files changed, 895 insertions(+), 404 deletions(-) delete mode 100644 include/filesystem/mounts.hpp create mode 100644 include/tty.hpp delete mode 100644 storage/devices/tty/ptmx.cpp delete mode 100644 storage/devices/tty/pty.cpp create mode 100644 tty/ptmx.cpp create mode 100644 tty/pty.cpp create mode 100644 tty/teletype.cpp rename {core => tty}/vt.cpp (58%) diff --git a/core/console.cpp b/core/console.cpp index 4c959d0..a70079d 100644 --- a/core/console.cpp +++ b/core/console.cpp @@ -17,7 +17,6 @@ #include -#include #include #include #include @@ -27,100 +26,6 @@ namespace KernelConsole { - int KConIoctl(struct Inode *Node, unsigned long Request, void *Argp) - { - fixme("KConIoctl"); - switch (Request) - { - case TCGETS: - { - struct termios *t = (struct termios *)Argp; - // memcpy(t, &term, sizeof(struct termios)); - return 0; - } - case TCSETS: - { - debug("TCSETS not supported"); - return -EINVAL; - - struct termios *t = (struct termios *)Argp; - // memcpy(&term, t, sizeof(struct termios)); - return 0; - } - case TIOCGPGRP: - { - *((pid_t *)Argp) = 0; - return 0; - } - case TIOCSPGRP: - { - *((pid_t *)Argp) = 0; - return 0; - } - case TIOCGWINSZ: - { - struct winsize *ws = (struct winsize *)Argp; - // memcpy(ws, &termSize, sizeof(struct winsize)); - return 0; - } - case TIOCSWINSZ: - { - debug("TIOCSWINSZ not supported"); - return -EINVAL; - - struct winsize *ws = (struct winsize *)Argp; - // memcpy(&termSize, ws, sizeof(struct winsize)); - return 0; - } - case TCSETSW: - case TCSETSF: - case TCGETA: - case TCSETA: - case TCSETAW: - case TCSETAF: - case TCSBRK: - case TCXONC: - case TCFLSH: - case TIOCEXCL: - case TIOCNXCL: - case TIOCSCTTY: - case TIOCOUTQ: - case TIOCSTI: - case TIOCMGET: - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - { - fixme("ioctl %#lx not implemented", Request); - return -ENOSYS; - } - case TIOCGPTN: - case 0xffffffff80045430: /* FIXME: ???? */ - { - fixme("stub ioctl %#lx", Request); - - int *n = (int *)Argp; - *n = -1; - break; - } - case TIOCSPTLCK: - { - fixme("stub ioctl %#lx", Request); - - int *n = (int *)Argp; - *n = 0; - break; - } - default: - { - debug("Unknown ioctl %#lx", Request); - return -EINVAL; - } - } - - return 0; - } - int TermColors[] = { [TerminalColor::BLACK] = 0x000000, [TerminalColor::RED] = 0xAA0000, @@ -369,8 +274,6 @@ namespace KernelConsole void LateInit() { - new vfs::PTMXDevice; - FileNode *rn = fs->GetByPath("/etc/term", thisProcess->Info.RootNode); if (rn == nullptr) return; diff --git a/core/driver/daemon.cpp b/core/driver/daemon.cpp index b6cad3d..a3bd54f 100644 --- a/core/driver/daemon.cpp +++ b/core/driver/daemon.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,8 @@ namespace Driver * 4 - /dev/random * 5 - /dev/mem * 6 - /dev/kcon + * 7 - /dev/tty + * 8 - /dev/ptmx * * maj = 1 * min: @@ -52,9 +55,13 @@ namespace Driver * ..- /dev/input/eventX */ + TTY::PTMXDevice *ptmx = nullptr; + int __fs_Lookup(struct Inode *_Parent, const char *Name, struct Inode **Result) { - auto Parent = (Manager::DeviceInode *)_Parent; + func("%#lx %s %#lx", _Parent, Name, Result); + + assert(_Parent != nullptr); const char *basename; size_t length; @@ -65,9 +72,10 @@ namespace Driver return -EINVAL; } + auto Parent = (Manager::DeviceInode *)_Parent; for (const auto &child : Parent->Children) { - debug("Comparing %s with %s", child->Name.c_str(), basename); + debug("Comparing %s with %s", basename, child->Name.c_str()); if (strcmp(child->Name.c_str(), basename) != 0) continue; @@ -81,6 +89,8 @@ namespace Driver int __fs_Create(struct Inode *_Parent, const char *Name, mode_t Mode, struct Inode **Result) { + func("%#lx %s %d", _Parent, Name, Mode); + assert(_Parent != nullptr); /* We expect to be /dev or children of it */ @@ -99,6 +109,7 @@ namespace Driver ssize_t __fs_Read(struct Inode *Node, void *Buffer, size_t Size, off_t Offset) { + func("%#lx %d %d", Node, Size, Offset); switch (Node->GetMajor()) { case 0: @@ -141,10 +152,11 @@ namespace Driver return 0; } case 6: /* /dev/kcon */ - { - stub; - return 0; - } + return KernelConsole::CurrentTerminal.load()->Read(Buffer, Size, Offset); + case 7: /* /dev/tty */ + return ((TTY::TeletypeDriver *)thisProcess->tty)->Read(Buffer, Size, Offset); + case 8: /* /dev/ptmx */ + return -ENOSYS; default: return -ENOENT; }; @@ -210,6 +222,8 @@ namespace Driver ssize_t __fs_Write(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset) { + func("%#lx %p %d %d", Node, Buffer, Size, Offset); + switch (Node->GetMajor()) { case 0: @@ -234,13 +248,11 @@ namespace Driver return 0; } case 6: /* /dev/kcon */ - { - char *buf = (char *)Buffer; - KernelConsole::VirtualTerminal *vt = KernelConsole::CurrentTerminal.load(); - for (size_t i = 0; i < Size; i++) - vt->Process(buf[i]); - return Size; - } + return KernelConsole::CurrentTerminal.load()->Write(Buffer, Size, Offset); + case 7: /* /dev/tty */ + return ((TTY::TeletypeDriver *)thisProcess->tty)->Write(Buffer, Size, Offset); + case 8: /* /dev/ptmx */ + return -ENOSYS; default: return -ENOENT; }; @@ -281,9 +293,180 @@ namespace Driver } } + int __fs_Open(struct Inode *Node, int Flags, mode_t Mode) + { + func("%#lx %d %d", Node, Flags, Mode); + + switch (Node->GetMajor()) + { + case 0: + { + switch (Node->GetMinor()) + { + case 2: /* /dev/null */ + case 3: /* /dev/zero */ + case 4: /* /dev/random */ + case 5: /* /dev/mem */ + return -ENOSYS; + case 6: /* /dev/kcon */ + return KernelConsole::CurrentTerminal.load()->Open(Flags, Mode); + case 7: /* /dev/tty */ + return ((TTY::TeletypeDriver *)thisProcess->tty)->Open(Flags, Mode); + case 8: /* /dev/ptmx */ + return ptmx->Open(); + default: + return -ENOENT; + }; + } + case 1: + { + switch (Node->GetMinor()) + { + case 0: /* /dev/input/keyboard */ + case 1: /* /dev/input/mouse */ + return -ENOTSUP; + default: + return -ENOENT; + }; + } + default: + { + std::unordered_map &drivers = + DriverManager->GetDrivers(); + const auto it = drivers.find(Node->GetMajor()); + if (it == drivers.end()) + ReturnLogError(-EINVAL, "Driver %d not found", Node->GetMajor()); + const Driver::DriverObject *drv = &it->second; + + auto dop = drv->DeviceOperations; + auto dOps = dop->find(Node->GetMinor()); + if (dOps == dop->end()) + ReturnLogError(-EINVAL, "Device %d not found", Node->GetMinor()); + AssertReturnError(dOps->second.Ops, -ENOTSUP); + AssertReturnError(dOps->second.Ops->Open, -ENOTSUP); + return dOps->second.Ops->Open(Node, Flags, Mode); + } + } + } + + int __fs_Close(struct Inode *Node) + { + func("%#lx", Node); + + switch (Node->GetMajor()) + { + case 0: + { + switch (Node->GetMinor()) + { + case 2: /* /dev/null */ + case 3: /* /dev/zero */ + case 4: /* /dev/random */ + case 5: /* /dev/mem */ + return -ENOSYS; + case 6: /* /dev/kcon */ + return KernelConsole::CurrentTerminal.load()->Close(); + case 7: /* /dev/tty */ + return ((TTY::TeletypeDriver *)thisProcess->tty)->Close(); + case 8: /* /dev/ptmx */ + return ptmx->Close(); + default: + return -ENOENT; + }; + } + case 1: + { + switch (Node->GetMinor()) + { + case 0: /* /dev/input/keyboard */ + case 1: /* /dev/input/mouse */ + return -ENOTSUP; + default: + return -ENOENT; + }; + } + default: + { + std::unordered_map &drivers = + DriverManager->GetDrivers(); + const auto it = drivers.find(Node->GetMajor()); + if (it == drivers.end()) + ReturnLogError(-EINVAL, "Driver %d not found", Node->GetMajor()); + const Driver::DriverObject *drv = &it->second; + + auto dop = drv->DeviceOperations; + auto dOps = dop->find(Node->GetMinor()); + if (dOps == dop->end()) + ReturnLogError(-EINVAL, "Device %d not found", Node->GetMinor()); + AssertReturnError(dOps->second.Ops, -ENOTSUP); + AssertReturnError(dOps->second.Ops->Close, -ENOTSUP); + return dOps->second.Ops->Close(Node); + } + } + } + + int __fs_Ioctl(struct Inode *Node, unsigned long Request, void *Argp) + { + func("%#lx %lu %#lx", Node, Request, Argp); + + switch (Node->GetMajor()) + { + case 0: + { + switch (Node->GetMinor()) + { + case 2: /* /dev/null */ + case 3: /* /dev/zero */ + case 4: /* /dev/random */ + case 5: /* /dev/mem */ + return -ENOSYS; + case 6: /* /dev/kcon */ + return KernelConsole::CurrentTerminal.load()->Ioctl(Request, Argp); + case 7: /* /dev/tty */ + return ((TTY::TeletypeDriver *)thisProcess->tty)->Ioctl(Request, Argp); + case 8: /* /dev/ptmx */ + return -ENOSYS; + default: + return -ENOENT; + }; + break; + } + case 1: + { + switch (Node->GetMinor()) + { + case 0: /* /dev/input/keyboard */ + case 1: /* /dev/input/mouse */ + return -ENOSYS; + default: + return -ENOENT; + }; + } + default: + { + std::unordered_map &drivers = + DriverManager->GetDrivers(); + const auto it = drivers.find(Node->GetMajor()); + if (it == drivers.end()) + ReturnLogError(-EINVAL, "Driver %d not found", Node->GetMajor()); + const Driver::DriverObject *drv = &it->second; + + auto dop = drv->DeviceOperations; + auto dOps = dop->find(Node->GetMinor()); + if (dOps == dop->end()) + ReturnLogError(-EINVAL, "Device %d not found", Node->GetMinor()); + AssertReturnError(dOps->second.Ops, -ENOTSUP); + AssertReturnError(dOps->second.Ops->Ioctl, -ENOTSUP); + return dOps->second.Ops->Ioctl(Node, Request, Argp); + } + } + } + __no_sanitize("alignment") ssize_t __fs_Readdir(struct Inode *_Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries) { + func("%#lx %#lx %d %d %d", _Node, Buffer, Size, Offset, Entries); + auto Node = (Manager::DeviceInode *)_Node; off_t realOffset = Offset; @@ -545,6 +728,8 @@ namespace Driver void Manager::InitializeDaemonFS() { + ptmx = new TTY::PTMXDevice; + dev_t MinorID = 0; DeviceInode *_dev = new DeviceInode; _dev->Name = "dev"; @@ -559,7 +744,7 @@ namespace Driver dev->Flags = I_FLAG_MOUNTPOINT | I_FLAG_CACHE_KEEP; FileSystemInfo *fsi = new FileSystemInfo; - fsi->Name = "Driver Manager"; + fsi->Name = "Device Virtual File System"; fsi->RootName = "dev"; fsi->Flags = I_FLAG_ROOT | I_FLAG_MOUNTPOINT | I_FLAG_CACHE_KEEP; fsi->SuperOps = {}; @@ -567,6 +752,9 @@ namespace Driver fsi->Ops.Create = __fs_Create; fsi->Ops.Read = __fs_Read; fsi->Ops.Write = __fs_Write; + fsi->Ops.Open = __fs_Open; + fsi->Ops.Close = __fs_Close; + fsi->Ops.Ioctl = __fs_Ioctl; fsi->Ops.ReadDir = __fs_Readdir; dev->Device = fs->RegisterFileSystem(fsi, dev); @@ -642,6 +830,20 @@ namespace Driver S_IFCHR; createDevice(_dev, devNode, "kcon", 0, MinorID++, mode); + /* c rw- rw- rw- */ + mode = S_IRUSR | S_IWUSR | + S_IRGRP | S_IWGRP | + S_IRUSR | S_IWUSR | + S_IFCHR; + createDevice(_dev, devNode, "tty", 0, MinorID++, mode); + + /* c rw- rw- rw- */ + mode = S_IRUSR | S_IWUSR | + S_IRGRP | S_IWGRP | + S_IRUSR | S_IWUSR | + S_IFCHR; + createDevice(_dev, devNode, "ptmx", 0, MinorID++, mode); + /* ------------------------------------------------------ */ MinorID = 0; diff --git a/exec/spawn.cpp b/exec/spawn.cpp index 7885f25..e068b3f 100644 --- a/exec/spawn.cpp +++ b/exec/spawn.cpp @@ -157,6 +157,10 @@ namespace Execute return false; }; + fixme("remove workarounds for stdio and tty"); + if (!Parent->tty) + Process->tty = KernelConsole::CurrentTerminal.load(); + if (!ForkStdio(Parent->stdin)) fdt->usr_open("/dev/kcon", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); diff --git a/include/driver.hpp b/include/driver.hpp index 4f5aa9e..6333dd6 100644 --- a/include/driver.hpp +++ b/include/driver.hpp @@ -93,6 +93,7 @@ namespace Driver FileNode *devNode = nullptr; FileNode *devInputNode = nullptr; + int LoadDriverFile(DriverObject &Drv, FileNode *File); void InitializeDaemonFS(); diff --git a/include/filesystem/mounts.hpp b/include/filesystem/mounts.hpp deleted file mode 100644 index 793a451..0000000 --- a/include/filesystem/mounts.hpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#ifndef __FENNIX_KERNEL_FILESYSTEM_DEV_H__ -#define __FENNIX_KERNEL_FILESYSTEM_DEV_H__ - -#include - -#include -#include -#include -#include -#include - -namespace vfs -{ - class PTYDevice - { - private: - Inode *pts; - int id; - termios term{}; - winsize termSize{}; - - class PTYSlave - { - }; - - class PTYMaster - { - }; - - public: - decltype(id) &ptyId = id; - - ssize_t Read(struct Inode *Node, void *Buffer, size_t Size, off_t Offset); - ssize_t Write(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset); - int Ioctl(struct Inode *Node, unsigned long Request, void *Argp); - - PTYDevice(Inode *pts, int id); - ~PTYDevice(); - }; - - class PTMXDevice - { - private: - NewLock(PTMXLock); - FileNode *ptmx; - FileNode *pts; - Bitmap ptysId; - std::unordered_map ptysList; - - public: - int Open(struct Inode *Node, int Flags, mode_t Mode, struct Inode *Result); - int Close(struct Inode *Node); - - PTMXDevice(); - ~PTMXDevice(); - }; -} - -#endif // !__FENNIX_KERNEL_FILESYSTEM_DEV_H__ diff --git a/include/kcon.hpp b/include/kcon.hpp index c57ecd9..2644f1f 100644 --- a/include/kcon.hpp +++ b/include/kcon.hpp @@ -19,8 +19,7 @@ #define __FENNIX_KERNEL_KERNEL_CONSOLE_H__ #include -#include -#include +#include namespace KernelConsole { @@ -86,7 +85,7 @@ namespace KernelConsole char Paint(long CellX, long CellY, char Char, uint32_t Foreground, uint32_t Background); }; - class VirtualTerminal + class VirtualTerminal : public TTY::TeletypeDriver { private: ANSIParser Parser{}; @@ -98,9 +97,17 @@ namespace KernelConsole PaintCallback PaintCB = nullptr; CursorCallback CursorCB = nullptr; + std::mutex Mutex; + public: - termios term; - winsize termSize; + termios *GetTermios() { return &this->TerminalConfig; } + winsize *GetWinsize() { return &this->TerminalSize; } + + int Open(int Flags, mode_t Mode) final; + int Close() final; + ssize_t Read(void *Buffer, size_t Size, off_t Offset) final; + ssize_t Write(const void *Buffer, size_t Size, off_t Offset) final; + int Ioctl(unsigned long Request, void *Argp) final; void Clear(unsigned short StartX, unsigned short StartY, unsigned short EndX, unsigned short EndY); void Scroll(unsigned short Lines); diff --git a/include/task.hpp b/include/task.hpp index b796c91..6f645d7 100644 --- a/include/task.hpp +++ b/include/task.hpp @@ -484,6 +484,7 @@ namespace Tasking FileNode *stdin; FileNode *stdout; FileNode *stderr; + /*TTY::TeletypeDriver*/ void *tty; /* Memory */ Memory::PageTable *PageTable; diff --git a/include/tty.hpp b/include/tty.hpp new file mode 100644 index 0000000..940a5a4 --- /dev/null +++ b/include/tty.hpp @@ -0,0 +1,130 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#ifndef __FENNIX_KERNEL_TTY_H__ +#define __FENNIX_KERNEL_TTY_H__ + +#include +#include + +namespace TTY +{ + class TerminalBuffer + { + private: + std::vector Buffer; + size_t ReadIndex; + size_t WriteIndex; + std::mutex Mutex; + + public: + TerminalBuffer(size_t Size) : Buffer(Size), ReadIndex(0), WriteIndex(0) {} + + ssize_t Read(char *OutputBuffer, size_t Size); + ssize_t Write(const char *InputBuffer, size_t Size); + + void DrainOutput() + { + std::lock_guard lock(Mutex); + ReadIndex = WriteIndex; + } + + size_t AvailableToRead() const + { + return (WriteIndex - ReadIndex + Buffer.size()) % Buffer.size(); + } + + size_t AvailableToWrite() const + { + return Buffer.size() - AvailableToRead() - 1; + } + }; + + class TeletypeDriver + { + protected: + termios TerminalConfig; + winsize TerminalSize; + TerminalBuffer TermBuf; + + public: + virtual int Open(int Flags, mode_t Mode); + virtual int Close(); + virtual ssize_t Read(void *Buffer, size_t Size, off_t Offset); + virtual ssize_t Write(const void *Buffer, size_t Size, off_t Offset); + virtual int Ioctl(unsigned long Request, void *Argp); + + TeletypeDriver(); + virtual ~TeletypeDriver(); + }; + + class PTYDevice + { + private: + class PTYMaster + { + private: + TerminalBuffer TermBuf; + + public: + PTYMaster(); + ~PTYMaster(); + ssize_t Read(void *Buffer, size_t Size); + ssize_t Write(const void *Buffer, size_t Size); + }; + + class PTYSlave + { + private: + TerminalBuffer TermBuf; + + public: + PTYSlave(); + ~PTYSlave(); + ssize_t Read(void *Buffer, size_t Size); + ssize_t Write(const void *Buffer, size_t Size); + }; + + PTYMaster Master; + PTYSlave Slave; + + public: + PTYDevice(); + ~PTYDevice(); + int Open(); + int Close(); + ssize_t Read(void *Buffer, size_t Size); + ssize_t Write(const void *Buffer, size_t Size); + }; + + class PTMXDevice + { + private: + std::vector PTYs; + std::mutex PTYMutex; + + public: + PTMXDevice(); + ~PTMXDevice(); + int Open(); + int Close(); + PTYDevice *CreatePTY(); + int RemovePTY(PTYDevice *pty); + }; +} + +#endif // !__FENNIX_KERNEL_TTY_H__ diff --git a/kernel.cpp b/kernel.cpp index 97e5427..50bd47f 100644 --- a/kernel.cpp +++ b/kernel.cpp @@ -17,7 +17,6 @@ #include "kernel.h" -#include #include #include #include diff --git a/kernel.h b/kernel.h index 463acde..85368ee 100644 --- a/kernel.h +++ b/kernel.h @@ -22,7 +22,6 @@ #include #ifdef __cplusplus -#include #include #include #include @@ -34,6 +33,7 @@ #include #include #include +#include #include #include #endif diff --git a/kernel_vfs.cpp b/kernel_vfs.cpp index 20e949c..965f6ab 100644 --- a/kernel_vfs.cpp +++ b/kernel_vfs.cpp @@ -17,7 +17,6 @@ #include "kernel.h" -#include #include #include diff --git a/storage/devices/tty/ptmx.cpp b/storage/devices/tty/ptmx.cpp deleted file mode 100644 index 01ea442..0000000 --- a/storage/devices/tty/ptmx.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include -#include -#include -#include - -#include "../../../kernel.h" - -namespace vfs -{ - int PTMXDevice::Open(Inode *Node, int Flags, mode_t Mode, struct Inode *Result) - { - // SmartLock(PTMXLock); - - // int ptyID = -1; - // for (int i = 0; i < (int)ptysId.Size; i++) - // { - // if (ptysId.Buffer[i]) - // continue; - - // ptyID = i; - // ptysId.Buffer[i] = true; - // break; - // } - - // if (ptyID == -1) - // return -ENFILE; - - // PTYDevice *pty = new PTYDevice(pts, ptyID); - // ptysList.insert(std::make_pair(ptyID, pty)); - // // return pty->OpenMaster(Flags, Mode); - assert(!"Function not implemented"); - } - - int PTMXDevice::Close(struct Inode *Node) - { - SmartLock(PTMXLock); - - PTYDevice *pty = ptysList.at(Node->Index); - ptysList.erase(Node->Index); - assert(!"Function not implemented"); - } - - PTMXDevice::PTMXDevice() - { - fixme("PTMXDevice"); - // /* c rw- rw- rw- */ - // mode_t mode = S_IRUSR | S_IWUSR | - // S_IRGRP | S_IWGRP | - // S_IROTH | S_IWOTH | - // S_IFCHR; - - // ptmx = fs->Create(ptmx, "pts", mode); - // assert(!"Function not implemented"); - // // ptmx->SetDevice(5, 2); - - // /* d rwx r-x r-x */ - // mode_t ptsMode = S_IRWXU | - // S_IRGRP | S_IXGRP | - // S_IROTH | S_IXOTH | - // S_IFDIR; - // pts = fs->Create(ptmx, "pts", ptsMode); - // assert(pts != nullptr); - - // ptysId.Buffer = new uint8_t[0x1000]; - // ptysId.Size = 0x1000; - } - - PTMXDevice::~PTMXDevice() - { - SmartLock(PTMXLock); - delete[] ptysId.Buffer; - } -} diff --git a/storage/devices/tty/pty.cpp b/storage/devices/tty/pty.cpp deleted file mode 100644 index 249979b..0000000 --- a/storage/devices/tty/pty.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include -#include -#include -#include - -#include "../../../kernel.h" - -namespace vfs -{ - PTYDevice::PTYDevice(Inode *_pts, int _id) - { - assert(!"Function not implemented"); - char nameBuffer[16]; - snprintf(nameBuffer, 16, "%d", id); - // this->Name = strdup(nameBuffer); - - /* - - ICRNL - Map Carriage Return to New Line - - IXON - Enable XON/XOFF flow control - - - OPOST - Enable output processing - - ONLCR - Map New Line to Carriage Return - New Line - - - CS8 - 8-bit characters - - CREAD - Enable receiver - - HUPCL - Hang up on last close - - - ECHO - Echo input characters - - ICANON - Enable canonical input (enable line editing) - */ - this->term.c_iflag = /*ICRNL |*/ IXON; - this->term.c_oflag = OPOST | ONLCR; - this->term.c_cflag = CS8 | CREAD | HUPCL; - this->term.c_lflag = ECHO | ICANON; - this->term.c_cc[VEOF] = 0x04; /* ^D */ - this->term.c_cc[VEOL] = 0x00; /* NUL */ - this->term.c_cc[VERASE] = 0x7f; /* DEL */ - this->term.c_cc[VINTR] = 0x03; /* ^C */ - this->term.c_cc[VKILL] = 0x15; /* ^U */ - this->term.c_cc[VMIN] = 1; /* Minimum number of characters for non-canonical read */ - this->term.c_cc[VQUIT] = 0x1c; /* ^\ */ - this->term.c_cc[VSTART] = 0x11; /* ^Q */ - this->term.c_cc[VSTOP] = 0x13; /* ^S */ - this->term.c_cc[VSUSP] = 0x1a; /* ^Z */ - this->term.c_cc[VTIME] = 0; /* Timeout for non-canonical read */ - this->term.c_cc[VWERASE] = 0x17; /* ^W */ - - // debug("Created PTY device %s", this->Name); - } - - PTYDevice::~PTYDevice() {} -} diff --git a/tasking/process.cpp b/tasking/process.cpp index 5b7c9f6..55ceb1a 100644 --- a/tasking/process.cpp +++ b/tasking/process.cpp @@ -213,6 +213,7 @@ namespace Tasking } this->FileDescriptors = new FileDescriptorTable(this); + this->tty = nullptr; /* If create page table */ if (UseKernelPageTable == false) @@ -268,6 +269,10 @@ namespace Tasking debug("Closing file descriptors"); delete this->FileDescriptors; + debug("Deleting tty"); + if (this->tty) + delete ((TTY::TeletypeDriver *)this->tty); + /* If we own the pointer to the PageTable, we need to free it */ if (this->PageTable && OwnPageTable) diff --git a/tty/ptmx.cpp b/tty/ptmx.cpp new file mode 100644 index 0000000..293e101 --- /dev/null +++ b/tty/ptmx.cpp @@ -0,0 +1,66 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include +#include +#include + +#include "../kernel.h" + +namespace TTY +{ + PTMXDevice::PTMXDevice() + { + } + + PTMXDevice::~PTMXDevice() + { + for (auto pty : PTYs) + delete pty; + } + + int PTMXDevice::Open() + { + stub; + return -ENOSYS; + } + + int PTMXDevice::Close() + { + stub; + return -ENOSYS; + } + + PTYDevice *PTMXDevice::CreatePTY() + { + std::lock_guard lock(PTYMutex); + PTYDevice *pty = new PTYDevice(); + PTYs.push_back(pty); + return pty; + } + + int PTMXDevice::RemovePTY(PTYDevice *pty) + { + std::lock_guard lock(PTYMutex); + auto it = PTYs.erase(std::remove(PTYs.begin(), PTYs.end(), pty), PTYs.end()); + if (it == PTYs.end()) + return -ENOENT; + delete pty; + return 0; + } +} diff --git a/tty/pty.cpp b/tty/pty.cpp new file mode 100644 index 0000000..0373387 --- /dev/null +++ b/tty/pty.cpp @@ -0,0 +1,95 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include +#include +#include + +#include "../kernel.h" + +namespace TTY +{ + PTYDevice::PTYDevice() + : Master(), Slave() + { + } + + PTYDevice::~PTYDevice() + { + } + + int PTYDevice::Open() + { + stub; + return -ENOSYS; + } + + int PTYDevice::Close() + { + stub; + return -ENOSYS; + } + + ssize_t PTYDevice::Read(void *Buffer, size_t Size) + { + return Slave.Read(Buffer, Size); + } + + ssize_t PTYDevice::Write(const void *Buffer, size_t Size) + { + return Master.Write(Buffer, Size); + } + + PTYDevice::PTYMaster::PTYMaster() + : TermBuf(1024) + { + } + + PTYDevice::PTYMaster::~PTYMaster() + { + } + + ssize_t PTYDevice::PTYMaster::Read(void *Buffer, size_t Size) + { + return TermBuf.Read((char *)Buffer, Size); + } + + ssize_t PTYDevice::PTYMaster::Write(const void *Buffer, size_t Size) + { + return TermBuf.Write((const char *)Buffer, Size); + } + + PTYDevice::PTYSlave::PTYSlave() + : TermBuf(1024) + { + } + + PTYDevice::PTYSlave::~PTYSlave() + { + } + + ssize_t PTYDevice::PTYSlave::Read(void *Buffer, size_t Size) + { + return TermBuf.Read((char *)Buffer, Size); + } + + ssize_t PTYDevice::PTYSlave::Write(const void *Buffer, size_t Size) + { + return TermBuf.Write((const char *)Buffer, Size); + } +} diff --git a/tty/teletype.cpp b/tty/teletype.cpp new file mode 100644 index 0000000..54d1a5a --- /dev/null +++ b/tty/teletype.cpp @@ -0,0 +1,141 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include +#include +#include + +#include "../kernel.h" + +namespace TTY +{ + ssize_t TerminalBuffer::Read(char *OutputBuffer, size_t Size) + { + std::lock_guard lock(Mutex); + size_t bytesRead = 0; + + while (bytesRead < Size && ReadIndex != WriteIndex) + { + OutputBuffer[bytesRead++] = Buffer[ReadIndex]; + ReadIndex = (ReadIndex + 1) % Buffer.size(); + } + + return bytesRead; + } + + ssize_t TerminalBuffer::Write(const char *InputBuffer, size_t Size) + { + std::lock_guard lock(Mutex); + size_t bytesWritten = 0; + + for (size_t i = 0; i < Size; ++i) + { + Buffer[WriteIndex] = InputBuffer[i]; + WriteIndex = (WriteIndex + 1) % Buffer.size(); + bytesWritten++; + } + + return bytesWritten; + } + + /* ======================================================================== */ + + int TeletypeDriver::Open(int Flags, mode_t Mode) + { + warn("Unimplemented open(%#x, %#x)", Flags, Mode); + return -ENOSYS; + } + + int TeletypeDriver::Close() + { + warn("Unimplemented close()"); + return -ENOSYS; + } + + ssize_t TeletypeDriver::Read(void *Buffer, size_t Size, off_t Offset) + { + warn("Unimplemented read(%#lx, %#lx, %#lx)", Buffer, Size, Offset); + return -ENOSYS; + } + + ssize_t TeletypeDriver::Write(const void *Buffer, size_t Size, off_t Offset) + { + warn("Unimplemented write(%#lx, %#lx, %#lx)", Buffer, Size, Offset); + return -ENOSYS; + } + + int TeletypeDriver::Ioctl(unsigned long Request, void *Argp) + { + warn("Unimplemented ioctl(%#lx, %#lx)", Request, Argp); + return -ENOSYS; + } + + TeletypeDriver::TeletypeDriver() + : TermBuf(1024) + { + this->TerminalSize = { + .ws_row = 0, + .ws_col = 0, + .ws_xpixel = 0, + .ws_ypixel = 0, + }; + + /* + - ICRNL - Map Carriage Return to New Line + - IXON - Enable XON/XOFF flow control + + - OPOST - Enable output processing + - ONLCR - Map New Line to Carriage Return - New Line + + - CS8 - 8-bit characters + - CREAD - Enable receiver + - HUPCL - Hang up on last close + + - ECHO - Echo input characters + - ICANON - Enable canonical input (enable line editing) + */ + this->TerminalConfig.c_iflag = /*ICRNL |*/ IXON; + this->TerminalConfig.c_oflag = OPOST | ONLCR; + this->TerminalConfig.c_cflag = CS8 | CREAD | HUPCL; + this->TerminalConfig.c_lflag = ECHO | ICANON; + + this->TerminalConfig.c_cc[VINTR] = 0x03; /* ^C */ + this->TerminalConfig.c_cc[VQUIT] = 0x1C; /* ^\ */ + this->TerminalConfig.c_cc[VERASE] = 0x7F; /* DEL */ + this->TerminalConfig.c_cc[VKILL] = 0x15; /* ^U */ + this->TerminalConfig.c_cc[VEOF] = 0x04; /* ^D */ + this->TerminalConfig.c_cc[VTIME] = 0; /* Timeout for non-canonical read */ + this->TerminalConfig.c_cc[VMIN] = 1; /* Minimum number of characters for non-canonical read */ + this->TerminalConfig.c_cc[VSWTC] = 0; /* ^O */ + this->TerminalConfig.c_cc[VSTART] = 0x11; /* ^Q */ + this->TerminalConfig.c_cc[VSTOP] = 0x13; /* ^S */ + this->TerminalConfig.c_cc[VSUSP] = 0x1A; /* ^Z */ + this->TerminalConfig.c_cc[VEOL] = 0x00; /* NUL */ + this->TerminalConfig.c_cc[VREPRINT] = 0x12; /* ^R */ + this->TerminalConfig.c_cc[VDISCARD] = 0x14; /* ^T */ + this->TerminalConfig.c_cc[VWERASE] = 0x17; /* ^W */ + this->TerminalConfig.c_cc[VLNEXT] = 0x19; /* ^Y */ + this->TerminalConfig.c_cc[VEOL2] = 0x7F; /* DEL (or sometimes EOF) */ + } + + TeletypeDriver::~TeletypeDriver() + { + } +} diff --git a/core/vt.cpp b/tty/vt.cpp similarity index 58% rename from core/vt.cpp rename to tty/vt.cpp index 39568d4..d1c2e85 100644 --- a/core/vt.cpp +++ b/tty/vt.cpp @@ -17,6 +17,7 @@ #include +#include #include #include #include @@ -26,16 +27,184 @@ namespace KernelConsole { + int VirtualTerminal::Open(int Flags, mode_t Mode) + { + std::lock_guard lock(Mutex); + stub; + return 0; + } + + int VirtualTerminal::Close() + { + std::lock_guard lock(Mutex); + stub; + return 0; + } + + ssize_t VirtualTerminal::Read(void *Buffer, size_t Size, off_t Offset) + { + std::lock_guard lock(Mutex); + + KeyboardReport report{}; + + /* FIXME: this is a hack, "static" is not a good idea */ + static bool upperCase = false; + + RecheckKeyboard: + while (DriverManager->GlobalKeyboardInputReports.Count() == 0) + TaskManager->Yield(); + + DriverManager->GlobalKeyboardInputReports.Read(&report, sizeof(report)); + + int pkey = report.Key & ~KEY_PRESSED; + if (pkey == KEY_LEFT_SHIFT || pkey == KEY_RIGHT_SHIFT) + { + if (report.Key & KEY_PRESSED) + upperCase = true; + else + upperCase = false; + goto RecheckKeyboard; + } + + if (!(report.Key & KEY_PRESSED)) + goto RecheckKeyboard; + + if (!Driver::IsValidChar(report.Key)) + goto RecheckKeyboard; + + char c = Driver::GetScanCode(report.Key, upperCase); + char *buf = (char *)Buffer; + buf[0] = c; + debug("KCON: %c", c); + + if (this->TerminalConfig.c_lflag & ECHO) + { + debug("ECHO"); + if (this->TerminalConfig.c_lflag & ICANON) + this->Process(buf[0]); + else + this->Append(buf[0]); + } + + if (this->TerminalConfig.c_lflag & ICANON) + { + fixme("ICANON"); + // if (pkey == KEY_RETURN) + // { + // + // return bufLength; + // } + } + else + { + debug("~ICANON"); + } + + debug("ret 1"); + return 1; + } + + ssize_t VirtualTerminal::Write(const void *Buffer, size_t Size, off_t Offset) + { + std::lock_guard lock(Mutex); + + char *buf = (char *)Buffer; + debug("string: \"%*s\"", Size, buf); + for (size_t i = 0; i < Size; i++) + { + if (this->TerminalConfig.c_lflag & ICANON) + this->Process(buf[i]); + else + this->Append(buf[i]); + } + + debug("ret %ld", Size); + return Size; + } + + int VirtualTerminal::Ioctl(unsigned long Request, void *Argp) + { + std::lock_guard lock(Mutex); + + switch (Request) + { + case 0xffffffff80045430: /* FIXME: ???? */ + debug("???"); + [[fallthrough]]; + case TIOCGPTN: + { + fixme("stub ioctl TIOCGPTN"); + + int *n = (int *)Argp; + *n = -1; + return 0; + } + case TIOCSPTLCK: + { + fixme("stub ioctl TIOCSPTLCK"); + + int *n = (int *)Argp; + *n = 0; + return 0; + } + case TCGETS: + { + struct termios *t = (struct termios *)Argp; + *t = TerminalConfig; + return 0; + } + case TCSETSW: + { + debug("draining output buffer..."); + TermBuf.DrainOutput(); + debug("output buffer drained"); + + TerminalConfig = *(struct termios *)Argp; + return 0; + } + case TIOCGWINSZ: + { + struct winsize *ws = (struct winsize *)Argp; + *ws = TerminalSize; + return 0; + } + case TIOCGPGRP: + { + *((pid_t *)Argp) = thisProcess->Security.ProcessGroupID; + debug("returning pgid %d", thisProcess->Security.ProcessGroupID); + return 0; + } + case TIOCSPGRP: + { + thisProcess->Security.ProcessGroupID = *((pid_t *)Argp); + debug("updated pgid to %d", thisProcess->Security.ProcessGroupID); + return 0; + } + case TIOCGSID: + { + *((pid_t *)Argp) = thisProcess->Security.SessionID; + debug("returning sid %d", thisProcess->Security.SessionID); + return 0; + } + + default: + { + debug("Unknown ioctl %#lx", Request); + return -ENOTSUP; + } + } + } + void VirtualTerminal::Clear(unsigned short StartX, unsigned short StartY, unsigned short EndX, unsigned short EndY) { assert(this->PaintCB != nullptr); - for (long i = StartX + StartY * this->termSize.ws_row; i < EndX + EndY * this->termSize.ws_row; i++) + for (long i = StartX + StartY * this->TerminalSize.ws_row; i < EndX + EndY * this->TerminalSize.ws_row; i++) { TerminalCell *cell = &this->Cells[i]; cell->c = ' '; cell->attr = {}; - this->PaintCB(cell, i % this->termSize.ws_row, i / this->termSize.ws_row); + this->PaintCB(cell, i % this->TerminalSize.ws_row, i / this->TerminalSize.ws_row); } } @@ -45,21 +214,21 @@ namespace KernelConsole if (Lines == 0) return; - Lines = Lines > this->termSize.ws_col ? this->termSize.ws_col : Lines; + Lines = Lines > this->TerminalSize.ws_col ? this->TerminalSize.ws_col : Lines; - for (int i = 0; i < ((this->termSize.ws_row * this->termSize.ws_col) - (this->termSize.ws_row * Lines)); i++) + for (int i = 0; i < ((this->TerminalSize.ws_row * this->TerminalSize.ws_col) - (this->TerminalSize.ws_row * Lines)); i++) { - this->Cells[i] = this->Cells[i + (this->termSize.ws_row * Lines)]; - this->PaintCB(&this->Cells[i], i % this->termSize.ws_row, i / this->termSize.ws_row); + this->Cells[i] = this->Cells[i + (this->TerminalSize.ws_row * Lines)]; + this->PaintCB(&this->Cells[i], i % this->TerminalSize.ws_row, i / this->TerminalSize.ws_row); } - for (int i = ((this->termSize.ws_row * this->termSize.ws_col) - (this->termSize.ws_row * Lines)); i < this->termSize.ws_row * this->termSize.ws_col; i++) + for (int i = ((this->TerminalSize.ws_row * this->TerminalSize.ws_col) - (this->TerminalSize.ws_row * Lines)); i < this->TerminalSize.ws_row * this->TerminalSize.ws_col; i++) { TerminalCell *cell = &this->Cells[i]; cell->attr = {}; cell->c = ' '; - this->PaintCB(cell, i % this->termSize.ws_row, i / this->termSize.ws_row); + this->PaintCB(cell, i % this->TerminalSize.ws_row, i / this->TerminalSize.ws_row); } // Move the cursor up $lines @@ -80,7 +249,7 @@ namespace KernelConsole this->Cursor.X = 0; this->Cursor.Y++; - if (this->Cursor.Y >= this->termSize.ws_col) + if (this->Cursor.Y >= this->TerminalSize.ws_col) this->Scroll(1); if (this->CursorCB != nullptr) @@ -113,7 +282,7 @@ namespace KernelConsole else { this->Cursor.Y--; - this->Cursor.X = this->termSize.ws_row - 1; + this->Cursor.X = this->TerminalSize.ws_row - 1; } if (this->CursorCB != nullptr) @@ -121,10 +290,10 @@ namespace KernelConsole } else { - if (this->Cursor.X >= this->termSize.ws_row) + if (this->Cursor.X >= this->TerminalSize.ws_row) this->NewLine(); - TerminalCell *cell = &this->Cells[this->Cursor.X + this->Cursor.Y * this->termSize.ws_row]; + TerminalCell *cell = &this->Cells[this->Cursor.X + this->Cursor.Y * this->TerminalSize.ws_row]; cell->c = c; cell->attr = this->Attribute; @@ -150,12 +319,12 @@ namespace KernelConsole if (Args[0].Empty) this->Cursor.Y = 0; else - this->Cursor.Y = MIN(Args[0].Value - 1, this->termSize.ws_col - 1); + this->Cursor.Y = MIN(Args[0].Value - 1, this->TerminalSize.ws_col - 1); if (Args[1].Empty) this->Cursor.Y = 0; else - this->Cursor.X = MIN(Args[1].Value - 1, this->termSize.ws_row - 1); + this->Cursor.X = MIN(Args[1].Value - 1, this->TerminalSize.ws_row - 1); } if (this->CursorCB != nullptr) @@ -167,17 +336,17 @@ namespace KernelConsole TerminalCursor cursor = this->Cursor; if (Args[0].Empty) - this->Clear(cursor.X, cursor.Y, this->termSize.ws_row, this->termSize.ws_col - 1); + this->Clear(cursor.X, cursor.Y, this->TerminalSize.ws_row, this->TerminalSize.ws_col - 1); else { int attr = Args[0].Value; if (attr == 0) - this->Clear(cursor.X, cursor.Y, this->termSize.ws_row, this->termSize.ws_col - 1); + this->Clear(cursor.X, cursor.Y, this->TerminalSize.ws_row, this->TerminalSize.ws_col - 1); else if (attr == 1) this->Clear(0, 0, cursor.X, cursor.Y); else if (attr == 2) - this->Clear(0, 0, this->termSize.ws_row, this->termSize.ws_col - 1); + this->Clear(0, 0, this->TerminalSize.ws_row, this->TerminalSize.ws_col - 1); } } @@ -186,17 +355,17 @@ namespace KernelConsole TerminalCursor cursor = this->Cursor; if (Args[0].Empty) - this->Clear(cursor.X, cursor.Y, this->termSize.ws_row, cursor.Y); + this->Clear(cursor.X, cursor.Y, this->TerminalSize.ws_row, cursor.Y); else { int attr = Args[0].Value; if (attr == 0) - this->Clear(cursor.X, cursor.Y, this->termSize.ws_row, cursor.Y); + this->Clear(cursor.X, cursor.Y, this->TerminalSize.ws_row, cursor.Y); else if (attr == 1) this->Clear(0, cursor.Y, cursor.X, cursor.Y); else if (attr == 2) - this->Clear(0, cursor.Y, this->termSize.ws_row, cursor.Y); + this->Clear(0, cursor.Y, this->TerminalSize.ws_row, cursor.Y); } } @@ -234,8 +403,8 @@ namespace KernelConsole { int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1; Cursor.Y += P1; - if (Cursor.Y >= this->termSize.ws_col) - Cursor.Y = this->termSize.ws_col - 1; + if (Cursor.Y >= this->TerminalSize.ws_col) + Cursor.Y = this->TerminalSize.ws_col - 1; if (CursorCB) CursorCB(&Cursor); } @@ -244,8 +413,8 @@ namespace KernelConsole { int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1; Cursor.X += P1; - if (Cursor.X >= this->termSize.ws_row) - Cursor.X = this->termSize.ws_row - 1; + if (Cursor.X >= this->TerminalSize.ws_row) + Cursor.X = this->TerminalSize.ws_row - 1; if (CursorCB) CursorCB(&Cursor); } @@ -264,8 +433,8 @@ namespace KernelConsole { int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1; Cursor.Y += P1; - if (Cursor.Y >= this->termSize.ws_col) - Cursor.Y = this->termSize.ws_col - 1; + if (Cursor.Y >= this->TerminalSize.ws_col) + Cursor.Y = this->TerminalSize.ws_col - 1; Cursor.X = 0; if (CursorCB) CursorCB(&Cursor); @@ -286,8 +455,8 @@ namespace KernelConsole { int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1; Cursor.X = P1 - 1; - if (Cursor.X >= this->termSize.ws_row) - Cursor.X = this->termSize.ws_row - 1; + if (Cursor.X >= this->TerminalSize.ws_row) + Cursor.X = this->TerminalSize.ws_row - 1; if (CursorCB) CursorCB(&Cursor); } @@ -378,8 +547,11 @@ namespace KernelConsole case ANSIParser::ParserState::EndValue: break; default: + { + error("Invalid parser state: %d", parser->State); assert(!"Invalid parser state"); } + } if (parser->State == ANSIParser::ParserState::EndValue) { @@ -442,7 +614,7 @@ namespace KernelConsole PaintCallback _Paint, CursorCallback _Print) : PaintCB(_Paint), CursorCB(_Print) { - this->termSize = { + this->TerminalSize = { .ws_row = Rows, .ws_col = Columns, .ws_xpixel = XPixels, @@ -463,28 +635,29 @@ namespace KernelConsole - ECHO - Echo input characters - ICANON - Enable canonical input (enable line editing) */ - this->term.c_iflag = /*ICRNL |*/ IXON; - this->term.c_oflag = OPOST | ONLCR; - this->term.c_cflag = CS8 | CREAD | HUPCL; - this->term.c_lflag = ECHO | ICANON; + this->TerminalConfig.c_iflag = /*ICRNL |*/ IXON; + this->TerminalConfig.c_oflag = OPOST | ONLCR; + this->TerminalConfig.c_cflag = CS8 | CREAD | HUPCL; + this->TerminalConfig.c_lflag = ECHO | ICANON; + this->TerminalConfig.c_lflag &= ~ICANON; /* FIXME: not ready for this yet */ - this->term.c_cc[VINTR] = 0x03; /* ^C */ - this->term.c_cc[VQUIT] = 0x1C; /* ^\ */ - this->term.c_cc[VERASE] = 0x7F; /* DEL */ - this->term.c_cc[VKILL] = 0x15; /* ^U */ - this->term.c_cc[VEOF] = 0x04; /* ^D */ - this->term.c_cc[VTIME] = 0; /* Timeout for non-canonical read */ - this->term.c_cc[VMIN] = 1; /* Minimum number of characters for non-canonical read */ - this->term.c_cc[VSWTC] = 0; /* ^O */ - this->term.c_cc[VSTART] = 0x11; /* ^Q */ - this->term.c_cc[VSTOP] = 0x13; /* ^S */ - this->term.c_cc[VSUSP] = 0x1A; /* ^Z */ - this->term.c_cc[VEOL] = 0x00; /* NUL */ - this->term.c_cc[VREPRINT] = 0x12; /* ^R */ - this->term.c_cc[VDISCARD] = 0x14; /* ^T */ - this->term.c_cc[VWERASE] = 0x17; /* ^W */ - this->term.c_cc[VLNEXT] = 0x19; /* ^Y */ - this->term.c_cc[VEOL2] = 0x7F; /* DEL (or sometimes EOF) */ + this->TerminalConfig.c_cc[VINTR] = 0x03; /* ^C */ + this->TerminalConfig.c_cc[VQUIT] = 0x1C; /* ^\ */ + this->TerminalConfig.c_cc[VERASE] = 0x7F; /* DEL */ + this->TerminalConfig.c_cc[VKILL] = 0x15; /* ^U */ + this->TerminalConfig.c_cc[VEOF] = 0x04; /* ^D */ + this->TerminalConfig.c_cc[VTIME] = 0; /* Timeout for non-canonical read */ + this->TerminalConfig.c_cc[VMIN] = 1; /* Minimum number of characters for non-canonical read */ + this->TerminalConfig.c_cc[VSWTC] = 0; /* ^O */ + this->TerminalConfig.c_cc[VSTART] = 0x11; /* ^Q */ + this->TerminalConfig.c_cc[VSTOP] = 0x13; /* ^S */ + this->TerminalConfig.c_cc[VSUSP] = 0x1A; /* ^Z */ + this->TerminalConfig.c_cc[VEOL] = 0x00; /* NUL */ + this->TerminalConfig.c_cc[VREPRINT] = 0x12; /* ^R */ + this->TerminalConfig.c_cc[VDISCARD] = 0x14; /* ^T */ + this->TerminalConfig.c_cc[VWERASE] = 0x17; /* ^W */ + this->TerminalConfig.c_cc[VLNEXT] = 0x19; /* ^Y */ + this->TerminalConfig.c_cc[VEOL2] = 0x7F; /* DEL (or sometimes EOF) */ this->Cells = new TerminalCell[Rows * Columns];