// SPDX-License-Identifier: MPL-2.0 use alloc::{sync::Arc, vec::Vec}; use core::fmt::Debug; use ostd::sync::{RwLock, WriteIrqDisabled}; use crate::{ InputDevice, input_dev::RegisteredInputDevice, input_handler::{BoundInputHandler, InputHandlerClass}, }; /// Registry entry for each registered device. /// /// This serves as the connection point between devices and their handlers. #[derive(Debug)] struct InputDeviceRegistry { /// The input device. device: Arc, /// Handlers connected to this device. handlers: Arc, WriteIrqDisabled>>, } /// The core component of the input subsystem. /// /// `InputCore` manages all registered input devices and handler classes. /// It coordinates the connection between devices and handlers, and routes /// input events from devices to their associated handlers. #[derive(Debug)] pub(crate) struct InputCore { /// All registered devices with their associated handlers. devices: Vec, /// All registered handler classes that can connect to devices. handler_classes: Vec>, } impl InputCore { /// Creates a new input core. pub(crate) fn new() -> Self { Self { devices: Vec::new(), handler_classes: Vec::new(), } } /// Registers a new handler class. pub(crate) fn register_handler_class(&mut self, handler_class: Arc) { // Connect to all existing devices for device_registry in self.devices.iter() { match handler_class.connect(device_registry.device.clone()) { Ok(handler) => { device_registry.handlers.write().push(BoundInputHandler { handler, handler_class: handler_class.clone(), }); log::info!( "Input: successfully connected handler class {} to device {}", handler_class.name(), device_registry.device.name() ); } Err(e) => { log::info!( "Input: failed to connect handler class {} to device {}: {:?}", handler_class.name(), device_registry.device.name(), e ); } } } log::info!("Input: registered handler class {}", handler_class.name()); self.handler_classes.push(handler_class); } /// Unregisters a handler class. pub(crate) fn unregister_handler_class( &mut self, handler_class: &Arc, ) -> Option> { // Find the handler class and remove it. let pos = self .handler_classes .iter() .position(|h| Arc::ptr_eq(h, handler_class))?; let handler_class = self.handler_classes.swap_remove(pos); for device_registry in self.devices.iter() { let mut handlers = device_registry.handlers.write(); let Some(pos) = handlers .iter() .position(|h| Arc::ptr_eq(&h.handler_class, &handler_class)) else { continue; }; let handler = handlers.swap_remove(pos); drop(handlers); drop(handler); handler_class.disconnect(&device_registry.device); } log::info!("Input: unregistered handler class {}", handler_class.name()); Some(handler_class) } /// Registers a new input device. pub(crate) fn register_device( &mut self, device: Arc, ) -> RegisteredInputDevice { // Connect all existing handler classes. let mut connected_handlers = Vec::new(); for handler_class in self.handler_classes.iter() { match handler_class.connect(device.clone()) { Ok(handler) => { connected_handlers.push(BoundInputHandler { handler, handler_class: handler_class.clone(), }); log::info!( "Input: successfully connected handler class {} to device {}", handler_class.name(), device.name() ); } Err(e) => { log::info!( "Input: failed to connect handler class {} to device {}: {:?}", handler_class.name(), device.name(), e ); } } } let handlers = Arc::new(RwLock::new(connected_handlers)); // Add the device registry. let new_registry = InputDeviceRegistry { device: device.clone(), handlers: handlers.clone(), }; self.devices.push(new_registry); log::info!("Input: registered device {}", device.name()); RegisteredInputDevice::new(device, handlers) } /// Unregisters an input device. pub(crate) fn unregister_device( &mut self, device: &Arc, ) -> Option> { // Find the device and remove it. let pos = self .devices .iter() .position(|registry| Arc::ptr_eq(®istry.device, device))?; let device_registry = self.devices.swap_remove(pos); // Take all handlers connected to this device and clear the list. let mut handlers = device_registry.handlers.write(); let bound_handlers = core::mem::take(&mut *handlers); drop(handlers); // Disconnect handler classes that were connected. for bound_handler in bound_handlers.into_iter() { bound_handler .handler_class .disconnect(&device_registry.device); } log::info!("Input: unregistered device {}", device.name()); Some(device_registry.device) } /// Counts the number of registered devices. pub(crate) fn count_devices(&self) -> usize { self.devices.len() } /// Counts the number of registered handler classes. pub(crate) fn count_handler_class(&self) -> usize { self.handler_classes.len() } /// Gets all registered devices. pub(crate) fn all_devices(&self) -> Vec> { self.devices .iter() .map(|registry| registry.device.clone()) .collect() } }