Mark Poliakov 18fa8b954a Add 'kernel/' from commit '7f1f6b73377367db17f98a740316b904c37ce3b1'
git-subtree-dir: kernel
git-subtree-mainline: 817f71f90f97270dd569fd44246bf74e57636552
git-subtree-split: 7f1f6b73377367db17f98a740316b904c37ce3b1
2024-03-12 15:52:48 +02:00

64 lines
1.7 KiB
Rust

use core::sync::atomic::{AtomicU16, Ordering};
use alloc::{collections::BTreeMap, sync::Arc};
use libk_util::{queue::UnboundedMpmcQueue, sync::spin_rwlock::IrqSafeRwLock};
use crate::{
class_driver,
device::{UsbBusAddress, UsbDeviceAccess},
UsbHostController,
};
pub struct UsbBusManager {
busses: IrqSafeRwLock<BTreeMap<u16, &'static dyn UsbHostController>>,
devices: IrqSafeRwLock<BTreeMap<UsbBusAddress, Arc<UsbDeviceAccess>>>,
last_bus_address: AtomicU16,
}
impl UsbBusManager {
pub fn register_bus(hc: &'static dyn UsbHostController) -> u16 {
let i = BUS_MANAGER.last_bus_address.fetch_add(1, Ordering::AcqRel);
BUS_MANAGER.busses.write().insert(i, hc);
i
}
pub fn register_device(device: Arc<UsbDeviceAccess>) {
BUS_MANAGER
.devices
.write()
.insert(device.bus_address(), device.clone());
QUEUE.push_back(device);
}
pub fn detach_device(address: UsbBusAddress) {
if let Some(device) = BUS_MANAGER.devices.write().remove(&address) {
device.handle_detach();
}
}
}
pub async fn bus_handler() {
class_driver::register_default_class_drivers();
loop {
let new_device = QUEUE.pop_front().await;
log::info!(
"New {:?}-speed USB device connected: {}",
new_device.speed(),
new_device.bus_address()
);
class_driver::spawn_driver(new_device).await.ok();
}
}
static BUS_MANAGER: UsbBusManager = UsbBusManager {
busses: IrqSafeRwLock::new(BTreeMap::new()),
devices: IrqSafeRwLock::new(BTreeMap::new()),
last_bus_address: AtomicU16::new(0),
};
static QUEUE: UnboundedMpmcQueue<Arc<UsbDeviceAccess>> = UnboundedMpmcQueue::new();