65 lines
1.8 KiB
Rust
65 lines
1.8 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, Arc<dyn UsbHostController>>>,
|
|
devices: IrqSafeRwLock<BTreeMap<UsbBusAddress, Arc<UsbDeviceAccess>>>,
|
|
|
|
last_bus_address: AtomicU16,
|
|
}
|
|
|
|
impl UsbBusManager {
|
|
pub fn register_bus(hc: Arc<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>) {
|
|
log::info!("usb: register device {}", device.bus_address());
|
|
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();
|