mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-09-10 13:04:53 -04:00
Review input handling
Make the IRQ handler much shorter Move the work to a kernel process
This commit is contained in:
parent
dd5d1c9d6d
commit
841986bec0
@ -24,7 +24,13 @@ struct virtual_terminal {
|
|||||||
bool active;
|
bool active;
|
||||||
bool canonical;
|
bool canonical;
|
||||||
bool mouse;
|
bool mouse;
|
||||||
|
size_t input_thread_pid;
|
||||||
|
|
||||||
|
// Filled by the IRQ
|
||||||
|
circular_buffer<char, 128> keyboard_buffer;
|
||||||
|
circular_buffer<size_t, 128> mouse_buffer;
|
||||||
|
|
||||||
|
// Handled by the input thread
|
||||||
circular_buffer<char, INPUT_BUFFER_SIZE> input_buffer;
|
circular_buffer<char, INPUT_BUFFER_SIZE> input_buffer;
|
||||||
circular_buffer<char, 2 * INPUT_BUFFER_SIZE> canonical_buffer;
|
circular_buffer<char, 2 * INPUT_BUFFER_SIZE> canonical_buffer;
|
||||||
circular_buffer<size_t, 3 * INPUT_BUFFER_SIZE> raw_buffer;
|
circular_buffer<size_t, 3 * INPUT_BUFFER_SIZE> raw_buffer;
|
||||||
@ -88,6 +94,8 @@ struct virtual_terminal {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void init_terminals();
|
void init_terminals();
|
||||||
|
void finalize();
|
||||||
|
|
||||||
virtual_terminal& get_active_terminal();
|
virtual_terminal& get_active_terminal();
|
||||||
virtual_terminal& get_terminal(size_t id);
|
virtual_terminal& get_terminal(size_t id);
|
||||||
|
|
||||||
|
@ -129,6 +129,7 @@ void kernel_main(){
|
|||||||
|
|
||||||
// Start the secondary kernel processes
|
// Start the secondary kernel processes
|
||||||
network::finalize();
|
network::finalize();
|
||||||
|
stdio::finalize();
|
||||||
|
|
||||||
// Start the scheduler
|
// Start the scheduler
|
||||||
scheduler::start();
|
scheduler::start();
|
||||||
|
@ -18,10 +18,91 @@ namespace {
|
|||||||
constexpr const size_t MAX_TERMINALS = 2;
|
constexpr const size_t MAX_TERMINALS = 2;
|
||||||
size_t active_terminal;
|
size_t active_terminal;
|
||||||
|
|
||||||
bool shift = false;
|
|
||||||
|
|
||||||
std::array<stdio::virtual_terminal, MAX_TERMINALS> terminals;
|
std::array<stdio::virtual_terminal, MAX_TERMINALS> terminals;
|
||||||
|
|
||||||
|
void input_thread(void* data){
|
||||||
|
auto& terminal = *reinterpret_cast<stdio::virtual_terminal*>(data);
|
||||||
|
|
||||||
|
auto pid = scheduler::get_pid();
|
||||||
|
|
||||||
|
logging::logf(logging::log_level::TRACE, "stdio: Input Thread for terminal %u started (pid:%u)\n", terminal.id, pid);
|
||||||
|
|
||||||
|
bool shift = false;
|
||||||
|
|
||||||
|
while(true){
|
||||||
|
// Wait for some input
|
||||||
|
scheduler::block_process(pid);
|
||||||
|
|
||||||
|
// Handle keyboard input
|
||||||
|
while(!terminal.keyboard_buffer.empty()){
|
||||||
|
auto key = terminal.keyboard_buffer.pop();
|
||||||
|
|
||||||
|
if(terminal.canonical){
|
||||||
|
//Key released
|
||||||
|
if(key & 0x80){
|
||||||
|
key &= ~(0x80);
|
||||||
|
if(key == keyboard::KEY_LEFT_SHIFT || key == keyboard::KEY_RIGHT_SHIFT){
|
||||||
|
shift = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Key pressed
|
||||||
|
else {
|
||||||
|
if(key == keyboard::KEY_LEFT_SHIFT || key == keyboard::KEY_RIGHT_SHIFT){
|
||||||
|
shift = true;
|
||||||
|
} else if(key == keyboard::KEY_BACKSPACE){
|
||||||
|
if(!terminal.input_buffer.empty()){
|
||||||
|
terminal.input_buffer.pop_last();
|
||||||
|
terminal.print('\b');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto qwertz_key =
|
||||||
|
shift
|
||||||
|
? keyboard::shift_key_to_ascii(key)
|
||||||
|
: keyboard::key_to_ascii(key);
|
||||||
|
|
||||||
|
if(qwertz_key){
|
||||||
|
terminal.input_buffer.push(qwertz_key);
|
||||||
|
|
||||||
|
terminal.print(qwertz_key);
|
||||||
|
|
||||||
|
if(qwertz_key == '\n'){
|
||||||
|
// Transfer current line to the canonical buffer
|
||||||
|
while(!terminal.input_buffer.empty()){
|
||||||
|
terminal.canonical_buffer.push(terminal.input_buffer.pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal.input_queue.wake_up();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The complete processing of the key will be done by the
|
||||||
|
// userspace program
|
||||||
|
auto code = keyboard::raw_key_to_keycode(key);
|
||||||
|
terminal.raw_buffer.push(static_cast<size_t>(code));
|
||||||
|
|
||||||
|
terminal.input_queue.wake_up();
|
||||||
|
|
||||||
|
thor_assert(!terminal.raw_buffer.full(), "raw buffer is full!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle mouse input
|
||||||
|
while(!terminal.mouse_buffer.empty()){
|
||||||
|
auto key = terminal.mouse_buffer.pop();
|
||||||
|
|
||||||
|
if(!terminal.canonical && terminal.mouse){
|
||||||
|
terminal.raw_buffer.push(key);
|
||||||
|
|
||||||
|
terminal.input_queue.wake_up();
|
||||||
|
|
||||||
|
thor_assert(!terminal.raw_buffer.full(), "raw buffer is full!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} //end of anonymous namespace
|
} //end of anonymous namespace
|
||||||
|
|
||||||
void stdio::virtual_terminal::print(char key){
|
void stdio::virtual_terminal::print(char key){
|
||||||
@ -30,71 +111,27 @@ void stdio::virtual_terminal::print(char key){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void stdio::virtual_terminal::send_input(char key){
|
void stdio::virtual_terminal::send_input(char key){
|
||||||
if(canonical){
|
if(!input_thread_pid){
|
||||||
//Key released
|
return;
|
||||||
if(key & 0x80){
|
|
||||||
key &= ~(0x80);
|
|
||||||
if(key == keyboard::KEY_LEFT_SHIFT || key == keyboard::KEY_RIGHT_SHIFT){
|
|
||||||
shift = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Key pressed
|
|
||||||
else {
|
|
||||||
if(key == keyboard::KEY_LEFT_SHIFT || key == keyboard::KEY_RIGHT_SHIFT){
|
|
||||||
shift = true;
|
|
||||||
} else if(key == keyboard::KEY_BACKSPACE){
|
|
||||||
if(!input_buffer.empty()){
|
|
||||||
input_buffer.pop_last();
|
|
||||||
print('\b');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
auto qwertz_key =
|
|
||||||
shift
|
|
||||||
? keyboard::shift_key_to_ascii(key)
|
|
||||||
: keyboard::key_to_ascii(key);
|
|
||||||
|
|
||||||
if(qwertz_key){
|
|
||||||
input_buffer.push(qwertz_key);
|
|
||||||
|
|
||||||
print(qwertz_key);
|
|
||||||
|
|
||||||
if(qwertz_key == '\n'){
|
|
||||||
// Transfer current line to the canonical buffer
|
|
||||||
while(!input_buffer.empty()){
|
|
||||||
canonical_buffer.push(input_buffer.pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!input_queue.empty()){
|
|
||||||
input_queue.wake_up();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// The complete processing of the key will be done by the
|
|
||||||
// userspace program
|
|
||||||
auto code = keyboard::raw_key_to_keycode(key);
|
|
||||||
raw_buffer.push(static_cast<size_t>(code));
|
|
||||||
|
|
||||||
if(!input_queue.empty()){
|
|
||||||
input_queue.wake_up();
|
|
||||||
}
|
|
||||||
|
|
||||||
thor_assert(!raw_buffer.full(), "raw buffer is full!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simply give the input to the input thread
|
||||||
|
keyboard_buffer.push(key);
|
||||||
|
thor_assert(!keyboard_buffer.full(), "keyboard buffer is full!");
|
||||||
|
|
||||||
|
scheduler::unblock_process_hint(input_thread_pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stdio::virtual_terminal::send_mouse_input(keycode key){
|
void stdio::virtual_terminal::send_mouse_input(keycode key){
|
||||||
if(!canonical && mouse){
|
if(!input_thread_pid){
|
||||||
raw_buffer.push(static_cast<size_t>(key));
|
return;
|
||||||
|
|
||||||
if(!input_queue.empty()){
|
|
||||||
input_queue.wake_up();
|
|
||||||
}
|
|
||||||
|
|
||||||
thor_assert(!raw_buffer.full(), "raw buffer is full!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simply give the input to the input thread
|
||||||
|
mouse_buffer.push(size_t(key));
|
||||||
|
thor_assert(!mouse_buffer.full(), "mouse buffer is full!");
|
||||||
|
|
||||||
|
scheduler::unblock_process_hint(input_thread_pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t stdio::virtual_terminal::read_input_can(char* buffer, size_t max){
|
size_t stdio::virtual_terminal::read_input_can(char* buffer, size_t max){
|
||||||
@ -190,6 +227,24 @@ void stdio::init_terminals(){
|
|||||||
terminals[active_terminal].active = true;
|
terminals[active_terminal].active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stdio::finalize(){
|
||||||
|
for(size_t i = 0; i < MAX_TERMINALS; ++i){
|
||||||
|
auto& terminal = terminals[i];
|
||||||
|
|
||||||
|
auto* user_stack = new char[scheduler::user_stack_size];
|
||||||
|
auto* kernel_stack = new char[scheduler::kernel_stack_size];
|
||||||
|
|
||||||
|
auto& input_process = scheduler::create_kernel_task_args("tty_input", user_stack, kernel_stack, &input_thread, &terminal);
|
||||||
|
|
||||||
|
input_process.ppid = 1;
|
||||||
|
input_process.priority = scheduler::DEFAULT_PRIORITY;
|
||||||
|
|
||||||
|
scheduler::queue_system_process(input_process.pid);
|
||||||
|
|
||||||
|
terminal.input_thread_pid = input_process.pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stdio::virtual_terminal& stdio::get_active_terminal(){
|
stdio::virtual_terminal& stdio::get_active_terminal(){
|
||||||
return terminals[active_terminal];
|
return terminals[active_terminal];
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user