diff --git a/.gitmodules b/.gitmodules index b12d272..f408cd3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "user/apps/badapple"] path = user/apps/badapple url = https://github.com/XunilGroup/xunil_badapple.git +[submodule "user/apps/shell"] + path = user/apps/shell + url = https://github.com/XunilGroup/xunil_shell.git diff --git a/assets/.gitignore b/assets/.gitignore index 9505710..597a985 100644 --- a/assets/.gitignore +++ b/assets/.gitignore @@ -2,3 +2,4 @@ doomgeneric* init helloworld* badapple* +shell* diff --git a/build_and_run.sh b/build_and_run.sh index 541493b..a63d609 100644 --- a/build_and_run.sh +++ b/build_and_run.sh @@ -1,7 +1,8 @@ -export KARCH=aarch64 -bash build_libxunil.sh -bash build_init.sh +export KARCH=x86_64 +bash build_rust_app.sh libxunil +bash build_rust_app.sh init bash build_doomgeneric.sh bash build_helloworld.sh -bash build_badapple.sh +bash build_rust_app.sh badapple +bash build_rust_app.sh shell make run diff --git a/build_badapple.sh b/build_badapple.sh deleted file mode 100644 index 2f9d32e..0000000 --- a/build_badapple.sh +++ /dev/null @@ -1,5 +0,0 @@ -bash build_libxunil.sh -cd user/apps/badapple -cargo build --target $KARCH-unknown-none --release --config profile.release.debug=true -cp ./target/$KARCH-unknown-none/release/badapple ../../../assets/$KARCH/badapple -cd ../../.. diff --git a/build_doomgeneric.sh b/build_doomgeneric.sh index e79bd6a..34f98c4 100644 --- a/build_doomgeneric.sh +++ b/build_doomgeneric.sh @@ -1,4 +1,3 @@ -bash build_libxunil.sh cd user/apps/doomgeneric/doomgeneric rm -r ./build make -j16 -f Makefile.xunil diff --git a/build_helloworld.sh b/build_helloworld.sh index 4058150..3ddb36f 100644 --- a/build_helloworld.sh +++ b/build_helloworld.sh @@ -1,4 +1,3 @@ -bash build_libxunil.sh cd user/apps/helloworld bash compile.sh cd ../../../ diff --git a/build_init.sh b/build_init.sh deleted file mode 100644 index bc0d829..0000000 --- a/build_init.sh +++ /dev/null @@ -1,5 +0,0 @@ -bash build_libxunil.sh -cd user/init -cargo build --target $KARCH-unknown-none --release --config profile.release.debug=true -cp ./target/$KARCH-unknown-none/release/init ../../assets/$KARCH/init -cd ../.. diff --git a/build_libxunil.sh b/build_libxunil.sh deleted file mode 100644 index b529599..0000000 --- a/build_libxunil.sh +++ /dev/null @@ -1,2 +0,0 @@ -cd user/libxunil -cargo build --target $KARCH-unknown-none --release --config profile.release.debug=true diff --git a/build_rust_app.sh b/build_rust_app.sh new file mode 100644 index 0000000..e91e37c --- /dev/null +++ b/build_rust_app.sh @@ -0,0 +1,13 @@ +#!/bin/bash +if [[ "$1" = "init" || "$1" = "libxunil" ]]; then + cd user/$1 +else + cd user/apps/$1 +fi + +cargo build --target $KARCH-unknown-none --release --config profile.release.debug=true +if [[ "$1" = "init" || "$1" = "libxunil" ]]; then + cp ./target/$KARCH-unknown-none/release/$1 ../../assets/$KARCH/$1 +else + cp ./target/$KARCH-unknown-none/release/$1 ../../../assets/$KARCH/$1 +fi diff --git a/config.mk b/config.mk index 152d679..11f68b9 100644 --- a/config.mk +++ b/config.mk @@ -1,4 +1,4 @@ -export KARCH ?= aarch64 +export KARCH ?= x86_64 export OUTPUT ?= kernel export MEMORY ?= 1G export TIMER_FREQUENCY_HZ ?= 1000 diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index d2de632..f0ba046 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -9,7 +9,6 @@ dependencies = [ "aarch64-cpu", "bitflags", "fdt", - "font8x8", "heapless", "lazy_static", "limine", @@ -59,12 +58,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67" -[[package]] -name = "font8x8" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875488b8711a968268c7cf5d139578713097ca4635a76044e8fe8eedf831d07e" - [[package]] name = "hash32" version = "0.3.1" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 9027837..cf395a2 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -10,7 +10,6 @@ bench = false [dependencies] bitflags = "2.11.1" -font8x8 = { version = "0.3.1", default-features = false } heapless = "0.9.2" lazy_static = { version = "1.5.0", features = ["spin_no_std"] } limine = "0.5" diff --git a/kernel/build.rs b/kernel/build.rs index f257f64..baa3e7f 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -34,7 +34,8 @@ fn main() { pub static DOOM_WAD: &[u8] = include_bytes!(\"../../../../../assets/doom1.wad\");\n\ pub static DOOM_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/doomgeneric\");\n\ pub static HELLOWORLD_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/helloworld.elf\");\n\ - pub static BADAPPLE_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/badapple\");" + pub static BADAPPLE_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/badapple\");\n\ + pub static SHELL_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/shell\");" ), ) .unwrap(); diff --git a/kernel/src/arch/syscall.rs b/kernel/src/arch/syscall.rs index a9170b0..f154cce 100644 --- a/kernel/src/arch/syscall.rs +++ b/kernel/src/arch/syscall.rs @@ -3,6 +3,9 @@ use core::sync::atomic::Ordering; #[cfg(target_arch = "x86_64")] use crate::arch::x86_64::paging::create_and_map_multiple_pages; +use crate::driver::io::input::{InputEvent, process_input}; +#[cfg(target_arch = "x86_64")] +use crate::driver::io::ps2::process_scancodes; use alloc::vec; use alloc::{string::String, vec::Vec}; #[cfg(target_arch = "x86_64")] @@ -16,20 +19,13 @@ use x86_64::{ #[cfg(target_arch = "aarch64")] use crate::arch::aarch64::paging::AArchPageTable; -#[cfg(target_arch = "x86_64")] -use crate::driver::io::ps2::process_scancodes; -#[cfg(target_arch = "aarch64")] -use crate::driver::io::virtio::input::process_keycodes; use crate::{ arch::arch::{FRAME_ALLOCATOR, GLOBAL_TICK_COUNT, serial_print}, config::TIMER_FREQUENCY_HZ, driver::{ elf::loader::run_elf, - graphics::framebuffer::{FRAMEBUFFER, USER_FB_BASE, with_framebuffer}, - io::{ - fs::vfs::{vfs_close, vfs_lseek, vfs_open, vfs_read}, - keyboard::KeyboardEvent, - }, + framebuffer::{FRAMEBUFFER, USER_FB_BASE, with_framebuffer}, + io::fs::vfs::{vfs_close, vfs_lseek, vfs_open, vfs_read}, ipc::{Permissions, create_port, manage_port, read_port, write_port}, timer::TIMER, }, @@ -71,7 +67,7 @@ const UNLINK: usize = 87; const GETDENTS64: usize = 217; const CLOCK_GETTIME: usize = 228; const EXIT_GROUP: usize = 231; -const KBD_READ: usize = 666; +const INPUT_READ: usize = 666; const SLEEP: usize = 909090; // zzz haha const IPC_CREATE: usize = 500; const IPC_READ: usize = 501; @@ -211,11 +207,11 @@ fn close(fd: isize) -> isize { vfs_close(fd as i64) as isize } -fn kbd_read(user_ptr: *mut KeyboardEvent, max_events: isize) -> isize { +fn input_read(user_ptr: *mut InputEvent, max_events: isize) -> isize { #[cfg(target_arch = "x86_64")] process_scancodes(); - #[cfg(target_arch = "aarch64")] - process_keycodes(); + + process_input(); if max_events <= 0 || user_ptr.is_null() { return -1; @@ -229,15 +225,15 @@ fn kbd_read(user_ptr: *mut KeyboardEvent, max_events: isize) -> isize { return SCHEDULER .with_process(pid as u64, |process| { - let to_copy = (max_events as usize).min(process.kbd_buffer.len()); + let to_copy = (max_events as usize).min(process.input_buffer.len()); if let Some(address_space) = process.address_space.as_mut() { if let Ok(_) = copy_to_user( &mut address_space.mapper, user_ptr as *mut u8, - process.kbd_buffer.as_ptr() as *const u8, - to_copy * size_of::(), + process.input_buffer.as_ptr() as *const u8, + to_copy * size_of::(), ) { - process.kbd_buffer.drain(0..to_copy); + process.input_buffer.drain(0..to_copy); return to_copy as isize; } else { @@ -695,7 +691,7 @@ pub unsafe extern "C" fn syscall_dispatch( EXECVE => exec(arg0), CLOCK_GETTIME => ((TIMER.now().elapsed() as usize) * (TIMER_FREQUENCY_HZ / 1000)) as isize, MAP_FRAMEBUFFER => map_framebuffer(), - KBD_READ => kbd_read(arg0 as *mut KeyboardEvent, arg1), + INPUT_READ => input_read(arg0 as *mut InputEvent, arg1), GETPID => { let pid = current_pid().unwrap_or(0); diff --git a/kernel/src/arch/x86_64/gdt.rs b/kernel/src/arch/x86_64/gdt.rs index f7b321c..cba0834 100644 --- a/kernel/src/arch/x86_64/gdt.rs +++ b/kernel/src/arch/x86_64/gdt.rs @@ -1,6 +1,5 @@ use core::mem::MaybeUninit; -use alloc::boxed::Box; use lazy_static::lazy_static; use spin::mutex::Mutex; use x86_64::VirtAddr; diff --git a/kernel/src/arch/x86_64/init.rs b/kernel/src/arch/x86_64/init.rs index 92dbbcb..5ad80af 100644 --- a/kernel/src/arch/x86_64/init.rs +++ b/kernel/src/arch/x86_64/init.rs @@ -1,17 +1,14 @@ use crate::{ - arch::{ - arch::serial_print, - x86_64::{ - gdt::load_gdt_x86_64, - heap::init_heap, - interrupts::{PICS, init_idt_x86_64}, - kmi::setup_kmi, - paging::{FRAME_ALLOCATOR_X86_64, initialize_paging_x86_64}, - syscall::init_syscalls, - }, + arch::x86_64::{ + gdt::load_gdt_x86_64, + heap::init_heap, + interrupts::{PICS, init_idt_x86_64}, + kmi::setup_kmi, + paging::{FRAME_ALLOCATOR_X86_64, initialize_paging_x86_64}, + syscall::init_syscalls, }, config::TIMER_FREQUENCY_HZ, - driver::{io::mouse::MOUSE, ipc::init_ipc}, + driver::ipc::init_ipc, mm::shm::init_shm, }; @@ -82,7 +79,7 @@ pub fn init_x86_64<'a>( pics.write_masks(master_mask, slave_mask); } - let kmi_status = setup_kmi(); + setup_kmi(); set_pit_interval(); @@ -94,8 +91,6 @@ pub fn init_x86_64<'a>( interrupts::enable(); - MOUSE.set_status(kmi_status); - init_ipc(); init_shm(); diff --git a/kernel/src/arch/x86_64/interrupts.rs b/kernel/src/arch/x86_64/interrupts.rs index b14ef8b..ae50e39 100644 --- a/kernel/src/arch/x86_64/interrupts.rs +++ b/kernel/src/arch/x86_64/interrupts.rs @@ -1,15 +1,9 @@ -use core::{arch::naked_asm, sync::atomic::Ordering}; +use core::arch::naked_asm; use crate::{ - arch::{arch::serial_print, x86_64::gdt}, - driver::{ - graphics::framebuffer::with_framebuffer, - io::ps2::{keyboard_interrupt, mouse_interrupt, push_scancode}, - serial::with_serial_console, - timer::TIMER, - }, + arch::x86_64::gdt, + driver::io::ps2::{keyboard_interrupt, mouse_interrupt, push_scancode}, println, - util::U64Buf, }; use lazy_static::lazy_static; use pic8259::ChainedPics; diff --git a/kernel/src/arch/x86_64/paging.rs b/kernel/src/arch/x86_64/paging.rs index 695ed8a..18b358d 100644 --- a/kernel/src/arch/x86_64/paging.rs +++ b/kernel/src/arch/x86_64/paging.rs @@ -8,10 +8,7 @@ use x86_64::{ }, }; -use crate::{ - arch::arch::{HHDM_OFFSET, XunilFrameAllocator, serial_print}, - println, -}; +use crate::arch::arch::{HHDM_OFFSET, XunilFrameAllocator}; unsafe fn active_level_4_table(mem_offset: VirtAddr) -> &'static mut PageTable { let (level_4_table, _) = Cr3::read(); diff --git a/kernel/src/config.rs b/kernel/src/config.rs index 82f0fdc..1a3ed00 100644 --- a/kernel/src/config.rs +++ b/kernel/src/config.rs @@ -1,2 +1,2 @@ pub const TIMER_FREQUENCY_HZ: usize = 1000; -pub const KARCH: &str = "aarch64"; \ No newline at end of file +pub const KARCH: &str = "x86_64"; \ No newline at end of file diff --git a/kernel/src/driver/elf/loader.rs b/kernel/src/driver/elf/loader.rs index e3927a5..75ee9b8 100644 --- a/kernel/src/driver/elf/loader.rs +++ b/kernel/src/driver/elf/loader.rs @@ -4,7 +4,7 @@ use core::{ }; #[cfg(target_arch = "x86_64")] -use crate::arch::x86_64::{interrupts, paging::create_and_map_multiple_pages}; +use crate::arch::x86_64::paging::create_and_map_multiple_pages; #[allow(unused_imports)] use crate::driver::elf::{ header::{ @@ -19,10 +19,7 @@ use crate::arch::aarch64::paging::{ AArchPageTable, create_and_map_multiple_pages, kernel_data_flags, user_data_flags, }; use crate::{ - arch::arch::KERNEL_MAPPER, - mm::address_space::AddressSpace, - println, - task::{context::UserContext, scheduler::SCHEDULER}, + arch::arch::KERNEL_MAPPER, mm::address_space::AddressSpace, println, task::scheduler::SCHEDULER, }; #[cfg(target_arch = "x86_64")] use x86_64::{ diff --git a/kernel/src/driver/graphics/framebuffer.rs b/kernel/src/driver/framebuffer.rs similarity index 85% rename from kernel/src/driver/graphics/framebuffer.rs rename to kernel/src/driver/framebuffer.rs index 5dacebb..888fc28 100644 --- a/kernel/src/driver/graphics/framebuffer.rs +++ b/kernel/src/driver/framebuffer.rs @@ -1,10 +1,10 @@ +use crate::arch::arch::safe_lock; use limine::framebuffer::Framebuffer as LimineFramebuffer; use spin::Mutex; + #[cfg(target_arch = "x86_64")] use x86_64::structures::paging::OffsetPageTable; -use crate::arch::arch::safe_lock; - #[repr(C)] pub struct UserFrameBuffer { pub buf_virt: *mut u32, @@ -56,11 +56,7 @@ impl Framebuffer { #[cfg(target_arch = "x86_64")] pub fn setup_x86_64(&mut self, mapper: &mut OffsetPageTable) { - use crate::{ - arch::arch::{FRAME_ALLOCATOR, HHDM_OFFSET, serial_print}, - arch::x86_64::paging::initialize_paging_x86_64, - util::U64Buf, - }; + use crate::arch::arch::FRAME_ALLOCATOR; use x86_64::{ PhysAddr, VirtAddr, structures::paging::{ @@ -85,8 +81,6 @@ impl Framebuffer { fa.allocate_frame().expect("framebuffer pixel frame"); } - let hhdm_offset = HHDM_OFFSET.load(core::sync::atomic::Ordering::Relaxed); - let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::NO_EXECUTE; let struct_page = Page::::containing_address(VirtAddr::new(KERNEL_FB_BASE)); @@ -167,31 +161,6 @@ impl Framebuffer { self.meta.struct_phys = struct_phys; } - #[inline(always)] - pub fn put_pixel(&mut self, x: usize, y: usize, color: u32) { - if x >= self.width || y >= self.height { - return; - } - let idx = y * self.pitch + x; - if idx >= self.meta.buf_len { - return; - } - unsafe { self.user_fb.buf_virt.add(idx).write(color) }; - } - - #[inline(always)] - pub fn fill_span(&mut self, x: usize, y: usize, len: usize, color: u32) { - if y >= self.height || x >= self.width || len == 0 { - return; - } - let len = core::cmp::min(len, self.width - x); - let start = y * self.pitch + x; - unsafe { - let slice = core::slice::from_raw_parts_mut(self.user_fb.buf_virt.add(start), len); - slice.fill(color); - } - } - pub fn present(&mut self) { unsafe { core::ptr::copy_nonoverlapping(self.user_fb.buf_virt, self.addr, self.meta.buf_len); diff --git a/kernel/src/driver/graphics/font_render.rs b/kernel/src/driver/graphics/font_render.rs deleted file mode 100644 index 2dd48a4..0000000 --- a/kernel/src/driver/graphics/font_render.rs +++ /dev/null @@ -1,69 +0,0 @@ -extern crate font8x8; - -use crate::driver::graphics::framebuffer::Framebuffer; -use font8x8::legacy::BASIC_LEGACY; - -pub fn rectangle_filled( - framebuffer: &mut Framebuffer, - x: usize, - y: usize, - width: usize, - height: usize, - color: u32, -) { - for yy in y..y + height { - framebuffer.fill_span(x, yy, width, color); - } -} - -pub fn render_char( - framebuffer: &mut Framebuffer, - start_x: usize, - start_y: usize, - char: usize, - font_size: usize, - color: u32, -) { - if let Some(glyph) = BASIC_LEGACY.get(char) { - for (row, row_bits) in glyph.iter().enumerate() { - for bit in 0..8 { - if (row_bits & (1 << bit)) != 0 { - rectangle_filled( - framebuffer, - start_x + bit * font_size, - start_y + row * font_size, - font_size, - font_size, - color, - ); - } - } - } - } -} - -pub fn render_text( - framebuffer: &mut Framebuffer, - start_x: usize, - start_y: usize, - text: &str, - font_size: usize, - color: u32, - margin_left: usize, -) -> (usize, usize) { - let mut x = start_x; - let mut y = start_y; - - for b in text.bytes() { - if b == b'\n' { - y += 12 * font_size; - x = margin_left; - continue; - } - - render_char(framebuffer, x, y, b as usize, font_size, color); - x += 8 * font_size; - } - - (x, y) -} diff --git a/kernel/src/driver/graphics/mod.rs b/kernel/src/driver/graphics/mod.rs deleted file mode 100644 index 66487e0..0000000 --- a/kernel/src/driver/graphics/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod font_render; -pub mod framebuffer; - -pub fn rgb(r: u8, g: u8, b: u8) -> u32 { - ((r as u32) << 16) | ((g as u32) << 8) | (b as u32) -} diff --git a/kernel/src/driver/io/fs/assets.rs b/kernel/src/driver/io/fs/assets.rs index 92d9f39..d070c71 100644 --- a/kernel/src/driver/io/fs/assets.rs +++ b/kernel/src/driver/io/fs/assets.rs @@ -1,5 +1,6 @@ -pub static INIT_ELF: &[u8] = include_bytes!("../../../../../assets/aarch64/init"); +pub static INIT_ELF: &[u8] = include_bytes!("../../../../../assets/x86_64/init"); pub static DOOM_WAD: &[u8] = include_bytes!("../../../../../assets/doom1.wad"); -pub static DOOM_ELF: &[u8] = include_bytes!("../../../../../assets/aarch64/doomgeneric"); -pub static HELLOWORLD_ELF: &[u8] = include_bytes!("../../../../../assets/aarch64/helloworld.elf"); -pub static BADAPPLE_ELF: &[u8] = include_bytes!("../../../../../assets/aarch64/badapple"); \ No newline at end of file +pub static DOOM_ELF: &[u8] = include_bytes!("../../../../../assets/x86_64/doomgeneric"); +pub static HELLOWORLD_ELF: &[u8] = include_bytes!("../../../../../assets/x86_64/helloworld.elf"); +pub static BADAPPLE_ELF: &[u8] = include_bytes!("../../../../../assets/x86_64/badapple"); +pub static SHELL_ELF: &[u8] = include_bytes!("../../../../../assets/x86_64/shell"); \ No newline at end of file diff --git a/kernel/src/driver/io/fs/vfs.rs b/kernel/src/driver/io/fs/vfs.rs index 9494e88..727ba7c 100644 --- a/kernel/src/driver/io/fs/vfs.rs +++ b/kernel/src/driver/io/fs/vfs.rs @@ -56,6 +56,10 @@ static FILES: &[FakeFileEntry] = &[ name: "doomgeneric", data: DOOM_ELF, }, + FakeFileEntry { + name: "shell", + data: SHELL_ELF, + }, FakeFileEntry { name: "doom1.wad", data: DOOM_WAD, diff --git a/kernel/src/driver/io/input.rs b/kernel/src/driver/io/input.rs new file mode 100644 index 0000000..37f4704 --- /dev/null +++ b/kernel/src/driver/io/input.rs @@ -0,0 +1,155 @@ +use heapless::spsc::{Consumer, Producer, Queue}; +use static_cell::StaticCell; + +use crate::task::scheduler::SCHEDULER; + +pub const KEY_RESERVED: u8 = 0; +pub const KEY_ESC: u8 = 1; +pub const KEY_1: u8 = 2; +pub const KEY_2: u8 = 3; +pub const KEY_3: u8 = 4; +pub const KEY_4: u8 = 5; +pub const KEY_5: u8 = 6; +pub const KEY_6: u8 = 7; +pub const KEY_7: u8 = 8; +pub const KEY_8: u8 = 9; +pub const KEY_9: u8 = 10; +pub const KEY_0: u8 = 11; +pub const KEY_MINUS: u8 = 12; +pub const KEY_EQUAL: u8 = 13; +pub const KEY_BACKSPACE: u8 = 14; +pub const KEY_TAB: u8 = 15; +pub const KEY_Q: u8 = 16; +pub const KEY_W: u8 = 17; +pub const KEY_E: u8 = 18; +pub const KEY_R: u8 = 19; +pub const KEY_T: u8 = 20; +pub const KEY_Y: u8 = 21; +pub const KEY_U: u8 = 22; +pub const KEY_I: u8 = 23; +pub const KEY_O: u8 = 24; +pub const KEY_P: u8 = 25; +pub const KEY_LEFTBRACE: u8 = 26; +pub const KEY_RIGHTBRACE: u8 = 27; +pub const KEY_ENTER: u8 = 28; +pub const KEY_LEFTCTRL: u8 = 29; +pub const KEY_A: u8 = 30; +pub const KEY_S: u8 = 31; +pub const KEY_D: u8 = 32; +pub const KEY_F: u8 = 33; +pub const KEY_G: u8 = 34; +pub const KEY_H: u8 = 35; +pub const KEY_J: u8 = 36; +pub const KEY_K: u8 = 37; +pub const KEY_L: u8 = 38; +pub const KEY_SEMICOLON: u8 = 39; +pub const KEY_APOSTROPHE: u8 = 40; +pub const KEY_GRAVE: u8 = 41; +pub const KEY_LEFTSHIFT: u8 = 42; +pub const KEY_BACKSLASH: u8 = 43; +pub const KEY_Z: u8 = 44; +pub const KEY_X: u8 = 45; +pub const KEY_C: u8 = 46; +pub const KEY_V: u8 = 47; +pub const KEY_B: u8 = 48; +pub const KEY_N: u8 = 49; +pub const KEY_M: u8 = 50; +pub const KEY_COMMA: u8 = 51; +pub const KEY_DOT: u8 = 52; +pub const KEY_SLASH: u8 = 53; +pub const KEY_RIGHTSHIFT: u8 = 54; +pub const KEY_KPASTERISK: u8 = 55; +pub const KEY_LEFTALT: u8 = 56; +pub const KEY_SPACE: u8 = 57; +pub const KEY_CAPSLOCK: u8 = 58; +pub const KEY_F1: u8 = 59; +pub const KEY_F2: u8 = 60; +pub const KEY_F3: u8 = 61; +pub const KEY_F4: u8 = 62; +pub const KEY_F5: u8 = 63; +pub const KEY_F6: u8 = 64; +pub const KEY_F7: u8 = 65; +pub const KEY_F8: u8 = 66; +pub const KEY_F9: u8 = 67; +pub const KEY_F10: u8 = 68; +pub const KEY_NUMLOCK: u8 = 69; +pub const KEY_SCROLLLOCK: u8 = 70; +pub const KEY_KP7: u8 = 71; +pub const KEY_KP8: u8 = 72; +pub const KEY_KP9: u8 = 73; +pub const KEY_KPMINUS: u8 = 74; +pub const KEY_KP4: u8 = 75; +pub const KEY_KP5: u8 = 76; +pub const KEY_KP6: u8 = 77; +pub const KEY_KPPLUS: u8 = 78; +pub const KEY_KP1: u8 = 79; +pub const KEY_KP2: u8 = 80; +pub const KEY_KP3: u8 = 81; +pub const KEY_KP0: u8 = 82; +pub const KEY_KPDOT: u8 = 83; +pub const KEY_RIGHTCTRL: u8 = 97; +pub const KEY_UP: u8 = 103; +pub const KEY_LEFT: u8 = 105; +pub const KEY_RIGHT: u8 = 106; +pub const KEY_DOWN: u8 = 108; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct InputEvent { + pub event_type: u16, + pub code: u16, + pub value: u32, +} + +pub const EVENT_KEY: u16 = 0x01; +pub const EVENT_REL: u16 = 0x02; + +pub const BTN_LEFT: u16 = 0x110; +pub const BTN_RIGHT: u16 = 0x111; +pub const BTN_MIDDLE: u16 = 0x112; + +pub const REL_X: u16 = 0x00; +pub const REL_Y: u16 = 0x01; +pub const REL_WHEEL: u16 = 0x08; + +pub static INPUT_QUEUE: StaticCell> = StaticCell::new(); +pub static mut INPUT_PROD: Option> = None; +pub static mut INPUT_CONS: Option> = None; + +pub fn init_input() { + let q = INPUT_QUEUE.init(Queue::new()); + let (p, c) = q.split(); + unsafe { + INPUT_PROD = Some(p); + INPUT_CONS = Some(c); + } +} + +pub fn process_input() { + loop { + let input_event = unsafe { + #[allow(static_mut_refs)] + match INPUT_CONS.as_mut() { + Some(cons) => match cons.dequeue() { + Some(b) => b, + None => break, + }, + None => break, + } + }; + + let mut scheduler = SCHEDULER.lock(); + for process in scheduler.processes.values_mut() { + process.input_buffer.push(input_event); + } + drop(scheduler); + } +} + +pub fn enqueue_input_event(input_event: InputEvent) { + #[allow(static_mut_refs)] + let _ = match unsafe { INPUT_PROD.as_mut() } { + Some(prod) => prod.enqueue(input_event).is_ok(), + _ => false, + }; +} diff --git a/kernel/src/driver/io/keyboard.rs b/kernel/src/driver/io/keyboard.rs deleted file mode 100644 index 6442ff8..0000000 --- a/kernel/src/driver/io/keyboard.rs +++ /dev/null @@ -1,192 +0,0 @@ -pub const KEY_RESERVED: u8 = 0; -pub const KEY_ESC: u8 = 1; -pub const KEY_1: u8 = 2; -pub const KEY_2: u8 = 3; -pub const KEY_3: u8 = 4; -pub const KEY_4: u8 = 5; -pub const KEY_5: u8 = 6; -pub const KEY_6: u8 = 7; -pub const KEY_7: u8 = 8; -pub const KEY_8: u8 = 9; -pub const KEY_9: u8 = 10; -pub const KEY_0: u8 = 11; -pub const KEY_MINUS: u8 = 12; -pub const KEY_EQUAL: u8 = 13; -pub const KEY_BACKSPACE: u8 = 14; -pub const KEY_TAB: u8 = 15; -pub const KEY_Q: u8 = 16; -pub const KEY_W: u8 = 17; -pub const KEY_E: u8 = 18; -pub const KEY_R: u8 = 19; -pub const KEY_T: u8 = 20; -pub const KEY_Y: u8 = 21; -pub const KEY_U: u8 = 22; -pub const KEY_I: u8 = 23; -pub const KEY_O: u8 = 24; -pub const KEY_P: u8 = 25; -pub const KEY_LEFTBRACE: u8 = 26; -pub const KEY_RIGHTBRACE: u8 = 27; -pub const KEY_ENTER: u8 = 28; -pub const KEY_LEFTCTRL: u8 = 29; -pub const KEY_A: u8 = 30; -pub const KEY_S: u8 = 31; -pub const KEY_D: u8 = 32; -pub const KEY_F: u8 = 33; -pub const KEY_G: u8 = 34; -pub const KEY_H: u8 = 35; -pub const KEY_J: u8 = 36; -pub const KEY_K: u8 = 37; -pub const KEY_L: u8 = 38; -pub const KEY_SEMICOLON: u8 = 39; -pub const KEY_APOSTROPHE: u8 = 40; -pub const KEY_GRAVE: u8 = 41; -pub const KEY_LEFTSHIFT: u8 = 42; -pub const KEY_BACKSLASH: u8 = 43; -pub const KEY_Z: u8 = 44; -pub const KEY_X: u8 = 45; -pub const KEY_C: u8 = 46; -pub const KEY_V: u8 = 47; -pub const KEY_B: u8 = 48; -pub const KEY_N: u8 = 49; -pub const KEY_M: u8 = 50; -pub const KEY_COMMA: u8 = 51; -pub const KEY_DOT: u8 = 52; -pub const KEY_SLASH: u8 = 53; -pub const KEY_RIGHTSHIFT: u8 = 54; -pub const KEY_KPASTERISK: u8 = 55; -pub const KEY_LEFTALT: u8 = 56; -pub const KEY_SPACE: u8 = 57; -pub const KEY_CAPSLOCK: u8 = 58; -pub const KEY_F1: u8 = 59; -pub const KEY_F2: u8 = 60; -pub const KEY_F3: u8 = 61; -pub const KEY_F4: u8 = 62; -pub const KEY_F5: u8 = 63; -pub const KEY_F6: u8 = 64; -pub const KEY_F7: u8 = 65; -pub const KEY_F8: u8 = 66; -pub const KEY_F9: u8 = 67; -pub const KEY_F10: u8 = 68; -pub const KEY_NUMLOCK: u8 = 69; -pub const KEY_SCROLLLOCK: u8 = 70; -pub const KEY_KP7: u8 = 71; -pub const KEY_KP8: u8 = 72; -pub const KEY_KP9: u8 = 73; -pub const KEY_KPMINUS: u8 = 74; -pub const KEY_KP4: u8 = 75; -pub const KEY_KP5: u8 = 76; -pub const KEY_KP6: u8 = 77; -pub const KEY_KPPLUS: u8 = 78; -pub const KEY_KP1: u8 = 79; -pub const KEY_KP2: u8 = 80; -pub const KEY_KP3: u8 = 81; -pub const KEY_KP0: u8 = 82; -pub const KEY_KPDOT: u8 = 83; -pub const KEY_RIGHTCTRL: u8 = 97; -pub const KEY_UP: u8 = 103; -pub const KEY_LEFT: u8 = 105; -pub const KEY_RIGHT: u8 = 106; -pub const KEY_DOWN: u8 = 108; - -pub const KEY_TO_CHAR: [Option<(char, char)>; 84] = [ - None, // 0 KEY_RESERVED - Some(('\x1b', '\x1b')), // 1 KEY_ESC - Some(('1', '!')), // 2 KEY_1 - Some(('2', '@')), // 3 KEY_2 - Some(('3', '#')), // 4 KEY_3 - Some(('4', '$')), // 5 KEY_4 - Some(('5', '%')), // 6 KEY_5 - Some(('6', '^')), // 7 KEY_6 - Some(('7', '&')), // 8 KEY_7 - Some(('8', '*')), // 9 KEY_8 - Some(('9', '(')), // 10 KEY_9 - Some(('0', ')')), // 11 KEY_0 - Some(('-', '_')), // 12 KEY_MINUS - Some(('=', '+')), // 13 KEY_EQUAL - Some(('\x08', '\x08')), // 14 KEY_BACKSPACE - Some(('\t', '\t')), // 15 KEY_TAB - Some(('q', 'Q')), // 16 KEY_Q - Some(('w', 'W')), // 17 KEY_W - Some(('e', 'E')), // 18 KEY_E - Some(('r', 'R')), // 19 KEY_R - Some(('t', 'T')), // 20 KEY_T - Some(('y', 'Y')), // 21 KEY_Y - Some(('u', 'U')), // 22 KEY_U - Some(('i', 'I')), // 23 KEY_I - Some(('o', 'O')), // 24 KEY_O - Some(('p', 'P')), // 25 KEY_P - Some(('[', '{')), // 26 KEY_LEFTBRACE - Some((']', '}')), // 27 KEY_RIGHTBRACE - Some(('\n', '\n')), // 28 KEY_ENTER - None, // 29 KEY_LEFTCTRL - Some(('a', 'A')), // 30 KEY_A - Some(('s', 'S')), // 31 KEY_S - Some(('d', 'D')), // 32 KEY_D - Some(('f', 'F')), // 33 KEY_F - Some(('g', 'G')), // 34 KEY_G - Some(('h', 'H')), // 35 KEY_H - Some(('j', 'J')), // 36 KEY_J - Some(('k', 'K')), // 37 KEY_K - Some(('l', 'L')), // 38 KEY_L - Some((';', ':')), // 39 KEY_SEMICOLON - Some(('\'', '"')), // 40 KEY_APOSTROPHE - Some(('`', '~')), // 41 KEY_GRAVE - None, // 42 KEY_LEFTSHIFT - Some(('\\', '|')), // 43 KEY_BACKSLASH - Some(('z', 'Z')), // 44 KEY_Z - Some(('x', 'X')), // 45 KEY_X - Some(('c', 'C')), // 46 KEY_C - Some(('v', 'V')), // 47 KEY_V - Some(('b', 'B')), // 48 KEY_B - Some(('n', 'N')), // 49 KEY_N - Some(('m', 'M')), // 50 KEY_M - Some((',', '<')), // 51 KEY_COMMA - Some(('.', '>')), // 52 KEY_DOT - Some(('/', '?')), // 53 KEY_SLASH - None, // 54 KEY_RIGHTSHIFT - Some(('*', '*')), // 55 KEY_KPASTERISK - None, // 56 KEY_LEFTALT - Some((' ', ' ')), // 57 KEY_SPACE - None, // 58 KEY_CAPSLOCK - None, // 59 KEY_F1 - None, // 60 KEY_F2 - None, // 61 KEY_F3 - None, // 62 KEY_F4 - None, // 63 KEY_F5 - None, // 64 KEY_F6 - None, // 65 KEY_F7 - None, // 66 KEY_F8 - None, // 67 KEY_F9 - None, // 68 KEY_F10 - None, // 69 KEY_NUMLOCK - None, // 70 KEY_SCROLLLOCK - Some(('7', '7')), // 71 KEY_KP7 - Some(('8', '8')), // 72 KEY_KP8 - Some(('9', '9')), // 73 KEY_KP9 - Some(('-', '-')), // 74 KEY_KPMINUS - Some(('4', '4')), // 75 KEY_KP4 - Some(('5', '5')), // 76 KEY_KP5 - Some(('6', '6')), // 77 KEY_KP6 - Some((('+'), '+')), // 78 KEY_KPPLUS - Some(('1', '1')), // 79 KEY_KP1 - Some(('2', '2')), // 80 KEY_KP2 - Some(('3', '3')), // 81 KEY_KP3 - Some(('0', '0')), // 82 KEY_KP0 - Some(('.', '.')), // 83 KEY_KPDOT -]; - -pub fn keycode_to_char(keycode: u8, shift: bool) -> Option { - let entry = KEY_TO_CHAR.get(keycode as usize)?.as_ref()?; - Some(if shift { entry.1 } else { entry.0 }) -} - -#[repr(C)] -#[derive(Clone, Debug, Copy, Default)] -pub struct KeyboardEvent { - pub state: u8, - pub _pad1: u8, - pub key: u16, - pub mods: u16, - pub _pad2: u16, - pub unicode: u32, -} diff --git a/kernel/src/driver/io/mod.rs b/kernel/src/driver/io/mod.rs index aab5f37..b8634d8 100644 --- a/kernel/src/driver/io/mod.rs +++ b/kernel/src/driver/io/mod.rs @@ -1,6 +1,5 @@ pub mod fs; -pub mod keyboard; -pub mod mouse; +pub mod input; #[cfg(target_arch = "x86_64")] pub mod ps2; pub mod virtio; diff --git a/kernel/src/driver/io/mouse.rs b/kernel/src/driver/io/mouse.rs deleted file mode 100644 index 610e46d..0000000 --- a/kernel/src/driver/io/mouse.rs +++ /dev/null @@ -1,45 +0,0 @@ -use core::sync::atomic::{AtomicBool, AtomicI16, AtomicU8, Ordering}; - -pub struct Mouse { - pub left_button_pressed: AtomicBool, - pub right_button_pressed: AtomicBool, - pub middle_button_pressed: AtomicBool, - pub x_delta: AtomicI16, - pub y_delta: AtomicI16, - pub status: AtomicU8, -} - -impl Mouse { - const fn new() -> Mouse { - Mouse { - left_button_pressed: AtomicBool::new(false), - right_button_pressed: AtomicBool::new(false), - middle_button_pressed: AtomicBool::new(false), - x_delta: AtomicI16::new(0), - y_delta: AtomicI16::new(0), - status: AtomicU8::new(0), - } - } - - pub fn button_state(&self) -> (bool, bool, bool) { - ( - self.left_button_pressed.load(Ordering::Relaxed), - self.right_button_pressed.load(Ordering::Relaxed), - self.middle_button_pressed.load(Ordering::Relaxed), - ) - } - pub fn take_motion(&self) -> (i16, i16) { - ( - self.x_delta.swap(0, Ordering::Relaxed), - self.y_delta.swap(0, Ordering::Relaxed), - ) - } - pub fn set_status(&self, status: u8) { - self.status.store(status, Ordering::Relaxed); - } - pub fn get_status(&self) -> u8 { - self.status.load(Ordering::Relaxed) - } -} - -pub static MOUSE: Mouse = Mouse::new(); diff --git a/kernel/src/driver/io/ps2.rs b/kernel/src/driver/io/ps2.rs index 8159af0..b147b29 100644 --- a/kernel/src/driver/io/ps2.rs +++ b/kernel/src/driver/io/ps2.rs @@ -1,23 +1,14 @@ -use core::sync::atomic::{AtomicU8, AtomicU64, Ordering}; +use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; use heapless::spsc::{Consumer, Producer, Queue}; -use pc_keyboard::{DecodedKey, HandleControl, KeyCode, KeyState, Keyboard, ScancodeSet2, layouts}; +use pc_keyboard::{HandleControl, KeyCode, KeyState, Keyboard, ScancodeSet2, layouts}; use static_cell::StaticCell; -#[cfg(target_arch = "aarch64")] -use crate::arch::aarch64::kmi::{ - read_keyboard_control, read_keyboard_data, read_mouse_control, read_mouse_data, -}; #[cfg(target_arch = "x86_64")] use crate::arch::x86_64::kmi::{ read_keyboard_control, read_keyboard_data, read_mouse_control, read_mouse_data, }; -use crate::{ - driver::io::{keyboard::*, mouse::MOUSE}, - println, - task::scheduler::SCHEDULER, - util::get_bit, -}; +use crate::{driver::io::input::*, util::get_bit}; pub fn keycode_to_linux(kc: KeyCode) -> Option { let code = match kc { @@ -118,7 +109,9 @@ static mut SCANCODE_PROD: Option> = None; static mut SCANCODE_CONS: Option> = None; static mut KEYBOARD: Option> = None; -static DROPPED_SCANCODES: AtomicU64 = AtomicU64::new(0); +static MOUSE_LEFT_BUTTON: AtomicBool = AtomicBool::new(false); +static MOUSE_RIGHT_BUTTON: AtomicBool = AtomicBool::new(false); +static MOUSE_MIDDLE_BUTTON: AtomicBool = AtomicBool::new(false); pub fn init_keyboard() { let q = SCANCODE_QUEUE.init(Queue::new()); @@ -136,17 +129,11 @@ pub fn init_keyboard() { } pub fn push_scancode(scancode: u8) { - let pushed = unsafe { - #[allow(static_mut_refs)] - match SCANCODE_PROD.as_mut() { - Some(prod) => prod.enqueue(scancode).is_ok(), - _ => false, - } + #[allow(static_mut_refs)] + match unsafe { SCANCODE_PROD.as_mut() } { + Some(prod) => prod.enqueue(scancode).is_ok(), + _ => false, }; - - if !pushed { - DROPPED_SCANCODES.fetch_add(1, Ordering::Relaxed); - } } pub fn process_scancodes() { @@ -162,45 +149,24 @@ pub fn process_scancodes() { } }; - if let Some(kbd_event) = process_scancode(scancode) { - let mut scheduler = SCHEDULER.lock(); - for process in scheduler.processes.values_mut() { - process.kbd_buffer.push(kbd_event); + #[allow(static_mut_refs)] + let kbd = unsafe { KEYBOARD.as_mut().unwrap() }; + if let Ok(Some(key_event)) = kbd.add_byte(scancode) { + if let Some(linux_keycode) = keycode_to_linux(key_event.code) { + enqueue_input_event(InputEvent { + event_type: EVENT_KEY, + code: linux_keycode as u16, + value: if key_event.state == KeyState::Down { + 1 + } else { + 0 + }, + }); } - drop(scheduler); } } } -pub fn process_scancode(scancode: u8) -> Option { - #[allow(static_mut_refs)] - let kbd = unsafe { KEYBOARD.as_mut().expect("keyboard not initialized") }; - if let Ok(Some(key_event)) = kbd.add_byte(scancode) { - let keycode = key_event.code; - let keystate = key_event.state; - let (unicode, state) = match (kbd.process_keyevent(key_event), keystate) { - (Some(DecodedKey::Unicode(ch)), st) => (ch as u32, st), - _ => (0, keystate), - }; - - if let Some(linux_keycode) = keycode_to_linux(keycode) { - let effective_shift = kbd.get_modifiers().is_shifted() & kbd.get_modifiers().capslock; - return Some(KeyboardEvent { - state: if state == KeyState::Down { 1 } else { 0 }, - _pad1: 0, - key: linux_keycode as u16, - mods: 0, - _pad2: 0, - unicode: keycode_to_char(linux_keycode, effective_shift).unwrap_or('\0') as u32, - }); - } else { - return None; - } - } else { - return None; - } -} - static CURRENTLY_RECEIVING_STATE: AtomicU8 = AtomicU8::new(0); static FLAGS_BYTE: AtomicU8 = AtomicU8::new(0); static X_DELTA_BYTE: AtomicU8 = AtomicU8::new(0); @@ -293,34 +259,53 @@ pub fn process_mouse_interrupt() -> Option<(bool, bool, bool, i16, i16)> { } pub fn mouse_interrupt() { - if let Some(interrupt_result) = process_mouse_interrupt() { - MOUSE - .left_button_pressed - .store(interrupt_result.0, Ordering::Relaxed); - MOUSE - .right_button_pressed - .store(interrupt_result.1, Ordering::Relaxed); - MOUSE - .middle_button_pressed - .store(interrupt_result.2, Ordering::Relaxed); - MOUSE - .x_delta - .fetch_add(interrupt_result.3, Ordering::Relaxed); - MOUSE - .y_delta - .fetch_add(interrupt_result.4, Ordering::Relaxed); + if let Some((left, right, middle, dx, dy)) = process_mouse_interrupt() { + if left != MOUSE_LEFT_BUTTON.swap(left, Ordering::Relaxed) { + enqueue_input_event(InputEvent { + event_type: EVENT_KEY, + code: BTN_LEFT, + value: left as u32, + }); + } + + if right != MOUSE_RIGHT_BUTTON.swap(right, Ordering::Relaxed) { + enqueue_input_event(InputEvent { + event_type: EVENT_KEY, + code: BTN_RIGHT, + value: right as u32, + }); + } + + if middle != MOUSE_MIDDLE_BUTTON.swap(middle, Ordering::Relaxed) { + enqueue_input_event(InputEvent { + event_type: EVENT_KEY, + code: BTN_MIDDLE, + value: middle as u32, + }); + } + + if dx != 0 { + enqueue_input_event(InputEvent { + event_type: EVENT_REL, + code: REL_X, + value: dx as i32 as u32, + }); + } + + if dy != 0 { + enqueue_input_event(InputEvent { + event_type: EVENT_REL, + code: REL_Y, + value: dy as i32 as u32, + }); + } } } pub fn keyboard_interrupt() -> Option { - #[cfg(target_arch = "x86_64")] if (unsafe { read_keyboard_control() } & 0x01) == 0 { return None; // OBF clear, no data } - #[cfg(target_arch = "aarch64")] - if (unsafe { read_keyboard_control() } & 0x10) == 0 { - return None; // RXFULL clear, no data - } let scancode = unsafe { read_keyboard_data() }; Some(scancode) diff --git a/kernel/src/driver/io/virtio/input.rs b/kernel/src/driver/io/virtio/input.rs index ff0d57e..261c6fc 100644 --- a/kernel/src/driver/io/virtio/input.rs +++ b/kernel/src/driver/io/virtio/input.rs @@ -1,34 +1,12 @@ -use heapless::spsc::{Consumer, Producer, Queue}; -use static_cell::StaticCell; - -use crate::{ - arch::arch::serial_print, - driver::io::{ - keyboard::{ - KEY_CAPSLOCK, KEY_LEFTALT, KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_RIGHTSHIFT, KeyboardEvent, - keycode_to_char, - }, - mouse::MOUSE, - virtio::{ - KEYBOARD_SLOT, MOUSE_SLOT, VIRTIO_MMIO_BASE, VIRTIO_MMIO_STRIDE, - queue::{QUEUE_SIZE, VirtqueueMem}, - transport::{VirtioMmio, VirtioMmioReg}, - }, +use crate::driver::io::{ + input::{InputEvent, enqueue_input_event}, + virtio::{ + KEYBOARD_SLOT, MOUSE_SLOT, VIRTIO_MMIO_BASE, VIRTIO_MMIO_STRIDE, + queue::{QUEUE_SIZE, VirtqueueMem}, + transport::{VirtioMmio, VirtioMmioReg}, }, - task::scheduler::SCHEDULER, }; -const BTN_LEFT: u16 = 0x110; -const BTN_RIGHT: u16 = 0x111; -const BTN_MIDDLE: u16 = 0x112; - -const REL_X: u16 = 0x00; -const REL_Y: u16 = 0x01; -const REL_WHEEL: u16 = 0x08; - -const EVENT_KEY: u16 = 0x01; -const EVENT_REL: u16 = 0x02; - #[repr(u8)] pub enum VirtioInputCfgSelect { Unset = 0x00, @@ -48,84 +26,8 @@ pub struct VirtioInputEvent { value: u32, } -pub struct ModState { - shift: bool, - caps_lock: bool, - ctrl: bool, - alt: bool, -} - -impl ModState { - pub const fn new() -> Self { - Self { - shift: false, - caps_lock: false, - ctrl: false, - alt: false, - } - } - pub fn update(&mut self, code: u8, value: u32) { - match code { - KEY_LEFTSHIFT | KEY_RIGHTSHIFT => self.shift = value != 0, - KEY_LEFTCTRL => self.ctrl = value != 0, - KEY_CAPSLOCK => self.caps_lock = value != 0, - KEY_LEFTALT => self.alt = value != 0, - _ => {} - } - } - - pub fn effective_shift(&self) -> bool { - self.shift ^ self.caps_lock - } -} - pub static mut VIRTIO_KEYBOARD_QUEUE: VirtqueueMem = unsafe { core::mem::zeroed() }; pub static mut VIRTIO_MOUSE_QUEUE: VirtqueueMem = unsafe { core::mem::zeroed() }; -pub static mut MODIFIERS: ModState = ModState::new(); - -static KEYCODE_QUEUE: StaticCell> = StaticCell::new(); -static mut KEYCODE_PROD: Option> = None; -static mut KEYCODE_CONS: Option> = None; - -pub fn init_keyboard() { - let q = KEYCODE_QUEUE.init(Queue::new()); - let (p, c) = q.split(); - - unsafe { - KEYCODE_PROD = Some(p); - KEYCODE_CONS = Some(c); - } -} - -pub fn process_keycodes() { - let mut scheduler = SCHEDULER.lock(); - - loop { - let keycode_data = unsafe { - #[allow(static_mut_refs)] - match KEYCODE_CONS.as_mut() { - Some(cons) => match cons.dequeue() { - Some(b) => b, - None => break, - }, - None => break, - } - }; - - for process in scheduler.processes.values_mut() { - process.kbd_buffer.push(KeyboardEvent { - state: keycode_data.1, - _pad1: 0, - key: keycode_data.0 as u16, - mods: 0, - _pad2: 0, - unicode: keycode_to_char(keycode_data.0, keycode_data.2).unwrap_or('\0') as u32, - }); - } - } - - drop(scheduler); -} pub fn read_device_name(device: &VirtioMmio) -> &str { return unsafe { @@ -214,59 +116,9 @@ pub fn handle_event(event: &VirtioInputEvent) { return; } - match event.event_type { - EVENT_KEY => { - unsafe { MODIFIERS.update(event.code as u8, event.value) }; - match event.code { - BTN_LEFT => { - MOUSE - .left_button_pressed - .store(event.value == 1, core::sync::atomic::Ordering::Relaxed); - } - BTN_RIGHT => { - MOUSE - .right_button_pressed - .store(event.value == 1, core::sync::atomic::Ordering::Relaxed); - } - BTN_MIDDLE => { - MOUSE - .middle_button_pressed - .store(event.value == 1, core::sync::atomic::Ordering::Relaxed); - } - _ => { - let state = match event.value { - 1 => 1, - 0 => 0, - _ => return, - }; - - let _ = match unsafe { KEYCODE_PROD.as_mut() } { - Some(prod) => prod - .enqueue(unsafe { - (event.code as u8, state, MODIFIERS.effective_shift()) - }) - .is_ok(), - _ => false, - }; - } - } - } - EVENT_REL => match event.code { - REL_X => { - MOUSE.x_delta.fetch_add( - event.value as i32 as i16, - core::sync::atomic::Ordering::Relaxed, - ); - } - REL_Y => { - MOUSE.y_delta.fetch_add( - event.value as i32 as i16, - core::sync::atomic::Ordering::Relaxed, - ); - } - REL_WHEEL => {} - _ => {} - }, - _ => serial_print("Could not recognize virtio input event from interrupt\n"), - }; + enqueue_input_event(InputEvent { + event_type: event.event_type, + code: event.code, + value: event.value, + }); } diff --git a/kernel/src/driver/mod.rs b/kernel/src/driver/mod.rs index fe9b2c6..8415cd6 100644 --- a/kernel/src/driver/mod.rs +++ b/kernel/src/driver/mod.rs @@ -1,6 +1,5 @@ pub mod elf; -pub mod graphics; +pub mod framebuffer; pub mod io; pub mod ipc; -pub mod serial; pub mod timer; diff --git a/kernel/src/driver/serial.rs b/kernel/src/driver/serial.rs deleted file mode 100644 index be9c3ef..0000000 --- a/kernel/src/driver/serial.rs +++ /dev/null @@ -1,115 +0,0 @@ -use crate::alloc::string::ToString; -use crate::arch::arch::serial_print; -use crate::driver::graphics::font_render::render_text; -use crate::driver::graphics::framebuffer::Framebuffer; -use crate::{arch::arch::safe_lock, driver::graphics::rgb}; -use alloc::string::String; -use core::fmt::{self, Write}; -use spin::Mutex; - -pub struct ConsoleWriter<'a> { - pub fb: &'a mut Framebuffer, - pub console: &'a mut SerialConsole, - pub should_center: bool, -} - -impl Write for ConsoleWriter<'_> { - fn write_str(&mut self, s: &str) -> fmt::Result { - serial_print(s); - self.console.print(s, self.fb); - Ok(()) - } -} - -pub struct SerialConsole { - text: String, - pub font_size: usize, - dirty: bool, -} - -impl SerialConsole { - pub fn new() -> SerialConsole { - SerialConsole { - text: String::new(), - font_size: 1, - dirty: false, - } - } - - pub fn print(&mut self, text: &str, fb: &mut Framebuffer) { - if text == "\x1b[2J" { - self.text.clear(); - return; - } - - let max_height = fb.height / (12 * self.font_size); - let max_width = fb.width / (8 * self.font_size); - - for ch in text.chars() { - if ch == '\n' { - self.text.push('\n'); - continue; - } - - let line_len = self - .text - .rsplit('\n') - .next() - .map(|l| l.chars().count()) - .unwrap_or(0); - - if line_len >= max_width { - self.text.push('\n'); - } - - self.text.push(ch); - } - - let lines = self.text.lines().count(); - - if lines > max_height { - let remove = lines - max_height; - let mut split = 0; - - for (i, c) in self.text.char_indices() { - if c == '\n' { - split += 1; - if split == remove { - self.text = self.text[i + 1..].to_string(); - break; - } - } - } - } - - self.dirty = true; - } - - pub fn render(&mut self, fb: &mut Framebuffer) { - if self.dirty { - fb.clear(rgb(0, 0, 0)); - self.dirty = false; - render_text(fb, 0, 0, &self.text, self.font_size, rgb(255, 255, 255), 0); - } - } - - pub fn clear(&mut self) { - self.dirty = true; - self.text.clear(); - } -} - -pub static SERIAL_CONSOLE: Mutex> = Mutex::new(None); - -pub fn init_serial_console() { - *SERIAL_CONSOLE.lock() = Some(SerialConsole::new()); -} - -pub fn with_serial_console(f: F) { - safe_lock(|| { - let mut guard = SERIAL_CONSOLE.lock(); - if let Some(sc) = guard.as_mut() { - f(sc); - } - }); -} diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 0caefba..e8c84de 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -5,7 +5,7 @@ extern crate alloc; -use core::fmt::Write; +use core::fmt::{self, Write}; use core::sync::atomic::{AtomicU64, Ordering}; use limine::{ @@ -20,10 +20,8 @@ use limine::{ use crate::arch::aarch64::paging::AArchPageTable; #[cfg(target_arch = "x86_64")] use crate::arch::arch::KERNEL_MAPPER; -#[cfg(target_arch = "aarch64")] -use crate::driver::io::virtio::input::init_keyboard; -#[cfg(target_arch = "aarch64")] -use crate::util::U64Buf; +use crate::driver::io::input::init_input; + #[cfg(target_arch = "aarch64")] use aarch64_cpu::registers::{DAIF, Writeable}; @@ -33,12 +31,9 @@ use crate::driver::io::ps2::init_keyboard; use crate::arch::arch::{HHDM_OFFSET, infinite_idle, init, kernel_crash, serial_print}; use crate::driver::{ elf::loader::run_elf, - graphics::{ - framebuffer::{init_framebuffer, with_framebuffer}, - rgb, - }, + framebuffer::{init_framebuffer, with_framebuffer}, io::fs::assets::INIT_ELF, - serial::{ConsoleWriter, init_serial_console, with_serial_console}, + // serial::{ConsoleWriter, init_serial_console, with_serial_console}, timer::TIMER, }; @@ -105,18 +100,19 @@ macro_rules! println { }; } +pub struct SerialWriter {} + +impl Write for SerialWriter { + fn write_str(&mut self, s: &str) -> fmt::Result { + serial_print(s); + Ok(()) + } +} + #[doc(hidden)] pub fn _print(args: core::fmt::Arguments) { - with_framebuffer(|fb| { - with_serial_console(|console| { - let mut writer = ConsoleWriter { - fb, - console, - should_center: false, - }; - let _ = writer.write_fmt(args); - }); - }); + let mut writer = SerialWriter {}; + let _ = writer.write_fmt(args); } #[unsafe(no_mangle)] @@ -189,9 +185,8 @@ pub unsafe extern "C" fn kernel_main_aarch64(mapper: &mut AArchPageTable) -> ! { } else { panic!("no framebuffers found"); } - init_serial_console(); - init_keyboard(); + init_input(); if let Some(date_at_boot_response) = DATE_AT_BOOT_REQUEST.get_response() { TIMER.set_date_at_boot(date_at_boot_response.timestamp().as_secs()); @@ -234,9 +229,8 @@ pub unsafe fn kernel_main_x86_64() -> ! { } } - init_serial_console(); - init_keyboard(); + init_input(); #[allow(static_mut_refs)] unsafe { @@ -294,22 +288,22 @@ fn rust_panic(_info: &core::panic::PanicInfo) -> ! { }; serial_print(msg); serial_print("\n"); - with_framebuffer(|mut fb| { - fb.clear(rgb(180, 0, 0)); + // with_framebuffer(|mut fb| { + // fb.clear(rgb(180, 0, 0)); - with_serial_console(|console| { - console.clear(); + // with_serial_console(|console| { + // console.clear(); - let mut writer = ConsoleWriter { - fb: &mut fb, - console, - should_center: true, - }; + // let mut writer = ConsoleWriter { + // fb: &mut fb, + // console, + // should_center: true, + // }; - let _ = writer.write_str("KERNEL PANIC\n\n"); - let _ = writer.write_fmt(core::format_args!("{}", _info)); - }); - }); + // let _ = writer.write_str("KERNEL PANIC\n\n"); + // let _ = writer.write_fmt(core::format_args!("{}", _info)); + // }); + // }); infinite_idle(); } diff --git a/kernel/src/task/process.rs b/kernel/src/task/process.rs index 1528185..322189f 100644 --- a/kernel/src/task/process.rs +++ b/kernel/src/task/process.rs @@ -3,8 +3,8 @@ use core::sync::atomic::Ordering; use alloc::vec::Vec; use crate::{ - arch::arch::GLOBAL_TICK_COUNT, driver::io::keyboard::KeyboardEvent, - mm::address_space::AddressSpace, task::context::UserContext, + arch::arch::GLOBAL_TICK_COUNT, driver::io::input::InputEvent, mm::address_space::AddressSpace, + task::context::UserContext, }; pub enum ProcessState { @@ -27,7 +27,7 @@ pub struct Process { pub kernel_stack_top: u64, pub heap_base: u64, pub heap_end: u64, - pub kbd_buffer: Vec, + pub input_buffer: Vec, pub address_space: Option, pub saved_ctx: Option, pub user_entry: u64, @@ -51,7 +51,7 @@ impl Process { heap_base, heap_end, last_switch_tick: GLOBAL_TICK_COUNT.load(Ordering::Relaxed), - kbd_buffer: Vec::new(), + input_buffer: Vec::new(), address_space: None, saved_ctx: None, user_entry, diff --git a/user/apps/doomgeneric b/user/apps/doomgeneric index c8cde8f..a04df50 160000 --- a/user/apps/doomgeneric +++ b/user/apps/doomgeneric @@ -1 +1 @@ -Subproject commit c8cde8fe456d3ef3b1d7ee1894952ea3119773d4 +Subproject commit a04df50195107be3f5c6f906505faf9adabff90e diff --git a/user/init b/user/init index 2c1ffa3..5ed48db 160000 --- a/user/init +++ b/user/init @@ -1 +1 @@ -Subproject commit 2c1ffa31d61358f68cd9d5a875df0c5332ca0114 +Subproject commit 5ed48dbd780a9c11de0dda933596a5bbb4a7e998 diff --git a/user/libxunil b/user/libxunil index a6448bc..7f9192f 160000 --- a/user/libxunil +++ b/user/libxunil @@ -1 +1 @@ -Subproject commit a6448bc1f25eebe051f4952ab0675ad7a7ecafb2 +Subproject commit 7f9192f4e8a57753da8c54829a9b6d36aa5851c9