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 x86_64::structures::idt::{InterruptStackFrame, PageFaultErrorCode};
|
||||||
use crate::interrupts::InterruptIndex;
|
use crate::{events::EVENTMAN, interrupts::InterruptIndex};
|
||||||
|
|
||||||
mod ps2_keyboard;
|
mod ps2_keyboard;
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ pub extern "x86-interrupt" fn breakpoint(sf: InterruptStackFrame){
|
||||||
pub extern "x86-interrupt" fn timer_interrupt(_: InterruptStackFrame){
|
pub extern "x86-interrupt" fn timer_interrupt(_: InterruptStackFrame){
|
||||||
//log::debug!("INT: TIMER\n{:#?}", sf);
|
//log::debug!("INT: TIMER\n{:#?}", sf);
|
||||||
// print!(".");
|
// print!(".");
|
||||||
|
EVENTMAN.lock().dispatch(&crate::events::Event::TimerInterrupt(None));
|
||||||
unsafe {
|
unsafe {
|
||||||
super::PICS.lock()
|
super::PICS.lock()
|
||||||
.notify_end_of_interrupt(InterruptIndex::Timer as u8);
|
.notify_end_of_interrupt(InterruptIndex::Timer as u8);
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
use pc_keyboard::DecodedKey;
|
||||||
use x86_64::structures::idt::InterruptStackFrame;
|
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){
|
pub extern "x86-interrupt" fn ps2_kb_int(_sf: InterruptStackFrame){
|
||||||
use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1};
|
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() };
|
let scancode: u8 = unsafe { port.read() };
|
||||||
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
|
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
|
||||||
if let Some(key) = keyboard.process_keyevent(key_event) {
|
if let Some(key) = keyboard.process_keyevent(key_event) {
|
||||||
if false {
|
EVENTMAN.lock().dispatch(&crate::events::Event::Ps2KeyPress(Some(key)));
|
||||||
match key {
|
|
||||||
DecodedKey::Unicode(character) => print!("{}", character),
|
|
||||||
DecodedKey::RawKey(key) => print!("{:?}", key),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use pic8259::ChainedPics;
|
use pic8259::ChainedPics;
|
||||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
use x86_64::structures::idt::InterruptDescriptorTable;
|
||||||
|
|
||||||
|
|
||||||
mod handlers;
|
mod handlers;
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(abi_x86_interrupt)]
|
#![feature(abi_x86_interrupt)]
|
||||||
|
#![feature(associated_type_defaults)]
|
||||||
|
|
||||||
use multiboot2::BootInformationHeader;
|
use events::EVENTMAN;
|
||||||
use x86_64::registers::control::Cr3;
|
|
||||||
|
|
||||||
use crate::mem::FrameAllocator;
|
use crate::events::Event;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod logger;
|
mod logger;
|
||||||
mod interrupts;
|
mod interrupts;
|
||||||
mod gdt;
|
mod gdt;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
#[macro_use]
|
||||||
mod events;
|
mod events;
|
||||||
mod mem;
|
mod mem;
|
||||||
|
|
||||||
|
@ -24,14 +25,15 @@ extern "C" fn kmain(mb2_info_addr: usize) -> ! {
|
||||||
gdt::init();
|
gdt::init();
|
||||||
interrupts::init_idt();
|
interrupts::init_idt();
|
||||||
let mem_info = mem::MemInfo::load(mb2_info_addr);
|
let mem_info = mem::MemInfo::load(mb2_info_addr);
|
||||||
let mut alloc = mem::area_frame_alloc::AreaFrameAllocator::new(mem_info);
|
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(())
|
||||||
|
});
|
||||||
|
|
||||||
for i in 0.. {
|
|
||||||
if let None = alloc.allocate_frame() {
|
|
||||||
println!("allocated {} frames", i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// let (level_4_page_table, _) = Cr3::read();
|
// let (level_4_page_table, _) = Cr3::read();
|
||||||
// println!("Level 4 page table at: {:?}", level_4_page_table.start_address());
|
// 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 super::{Frame, FrameAllocator, MemInfo, MemoryAreaIter};
|
||||||
use multiboot2::MemoryArea;
|
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;
|
pub mod area_frame_alloc;
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ pub mod area_frame_alloc;
|
||||||
static GLOBAL_ALLOCATOR: DummyAlloc = DummyAlloc;
|
static GLOBAL_ALLOCATOR: DummyAlloc = DummyAlloc;
|
||||||
pub struct DummyAlloc;
|
pub struct DummyAlloc;
|
||||||
unsafe impl GlobalAlloc for DummyAlloc {
|
unsafe impl GlobalAlloc for DummyAlloc {
|
||||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 { 0 as *mut u8 }
|
unsafe fn alloc(&self, _: Layout) -> *mut u8 { 0 as *mut u8 }
|
||||||
unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) {}
|
unsafe fn dealloc(&self, _ptr: *mut u8, _: Layout) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const PAGE_SIZE: usize = 4096;
|
pub const PAGE_SIZE: usize = 4096;
|
||||||
|
@ -26,6 +26,7 @@ impl Frame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub trait FrameAllocator {
|
pub trait FrameAllocator {
|
||||||
fn allocate_frame(&mut self) -> Option<Frame>;
|
fn allocate_frame(&mut self) -> Option<Frame>;
|
||||||
fn deallocate_frame(&mut self, frame: Frame);
|
fn deallocate_frame(&mut self, frame: Frame);
|
||||||
|
@ -83,7 +84,7 @@ impl MemInfo {
|
||||||
let boot_info = unsafe {
|
let boot_info = unsafe {
|
||||||
multiboot2::BootInformation::load(mb_ptr as *const BootInformationHeader).unwrap()
|
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:");
|
// log::debug!("Memory areas:");
|
||||||
// for area in mmap_tag.memory_areas() {
|
// for area in mmap_tag.memory_areas() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user