Kernel: Add better termios support

I'm not sure if this is correct but at least it's better than before :)
This commit is contained in:
Bananymous 2025-05-30 22:10:39 +03:00
parent 9b875fb930
commit 8ff9c030bf
6 changed files with 67 additions and 24 deletions

View File

@ -14,7 +14,7 @@
#define dprintln(...) \
do { \
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
BAN::Formatter::print(__debug_putchar,"\r\n"); \
BAN::Formatter::print(__debug_putchar,"\n"); \
fflush(stddbg); \
} while (false)
@ -22,7 +22,7 @@
do { \
BAN::Formatter::print(__debug_putchar, "\e[33m"); \
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
BAN::Formatter::print(__debug_putchar, "\e[m\r\n"); \
BAN::Formatter::print(__debug_putchar, "\e[m\n"); \
fflush(stddbg); \
} while(false)
@ -30,7 +30,7 @@
do { \
BAN::Formatter::print(__debug_putchar, "\e[31m"); \
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
BAN::Formatter::print(__debug_putchar, "\e[m\r\n"); \
BAN::Formatter::print(__debug_putchar, "\e[m\n"); \
fflush(stddbg); \
} while(false)

View File

@ -57,7 +57,7 @@ namespace Kernel
virtual bool has_hungup_impl() const override { return false; }
protected:
TTY(mode_t mode, uid_t uid, gid_t gid);
TTY(termios termios, mode_t mode, uid_t uid, gid_t gid);
virtual bool putchar_impl(uint8_t ch) = 0;
virtual void update_cursor() {}

View File

@ -158,7 +158,15 @@ namespace Kernel
}
PseudoTerminalSlave::PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t mode, uid_t uid, gid_t gid)
: TTY(mode, uid, gid)
: TTY({
.c_iflag = 0,
.c_oflag = 0,
.c_cflag = CS8,
.c_lflag = ECHO | ICANON,
.c_cc = {},
.c_ospeed = B38400,
.c_ispeed = B38400,
}, mode, uid, gid)
, m_name(BAN::move(name))
, m_number(number)
{}

View File

@ -170,7 +170,15 @@ namespace Kernel
}
SerialTTY::SerialTTY(Serial serial)
: TTY(0600, 0, 0)
: TTY({
.c_iflag = ICRNL,
.c_oflag = OPOST | ONLCR,
.c_cflag = CS8,
.c_lflag = ECHO | ICANON,
.c_cc = {},
.c_ospeed = B38400,
.c_ispeed = B38400,
}, 0600, 0, 0)
, m_name(MUST(BAN::String::formatted("ttyS{}", s_next_tty_number++)))
, m_serial(serial)
{}
@ -235,8 +243,6 @@ namespace Kernel
while (!m_input.empty())
{
*ptr = m_input.front();
if (*ptr == '\r')
*ptr = '\n';
m_input.pop();
ptr++;
}

View File

@ -66,18 +66,11 @@ namespace Kernel
return makedev(DeviceNumber::TTY, s_minor++);
}
TTY::TTY(mode_t mode, uid_t uid, gid_t gid)
TTY::TTY(termios termios, mode_t mode, uid_t uid, gid_t gid)
: CharacterDevice(mode, uid, gid)
, m_termios(termios)
, m_rdev(next_tty_rdev())
{
// FIXME: add correct baud and flags
m_termios.c_iflag = 0;
m_termios.c_oflag = 0;
m_termios.c_cflag = CS8;
m_termios.c_lflag = ECHO | ICANON;
m_termios.c_ospeed = B38400;
m_termios.c_ispeed = B38400;
}
{ }
BAN::RefPtr<TTY> TTY::current()
{
@ -228,6 +221,17 @@ namespace Kernel
LockGuard _(m_mutex);
if ((m_termios.c_iflag & ISTRIP))
ch &= 0x7F;
if ((m_termios.c_iflag & IGNCR) && ch == '\r')
return;
uint8_t conv = ch;
if ((m_termios.c_iflag & ICRNL) && ch == '\r')
conv = '\n';
if ((m_termios.c_iflag & INLCR) && ch == '\n')
conv = '\r';
ch = conv;
// ^C
if (ch == '\x03')
{
@ -252,6 +256,10 @@ namespace Kernel
return;
}
// FIXME: don't ignore these bytes
if (m_output.bytes >= m_output.buffer.size())
return;
m_output.buffer[m_output.bytes++] = ch;
if (m_termios.c_lflag & ECHO)
@ -280,7 +288,7 @@ namespace Kernel
}
}
if (ch == '\n' || !(m_termios.c_lflag & ICANON))
if (ch == '\n' || !(m_termios.c_lflag & ICANON) || m_output.bytes == m_output.buffer.size())
{
m_output.flush = true;
epoll_notify(EPOLLIN);
@ -334,9 +342,16 @@ namespace Kernel
bool TTY::putchar(uint8_t ch)
{
SpinLockGuard _(m_write_lock);
if (m_tty_ctrl.draw_graphics)
return putchar_impl(ch);
if (!m_tty_ctrl.draw_graphics)
return true;
if (m_termios.c_oflag & OPOST)
{
if ((m_termios.c_oflag & ONLCR) && ch == '\n')
return putchar_impl('\r') && putchar_impl('\n');
if ((m_termios.c_oflag & OCRNL) && ch == '\r')
return putchar_impl('\n');
}
return putchar_impl(ch);
}
BAN::ErrorOr<size_t> TTY::read_impl(off_t, BAN::ByteSpan buffer)
@ -353,7 +368,13 @@ namespace Kernel
return 0;
}
size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_output.bytes);
const size_t max_to_copy = BAN::Math::min<size_t>(buffer.size(), m_output.bytes);
size_t to_copy = max_to_copy;
if (m_termios.c_lflag & ICANON)
for (to_copy = 1; to_copy < max_to_copy; to_copy++)
if (m_output.buffer[to_copy - 1] == '\n')
break;
memcpy(buffer.data(), m_output.buffer.data(), to_copy);
memmove(m_output.buffer.data(), m_output.buffer.data() + to_copy, m_output.bytes - to_copy);

View File

@ -36,7 +36,15 @@ namespace Kernel
}
VirtualTTY::VirtualTTY(BAN::RefPtr<TerminalDriver> driver)
: TTY(0600, 0, 0)
: TTY({
.c_iflag = 0,
.c_oflag = 0,
.c_cflag = CS8,
.c_lflag = ECHO | ICANON,
.c_cc = {},
.c_ospeed = B38400,
.c_ispeed = B38400,
}, 0600, 0, 0)
, m_name(MUST(BAN::String::formatted("tty{}", s_next_tty_number++)))
, m_terminal_driver(driver)
, m_palette(driver->palette())