Event system
This commit is contained in:
parent
1b2dd2bfbe
commit
638bfb2d5c
|
@ -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<EventManager> = Mutex::new(EventManager::new());
|
||||
);
|
||||
|
||||
|
||||
pub struct EventManager {
|
||||
listeners: [Option<EventManagerEntry>; 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<EventManagerEntry> = 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 {
|
||||
|
||||
|
||||
}
|
||||
|
|
19
kernel/src/events/types.rs
Normal file
19
kernel/src/events/types.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use pc_keyboard::DecodedKey;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum Event {
|
||||
TimerInterrupt(Option<usize>), // trash unused value
|
||||
Ps2KeyPress(Option<DecodedKey>)
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! get_event_value {
|
||||
($typ:pat, $ev:expr) => {
|
||||
match $ev {
|
||||
$typ(v) => v.unwrap(),
|
||||
_ => panic!("Bad event value")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use pic8259::ChainedPics;
|
||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
||||
use x86_64::structures::idt::InterruptDescriptorTable;
|
||||
|
||||
|
||||
mod handlers;
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use core::slice::Iter;
|
||||
|
||||
use super::{Frame, FrameAllocator, MemInfo, MemoryAreaIter};
|
||||
use multiboot2::MemoryArea;
|
||||
|
||||
|
|
|
@ -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<Frame>;
|
||||
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() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user