Improve USB hub driver
This commit is contained in:
+70
-44
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user