xhcid: use lang id when reading string descriptors
This commit is contained in:
+7
-4
@@ -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
|
||||
|
||||
@@ -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],
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+37
-7
@@ -99,7 +99,8 @@ impl Xhci {
|
||||
port: PortId,
|
||||
slot: u8,
|
||||
kind: usb::DescriptorKind,
|
||||
index: u8,
|
||||
value: u8,
|
||||
index: u16,
|
||||
desc: &mut Dma<T>,
|
||||
) -> Result<()> {
|
||||
if self.interrupt_is_pending(0) {
|
||||
@@ -108,10 +109,11 @@ impl Xhci {
|
||||
}
|
||||
let len = mem::size_of::<T>();
|
||||
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<usb::DeviceDescriptor8Byte> {
|
||||
let mut desc = unsafe { self.alloc_dma_zeroed::<usb::DeviceDescriptor8Byte>()? };
|
||||
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<usb::DeviceDescriptor> {
|
||||
let mut desc = unsafe { self.alloc_dma_zeroed::<usb::DeviceDescriptor>()? };
|
||||
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<String> {
|
||||
async fn fetch_lang_ids_desc(&self, port: PortId, slot: u8) -> Result<Vec<u16>> {
|
||||
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<String> {
|
||||
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()))
|
||||
|
||||
@@ -550,13 +550,14 @@ impl Xhci {
|
||||
desc: usb::InterfaceDescriptor,
|
||||
endps: impl IntoIterator<Item = EndpDesc>,
|
||||
hid_descs: impl IntoIterator<Item = HidDesc>,
|
||||
lang_id: u16,
|
||||
) -> Result<IfDesc> {
|
||||
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 {
|
||||
|
||||
Reference in New Issue
Block a user