mirror of
https://github.com/XunilGroup/XunilOS.git
synced 2026-06-02 12:44:24 +02:00
Remove unused imports, merge ps2 and virtio to both use linux input
events and move parsing code to libxunil, and add mouse support again by using them, remove unneeded graphics and console output code, merge build files to a rust app builder, make framebuffer a driver and remove the graphics folder, add shell as an app in VFS
This commit is contained in:
Generated
-7
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
+2
-1
@@ -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();
|
||||
|
||||
+14
-18
@@ -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::<KeyboardEvent>(),
|
||||
process.input_buffer.as_ptr() as *const u8,
|
||||
to_copy * size_of::<InputEvent>(),
|
||||
) {
|
||||
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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
pub const TIMER_FREQUENCY_HZ: usize = 1000;
|
||||
pub const KARCH: &str = "aarch64";
|
||||
pub const KARCH: &str = "x86_64";
|
||||
@@ -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::{
|
||||
|
||||
@@ -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::<Size4KiB>::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);
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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");
|
||||
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");
|
||||
@@ -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,
|
||||
|
||||
@@ -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<Queue<InputEvent, 256>> = StaticCell::new();
|
||||
pub static mut INPUT_PROD: Option<Producer<'static, InputEvent>> = None;
|
||||
pub static mut INPUT_CONS: Option<Consumer<'static, InputEvent>> = 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,
|
||||
};
|
||||
}
|
||||
@@ -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<char> {
|
||||
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,
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
+63
-78
@@ -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<u8> {
|
||||
let code = match kc {
|
||||
@@ -118,7 +109,9 @@ static mut SCANCODE_PROD: Option<Producer<'static, u8>> = None;
|
||||
static mut SCANCODE_CONS: Option<Consumer<'static, u8>> = None;
|
||||
static mut KEYBOARD: Option<Keyboard<layouts::Us104Key, ScancodeSet2>> = 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<KeyboardEvent> {
|
||||
#[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<u8> {
|
||||
#[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)
|
||||
|
||||
@@ -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<Queue<(u8, u8, bool), 256>> = StaticCell::new();
|
||||
static mut KEYCODE_PROD: Option<Producer<'static, (u8, u8, bool)>> = None;
|
||||
static mut KEYCODE_CONS: Option<Consumer<'static, (u8, u8, bool)>> = 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,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<Option<SerialConsole>> = Mutex::new(None);
|
||||
|
||||
pub fn init_serial_console() {
|
||||
*SERIAL_CONSOLE.lock() = Some(SerialConsole::new());
|
||||
}
|
||||
|
||||
pub fn with_serial_console<F: FnOnce(&mut SerialConsole)>(f: F) {
|
||||
safe_lock(|| {
|
||||
let mut guard = SERIAL_CONSOLE.lock();
|
||||
if let Some(sc) = guard.as_mut() {
|
||||
f(sc);
|
||||
}
|
||||
});
|
||||
}
|
||||
+31
-37
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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<KeyboardEvent>,
|
||||
pub input_buffer: Vec<InputEvent>,
|
||||
pub address_space: Option<AddressSpace>,
|
||||
pub saved_ctx: Option<UserContext>,
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user