diff --git a/usbhubd/src/main.rs b/usbhubd/src/main.rs index 16da57caf5..08013df206 100644 --- a/usbhubd/src/main.rs +++ b/usbhubd/src/main.rs @@ -56,7 +56,10 @@ fn main() { Some((conf_desc.clone(), if_desc)) }) .expect("Failed to find suitable configuration"); + + //TODO: is it required to configure before reading hub descriptor? + // Read hub descriptor let mut hub_desc = usb::HubDescriptor::default(); handle .device_request( @@ -64,12 +67,12 @@ fn main() { PortReqRecipient::Device, usb::SetupReq::GetDescriptor as u8, 0, - //TODO: should this be an index into interface_descs? - interface_num as u16, + 0, DeviceReqData::In(unsafe { plain::as_mut_bytes(&mut hub_desc) }), ) - .expect("Failed to retrieve hub descriptor"); + .expect("Failed to read hub descriptor"); + // Configure as hub device handle .configure_endpoints(&ConfigureEndpointsReq { config_desc: conf_desc.configuration_value, @@ -77,7 +80,7 @@ fn main() { alternate_setting: Some(if_desc.alternate_setting), hub_ports: Some(hub_desc.ports), }) - .expect("Failed to configure endpoints"); + .expect("Failed to configure endpoints after reading hub descriptor"); /*TODO: only set hub depth on USB 3+ hubs handle diff --git a/xhcid/src/usb/hub.rs b/xhcid/src/usb/hub.rs index f83d734fe6..2eeff3ab3d 100644 --- a/xhcid/src/usb/hub.rs +++ b/xhcid/src/usb/hub.rs @@ -2,14 +2,17 @@ #[derive(Clone, Copy, Debug)] pub struct HubDescriptor { pub length: u8, + // 0x29 for USB 2, 0x2A for USB 3 pub kind: u8, pub ports: u8, pub characteristics: u16, pub power_on_good: u8, pub current: u8, + /*TODO: USB 2 and 3 disagree on the descriptor, so some fields are disabled // device_removable: bitmap of ports, maximum of 256 bits (32 bytes) // power_control_mask: bitmap of ports, maximum of 256 bits (32 bytes) bitmaps: [u8; 64], + */ } unsafe impl plain::Plain for HubDescriptor {} @@ -23,7 +26,9 @@ impl Default for HubDescriptor { characteristics: 0, power_on_good: 0, current: 0, + /* bitmaps: [0; 64], + */ } } } diff --git a/xhcid/src/xhci/mod.rs b/xhcid/src/xhci/mod.rs index 3ceec1e196..61daf60307 100644 --- a/xhcid/src/xhci/mod.rs +++ b/xhcid/src/xhci/mod.rs @@ -99,7 +99,8 @@ impl Xhci { port: PortId, slot: u8, kind: usb::DescriptorKind, - index: u8, + value: u8, + index: u16, desc: &mut Dma, ) -> Result<()> { if self.interrupt_is_pending(0) { @@ -108,10 +109,11 @@ impl Xhci { } let len = mem::size_of::(); log::debug!( - "get_desc_raw port {} slot {} kind {:?} index {} len {}", + "get_desc_raw port {} slot {} kind {:?} value {} index {} len {}", port, slot, kind, + value, index, len ); @@ -128,7 +130,7 @@ impl Xhci { let first_index = ring.next_index(); let (cmd, cycle) = (&mut ring.trbs[first_index], ring.cycle); cmd.setup( - usb::Setup::get_descriptor(kind, index, 0, len as u16), + usb::Setup::get_descriptor(kind, value, index, len as u16), TransferKind::In, cycle, ); @@ -173,14 +175,14 @@ impl Xhci { slot: u8, ) -> Result { let mut desc = unsafe { self.alloc_dma_zeroed::()? }; - self.get_desc_raw(port, slot, usb::DescriptorKind::Device, 0, &mut desc) + self.get_desc_raw(port, slot, usb::DescriptorKind::Device, 0, 0, &mut desc) .await?; Ok(*desc) } async fn fetch_dev_desc(&self, port: PortId, slot: u8) -> Result { let mut desc = unsafe { self.alloc_dma_zeroed::()? }; - self.get_desc_raw(port, slot, usb::DescriptorKind::Device, 0, &mut desc) + self.get_desc_raw(port, slot, usb::DescriptorKind::Device, 0, 0, &mut desc) .await?; Ok(*desc) } @@ -197,6 +199,7 @@ impl Xhci { slot, usb::DescriptorKind::Configuration, config, + 0, &mut desc, ) .await?; @@ -214,17 +217,44 @@ impl Xhci { slot, usb::DescriptorKind::BinaryObjectStorage, 0, + 0, &mut desc, ) .await?; Ok(*desc) } - async fn fetch_string_desc(&self, port: PortId, slot: u8, index: u8) -> Result { + async fn fetch_lang_ids_desc(&self, port: PortId, slot: u8) -> Result> { let mut sdesc = unsafe { self.alloc_dma_zeroed::<(u8, u8, [u16; 127])>()? }; - self.get_desc_raw(port, slot, usb::DescriptorKind::String, index, &mut sdesc) + self.get_desc_raw(port, slot, usb::DescriptorKind::String, 0, 0, &mut sdesc) .await?; + let len = sdesc.0 as usize; + if len > 2 { + Ok(sdesc.2[..(len - 2) / 2].to_vec()) + } else { + Ok(Vec::new()) + } + } + + async fn fetch_string_desc( + &self, + port: PortId, + slot: u8, + value: u8, + lang_id: u16, + ) -> Result { + let mut sdesc = unsafe { self.alloc_dma_zeroed::<(u8, u8, [u16; 127])>()? }; + self.get_desc_raw( + port, + slot, + usb::DescriptorKind::String, + value, + lang_id, + &mut sdesc, + ) + .await?; + let len = sdesc.0 as usize; if len > 2 { Ok(String::from_utf16(&sdesc.2[..(len - 2) / 2]).unwrap_or(String::new())) diff --git a/xhcid/src/xhci/scheme.rs b/xhcid/src/xhci/scheme.rs index 4120365096..8c97271610 100644 --- a/xhcid/src/xhci/scheme.rs +++ b/xhcid/src/xhci/scheme.rs @@ -550,13 +550,14 @@ impl Xhci { desc: usb::InterfaceDescriptor, endps: impl IntoIterator, hid_descs: impl IntoIterator, + lang_id: u16, ) -> Result { Ok(IfDesc { alternate_setting: desc.alternate_setting, class: desc.class, interface_str: if desc.interface_str > 0 { Some( - self.fetch_string_desc(port_id, slot, desc.interface_str) + self.fetch_string_desc(port_id, slot, desc.interface_str, lang_id) .await?, ) } else { @@ -1443,10 +1444,23 @@ impl Xhci { let raw_dd = self.fetch_dev_desc(port_id, slot).await?; log::debug!("port {} slot {} desc {:X?}", port_id, slot, raw_dd); + let lang_ids = self.fetch_lang_ids_desc(port_id, slot).await?; + // Prefer US English, but fall back to first language ID, or zero + let en_us_id = 0x409; + let lang_id = if lang_ids.contains(&en_us_id) { + en_us_id + } else { + match lang_ids.first() { + Some(some) => *some, + None => 0, + } + }; + log::debug!("port {} using language ID 0x{:04x}", port_id, lang_id); + let (manufacturer_str, product_str, serial_str) = ( if raw_dd.manufacturer_str > 0 { Some( - self.fetch_string_desc(port_id, slot, raw_dd.manufacturer_str) + self.fetch_string_desc(port_id, slot, raw_dd.manufacturer_str, lang_id) .await?, ) } else { @@ -1454,7 +1468,7 @@ impl Xhci { }, if raw_dd.product_str > 0 { Some( - self.fetch_string_desc(port_id, slot, raw_dd.product_str) + self.fetch_string_desc(port_id, slot, raw_dd.product_str, lang_id) .await?, ) } else { @@ -1462,7 +1476,7 @@ impl Xhci { }, if raw_dd.serial_str > 0 { Some( - self.fetch_string_desc(port_id, slot, raw_dd.serial_str) + self.fetch_string_desc(port_id, slot, raw_dd.serial_str, lang_id) .await?, ) } else { @@ -1548,7 +1562,7 @@ impl Xhci { } interface_descs.push( - self.new_if_desc(port_id, slot, idesc, endpoints, hid_descs) + self.new_if_desc(port_id, slot, idesc, endpoints, hid_descs, lang_id) .await?, ); } else { @@ -1562,7 +1576,7 @@ impl Xhci { kind: desc.kind, configuration: if desc.configuration_str > 0 { Some( - self.fetch_string_desc(port_id, slot, desc.configuration_str) + self.fetch_string_desc(port_id, slot, desc.configuration_str, lang_id) .await?, ) } else {