Files
asterinas/kernel/comps/console/src/lib.rs
2024-06-27 15:45:49 +08:00

71 lines
1.8 KiB
Rust

// SPDX-License-Identifier: MPL-2.0
//! The console device of Asterinas.
#![no_std]
#![deny(unsafe_code)]
#![feature(fn_traits)]
extern crate alloc;
use alloc::{collections::BTreeMap, fmt::Debug, string::String, sync::Arc, vec::Vec};
use core::any::Any;
use component::{init_component, ComponentInitError};
use ostd::{mm::VmReader, sync::SpinLock};
use spin::Once;
pub type ConsoleCallback = dyn Fn(VmReader) + Send + Sync;
pub trait AnyConsoleDevice: Send + Sync + Any + Debug {
fn send(&self, buf: &[u8]);
/// Registers callback to the console device.
/// The callback will be called once the console device receive data.
///
/// Since the callback will be called in interrupt context,
/// the callback should NEVER sleep.
fn register_callback(&self, callback: &'static ConsoleCallback);
}
pub fn register_device(name: String, device: Arc<dyn AnyConsoleDevice>) {
COMPONENT
.get()
.unwrap()
.console_device_table
.lock_irq_disabled()
.insert(name, device);
}
pub fn all_devices() -> Vec<(String, Arc<dyn AnyConsoleDevice>)> {
let console_devs = COMPONENT
.get()
.unwrap()
.console_device_table
.lock_irq_disabled();
console_devs
.iter()
.map(|(name, device)| (name.clone(), device.clone()))
.collect()
}
static COMPONENT: Once<Component> = Once::new();
#[init_component]
fn component_init() -> Result<(), ComponentInitError> {
let a = Component::init()?;
COMPONENT.call_once(|| a);
Ok(())
}
#[derive(Debug)]
struct Component {
console_device_table: SpinLock<BTreeMap<String, Arc<dyn AnyConsoleDevice>>>,
}
impl Component {
pub fn init() -> Result<Self, ComponentInitError> {
Ok(Self {
console_device_table: SpinLock::new(BTreeMap::new()),
})
}
}