From e60fa7740cd7d245d1b22a25fea9df0768d32668 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Sun, 19 May 2024 04:34:40 -0400 Subject: mouse support (working in qemu, semi-working in virtualbox) --- kernel/source/input.cpp | 4 +- kernel/source/interrupts.asm | 102 +++++++++++++++++++++++++++++++++++++------ kernel/source/interrupts.cpp | 49 ++++++++++++++++++++- kernel/source/syscall.cpp | 19 +++++--- 4 files changed, 152 insertions(+), 22 deletions(-) (limited to 'kernel/source') diff --git a/kernel/source/input.cpp b/kernel/source/input.cpp index 696cb13..921ae7b 100644 --- a/kernel/source/input.cpp +++ b/kernel/source/input.cpp @@ -5,10 +5,10 @@ namespace hilbert::kernel::input { - utility::queue *key_queue; + utility::queue *input_queue; void init_input() { - key_queue = new utility::queue(); + input_queue = new utility::queue(); } void got_input() { diff --git a/kernel/source/interrupts.asm b/kernel/source/interrupts.asm index babc020..e0c3cdb 100644 --- a/kernel/source/interrupts.asm +++ b/kernel/source/interrupts.asm @@ -227,14 +227,6 @@ section .bss section .text -write_keyboard_byte: - in al, 0x64 - test al, 0x02 - jnz write_keyboard_byte - mov al, dil - out 0x60, al - ret - extern on_keyboard_interrupt keyboard_isr: @@ -249,6 +241,7 @@ keyboard_isr: push rcx push rax + call wait_read_ps2 in al, 0x60 mov dil, al @@ -269,6 +262,54 @@ keyboard_isr: iretq +extern on_mouse_interrupt + +mouse_isr: + + push r11 + push r10 + push r9 + push r8 + push rsi + push rdi + push rdx + push rcx + push rax + + call wait_read_ps2 + in al, 0x60 + mov dil, al + + call on_mouse_interrupt + + mov al, 0x20 + out 0x20, al + out 0xa0, al + + pop rax + pop rcx + pop rdx + pop rdi + pop rsi + pop r8 + pop r9 + pop r10 + pop r11 + + iretq + +wait_send_ps2: + in al, 0x64 + test al, 0x02 + jnz wait_send_ps2 + ret + +wait_read_ps2: + in al, 0x64 + test al, 0x01 + jz wait_send_ps2 + ret + load_gdt_and_idt: ;fill exception entries in idt @@ -294,7 +335,7 @@ load_gdt_and_idt: out 0x21, al mov al, 0x01 out 0x21, al - mov al, 0xfd ;mask all but irq 1 + mov al, 0xf9 ;mask all but irq 1 and 2 out 0x21, al mov al, 0x11 @@ -305,19 +346,54 @@ load_gdt_and_idt: out 0xa1, al mov al, 0x01 out 0xa1, al - mov al, 0xff ;mask all + mov al, 0xef ;mask all but irq 12 out 0xa1, al + ;register keyboard and mouse interrupts + mov rdi, 0x21 mov rsi, keyboard_isr call set_isr - ;set keyboard config + mov rdi, 0x2c + mov rsi, mouse_isr + call set_isr + + ;set ps2 config + call wait_send_ps2 mov al, 0x60 out 0x64, al - mov dil, 0x01 - call write_keyboard_byte + + call wait_send_ps2 + mov al, 0x03 + out 0x60, al + + ;set mouse defaults + + call wait_send_ps2 + mov al, 0xd4 + out 0x64, al + + call wait_send_ps2 + mov al, 0xf6 + out 0x60, al + + call wait_read_ps2 + in al, 0x60 + + ;enable mouse reporting + + call wait_send_ps2 + mov al, 0xd4 + out 0x64, al + + call wait_send_ps2 + mov al, 0xf4 + out 0x60, al + + call wait_read_ps2 + in al, 0x60 ;make tss entry in gdt diff --git a/kernel/source/interrupts.cpp b/kernel/source/interrupts.cpp index 6e22121..9b6495e 100644 --- a/kernel/source/interrupts.cpp +++ b/kernel/source/interrupts.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -54,7 +55,9 @@ static uint32_t current_flags = 0; static void got_key(uint32_t key) { - input::key_queue->insert(current_flags | key); + input::input_queue->insert({ + .keyboard = current_flags | key, .is_mouse = false}); + input::got_input(); if (key == (input::BREAK | 0x77)) @@ -90,7 +93,7 @@ static void got_key(uint32_t key) { } static uint8_t key_so_far[8]; -uint8_t key_so_far_len = 0; +static uint8_t key_so_far_len = 0; extern "C" void on_keyboard_interrupt(uint8_t byte) { @@ -150,3 +153,45 @@ extern "C" void on_keyboard_interrupt(uint8_t byte) { } } + +static uint8_t mouse_packet_so_far[3]; +static uint8_t mouse_packet_so_far_len = 0; + +extern "C" void on_mouse_interrupt(uint8_t byte) { + + if (mouse_packet_so_far_len == 0 && byte == 0xfa) + //dirty hack + return; + + mouse_packet_so_far[mouse_packet_so_far_len++] = byte; + if (mouse_packet_so_far_len < 3) + return; + + mouse_packet_so_far_len = 0; + + int16_t x_change = mouse_packet_so_far[1]; + int16_t y_change = -(int16_t)mouse_packet_so_far[2]; + if (mouse_packet_so_far[0] & 0x10) + x_change -= 0x100; + if (mouse_packet_so_far[0] & 0x20) + y_change += 0x100; + + input::input_packet packet = { + .mouse = { + .x_change = x_change, .y_change = y_change, + .buttons = (input::buttons_t)(mouse_packet_so_far[0] & 7) }, + .is_mouse = true }; + + if (input::input_queue->count > 0 && + input::input_queue->last_inserted().is_mouse && + input::input_queue->last_inserted().mouse.buttons == + packet.mouse.buttons) { + input::input_queue->last_inserted().mouse.x_change = packet.mouse.x_change; + input::input_queue->last_inserted().mouse.y_change = packet.mouse.y_change; + } + else + input::input_queue->insert(packet); + + input::got_input(); + +} diff --git a/kernel/source/syscall.cpp b/kernel/source/syscall.cpp index 768ff0d..5d9714c 100644 --- a/kernel/source/syscall.cpp +++ b/kernel/source/syscall.cpp @@ -157,7 +157,7 @@ namespace hilbert::kernel::syscall { } - void read_key_packet_syscall( + void get_input_packet_syscall( uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx ) { @@ -165,8 +165,17 @@ namespace hilbert::kernel::syscall { auto *t = application::running_thread; do - if (input::key_queue->count > 0) { - rax = (uint64_t)input::key_queue->take(); + if (input::input_queue->count > 0) { + input::input_packet packet = input::input_queue->take(); + if (packet.is_mouse) { + rax = packet.mouse.buttons | 0x80; + rdi = (uint16_t)packet.mouse.x_change; + rsi = (uint16_t)packet.mouse.y_change; + } + else { + rax = 0; + rdi = packet.keyboard; + } return; } while (application::save_thread_state(t->cpu)); @@ -504,7 +513,7 @@ namespace hilbert::kernel::syscall { &open_file_syscall, &end_this_thread_syscall, &get_new_pages_syscall, - &read_key_packet_syscall, + &get_input_packet_syscall, &create_private_socket_syscall, &create_socket_listener_syscall, &stop_socket_listener_syscall, @@ -520,7 +529,7 @@ namespace hilbert::kernel::syscall { &set_stream_length_syscall }; - static constexpr int max_syscall_number = 18; + static constexpr int max_syscall_number = 19; } -- cgit v1.2.3