Kernel: TTY now reads input byte by byte
This allows correct behaviour for character streams / keyboard handling. Serial input can now send working ^C :D
This commit is contained in:
parent
5e1725abb2
commit
b30af0edca
|
@ -29,7 +29,7 @@ namespace Kernel
|
||||||
|
|
||||||
static void initialize_devices();
|
static void initialize_devices();
|
||||||
void on_key_event(Input::KeyEvent);
|
void on_key_event(Input::KeyEvent);
|
||||||
void handle_input(const uint8_t* ch);
|
void handle_input_byte(uint8_t);
|
||||||
|
|
||||||
virtual bool is_tty() const override { return true; }
|
virtual bool is_tty() const override { return true; }
|
||||||
|
|
||||||
|
|
|
@ -244,12 +244,13 @@ namespace Kernel
|
||||||
if (m_serial.port() != COM1_PORT && m_serial.port() != COM2_PORT)
|
if (m_serial.port() != COM1_PORT && m_serial.port() != COM2_PORT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
static uint8_t buffer[128];
|
||||||
|
|
||||||
auto update_com =
|
auto update_com =
|
||||||
[&](auto& device, auto& input_queue)
|
[&](auto& device, auto& input_queue)
|
||||||
{
|
{
|
||||||
if (input_queue.empty())
|
if (input_queue.empty())
|
||||||
return;
|
return;
|
||||||
uint8_t buffer[128];
|
|
||||||
uint8_t* ptr = buffer;
|
uint8_t* ptr = buffer;
|
||||||
while (!input_queue.empty())
|
while (!input_queue.empty())
|
||||||
{
|
{
|
||||||
|
@ -262,7 +263,10 @@ namespace Kernel
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
device->handle_input(buffer);
|
|
||||||
|
ptr = buffer;
|
||||||
|
while (*ptr)
|
||||||
|
device->handle_input_byte(*ptr++);
|
||||||
};
|
};
|
||||||
|
|
||||||
CriticalScope _;
|
CriticalScope _;
|
||||||
|
|
|
@ -54,20 +54,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
Input::KeyEvent event;
|
Input::KeyEvent event;
|
||||||
ASSERT(MUST(Process::current().sys_read(fd, &event, sizeof(event))) == sizeof(event));
|
ASSERT(MUST(Process::current().sys_read(fd, &event, sizeof(event))) == sizeof(event));
|
||||||
|
TTY::current()->on_key_event(event);
|
||||||
TTY& current_tty = *TTY::current();
|
|
||||||
if (current_tty.m_foreground_pgrp &&
|
|
||||||
event.pressed() &&
|
|
||||||
event.ctrl() &&
|
|
||||||
!event.shift()
|
|
||||||
&& event.key == Input::Key::C
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (auto ret = Process::sys_kill(-current_tty.m_foreground_pgrp, SIGINT); ret.is_error())
|
|
||||||
dwarnln("TTY: {}", ret.error());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
current_tty.on_key_event(event);
|
|
||||||
}
|
}
|
||||||
}, nullptr
|
}, nullptr
|
||||||
);
|
);
|
||||||
|
@ -146,91 +133,73 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_input((const uint8_t*)ansi_c_str);
|
if (ansi_c_str)
|
||||||
|
{
|
||||||
|
auto* ptr = (const uint8_t*)ansi_c_str;
|
||||||
|
while (*ptr)
|
||||||
|
handle_input_byte(*ptr++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTY::handle_input(const uint8_t* ansi)
|
void TTY::handle_input_byte(uint8_t ch)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
if (ch == 0)
|
||||||
|
|
||||||
bool eof = ansi && (
|
|
||||||
ansi[0] == '\x04' || // ^D
|
|
||||||
ansi[0] == '\n' // \n
|
|
||||||
);
|
|
||||||
|
|
||||||
if (ansi && m_termios.canonical)
|
|
||||||
{
|
|
||||||
// EOF from ^D
|
|
||||||
if (ansi[0] == '\x04')
|
|
||||||
goto flush;
|
|
||||||
else if (ansi[0] == '\b')
|
|
||||||
{
|
|
||||||
ansi = nullptr;
|
|
||||||
do_backspace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ansi == nullptr)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (size_t i = 0; ansi[i]; i++)
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
|
// ^C
|
||||||
|
if (ch == '\x03')
|
||||||
{
|
{
|
||||||
if (m_output.bytes >= m_output.buffer.size())
|
if (auto ret = Process::sys_kill(-m_foreground_pgrp, SIGINT); ret.is_error())
|
||||||
{
|
dwarnln("TTY: {}", ret.error());
|
||||||
dprintln("TTY buffer full");
|
return;
|
||||||
break;
|
|
||||||
}
|
|
||||||
m_output.buffer[m_output.bytes++] = ansi[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ^D + canonical
|
||||||
|
if (ch == '\x04' && m_termios.canonical)
|
||||||
|
{
|
||||||
|
m_output.flush = true;
|
||||||
|
m_output.semaphore.unblock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// backspace + canonical
|
||||||
|
if (ch == '\b' && m_termios.canonical)
|
||||||
|
{
|
||||||
|
do_backspace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_output.buffer[m_output.bytes++] = ch;
|
||||||
|
|
||||||
if (m_termios.echo)
|
if (m_termios.echo)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; ansi[i]; i++)
|
if ((ch <= 31 || ch == 127) && ch != '\n')
|
||||||
{
|
{
|
||||||
if (ansi[i] <= 26 && ansi[i] != 10)
|
putchar('^');
|
||||||
{
|
if (ch <= 26 && ch != 10)
|
||||||
putchar('^');
|
putchar('A' + ch - 1);
|
||||||
putchar('A' + ansi[i] - 1);
|
else if (ch == 27)
|
||||||
}
|
|
||||||
else if (ansi[i] == 27)
|
|
||||||
{
|
|
||||||
putchar('^');
|
|
||||||
putchar('[');
|
putchar('[');
|
||||||
}
|
else if (ch == 28)
|
||||||
else if (ansi[i] == 28)
|
|
||||||
{
|
|
||||||
putchar('^');
|
|
||||||
putchar('\\');
|
putchar('\\');
|
||||||
}
|
else if (ch == 29)
|
||||||
else if (ansi[i] == 29)
|
|
||||||
{
|
|
||||||
putchar('^');
|
|
||||||
putchar(']');
|
putchar(']');
|
||||||
}
|
else if (ch == 30)
|
||||||
else if (ansi[i] == 30)
|
|
||||||
{
|
|
||||||
putchar('^');
|
|
||||||
putchar('^');
|
|
||||||
}
|
|
||||||
else if (ansi[i] == 31)
|
|
||||||
{
|
|
||||||
putchar('^');
|
putchar('^');
|
||||||
|
else if (ch == 31)
|
||||||
putchar('_');
|
putchar('_');
|
||||||
}
|
else if (ch == 127)
|
||||||
else if (ansi[i] == 127)
|
|
||||||
{
|
|
||||||
putchar('^');
|
|
||||||
putchar('?');
|
putchar('?');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
putchar(ansi[i]);
|
putchar(ch);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flush:
|
if (ch == '\n' || !m_termios.canonical)
|
||||||
if (eof || !m_termios.canonical)
|
|
||||||
{
|
{
|
||||||
m_output.flush = true;
|
m_output.flush = true;
|
||||||
m_output.semaphore.unblock();
|
m_output.semaphore.unblock();
|
||||||
|
|
Loading…
Reference in New Issue