From 638bfb2d5c5d1524886c14aac056c4713f068260 Mon Sep 17 00:00:00 2001 From: MCorange Date: Wed, 12 Jun 2024 02:18:10 +0300 Subject: [PATCH] Event system --- kernel/src/events/mod.rs | 61 +++++++++++++++++-- kernel/src/events/types.rs | 19 ++++++ kernel/src/interrupts/handlers/mod.rs | 3 +- .../src/interrupts/handlers/ps2_keyboard.rs | 12 ++-- kernel/src/interrupts/mod.rs | 3 +- kernel/src/lib.rs | 24 ++++---- kernel/src/mem/area_frame_alloc.rs | 2 - kernel/src/mem/mod.rs | 11 ++-- 8 files changed, 103 insertions(+), 32 deletions(-) create mode 100644 kernel/src/events/types.rs diff --git a/kernel/src/events/mod.rs b/kernel/src/events/mod.rs index bb97166..0536cbc 100644 --- a/kernel/src/events/mod.rs +++ b/kernel/src/events/mod.rs @@ -1,12 +1,63 @@ +use core::mem::discriminant; + +use lazy_static::lazy_static; + +#[macro_use] +mod types; +use spin::Mutex; +pub use types::*; +const MAX_EVENT_LISTENERS: usize = 255; -pub struct KernelEventHandler { +lazy_static!( + pub static ref EVENTMAN: Mutex = Mutex::new(EventManager::new()); +); +pub struct EventManager { + listeners: [Option; MAX_EVENT_LISTENERS], + listener_count: usize, +} + +type EventListenerFunc = fn(ev: &Event) -> Result<(), ()>; +pub struct EventManagerEntry { + pub func: EventListenerFunc, + pub typ: Event +} + + +const ARRAY_REPEAT_VALUE: Option = None; + +impl EventManager { + pub fn new() -> Self { + Self { + listeners: [ARRAY_REPEAT_VALUE; MAX_EVENT_LISTENERS], + listener_count: 0 + } + } + + pub fn dispatch(&self, ev: &Event){ + for listener in &self.listeners { + if let Some(l) = listener { + if discriminant(ev) == discriminant(&l.typ) { + // TODO: Do something with the result + let _ = (l.func)(ev); + } + } + } + } + + pub fn add_listener(&mut self, typ: Event, func: EventListenerFunc) { + self.listeners[self.listener_count] = Some(EventManagerEntry { + func, typ + }) + } + + #[allow(dead_code)] + pub fn remove_listener(&mut self, _: &str) { + todo!() + } + } -impl KernelEventHandler { - - -} diff --git a/kernel/src/events/types.rs b/kernel/src/events/types.rs new file mode 100644 index 0000000..a983df6 --- /dev/null +++ b/kernel/src/events/types.rs @@ -0,0 +1,19 @@ +use pc_keyboard::DecodedKey; + +#[allow(dead_code)] +#[derive(Debug)] +pub enum Event { + TimerInterrupt(Option), // trash unused value + Ps2KeyPress(Option) +} + +#[macro_export] +macro_rules! get_event_value { + ($typ:pat, $ev:expr) => { + match $ev { + $typ(v) => v.unwrap(), + _ => panic!("Bad event value") + } + }; +} + diff --git a/kernel/src/interrupts/handlers/mod.rs b/kernel/src/interrupts/handlers/mod.rs index 95b0134..3601c09 100644 --- a/kernel/src/interrupts/handlers/mod.rs +++ b/kernel/src/interrupts/handlers/mod.rs @@ -1,5 +1,5 @@ use x86_64::structures::idt::{InterruptStackFrame, PageFaultErrorCode}; -use crate::interrupts::InterruptIndex; +use crate::{events::EVENTMAN, interrupts::InterruptIndex}; mod ps2_keyboard; @@ -12,6 +12,7 @@ pub extern "x86-interrupt" fn breakpoint(sf: InterruptStackFrame){ pub extern "x86-interrupt" fn timer_interrupt(_: InterruptStackFrame){ //log::debug!("INT: TIMER\n{:#?}", sf); // print!("."); + EVENTMAN.lock().dispatch(&crate::events::Event::TimerInterrupt(None)); unsafe { super::PICS.lock() .notify_end_of_interrupt(InterruptIndex::Timer as u8); diff --git a/kernel/src/interrupts/handlers/ps2_keyboard.rs b/kernel/src/interrupts/handlers/ps2_keyboard.rs index 7f82c66..416d2b7 100644 --- a/kernel/src/interrupts/handlers/ps2_keyboard.rs +++ b/kernel/src/interrupts/handlers/ps2_keyboard.rs @@ -1,6 +1,9 @@ +use pc_keyboard::DecodedKey; use x86_64::structures::idt::InterruptStackFrame; -use crate::interrupts::PICS; +use crate::{events::EVENTMAN, interrupts::PICS}; + +pub struct Ps2KbPressEvent(DecodedKey); pub extern "x86-interrupt" fn ps2_kb_int(_sf: InterruptStackFrame){ use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1}; @@ -20,12 +23,7 @@ pub extern "x86-interrupt" fn ps2_kb_int(_sf: InterruptStackFrame){ let scancode: u8 = unsafe { port.read() }; if let Ok(Some(key_event)) = keyboard.add_byte(scancode) { if let Some(key) = keyboard.process_keyevent(key_event) { - if false { - match key { - DecodedKey::Unicode(character) => print!("{}", character), - DecodedKey::RawKey(key) => print!("{:?}", key), - } - } + EVENTMAN.lock().dispatch(&crate::events::Event::Ps2KeyPress(Some(key))); } } unsafe { diff --git a/kernel/src/interrupts/mod.rs b/kernel/src/interrupts/mod.rs index a54e618..d78518d 100644 --- a/kernel/src/interrupts/mod.rs +++ b/kernel/src/interrupts/mod.rs @@ -1,5 +1,6 @@ use pic8259::ChainedPics; -use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; +use x86_64::structures::idt::InterruptDescriptorTable; + mod handlers; diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 811d06a..1ee2624 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -1,17 +1,18 @@ #![no_std] #![no_main] #![feature(abi_x86_interrupt)] +#![feature(associated_type_defaults)] -use multiboot2::BootInformationHeader; -use x86_64::registers::control::Cr3; +use events::EVENTMAN; -use crate::mem::FrameAllocator; +use crate::events::Event; #[macro_use] mod logger; mod interrupts; mod gdt; mod utils; +#[macro_use] mod events; mod mem; @@ -24,15 +25,16 @@ extern "C" fn kmain(mb2_info_addr: usize) -> ! { gdt::init(); interrupts::init_idt(); let mem_info = mem::MemInfo::load(mb2_info_addr); - let mut alloc = mem::area_frame_alloc::AreaFrameAllocator::new(mem_info); - - for i in 0.. { - if let None = alloc.allocate_frame() { - println!("allocated {} frames", i); - break; - } -} + let mut _alloc = mem::area_frame_alloc::AreaFrameAllocator::new(mem_info); + EVENTMAN.lock().add_listener(events::Event::Ps2KeyPress(None), |k| { + let Event::Ps2KeyPress(v) = k else {panic!()}; + + log::debug!("Keypress event received! ({:?})", v.unwrap()); + Ok(()) + }); + + // let (level_4_page_table, _) = Cr3::read(); // println!("Level 4 page table at: {:?}", level_4_page_table.start_address()); diff --git a/kernel/src/mem/area_frame_alloc.rs b/kernel/src/mem/area_frame_alloc.rs index f210bb3..6ae52ec 100644 --- a/kernel/src/mem/area_frame_alloc.rs +++ b/kernel/src/mem/area_frame_alloc.rs @@ -1,5 +1,3 @@ -use core::slice::Iter; - use super::{Frame, FrameAllocator, MemInfo, MemoryAreaIter}; use multiboot2::MemoryArea; diff --git a/kernel/src/mem/mod.rs b/kernel/src/mem/mod.rs index 3d1a737..670bf3e 100644 --- a/kernel/src/mem/mod.rs +++ b/kernel/src/mem/mod.rs @@ -1,6 +1,6 @@ -use core::{alloc::{GlobalAlloc, Layout}, ops::Deref}; +use core::alloc::{GlobalAlloc, Layout}; -use multiboot2::{BootInformation, BootInformationHeader, MemoryArea, MemoryAreaType, MemoryMapTag, TagTrait}; +use multiboot2::{BootInformationHeader, MemoryArea, MemoryAreaType, MemoryMapTag, TagTrait}; pub mod area_frame_alloc; @@ -8,8 +8,8 @@ pub mod area_frame_alloc; static GLOBAL_ALLOCATOR: DummyAlloc = DummyAlloc; pub struct DummyAlloc; unsafe impl GlobalAlloc for DummyAlloc { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { 0 as *mut u8 } - unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) {} + unsafe fn alloc(&self, _: Layout) -> *mut u8 { 0 as *mut u8 } + unsafe fn dealloc(&self, _ptr: *mut u8, _: Layout) {} } pub const PAGE_SIZE: usize = 4096; @@ -26,6 +26,7 @@ impl Frame { } } +#[allow(dead_code)] pub trait FrameAllocator { fn allocate_frame(&mut self) -> Option; fn deallocate_frame(&mut self, frame: Frame); @@ -83,7 +84,7 @@ impl MemInfo { let boot_info = unsafe { multiboot2::BootInformation::load(mb_ptr as *const BootInformationHeader).unwrap() }; - let mmap_tag = boot_info.memory_map_tag().unwrap().clone(); + let mmap_tag = boot_info.memory_map_tag().unwrap(); // log::debug!("Memory areas:"); // for area in mmap_tag.memory_areas() {