feat: Integrate LVGL v8.3 desktop GUI, PS/2 mouse driver, live system monitor, and make gui target
This commit is contained in:
@@ -13,7 +13,7 @@ pub unsafe fn init() {
|
||||
|
||||
/// Enable SSE/SSE2/XSAVE for user-space SIMD operations.
|
||||
/// Required to prevent #GP when user programs use XMM registers or compiler-generated SSE code.
|
||||
unsafe fn enable_sse() {
|
||||
pub unsafe fn enable_sse() {
|
||||
// Clear CR0.EM (bit 2) - disable x87 FPU emulation
|
||||
// Set CR0.MP (bit 1) - monitor coprocessor (allow WAIT)
|
||||
let mut cr0: u64;
|
||||
|
||||
@@ -13,6 +13,7 @@ pub extern "C" fn ap_startup(info: *const LimineSmpInfo) -> ! {
|
||||
let lapic_id = (*info).lapic_id;
|
||||
|
||||
// Initialize CPU Architecture for this AP with dedicated TSS selector
|
||||
super::enable_sse();
|
||||
super::gdt::init_ap(cpu_id as usize);
|
||||
super::idt::init();
|
||||
super::syscall::init();
|
||||
|
||||
@@ -488,8 +488,30 @@ pub extern "C" fn kernel_syscall_dispatcher(regs: &mut SyscallRegisters) {
|
||||
}
|
||||
regs.rax = (-1i64) as u64;
|
||||
}
|
||||
// SYS_MOUSE_GET = 21 (Read mouse coordinates and buttons)
|
||||
21 => {
|
||||
let out_ptr = regs.rdi as *mut MouseInfoPayload;
|
||||
if !out_ptr.is_null() {
|
||||
let (mx, my, mb) = crate::drivers::mouse::get_mouse_info();
|
||||
unsafe {
|
||||
(*out_ptr).x = mx;
|
||||
(*out_ptr).y = my;
|
||||
(*out_ptr).buttons = mb;
|
||||
}
|
||||
regs.rax = 0;
|
||||
return;
|
||||
}
|
||||
regs.rax = (-1i64) as u64;
|
||||
}
|
||||
_ => {
|
||||
regs.rax = (-1i64) as u64; // SYS_ERR_INVALID_ARG
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct MouseInfoPayload {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub buttons: u32,
|
||||
}
|
||||
|
||||
@@ -72,14 +72,20 @@ pub fn init() {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn keyboard_interrupt_handler() {
|
||||
unsafe {
|
||||
let scancode = inb(PS2_DATA_PORT);
|
||||
let status = inb(0x64);
|
||||
let data = inb(PS2_DATA_PORT);
|
||||
|
||||
// Process only key-down events (bit 7 clear)
|
||||
if (scancode as usize) < SCANCODE_MAP.len() {
|
||||
let ascii = SCANCODE_MAP[scancode as usize];
|
||||
if ascii != 0 {
|
||||
let buf = &mut *core::ptr::addr_of_mut!(KEY_BUFFER);
|
||||
buf.push(ascii);
|
||||
if (status & 0x20) != 0 {
|
||||
let mouse = &mut *core::ptr::addr_of_mut!(crate::drivers::mouse::MOUSE_STATE);
|
||||
mouse.handle_byte(data);
|
||||
} else {
|
||||
// Process only key-down events (bit 7 clear)
|
||||
if (data as usize) < SCANCODE_MAP.len() {
|
||||
let ascii = SCANCODE_MAP[data as usize];
|
||||
if ascii != 0 {
|
||||
let buf = &mut *core::ptr::addr_of_mut!(KEY_BUFFER);
|
||||
buf.push(ascii);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,3 +3,4 @@ pub mod timer;
|
||||
pub mod keyboard;
|
||||
pub mod rtc;
|
||||
pub mod dmesg;
|
||||
pub mod mouse;
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
//! PS/2 Mouse Driver
|
||||
//! Handles 8042 Auxiliary Device communication, 3-byte packet assembly, and coordinate tracking.
|
||||
|
||||
use crate::kprintln;
|
||||
|
||||
const PS2_DATA_PORT: u16 = 0x60;
|
||||
const PS2_STATUS_PORT: u16 = 0x64;
|
||||
const PS2_COMMAND_PORT: u16 = 0x64;
|
||||
|
||||
#[inline]
|
||||
unsafe fn inb(port: u16) -> u8 {
|
||||
let mut val: u8;
|
||||
core::arch::asm!("in al, dx", in("dx") port, out("al") val, options(nomem, nostack, preserves_flags));
|
||||
val
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn outb(port: u16, val: u8) {
|
||||
core::arch::asm!("out dx, al", in("dx") port, in("al") val, options(nomem, nostack, preserves_flags));
|
||||
}
|
||||
|
||||
unsafe fn wait_ps2_write() {
|
||||
let mut timeout = 100000;
|
||||
while (inb(PS2_STATUS_PORT) & 0x02) != 0 && timeout > 0 {
|
||||
timeout -= 1;
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn wait_ps2_read() {
|
||||
let mut timeout = 100000;
|
||||
while (inb(PS2_STATUS_PORT) & 0x01) == 0 && timeout > 0 {
|
||||
timeout -= 1;
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MouseState {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub buttons: u32, // bit 0 = Left, bit 1 = Right, bit 2 = Middle
|
||||
packet: [u8; 3],
|
||||
packet_index: usize,
|
||||
max_x: i32,
|
||||
max_y: i32,
|
||||
}
|
||||
|
||||
pub static mut MOUSE_STATE: MouseState = MouseState {
|
||||
x: 640,
|
||||
y: 400,
|
||||
buttons: 0,
|
||||
packet: [0; 3],
|
||||
packet_index: 0,
|
||||
max_x: 1280,
|
||||
max_y: 800,
|
||||
};
|
||||
|
||||
impl MouseState {
|
||||
pub fn handle_byte(&mut self, b: u8) {
|
||||
if self.packet_index == 0 {
|
||||
// First byte must have bit 3 set (sync bit)
|
||||
if (b & 0x08) == 0 {
|
||||
return; // Out of sync, discard
|
||||
}
|
||||
}
|
||||
|
||||
self.packet[self.packet_index] = b;
|
||||
self.packet_index += 1;
|
||||
|
||||
if self.packet_index == 3 {
|
||||
self.packet_index = 0;
|
||||
|
||||
let flags = self.packet[0];
|
||||
let raw_dx = self.packet[1];
|
||||
let raw_dy = self.packet[2];
|
||||
|
||||
// Buttons: bit 0 = Left, bit 1 = Right, bit 2 = Middle
|
||||
self.buttons = (flags & 0x07) as u32;
|
||||
|
||||
// X offset with 9-bit sign extension
|
||||
let mut dx = raw_dx as i32;
|
||||
if (flags & 0x10) != 0 {
|
||||
dx |= !0xFF; // sign extend negative
|
||||
}
|
||||
|
||||
// Y offset with 9-bit sign extension (PS/2 Y points upwards, screen points downwards)
|
||||
let mut dy = raw_dy as i32;
|
||||
if (flags & 0x20) != 0 {
|
||||
dy |= !0xFF; // sign extend negative
|
||||
}
|
||||
|
||||
self.x += dx;
|
||||
self.y -= dy; // Invert Y for screen coordinates
|
||||
|
||||
// Clamp to screen boundaries
|
||||
if self.x < 0 { self.x = 0; }
|
||||
if self.x >= self.max_x { self.x = self.max_x - 1; }
|
||||
if self.y < 0 { self.y = 0; }
|
||||
if self.y >= self.max_y { self.y = self.max_y - 1; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(screen_w: i32, screen_h: i32) {
|
||||
unsafe {
|
||||
MOUSE_STATE.max_x = screen_w;
|
||||
MOUSE_STATE.max_y = screen_h;
|
||||
MOUSE_STATE.x = screen_w / 2;
|
||||
MOUSE_STATE.y = screen_h / 2;
|
||||
|
||||
// 1. Enable auxiliary device (Mouse) in 8042 controller
|
||||
wait_ps2_write();
|
||||
outb(PS2_COMMAND_PORT, 0xA8);
|
||||
|
||||
// 2. Enable auxiliary device interrupts in 8042 controller configuration byte
|
||||
wait_ps2_write();
|
||||
outb(PS2_COMMAND_PORT, 0x20); // Read Controller Command Byte
|
||||
wait_ps2_read();
|
||||
let mut status = inb(PS2_DATA_PORT);
|
||||
status |= 0x02; // Enable IRQ 12 (mouse interrupt)
|
||||
status &= !0x20; // Clear mouse clock disable
|
||||
|
||||
wait_ps2_write();
|
||||
outb(PS2_COMMAND_PORT, 0x60); // Write Controller Command Byte
|
||||
wait_ps2_write();
|
||||
outb(PS2_DATA_PORT, status);
|
||||
|
||||
// 3. Set Defaults (command 0xF6) to mouse
|
||||
wait_ps2_write();
|
||||
outb(PS2_COMMAND_PORT, 0xD4);
|
||||
wait_ps2_write();
|
||||
outb(PS2_DATA_PORT, 0xF6);
|
||||
wait_ps2_read();
|
||||
let _ = inb(PS2_DATA_PORT); // ACK (0xFA)
|
||||
|
||||
// 4. Enable Data Reporting (command 0xF4) to mouse
|
||||
wait_ps2_write();
|
||||
outb(PS2_COMMAND_PORT, 0xD4);
|
||||
wait_ps2_write();
|
||||
outb(PS2_DATA_PORT, 0xF4);
|
||||
wait_ps2_read();
|
||||
let _ = inb(PS2_DATA_PORT); // ACK (0xFA)
|
||||
|
||||
kprintln!("[MOUSE] PS/2 Mouse Driver Initialized (Screen: {}x{}).", screen_w, screen_h);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mouse_info() -> (i32, i32, u32) {
|
||||
unsafe {
|
||||
(MOUSE_STATE.x, MOUSE_STATE.y, MOUSE_STATE.buttons)
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,7 @@ pub extern "C" fn _start() -> ! {
|
||||
unsafe {
|
||||
drivers::timer::init(100);
|
||||
drivers::keyboard::init();
|
||||
drivers::mouse::init(1280, 800);
|
||||
}
|
||||
|
||||
// 7. Initialize IPC & Capability System
|
||||
@@ -103,6 +104,8 @@ pub extern "C" fn _start() -> ! {
|
||||
0 => "init_server",
|
||||
1 => "uart_driver",
|
||||
2 => "sh",
|
||||
3 => "procmgr",
|
||||
4 => "gui_server",
|
||||
_ => "user_server",
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user