From e3a13a0ce7d080d59c0fbc746e417af5a533b189 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 20 Mar 2025 21:27:17 -0600 Subject: [PATCH] xhcid and friends: use newtype PortId to ensure route string can be passed where needed --- input/usbhidd/src/main.rs | 7 +- storage/usbscsid/src/main.rs | 8 +- usbctl/src/main.rs | 6 +- usbhubd/src/main.rs | 11 +- xhcid/src/driver_interface.rs | 74 ++++++++++- xhcid/src/xhci/device_enumerator.rs | 47 +++---- xhcid/src/xhci/irq_reactor.rs | 10 +- xhcid/src/xhci/mod.rs | 141 ++++++++++----------- xhcid/src/xhci/scheme.rs | 189 +++++++++++++++------------- 9 files changed, 283 insertions(+), 210 deletions(-) diff --git a/input/usbhidd/src/main.rs b/input/usbhidd/src/main.rs index da4e798cdd..da6af6a82e 100644 --- a/input/usbhidd/src/main.rs +++ b/input/usbhidd/src/main.rs @@ -8,7 +8,8 @@ use rehid::{ usage_tables::{GenericDesktopUsage, UsagePage}, }; use xhcid_interface::{ - ConfigureEndpointsReq, DevDesc, EndpDirection, EndpointTy, PortReqRecipient, XhciClientHandle, + ConfigureEndpointsReq, DevDesc, EndpDirection, EndpointTy, PortId, PortReqRecipient, + XhciClientHandle, }; mod keymap; @@ -182,8 +183,8 @@ fn main() { let port = args .next() .expect(USAGE) - .parse::() - .expect("Expected integer as input of port"); + .parse::() + .expect("Expected port ID"); let interface_num = args .next() .expect(USAGE) diff --git a/storage/usbscsid/src/main.rs b/storage/usbscsid/src/main.rs index 9950814e7c..ff87d2109e 100644 --- a/storage/usbscsid/src/main.rs +++ b/storage/usbscsid/src/main.rs @@ -3,7 +3,7 @@ use std::env; use driver_block::{Disk, DiskScheme}; use syscall::{Error, EIO}; -use xhcid_interface::{ConfigureEndpointsReq, XhciClientHandle}; +use xhcid_interface::{ConfigureEndpointsReq, PortId, XhciClientHandle}; pub mod protocol; pub mod scsi; @@ -20,8 +20,8 @@ fn main() { let port = args .next() .expect(USAGE) - .parse::() - .expect("port has to be a number"); + .parse::() + .expect("Expected port ID"); let protocol = args .next() .expect(USAGE) @@ -36,7 +36,7 @@ fn main() { redox_daemon::Daemon::new(move |d| daemon(d, scheme, port, protocol)) .expect("usbscsid: failed to daemonize"); } -fn daemon(daemon: redox_daemon::Daemon, scheme: String, port: usize, protocol: u8) -> ! { +fn daemon(daemon: redox_daemon::Daemon, scheme: String, port: PortId, protocol: u8) -> ! { let disk_scheme_name = format!("disk.usb-{scheme}+{port}-scsi"); // TODO: Use eventfds. diff --git a/usbctl/src/main.rs b/usbctl/src/main.rs index fb2f20d1c1..517cde041a 100644 --- a/usbctl/src/main.rs +++ b/usbctl/src/main.rs @@ -1,5 +1,5 @@ use clap::{App, Arg}; -use xhcid_interface::XhciClientHandle; +use xhcid_interface::{PortId, XhciClientHandle}; fn main() { let matches = App::new("usbctl") @@ -32,8 +32,8 @@ fn main() { let port = port_scmd_matches .value_of("PORT") .expect("invalid utf-8 for PORT argument") - .parse::() - .expect("expected PORT to be an integer"); + .parse::() + .expect("expected PORT ID"); let handle = XhciClientHandle::new(scheme.to_owned(), port); diff --git a/usbhubd/src/main.rs b/usbhubd/src/main.rs index c029c278c7..198641cc1a 100644 --- a/usbhubd/src/main.rs +++ b/usbhubd/src/main.rs @@ -1,7 +1,8 @@ use std::{env, thread, time}; use xhcid_interface::{ - plain, usb, ConfigureEndpointsReq, DevDesc, DeviceReqData, PortReqRecipient, PortReqTy, XhciClientHandle, + plain, usb, ConfigureEndpointsReq, DevDesc, DeviceReqData, PortId, PortReqRecipient, PortReqTy, + XhciClientHandle, }; fn main() { @@ -21,8 +22,8 @@ fn main() { let port = args .next() .expect(USAGE) - .parse::() - .expect("Expected integer as input of port"); + .parse::() + .expect("Expected port ID"); let interface_num = args .next() .expect(USAGE) @@ -40,7 +41,6 @@ fn main() { let desc: DevDesc = handle .get_standard_descs() .expect("Failed to get standard descriptors"); - log::info!("{:X?}", desc); let (conf_desc, if_desc) = desc .config_descs @@ -77,10 +77,9 @@ fn main() { DeviceReqData::In(unsafe { plain::as_mut_bytes(&mut hub_desc) }), ) .expect("Failed to retrieve hub descriptor"); - log::info!("{:X?}", hub_desc); //TODO: use change flags? - let mut last_port_statuses = vec![usb::HubPortStatus::default(); hub_desc.ports.into()]; + 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(); diff --git a/xhcid/src/driver_interface.rs b/xhcid/src/driver_interface.rs index 37bc50d68d..d974a0468f 100644 --- a/xhcid/src/driver_interface.rs +++ b/xhcid/src/driver_interface.rs @@ -5,7 +5,7 @@ use std::convert::TryFrom; use std::fs::{File, OpenOptions}; use std::io::prelude::*; use std::num::NonZeroU8; -use std::{io, result, str}; +use std::{fmt, io, result, str}; use serde::{Deserialize, Serialize}; use smallvec::SmallVec; @@ -280,10 +280,78 @@ pub enum PortReqRecipient { VendorSpecific, } +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct PortId { + pub root_hub_port_num: u8, + pub route_string: u32, +} + +impl PortId { + pub fn root_hub_port_index(&self) -> usize { + self.root_hub_port_num.checked_sub(1).unwrap().into() + } +} + +impl fmt::Display for PortId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.root_hub_port_num)?; + // USB 3.1 Revision 1.1 Specification Section 8.9 Route String Field + // The Route String is a 20-bit field in downstream directed packets that the hub uses to route + // each packet to the designated downstream port. It is composed of a concatenation of the + // downstream port numbers (4 bits per hub) for each hub traversed to reach a device. + // The lowest 4 bits are ignored. + let mut route_string = self.route_string >> 4; + while route_string > 0 { + write!(f, ".{}", route_string & 0xF)?; + route_string >>= 4; + } + Ok(()) + } +} + +impl str::FromStr for PortId { + type Err = String; + + fn from_str(s: &str) -> Result { + let mut root_hub_port_num = 0; + let mut route_string = 0; + for (i, part) in s.split('.').enumerate() { + let value: u8 = part + .parse() + .map_err(|e| format!("failed to parse {:?}: {}", part, e))?; + + // Parse root hub port number + if i == 0 { + root_hub_port_num = value; + continue; + } + + // Parse route string component + if value & 0xF0 != 0 { + return Err(format!( + "value {:?} is too large for route string component", + value + )); + } + route_string |= (value as u32) << (i * 4); + } + if root_hub_port_num == 0 { + return Err(format!( + "invalid root hub port number {:?}", + root_hub_port_num + )); + } + Ok(Self { + root_hub_port_num, + route_string, + }) + } +} + #[derive(Debug)] pub struct XhciClientHandle { scheme: String, - port: usize, + port: PortId, } #[repr(u8)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] @@ -410,7 +478,7 @@ impl DeviceReqData<'_> { } impl XhciClientHandle { - pub fn new(scheme: String, port: usize) -> Self { + pub fn new(scheme: String, port: PortId) -> Self { Self { scheme, port } } diff --git a/xhcid/src/xhci/device_enumerator.rs b/xhcid/src/xhci/device_enumerator.rs index 207211133b..c418ef8b07 100644 --- a/xhcid/src/xhci/device_enumerator.rs +++ b/xhcid/src/xhci/device_enumerator.rs @@ -1,5 +1,5 @@ use crate::xhci::port::PortFlags; -use crate::xhci::Xhci; +use crate::xhci::{PortId, Xhci}; use common::io::Io; use crossbeam_channel; use log::{debug, info, warn}; @@ -108,24 +108,29 @@ impl DeviceEnumerator { panic!("Failed to received an enumeration request! error: {}", err) } }; - info!("Device Enumerator request for port {}", request.port_number); - let port_array_index = request.port_number - 1; + let port_id = PortId { + root_hub_port_num: request.port_number, + route_string: 0, + }; + let port_array_index = port_id.root_hub_port_index(); + + info!("Device Enumerator request for port {}", port_id); let (len, flags) = { let ports = self.hci.ports.lock().unwrap(); let len = ports.len(); - if port_array_index as usize >= len { + if port_array_index >= len { warn!( "Received out of bounds Device Enumeration request for port {}", - request.port_number + port_id ); continue; } - (len, ports[port_array_index as usize].flags()) + (len, ports[port_array_index].flags()) }; if flags.contains(PortFlags::PORT_CCS) { @@ -145,21 +150,18 @@ impl DeviceEnumerator { if !disabled_state { panic!( "Port {} isn't in the disabled state! Current flags: {:?}", - request.port_number, flags + port_id, flags ); } else { - debug!( - "Port {} has entered the disabled state.", - request.port_number - ); + debug!("Port {} has entered the disabled state.", port_id); } //THIS LOCKS THE PORTS. DO NOT LOCK PORTS BEFORE THIS POINT - info!("Received a device connect on port {}, but it's not enabled. Resetting the port.", request.port_number); - self.hci.reset_port((port_array_index as usize)); + info!("Received a device connect on port {}, but it's not enabled. Resetting the port.", port_id); + self.hci.reset_port(port_array_index); let mut ports = self.hci.ports.lock().unwrap(); - let port = &mut ports[port_array_index as usize]; + let port = &mut ports[port_array_index]; port.portsc.writef(PortFlags::PORT_PRC.bits(), true); @@ -175,20 +177,20 @@ impl DeviceEnumerator { if !enabled_state { warn!( "Port {} isn't in the enabled state! Current flags: {:?}", - request.port_number, flags + port_id, flags ); } else { debug!( "Port {} is in the enabled state. Proceeding with enumeration", - request.port_number + port_id ); } } - let result = futures::executor::block_on(self.hci.attach_device(port_array_index)); + let result = futures::executor::block_on(self.hci.attach_device(port_id)); match result { Ok(_) => { - info!("Device on port {} was attached", port_array_index); + info!("Device on port {} was attached", port_id); } Err(err) => { if err.errno == EAGAIN { @@ -201,14 +203,13 @@ impl DeviceEnumerator { } else { info!( "Device Enumerator received Detach request on port {} which is in state {}", - request.port_number, - self.hci.get_pls((port_array_index) as usize) + port_id, + self.hci.get_pls(port_id) ); - let result = - futures::executor::block_on(self.hci.detach_device(port_array_index as usize)); + let result = futures::executor::block_on(self.hci.detach_device(port_id)); match result { Ok(_) => { - info!("Device on port {} was detached", port_array_index); + info!("Device on port {} was detached", port_id); } Err(err) => { warn!("processing of device attach request failed! Error: {}", err); diff --git a/xhcid/src/xhci/irq_reactor.rs b/xhcid/src/xhci/irq_reactor.rs index 298e52ddcc..ee271e228e 100644 --- a/xhcid/src/xhci/irq_reactor.rs +++ b/xhcid/src/xhci/irq_reactor.rs @@ -14,7 +14,7 @@ use super::doorbell::Doorbell; use super::event::EventRing; use super::ring::Ring; use super::trb::{Trb, TrbCompletionCode, TrbType}; -use super::Xhci; +use super::{PortId, Xhci}; use crate::xhci::device_enumerator::DeviceEnumerationRequest; use crate::xhci::port::PortFlags; use common::io::Io as _; @@ -48,12 +48,12 @@ pub struct NextEventTrb { // indexed using this struct instead. #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct RingId { - pub port: u8, + pub port: PortId, pub endpoint_num: u8, pub stream_id: u16, } impl RingId { - pub const fn default_control_pipe(port: u8) -> Self { + pub const fn default_control_pipe(port: PortId) -> Self { Self { port, endpoint_num: 0, @@ -623,7 +623,7 @@ impl Xhci { pub fn with_ring T>(&self, id: RingId, function: F) -> Option { use super::RingOrStreams; - let slot_state = self.port_states.get(&(id.port as usize))?; + let slot_state = self.port_states.get(&id.port)?; let endpoint_state = slot_state.endpoint_states.get(&id.endpoint_num)?; let ring_ref = match endpoint_state.transfer { @@ -640,7 +640,7 @@ impl Xhci { ) -> Option { use super::RingOrStreams; - let mut slot_state = self.port_states.get_mut(&(id.port as usize))?; + let mut slot_state = self.port_states.get_mut(&id.port)?; let mut endpoint_state = slot_state.endpoint_states.get_mut(&id.endpoint_num)?; let ring_ref = match endpoint_state.transfer { diff --git a/xhcid/src/xhci/mod.rs b/xhcid/src/xhci/mod.rs index a625b77216..a7cde500f5 100644 --- a/xhcid/src/xhci/mod.rs +++ b/xhcid/src/xhci/mod.rs @@ -59,6 +59,7 @@ use self::trb::{TransferKind, Trb, TrbCompletionCode}; use self::scheme::EndpIfState; +pub use crate::driver_interface::PortId; use crate::driver_interface::*; /// Specifies the configurable interrupt mechanism used by the xhci subsystem for registering @@ -95,7 +96,7 @@ impl Xhci { /// Gets descriptors, before the port state is initiated. async fn get_desc_raw( &self, - port: usize, + port: PortId, slot: u8, kind: usb::DescriptorKind, index: u8, @@ -147,7 +148,7 @@ impl Xhci { cmd.status(interrupter, input, ioc, ch, ent, cycle); self.next_transfer_event_trb( - RingId::default_control_pipe(port as u8), + RingId::default_control_pipe(port), &ring, &ring.trbs[first_index], &ring.trbs[last_index], @@ -168,7 +169,7 @@ impl Xhci { async fn fetch_dev_desc_8_byte( &self, - port: usize, + port: PortId, slot: u8, ) -> Result { let mut desc = unsafe { self.alloc_dma_zeroed::()? }; @@ -177,7 +178,7 @@ impl Xhci { Ok(*desc) } - async fn fetch_dev_desc(&self, port: usize, slot: u8) -> Result { + 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) .await?; @@ -186,7 +187,7 @@ impl Xhci { async fn fetch_config_desc( &self, - port: usize, + port: PortId, slot: u8, config: u8, ) -> Result<(usb::ConfigDescriptor, [u8; 4087])> { @@ -204,7 +205,7 @@ impl Xhci { async fn fetch_bos_desc( &self, - port: usize, + port: PortId, slot: u8, ) -> Result<(usb::BosDescriptor, [u8; 4087])> { let mut desc = unsafe { self.alloc_dma_zeroed::<(usb::BosDescriptor, [u8; 4087])>()? }; @@ -219,7 +220,7 @@ impl Xhci { Ok(*desc) } - async fn fetch_string_desc(&self, port: usize, slot: u8, index: u8) -> Result { + async fn fetch_string_desc(&self, port: PortId, slot: u8, index: 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) .await?; @@ -266,8 +267,8 @@ pub struct Xhci { handles: CHashMap, next_handle: AtomicUsize, - port_states: CHashMap, - drivers: CHashMap>, + port_states: CHashMap, + drivers: CHashMap>, scheme_name: String, interrupt_method: InterruptMethod, @@ -546,9 +547,9 @@ impl Xhci { Ok(()) } - pub fn get_pls(&self, port_num: usize) -> u32 { + pub fn get_pls(&self, port_id: PortId) -> u32 { let mut ports = self.ports.lock().unwrap(); - let port = ports.get_mut(port_num).unwrap(); + let port = ports.get_mut(port_id.root_hub_port_index()).unwrap(); let state = port.portsc.read(); (state >> 5) & 4 } @@ -594,23 +595,28 @@ impl Xhci { len = ports.len(); } - for port in 0..len { - let state = self.get_pls(port); + for root_hub_port_num in 1..=(len as u8) { + let port_id = PortId { + root_hub_port_num, + route_string: 0, + }; + + let state = self.get_pls(port_id); let mut flags; { let mut ports = self.ports.lock().unwrap(); - flags = ports[port].flags(); + flags = ports[port_id.root_hub_port_index()].flags(); } - match self.supported_protocol(port as u8) { + match self.supported_protocol(port_id) { None => { - warn!("No detected supported protocol for port {}", port); + warn!("No detected supported protocol for port {}", port_id); } Some(protocol) => { info!( "Port {} is a USB {}.{} port with slot type {} and in current state {}: {:?}", - port + 1, + port_id, protocol.rev_major(), protocol.rev_minor(), protocol.proto_slot_ty(), @@ -728,25 +734,23 @@ impl Xhci { Self::alloc_dma_zeroed_unsized_raw(self.cap.ac64(), count) } - pub async fn attach_device(&self, port_number: u8) -> syscall::Result<()> { - let i = port_number as usize; - - if self.port_states.contains_key(&i) { + pub async fn attach_device(&self, port_id: PortId) -> syscall::Result<()> { + if self.port_states.contains_key(&port_id) { return Err(syscall::Error::new(EAGAIN)); } let (data, state, speed, flags) = { - let port = &self.ports.lock().unwrap()[i]; + let port = &self.ports.lock().unwrap()[port_id.root_hub_port_index()]; (port.read(), port.state(), port.speed(), port.flags()) }; info!( "XHCI Port {}: {:X}, State {}, Speed {}, Flags {:?}", - i, data, state, speed, flags + port_id, data, state, speed, flags ); if flags.contains(port::PortFlags::PORT_CCS) { - let slot_ty = match self.supported_protocol(i as u8) { + let slot_ty = match self.supported_protocol(port_id) { Some(protocol) => protocol.proto_slot_ty(), None => { warn!("Failed to find supported protocol information for port"); @@ -759,23 +763,23 @@ impl Xhci { let slot = match self.enable_port_slot(slot_ty).await { Ok(ok) => ok, Err(err) => { - error!("Failed to enable slot for port {}: {}", i, err); + error!("Failed to enable slot for port {}: {}", port_id, err); return Err(err); } }; - info!("Enabled port {}, which the xHC mapped to {}", i, slot); + info!("Enabled port {}, which the xHC mapped to {}", port_id, slot); let mut input = unsafe { self.alloc_dma_zeroed::()? }; info!("Attempting to address the device"); let mut ring = match self - .address_device(&mut input, i, slot_ty, slot, speed) + .address_device(&mut input, port_id, slot_ty, slot, speed) .await { Ok(device_ring) => device_ring, Err(err) => { - error!("Failed to spawn driver for port {}: `{}`", i, err); + error!("Failed to spawn driver for port {}: `{}`", port_id, err); return Err(err); } }; @@ -798,13 +802,13 @@ impl Xhci { )) .collect::>(), }; - self.port_states.insert(i, port_state); + self.port_states.insert(port_id, port_state); debug!("Got port states!"); // Ensure correct packet size is used - let dev_desc_8_byte = self.fetch_dev_desc_8_byte(i, slot).await?; + let dev_desc_8_byte = self.fetch_dev_desc_8_byte(port_id, slot).await?; { - let mut port_state = self.port_states.get_mut(&i).unwrap(); + let mut port_state = self.port_states.get_mut(&port_id).unwrap(); let mut input = port_state.input_context.lock().unwrap(); @@ -814,13 +818,13 @@ impl Xhci { debug!("Got the 8 byte dev descriptor"); - let dev_desc = self.get_desc(i, slot).await?; + let dev_desc = self.get_desc(port_id, slot).await?; debug!("Got the full device descriptor!"); - self.port_states.get_mut(&i).unwrap().dev_desc = Some(dev_desc); + self.port_states.get_mut(&port_id).unwrap().dev_desc = Some(dev_desc); debug!("Got the port states again!"); { - let mut port_state = self.port_states.get_mut(&i).unwrap(); + let mut port_state = self.port_states.get_mut(&port_id).unwrap(); let mut input = port_state.input_context.lock().unwrap(); debug!("Got the input context!"); @@ -832,10 +836,10 @@ impl Xhci { debug!("Updated the default control pipe"); - match self.spawn_drivers(i) { + match self.spawn_drivers(port_id) { Ok(()) => (), Err(err) => { - error!("Failed to spawn driver for port {}: `{}`", i, err) + error!("Failed to spawn driver for port {}: `{}`", port_id, err) } } } else { @@ -845,28 +849,20 @@ impl Xhci { Ok(()) } - pub async fn detach_device(&self, port_number: usize) -> Result<()> { - if let Some(children) = self.drivers.remove(&port_number) { + pub async fn detach_device(&self, port_id: PortId) -> Result<()> { + if let Some(children) = self.drivers.remove(&port_id) { for mut child in children { - info!( - "killing driver process {} for port {}", - child.id(), - port_number - ); + info!("killing driver process {} for port {}", child.id(), port_id); match child.kill() { Ok(()) => { - info!( - "killed driver process {} for port {}", - child.id(), - port_number - ); + info!("killed driver process {} for port {}", child.id(), port_id); match child.try_wait() { Ok(status_opt) => match status_opt { Some(status) => { info!( "driver process {} for port {} exited with status {}", child.id(), - port_number, + port_id, status ); } @@ -875,7 +871,7 @@ impl Xhci { info!( "driver process {} for port {} still running", child.id(), - port_number + port_id ); } }, @@ -883,7 +879,7 @@ impl Xhci { info!( "failed to wait for the driver process {} for port {}: {}", child.id(), - port_number, + port_id, err ); } @@ -893,7 +889,7 @@ impl Xhci { warn!( "failed to kill the driver process {} for port {}: {}", child.id(), - port_number, + port_id, err ); } @@ -901,22 +897,19 @@ impl Xhci { } } - if let Some(state) = self.port_states.remove(&port_number) { - info!( - "disabling port slot {} for port {}", - state.slot, port_number - ); + if let Some(state) = self.port_states.remove(&port_id) { + info!("disabling port slot {} for port {}", state.slot, port_id); let result = self.disable_port_slot(state.slot).await; info!( "disabled port slot {} for port {} with result: {:?}", - state.slot, port_number, result + state.slot, port_id, result ); result } else { warn!( "Attempted to detach from port {}, which wasn't previously attached.", - port_number + port_id ); Ok(()) } @@ -989,7 +982,7 @@ impl Xhci { pub async fn address_device( &self, input_context: &mut Dma, - i: usize, + port: PortId, slot_ty: u8, slot: u8, speed: u8, @@ -1001,7 +994,7 @@ impl Xhci { let slot_ctx = &mut input_context.device.slot; - let route_string = 0u32; // TODO + let route_string = port.route_string; let context_entries = 1u8; let mtt = false; let hub = false; @@ -1015,7 +1008,7 @@ impl Xhci { ); let max_exit_latency = 0u16; - let root_hub_port_num = (i + 1) as u8; + let root_hub_port_num = port.root_hub_port_num; let number_of_ports = 0u8; slot_ctx.b.write( u32::from(max_exit_latency) @@ -1040,7 +1033,7 @@ impl Xhci { let endp_ctx = &mut input_context.device.endpoints[0]; let speed_id = self - .lookup_psiv(root_hub_port_num, speed) + .lookup_psiv(port, speed) .expect("Failed to retrieve speed ID"); let max_error_count = 3u8; // recommended value according to the XHCI spec @@ -1085,7 +1078,7 @@ impl Xhci { error!( "Failed to address device at slot {} (port {}), completion code 0x{:X}", slot, - i, + port, event_trb.completion_code() ); //self.event_handler_finished(); @@ -1155,14 +1148,14 @@ impl Xhci { false } } - fn spawn_drivers(&self, port: usize) -> Result<()> { + fn spawn_drivers(&self, port: PortId) -> Result<()> { // TODO: There should probably be a way to select alternate interfaces, and not just the // first one. // TODO: Now that there are some good error crates, I don't think errno.h error codes are // suitable here. let ps = self.port_states.get(&port).unwrap(); - trace!("Spawning driver on port: {}", port + 1); + trace!("Spawning driver on port: {}", port); //TODO: support choosing config? let config_desc = &ps @@ -1179,7 +1172,7 @@ impl Xhci { Error::new(EBADF) })?; - trace!("Got config and device descriptors on port {}", port + 1); + trace!("Got config and device descriptors on port {}", port); let drivers_usercfg: &DriversConfig = &DRIVERS_CONFIG; for ifdesc in config_desc.interface_descs.iter() { @@ -1244,14 +1237,16 @@ impl Xhci { } }) } - pub fn supported_protocol(&self, port: u8) -> Option<&'static SupportedProtoCap> { - self.supported_protocols_iter() - .find(|supp_proto| supp_proto.compat_port_range().contains(&(port + 1))) - //Increment by 1, because USB ports index themselves by 1. + pub fn supported_protocol(&self, port: PortId) -> Option<&'static SupportedProtoCap> { + self.supported_protocols_iter().find(|supp_proto| { + supp_proto + .compat_port_range() + .contains(&port.root_hub_port_num) + }) } pub fn supported_protocol_speeds( &self, - port: u8, + port: PortId, ) -> impl Iterator { use extended::*; const DEFAULT_SUPP_PROTO_SPEEDS: [ProtocolSpeed; 7] = [ @@ -1334,7 +1329,7 @@ impl Xhci { } } } - pub fn lookup_psiv(&self, port: u8, psiv: u8) -> Option<&'static ProtocolSpeed> { + pub fn lookup_psiv(&self, port: PortId, psiv: u8) -> Option<&'static ProtocolSpeed> { self.supported_protocol_speeds(port) .find(|speed| speed.psiv() == psiv) } diff --git a/xhcid/src/xhci/scheme.rs b/xhcid/src/xhci/scheme.rs index f7a5a803c7..924ed612e6 100644 --- a/xhcid/src/xhci/scheme.rs +++ b/xhcid/src/xhci/scheme.rs @@ -37,7 +37,7 @@ use syscall::{ }; use super::{port, usb}; -use super::{EndpointState, Xhci}; +use super::{EndpointState, PortId, Xhci}; use super::context::{SlotState, StreamContextArray, StreamContextType}; use super::extended::ProtocolSpeed; @@ -50,21 +50,21 @@ use crate::driver_interface::*; use regex::Regex; lazy_static! { - static ref REGEX_PORT_CONFIGURE: Regex = Regex::new(r"^port(\d{1,3})/configure$") + static ref REGEX_PORT_CONFIGURE: Regex = Regex::new(r"^port([\d\.]+)/configure$") .expect("Failed to create the regex for the port/configure scheme."); - static ref REGEX_PORT_DESCRIPTORS: Regex = Regex::new(r"^port(\d{1,3})/descriptors$") + static ref REGEX_PORT_DESCRIPTORS: Regex = Regex::new(r"^port([\d\.]+)/descriptors$") .expect("Failed to create the regex for the port/descriptors"); - static ref REGEX_PORT_STATE: Regex = Regex::new(r"^port(\d{1,3})/state$") + static ref REGEX_PORT_STATE: Regex = Regex::new(r"^port([\d\.]+)/state$") .expect("Failed to create the regex for the port/state scheme"); - static ref REGEX_PORT_REQUEST: Regex = Regex::new(r"^port(\d{1,3})/request$") + static ref REGEX_PORT_REQUEST: Regex = Regex::new(r"^port([\d\.]+)/request$") .expect("Failed to create the regex for the port/request scheme"); - static ref REGEX_PORT_ENDPOINTS: Regex = Regex::new(r"^port(\d{1,3})/endpoints$") + static ref REGEX_PORT_ENDPOINTS: Regex = Regex::new(r"^port([\d\.]+)/endpoints$") .expect("Failed to create the regex for the port/endpoints scheme"); static ref REGEX_PORT_SPECIFIC_ENDPOINT: Regex = - Regex::new(r"^port(\d{1,3})/endpoints/(\d{1,3})$") + Regex::new(r"^port([\d\.]+)/endpoints/(\d{1,3})$") .expect("Failed to create the regex for the port/endpoints/ scheme"); static ref REGEX_PORT_SUB_ENDPOINT: Regex = Regex::new( - r"port(\d{1,3})/endpoints/(\d{1,3})/(ctl|data)$" + r"port([\d\.]+)/endpoints/(\d{1,3})/(ctl|data)$" ) .expect("Failed to create the regex for the port/endpoints// scheme"); static ref REGEX_TOP_LEVEL: Regex = @@ -123,14 +123,14 @@ pub enum PortReqState { /// Contains some information about the data requested via the handle. #[derive(Debug)] pub enum Handle { - TopLevel(Vec), // contents (ports) - Port(usize, Vec), // port, contents - PortDesc(usize, Vec), // port, contents - PortState(usize), // port - PortReq(usize, PortReqState), // port, state - Endpoints(usize, Vec), // port, contents - Endpoint(usize, u8, EndpointHandleTy), // port, endpoint, state - ConfigureEndpoints(usize), // port + TopLevel(Vec), // contents (ports) + Port(PortId, Vec), // port, contents + PortDesc(PortId, Vec), // port, contents + PortState(PortId), // port + PortReq(PortId, PortReqState), // port, state + Endpoints(PortId, Vec), // port, contents + Endpoint(PortId, u8, EndpointHandleTy), // port, endpoint, state + ConfigureEndpoints(PortId), // port } /// The type of handle. @@ -154,22 +154,22 @@ enum SchemeParameters { /// The scheme references the top-level XHCI driver endpoint TopLevel, /// /port - Port(usize), // port number + Port(PortId), // port number /// /port/descriptors - PortDesc(usize), // port number + PortDesc(PortId), // port number /// /port/state - PortState(usize), // port number + PortState(PortId), // port number /// /port/request - PortReq(usize), // port number + PortReq(PortId), // port number /// /port/endpoints - Endpoints(usize), // port number + Endpoints(PortId), // port number /// /port/endpoints//(data|ctl) /// /// This can also represent /// /port/endpoints/ - Endpoint(usize, u8, String), // port number, endpoint number, handle type + Endpoint(PortId, u8, String), // port number, endpoint number, handle type /// /port/configure - ConfigureEndpoints(usize), // port number + ConfigureEndpoints(PortId), // port number } impl Handle { @@ -305,15 +305,15 @@ impl SchemeParameters { Err(Error::new(ENOENT)) }; - fn get_usize_from_regex( + fn get_port_id_from_regex( rgx: &Regex, scheme: &str, capture_idx: usize, - ) -> syscall::Result { + ) -> syscall::Result { if let Some(capture_list) = rgx.captures(scheme) { if let Some(value) = capture_list.get(capture_idx + 1) { - if let Ok(integer) = value.as_str().parse::() { - return Ok(integer); + if let Ok(port_id) = value.as_str().parse::() { + return Ok(port_id); } } } @@ -342,32 +342,32 @@ impl SchemeParameters { //Check if we have a match and either return a partially initialized scheme, OR ENOENT if REGEX_PORT_CONFIGURE.is_match(scheme) { - let port_num = get_usize_from_regex(®EX_PORT_CONFIGURE, scheme, 0)?; + let port_num = get_port_id_from_regex(®EX_PORT_CONFIGURE, scheme, 0)?; Ok(Self::ConfigureEndpoints(port_num)) } else if REGEX_PORT_DESCRIPTORS.is_match(scheme) { - let port_num = get_usize_from_regex(®EX_PORT_DESCRIPTORS, scheme, 0)?; + let port_num = get_port_id_from_regex(®EX_PORT_DESCRIPTORS, scheme, 0)?; Ok(Self::PortDesc(port_num)) } else if REGEX_PORT_STATE.is_match(scheme) { - let port_num = get_usize_from_regex(®EX_PORT_STATE, scheme, 0)?; + let port_num = get_port_id_from_regex(®EX_PORT_STATE, scheme, 0)?; Ok(Self::PortState(port_num)) } else if REGEX_PORT_REQUEST.is_match(scheme) { - let port_num = get_usize_from_regex(®EX_PORT_REQUEST, scheme, 0)?; + let port_num = get_port_id_from_regex(®EX_PORT_REQUEST, scheme, 0)?; Ok(Self::PortReq(port_num)) } else if REGEX_PORT_ENDPOINTS.is_match(scheme) { - let port_num = get_usize_from_regex(®EX_PORT_ENDPOINTS, scheme, 0)?; + let port_num = get_port_id_from_regex(®EX_PORT_ENDPOINTS, scheme, 0)?; Ok(Self::Endpoints(port_num)) } else if REGEX_PORT_SPECIFIC_ENDPOINT.is_match(scheme) { - let port_num = get_usize_from_regex(®EX_PORT_SPECIFIC_ENDPOINT, scheme, 0)?; + let port_num = get_port_id_from_regex(®EX_PORT_SPECIFIC_ENDPOINT, scheme, 0)?; let endpoint_num = get_u8_from_regex(®EX_PORT_SPECIFIC_ENDPOINT, scheme, 1)?; Ok(Self::Endpoint(port_num, endpoint_num, String::from("root"))) } else if REGEX_PORT_SUB_ENDPOINT.is_match(scheme) { - let port_num = get_usize_from_regex(®EX_PORT_SUB_ENDPOINT, scheme, 0)?; + let port_num = get_port_id_from_regex(®EX_PORT_SUB_ENDPOINT, scheme, 0)?; let endpoint_num = get_u8_from_regex(®EX_PORT_SUB_ENDPOINT, scheme, 1)?; let handle_type = get_string_from_regex(®EX_PORT_SUB_ENDPOINT, scheme, 2)?; @@ -517,7 +517,7 @@ impl AnyDescriptor { impl Xhci { async fn new_if_desc( &self, - port_id: usize, + port_id: PortId, slot: u8, desc: usb::InterfaceDescriptor, endps: impl IntoIterator, @@ -588,7 +588,7 @@ impl Xhci { } pub async fn execute_control_transfer( &self, - port_num: usize, + port_num: PortId, setup: usb::Setup, tk: TransferKind, name: &str, @@ -634,7 +634,7 @@ impl Xhci { cmd.status(interrupter, input, ioc, ch, ent, cycle); self.next_transfer_event_trb( - RingId::default_control_pipe(port_num as u8), + RingId::default_control_pipe(port_num), ring, &ring.trbs[first_index], &ring.trbs[last_index], @@ -658,7 +658,7 @@ impl Xhci { /// will never complete. pub async fn execute_transfer( &self, - port_num: usize, + port_num: PortId, endp_num: u8, stream_id: u16, name: &str, @@ -714,7 +714,7 @@ impl Xhci { ControlFlow::Break => { break self.next_transfer_event_trb( super::irq_reactor::RingId { - port: port_num as u8, + port: port_num, endpoint_num: endp_num, stream_id, }, @@ -758,7 +758,7 @@ impl Xhci { Ok(event_trb) } - async fn device_req_no_data(&self, port: usize, req: usb::Setup) -> Result<()> { + async fn device_req_no_data(&self, port: PortId, req: usb::Setup) -> Result<()> { trace!("DEVICE_REQ_NO_DATA port {}, req: {:?}", port, req); self.execute_control_transfer( @@ -772,7 +772,7 @@ impl Xhci { Ok(()) } - async fn set_configuration(&self, port: usize, config: u8) -> Result<()> { + async fn set_configuration(&self, port: PortId, config: u8) -> Result<()> { debug!("Setting configuration value {} to port {}", config, port); self.device_req_no_data(port, usb::Setup::set_configuration(config)) .await @@ -780,7 +780,7 @@ impl Xhci { async fn set_interface( &self, - port: usize, + port: PortId, interface_num: u8, alternate_setting: u8, ) -> Result<()> { @@ -795,7 +795,7 @@ impl Xhci { .await } - async fn reset_endpoint(&self, port_num: usize, endp_num: u8, tsp: bool) -> Result<()> { + async fn reset_endpoint(&self, port_num: PortId, endp_num: u8, tsp: bool) -> Result<()> { let endp_idx = endp_num.checked_sub(1).ok_or(Error::new(EIO))?; let port_state = self.port_states.get(&port_num).ok_or(Error::new(EBADFD))?; @@ -894,19 +894,22 @@ impl Xhci { } } - fn port_state(&self, port: usize) -> Result> { + fn port_state( + &self, + port: PortId, + ) -> Result> { self.port_states.get(&port).ok_or(Error::new(EBADF)) } fn port_state_mut( &self, - port: usize, - ) -> Result> { + port: PortId, + ) -> Result> { self.port_states.get_mut(&port).ok_or(Error::new(EBADF)) } async fn configure_endpoints_once( &self, - port: usize, + port: PortId, req: &ConfigureEndpointsReq, ) -> Result<()> { let (endp_desc_count, new_context_entries, configuration_value) = { @@ -951,12 +954,11 @@ impl Xhci { let lec = self.cap.lec(); let log_max_psa_size = self.cap.max_psa_size(); - let port_speed_id = self.ports.lock().unwrap()[port].speed(); - let speed_id: &ProtocolSpeed = - self.lookup_psiv(port as u8, port_speed_id).ok_or_else(|| { - warn!("no speed_id"); - Error::new(EIO) - })?; + let port_speed_id = self.ports.lock().unwrap()[port.root_hub_port_index()].speed(); + let speed_id: &ProtocolSpeed = self.lookup_psiv(port, port_speed_id).ok_or_else(|| { + warn!("no speed_id"); + Error::new(EIO) + })?; { let port_state = self.port_states.get(&port).ok_or(Error::new(EBADFD))?; @@ -1155,7 +1157,7 @@ impl Xhci { Ok(()) } - async fn configure_endpoints(&self, port: usize, json_buf: &[u8]) -> Result<()> { + async fn configure_endpoints(&self, port: PortId, json_buf: &[u8]) -> Result<()> { let mut req: ConfigureEndpointsReq = serde_json::from_slice(json_buf).or(Err(Error::new(EBADMSG)))?; @@ -1188,7 +1190,7 @@ impl Xhci { } async fn transfer_read( &self, - port_num: usize, + port_num: PortId, endp_idx: u8, buf: &mut [u8], ) -> Result<(u8, u32)> { @@ -1211,7 +1213,7 @@ impl Xhci { } async fn transfer_write( &self, - port_num: usize, + port_num: PortId, endp_idx: u8, sbuf: &[u8], ) -> Result<(u8, u32)> { @@ -1267,7 +1269,7 @@ impl Xhci { // TODO: Rename DeviceReqData to something more general. async fn transfer( &self, - port_num: usize, + port_num: PortId, endp_idx: u8, dma_buf: Option>, direction: PortReqDirection, @@ -1386,9 +1388,11 @@ impl Xhci { Ok((event.completion_code(), bytes_transferred, dma_buf)) } - pub async fn get_desc(&self, port_id: usize, slot: u8) -> Result { + pub async fn get_desc(&self, port_id: PortId, slot: u8) -> Result { let ports = self.ports.lock().unwrap(); - let port = ports.get(port_id).ok_or(Error::new(ENOENT))?; + let port = ports + .get(port_id.root_hub_port_index()) + .ok_or(Error::new(ENOENT))?; if !port.flags().contains(port::PortFlags::PORT_CCS) { return Err(Error::new(ENOENT)); } @@ -1544,7 +1548,7 @@ impl Xhci { config_descs, }) } - fn port_desc_json(&self, port_id: usize) -> Result> { + fn port_desc_json(&self, port_id: PortId) -> Result> { let dev_desc = &self .port_states .get(&port_id) @@ -1561,7 +1565,7 @@ impl Xhci { } async fn port_req_transfer( &self, - port_num: usize, + port_num: PortId, data_buffer: Option<&mut Dma<[u8]>>, setup: usb::Setup, transfer_kind: TransferKind, @@ -1584,7 +1588,7 @@ impl Xhci { .await?; Ok(()) } - fn port_req_init_st(&self, port_num: usize, req: &PortReq) -> Result { + fn port_req_init_st(&self, port_num: PortId, req: &PortReq) -> Result { use usb::setup::*; let direction = ReqDirection::from(req.direction); @@ -1634,7 +1638,7 @@ impl Xhci { async fn handle_port_req_write( &self, fd: usize, - port_num: usize, + port_num: PortId, mut st: PortReqState, buf: &[u8], ) -> Result { @@ -1678,7 +1682,7 @@ impl Xhci { async fn handle_port_req_read( &self, fd: usize, - port_num: usize, + port_num: PortId, mut st: PortReqState, buf: &mut [u8], ) -> Result { @@ -1743,7 +1747,7 @@ impl Xhci { /// implements open() for /port/descriptors /// /// # Arguments - /// - 'port_num: [usize]' - The port number specified in the scheme path + /// - 'port_num: [PortId]' - The port number specified in the scheme path /// - 'flags: [usize]' - The flags parameter passed to open() /// /// # Returns @@ -1751,7 +1755,7 @@ impl Xhci { /// /// - [Handle::PortDesc] - The handle was opened successfully /// - [ENOTDIR] - Directory-specific flags were passed to open(), but this endpoint is not a directory. - fn open_handle_port_descriptors(&self, port_num: usize, flags: usize) -> Result { + fn open_handle_port_descriptors(&self, port_num: PortId, flags: usize) -> Result { if flags & O_DIRECTORY != 0 && flags & O_STAT == 0 { return Err(Error::new(ENOTDIR)); } @@ -1763,7 +1767,7 @@ impl Xhci { /// implements open() for /port /// /// # Arguments - /// - 'port_num: [usize]' - The port number specified in the scheme path + /// - 'port_num: [PortId]' - The port number specified in the scheme path /// - 'flags: [usize]' - The flags parameter passed to open() /// /// # Returns @@ -1772,7 +1776,7 @@ impl Xhci { /// - [Handle::Port] - The handle was opened successfully /// - [ENOENT] - The scheme is valid, but there is no port associated with the given port_num /// - [EISDIR] - open() was called on this scheme endpoint, but no directory-specific flags were passed to open - fn open_handle_port(&self, port_num: usize, flags: usize) -> Result { + fn open_handle_port(&self, port_num: PortId, flags: usize) -> Result { // The != here is unintuitive. You would assume that you could do // flags & O_DIRECTORY || flags & O_STAT, but rust doesn't allow // you to cast integers to booleans. @@ -1800,7 +1804,7 @@ impl Xhci { /// implements open() for /port/state /// /// # Arguments - /// - 'port_num: [usize]' - The port number specified in the scheme path + /// - 'port_num: [PortId]' - The port number specified in the scheme path /// - 'flags: [usize]' - The flags parameter passed to open() /// /// # Returns @@ -1808,7 +1812,7 @@ impl Xhci { /// /// - [Handle::Port] - The handle was opened successfully /// - [ENOTDIR] - open() was called on this scheme endpoint, but directory-specific flags were passed to open - fn open_handle_port_state(&self, port_num: usize, flags: usize) -> Result { + fn open_handle_port_state(&self, port_num: PortId, flags: usize) -> Result { if flags & O_DIRECTORY != 0 && flags & O_STAT == 0 { return Err(Error::new(ENOTDIR)); } @@ -1819,7 +1823,7 @@ impl Xhci { /// implements open() for /port/endpoints /// /// # Arguments - /// - 'port_num: [usize]' - The port number specified in the scheme path + /// - 'port_num: [PortId]' - The port number specified in the scheme path /// - 'flags: [usize]' - The flags parameter passed to open() /// /// # Returns @@ -1827,7 +1831,7 @@ impl Xhci { /// /// - [Handle::Port] - The handle was opened successfully /// - [EISDIR] - open() was called on this scheme endpoint, but no directory-specific flags were passed to open - fn open_handle_port_endpoints(&self, port_num: usize, flags: usize) -> Result { + fn open_handle_port_endpoints(&self, port_num: PortId, flags: usize) -> Result { if flags & O_DIRECTORY == 0 && flags & O_STAT == 0 { return Err(Error::new(EISDIR)); }; @@ -1848,7 +1852,7 @@ impl Xhci { /// implements open() for /port/endpoints/ /// /// # Arguments - /// - 'port_num: [usize]' - The port number specified in the scheme path + /// - 'port_num: [PortId]' - The port number specified in the scheme path /// - 'endpoint_num: [u8]' - The endpoint number to access /// - 'flags: [usize]' - The flags parameter passed to open() /// @@ -1860,7 +1864,7 @@ impl Xhci { /// - [ENOENT] - The scheme is valid, but there is no port associated with the given port_num fn open_handle_endpoint_root( &self, - port_num: usize, + port_num: PortId, endpoint_num: u8, flags: usize, ) -> Result { @@ -1892,7 +1896,7 @@ impl Xhci { /// implements open() for /port/endpoints//data and /port/endpoints//ctl /// /// # Arguments - /// - 'port_num: [usize]' - The port number specified in the scheme path + /// - 'port_num: [PortId]' - The port number specified in the scheme path /// - 'endpoint_num: [u8]' - The endpoint number to access /// - 'handle_type: [String]' - The type of the handle /// - 'flags: [usize]' - The flags parameter passed to open() @@ -1905,7 +1909,7 @@ impl Xhci { /// - [ENOENT] - The scheme is valid, but there is no port associated with the given port_num, or no endpoint with the given endpoint_num fn open_handle_single_endpoint( &self, - port_num: usize, + port_num: PortId, endpoint_num: u8, handle_type: String, flags: usize, @@ -1940,7 +1944,7 @@ impl Xhci { /// implements open() for /port/configure /// /// # Arguments - /// - 'port_num: [usize]' - The port number specified in the scheme path + /// - 'port_num: [PortId]' - The port number specified in the scheme path /// - 'endpoint_num: [u8]' - The endpoint number to access /// - 'flags: [usize]' - The flags parameter passed to open() /// @@ -1950,7 +1954,7 @@ impl Xhci { /// - [Handle::Port] - The handle was opened successfully /// - [EISDIR] - open() was called on this scheme endpoint, but no directory-specific flags were passed to open /// - [ENOENT] - The scheme is valid, but there is no port associated with the given port_num, or no endpoint with the given endpoint_num - fn open_handle_configure_endpoints(&self, port_num: usize, flags: usize) -> Result { + fn open_handle_configure_endpoints(&self, port_num: PortId, flags: usize) -> Result { if flags & O_DIRECTORY != 0 && flags & O_STAT == 0 { return Err(Error::new(ENOTDIR)); } @@ -1965,7 +1969,7 @@ impl Xhci { /// implements open() for /port/request /// /// # Arguments - /// - 'port_num: [usize]' - The port number specified in the scheme path + /// - 'port_num: [PortId]' - The port number specified in the scheme path /// - 'flags: [usize]' - The flags parameter passed to open() /// /// # Returns @@ -1973,7 +1977,7 @@ impl Xhci { /// /// - [Handle::Port] - The handle was opened successfully /// - [ENOTDIR] - open() was called on this scheme endpoint, but directory-specific flags were passed to open - fn open_handle_port_request(&self, port_num: usize, flags: usize) -> Result { + fn open_handle_port_request(&self, port_num: PortId, flags: usize) -> Result { if flags & O_DIRECTORY != 0 && flags & O_STAT == 0 { return Err(Error::new(ENOTDIR)); } @@ -2169,7 +2173,7 @@ impl Xhci { self.handles.remove(&fd); } - pub fn get_endp_status(&self, port_num: usize, endp_num: u8) -> Result { + pub fn get_endp_status(&self, port_num: PortId, endp_num: u8) -> Result { let port_state = self.port_states.get(&port_num).ok_or(Error::new(EBADFD))?; let slot = port_state.slot; @@ -2217,7 +2221,7 @@ impl Xhci { } pub async fn on_req_reset_device( &self, - port_num: usize, + port_num: PortId, endp_num: u8, clear_feature: bool, ) -> Result<()> { @@ -2244,7 +2248,7 @@ impl Xhci { } Ok(()) } - pub async fn restart_endpoint(&self, port_num: usize, endp_num: u8) -> Result<()> { + pub async fn restart_endpoint(&self, port_num: PortId, endp_num: u8) -> Result<()> { let mut port_state = self .port_states .get_mut(&port_num) @@ -2297,7 +2301,7 @@ impl Xhci { Ok(()) } - pub fn endp_direction(&self, port_num: usize, endp_num: u8) -> Result { + pub fn endp_direction(&self, port_num: PortId, endp_num: u8) -> Result { Ok(self .port_states .get(&port_num) @@ -2316,12 +2320,12 @@ impl Xhci { .ok_or(Error::new(EIO))? .direction()) } - pub fn slot(&self, port_num: usize) -> Result { + pub fn slot(&self, port_num: PortId) -> Result { Ok(self.port_states.get(&port_num).ok_or(Error::new(EIO))?.slot) } pub async fn set_tr_deque_ptr( &self, - port_num: usize, + port_num: PortId, endp_num: u8, deque_ptr_and_cycle: u64, ) -> Result<()> { @@ -2352,7 +2356,7 @@ impl Xhci { } pub async fn on_write_endp_ctl( &self, - port_num: usize, + port_num: PortId, endp_num: u8, buf: &[u8], ) -> Result { @@ -2442,7 +2446,7 @@ impl Xhci { } pub async fn on_write_endp_data( &self, - port_num: usize, + port_num: PortId, endp_num: u8, buf: &[u8], ) -> Result { @@ -2506,7 +2510,12 @@ impl Xhci { _ => return Err(Error::new(EBADF)), } } - pub fn on_read_endp_ctl(&self, port_num: usize, endp_num: u8, buf: &mut [u8]) -> Result { + pub fn on_read_endp_ctl( + &self, + port_num: PortId, + endp_num: u8, + buf: &mut [u8], + ) -> Result { let port_state = &mut self .port_states .get_mut(&port_num) @@ -2538,7 +2547,7 @@ impl Xhci { } pub async fn on_read_endp_data( &self, - port_num: usize, + port_num: PortId, endp_num: u8, buf: &mut [u8], ) -> Result {