130 lines
3.5 KiB
Rust
130 lines
3.5 KiB
Rust
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
//! The input devices of Asterinas.
|
|
//!
|
|
//! This crate provides a comprehensive input subsystem for handling various input devices,
|
|
//! including keyboards, mice, etc. It implements an event-driven architecture similar to
|
|
//! the Linux input subsystem.
|
|
//!
|
|
//! # Architecture
|
|
//!
|
|
//! ```text
|
|
//! Input Device → Input Core → Input Handler
|
|
//! ↓ ↓ ↓
|
|
//! Hardware Event Router Event Consumer
|
|
//! (e.g., evdev)
|
|
//! ```
|
|
//!
|
|
//! # Example Usage
|
|
//!
|
|
//! ```
|
|
//! // Register an input device
|
|
//! let device = Arc::new(MyInputDevice::new());
|
|
//! let registered_device = input::register_device(device);
|
|
//!
|
|
//! // Register an input handler
|
|
//! let handler = Arc::new(MyInputHandler::new());
|
|
//! input::register_handler(handler);
|
|
//!
|
|
//! // Submit a key event from device
|
|
//! let key_event = InputEvent::from_key_and_status(linux_key, key_status);
|
|
//! registered_device.submit_events(&[key_event]);
|
|
//! ```
|
|
//!
|
|
#![no_std]
|
|
#![deny(unsafe_code)]
|
|
|
|
extern crate alloc;
|
|
|
|
pub mod event_type_codes;
|
|
mod input_core;
|
|
pub mod input_dev;
|
|
pub mod input_handler;
|
|
|
|
use alloc::{sync::Arc, vec::Vec};
|
|
|
|
use component::{ComponentInitError, init_component};
|
|
use ostd::sync::Mutex;
|
|
use spin::Once;
|
|
|
|
use self::input_core::InputCore;
|
|
use crate::{
|
|
input_dev::{InputDevice, RegisteredInputDevice},
|
|
input_handler::{InputHandlerClass, RegisteredInputHandlerClass},
|
|
};
|
|
|
|
/// Registers a handler class.
|
|
pub fn register_handler_class(
|
|
handler_class: Arc<dyn InputHandlerClass>,
|
|
) -> RegisteredInputHandlerClass {
|
|
let component = COMPONENT.get().unwrap();
|
|
component
|
|
.input_core
|
|
.lock()
|
|
.register_handler_class(handler_class.clone());
|
|
RegisteredInputHandlerClass(handler_class)
|
|
}
|
|
|
|
/// Unregisters a handler class.
|
|
pub(crate) fn unregister_handler_class(
|
|
handler_class: &Arc<dyn InputHandlerClass>,
|
|
) -> Option<Arc<dyn InputHandlerClass>> {
|
|
let component = COMPONENT.get().unwrap();
|
|
component
|
|
.input_core
|
|
.lock()
|
|
.unregister_handler_class(handler_class)
|
|
}
|
|
|
|
/// Registers an input device.
|
|
pub fn register_device(device: Arc<dyn InputDevice>) -> RegisteredInputDevice {
|
|
let component = COMPONENT.get().unwrap();
|
|
component.input_core.lock().register_device(device)
|
|
}
|
|
|
|
/// Unregisters an input device.
|
|
pub(crate) fn unregister_device(device: &Arc<dyn InputDevice>) -> Option<Arc<dyn InputDevice>> {
|
|
let component = COMPONENT.get().unwrap();
|
|
component.input_core.lock().unregister_device(device)
|
|
}
|
|
|
|
/// Counts the number of registered devices.
|
|
pub fn count_devices() -> usize {
|
|
let component = COMPONENT.get().unwrap();
|
|
component.input_core.lock().count_devices()
|
|
}
|
|
|
|
/// Counts the number of registered handler classes.
|
|
pub fn count_handler_class() -> usize {
|
|
let component = COMPONENT.get().unwrap();
|
|
component.input_core.lock().count_handler_class()
|
|
}
|
|
|
|
/// Gets all registered devices.
|
|
pub fn all_devices() -> Vec<Arc<dyn InputDevice>> {
|
|
let component = COMPONENT.get().unwrap();
|
|
component.input_core.lock().all_devices()
|
|
}
|
|
|
|
static COMPONENT: Once<Component> = Once::new();
|
|
|
|
#[init_component]
|
|
fn component_init() -> Result<(), ComponentInitError> {
|
|
let component = Component::init()?;
|
|
COMPONENT.call_once(|| component);
|
|
Ok(())
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
struct Component {
|
|
input_core: Mutex<InputCore>,
|
|
}
|
|
|
|
impl Component {
|
|
pub fn init() -> Result<Self, ComponentInitError> {
|
|
Ok(Self {
|
|
input_core: Mutex::new(InputCore::new()),
|
|
})
|
|
}
|
|
}
|