From 9ec71c6ba49eaee5f3fc4c9fab1395eff3f22550 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 17 Apr 2024 08:51:02 -0600 Subject: [PATCH] xhcid/usbhidd: build out USB HUB driver --- usbhubd/src/main.rs | 51 ++++++++++++++++++++++++++++++++++++++++-- xhcid/src/usb/hub.rs | 48 +++++++++++++++++++++++++++++++++++++++ xhcid/src/usb/mod.rs | 4 ++-- xhcid/src/usb/setup.rs | 15 +++++++++++++ 4 files changed, 114 insertions(+), 4 deletions(-) diff --git a/usbhubd/src/main.rs b/usbhubd/src/main.rs index 7c95cb6b5d..21cccadd14 100644 --- a/usbhubd/src/main.rs +++ b/usbhubd/src/main.rs @@ -120,13 +120,60 @@ fn main() { .device_request( PortReqTy::Class, PortReqRecipient::Device, - 0x6, + usb::SetupReq::GetDescriptor as u8, 0, //TODO: should this be an index into interface_descs? interface_num as u16, DeviceReqData::In(unsafe { plain::as_mut_bytes(&mut hub_desc) }), ) .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}"); + 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"); + */ + //TODO: address device + } + } + + //TODO: read interrupt port for changes } diff --git a/xhcid/src/usb/hub.rs b/xhcid/src/usb/hub.rs index b81d86a74b..854ff30a74 100644 --- a/xhcid/src/usb/hub.rs +++ b/xhcid/src/usb/hub.rs @@ -27,3 +27,51 @@ impl Default for HubDescriptor { } } } + +#[derive(Clone, Copy, Debug)] +#[repr(u8)] +pub enum HubFeature { + //TODO: CHubLocalPower = 0, + //TODO: CHubOverCurrent = 1, + PortConnection = 0, + PortEnable = 1, + PortSuspend = 2, + PortOverCurrent = 3, + PortReset = 4, + PortPower = 8, + PortLowSpeed = 9, + CPortConnection = 16, + CPortEnable = 17, + CPortSuspend = 18, + CPortOverCurrent = 19, + CPortReset = 20, + PortTest = 21, + PortIndicator = 22, +} + +bitflags::bitflags! { + #[derive(Default)] + #[repr(transparent)] + pub struct HubPortStatus: u32 { + const CONNECTION = 1 << 0; + const ENABLE = 1 << 1; + const SUSPEND = 1 << 2; + const OVER_CURRENT = 1 << 3; + const RESET = 1 << 4; + // bits 5-7 reserved + const POWER = 1 << 8; + const LOW_SPEED = 1 << 9; + const HIGH_SPEED = 1 << 10; + const TEST = 1 << 11; + const INDICATOR = 1 << 12; + // bits 13-15 reserved + const CONNECTION_CHANGED = 1 << 16; + const ENABLE_CHANGED = 1 << 17; + const SUSPEND_CHANGED = 1 << 18; + const OVER_CURRENT_CHANGED = 1 << 19; + const RESET_CHANGED = 1 << 20; + // bits 21 - 31 reserved + } +} + +unsafe impl plain::Plain for HubPortStatus {} diff --git a/xhcid/src/usb/mod.rs b/xhcid/src/usb/mod.rs index 989f26b09a..246cc77f8b 100644 --- a/xhcid/src/usb/mod.rs +++ b/xhcid/src/usb/mod.rs @@ -5,9 +5,9 @@ pub use self::endpoint::{ EndpointDescriptor, EndpointTy, HidDescriptor, SuperSpeedCompanionDescriptor, SuperSpeedPlusIsochCmpDescriptor, ENDP_ATTR_TY_MASK, }; -pub use self::hub::HubDescriptor; +pub use self::hub::*; pub use self::interface::InterfaceDescriptor; -pub use self::setup::Setup; +pub use self::setup::{Setup, SetupReq}; #[derive(Clone, Copy, Debug)] #[repr(u8)] diff --git a/xhcid/src/usb/setup.rs b/xhcid/src/usb/setup.rs index 879a424776..aa430e2363 100644 --- a/xhcid/src/usb/setup.rs +++ b/xhcid/src/usb/setup.rs @@ -71,6 +71,21 @@ impl From for ReqRecipient { } } +#[repr(u8)] +pub enum SetupReq { + GetStatus = 0x00, + ClearFeature = 0x01, + SetFeature = 0x03, + SetAddress = 0x05, + GetDescriptor = 0x06, + SetDescriptor = 0x07, + GetConfiguration = 0x08, + SetConfiguration = 0x09, + GetInterface = 0x0A, + SetInterface = 0x0B, + SynchFrame = 0x0C, +} + pub const USB_SETUP_DIR_BIT: u8 = 1 << 7; pub const USB_SETUP_DIR_SHIFT: u8 = 7; pub const USB_SETUP_REQ_TY_MASK: u8 = 0x60;