Improve USB hub driver

This commit is contained in:
Jeremy Soller
2025-03-20 13:24:45 -06:00
parent 2299bb0b27
commit 68760cf5af
+70 -44
View File
@@ -1,7 +1,7 @@
use std::env;
use std::{env, thread, time};
use xhcid_interface::{
plain, usb, DevDesc, DeviceReqData, PortReqRecipient, PortReqTy, XhciClientHandle,
plain, usb, ConfigureEndpointsReq, DevDesc, DeviceReqData, PortReqRecipient, PortReqTy, XhciClientHandle,
};
fn main() {
@@ -42,11 +42,10 @@ fn main() {
.expect("Failed to get standard descriptors");
log::info!("{:X?}", desc);
let (conf_desc, conf_num, if_desc) = desc
let (conf_desc, if_desc) = desc
.config_descs
.iter()
.enumerate()
.find_map(|(conf_num, conf_desc)| {
.find_map(|conf_desc| {
let if_desc = conf_desc.interface_descs.iter().find_map(|if_desc| {
if if_desc.number == interface_num {
Some(if_desc.clone())
@@ -54,11 +53,10 @@ fn main() {
None
}
})?;
Some((conf_desc.clone(), conf_num, if_desc))
Some((conf_desc.clone(), if_desc))
})
.expect("Failed to find suitable configuration");
/*TODO
handle
.configure_endpoints(&ConfigureEndpointsReq {
config_desc: conf_desc.configuration_value,
@@ -66,7 +64,6 @@ fn main() {
alternate_setting: Some(if_desc.alternate_setting),
})
.expect("Failed to configure endpoints");
*/
let mut hub_desc = usb::HubDescriptor::default();
handle
@@ -82,50 +79,79 @@ fn main() {
.expect("Failed to retrieve hub descriptor");
log::info!("{:X?}", hub_desc);
for port in 1..=hub_desc.ports {
log::info!("power on port {port}");
handle
.device_request(
PortReqTy::Class,
PortReqRecipient::Other,
usb::SetupReq::SetFeature as u8,
usb::HubFeature::PortPower as u16,
port as u16,
DeviceReqData::NoData,
)
.expect("Failed to set port power");
}
for port in 1..=hub_desc.ports {
let mut port_sts = usb::HubPortStatus::default();
handle
.device_request(
PortReqTy::Class,
PortReqRecipient::Other,
usb::SetupReq::GetStatus as u8,
0,
port as u16,
DeviceReqData::In(unsafe { plain::as_mut_bytes(&mut port_sts) }),
)
.expect("Failed to retrieve port status");
log::info!("port {} status {:X?}", port, port_sts);
if port_sts.contains(usb::HubPortStatus::CONNECTION) {
/*TODO
log::info!("reset port {port}");
//TODO: use change flags?
let mut last_port_statuses = vec![usb::HubPortStatus::default(); hub_desc.ports.into()];
loop {
for port in 1..=hub_desc.ports {
let mut port_sts = usb::HubPortStatus::default();
handle
.device_request(
PortReqTy::Class,
PortReqRecipient::Other,
usb::SetupReq::SetFeature as u8,
usb::HubFeature::PortReset as u16,
usb::SetupReq::GetStatus as u8,
0,
port as u16,
DeviceReqData::NoData,
DeviceReqData::In(unsafe { plain::as_mut_bytes(&mut port_sts) }),
)
.expect("Failed to set port enable");
*/
.expect("Failed to retrieve port status");
{
let port_idx: usize = port.checked_sub(1).unwrap().into();
let last_port_sts = last_port_statuses.get_mut(port_idx).unwrap();
if *last_port_sts != port_sts {
*last_port_sts = port_sts;
log::info!("port {} status {:X?}", port, port_sts);
}
}
// Ensure port is powered on
if !port_sts.contains(usb::HubPortStatus::POWER) {
log::info!("power on port {port}");
handle
.device_request(
PortReqTy::Class,
PortReqRecipient::Other,
usb::SetupReq::SetFeature as u8,
usb::HubFeature::PortPower as u16,
port as u16,
DeviceReqData::NoData,
)
.expect("Failed to set port power");
continue;
}
// Ignore disconnected port
//TODO: turn off disconnected ports?
if !port_sts.contains(usb::HubPortStatus::CONNECTION) {
continue;
}
// Ignore port in reset
if port_sts.contains(usb::HubPortStatus::RESET) {
continue;
}
// Ensure port is enabled
if !port_sts.contains(usb::HubPortStatus::ENABLE) {
log::info!("reset port {port}");
handle
.device_request(
PortReqTy::Class,
PortReqRecipient::Other,
usb::SetupReq::SetFeature as u8,
usb::HubFeature::PortReset as u16,
port as u16,
DeviceReqData::NoData,
)
.expect("Failed to set port enable");
continue;
}
//TODO: address device
}
//TODO: use interrupts or poll faster?
thread::sleep(time::Duration::new(1, 0));
}
//TODO: read interrupt port for changes