xhcid and friends: use newtype PortId to ensure route string can be passed where needed

This commit is contained in:
Jeremy Soller
2025-03-20 21:27:17 -06:00
parent 68760cf5af
commit e3a13a0ce7
9 changed files with 283 additions and 210 deletions
+4 -3
View File
@@ -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::<usize>()
.expect("Expected integer as input of port");
.parse::<PortId>()
.expect("Expected port ID");
let interface_num = args
.next()
.expect(USAGE)
+4 -4
View File
@@ -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::<usize>()
.expect("port has to be a number");
.parse::<PortId>()
.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.
+3 -3
View File
@@ -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::<usize>()
.expect("expected PORT to be an integer");
.parse::<PortId>()
.expect("expected PORT ID");
let handle = XhciClientHandle::new(scheme.to_owned(), port);
+5 -6
View File
@@ -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::<usize>()
.expect("Expected integer as input of port");
.parse::<PortId>()
.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();
+71 -3
View File
@@ -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<Self, Self::Err> {
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 }
}
+24 -23
View File
@@ -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);
+5 -5
View File
@@ -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, F: FnOnce(&Ring) -> T>(&self, id: RingId, function: F) -> Option<T> {
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<T> {
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 {
+68 -73
View File
@@ -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<T>(
&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<usb::DeviceDescriptor8Byte> {
let mut desc = unsafe { self.alloc_dma_zeroed::<usb::DeviceDescriptor8Byte>()? };
@@ -177,7 +178,7 @@ impl Xhci {
Ok(*desc)
}
async fn fetch_dev_desc(&self, port: usize, slot: u8) -> Result<usb::DeviceDescriptor> {
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)
.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<String> {
async fn fetch_string_desc(&self, port: PortId, slot: u8, index: u8) -> Result<String> {
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<usize, scheme::Handle>,
next_handle: AtomicUsize,
port_states: CHashMap<usize, PortState>,
drivers: CHashMap<usize, Vec<process::Child>>,
port_states: CHashMap<PortId, PortState>,
drivers: CHashMap<PortId, Vec<process::Child>>,
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::<InputContext>()? };
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::<BTreeMap<_, _>>(),
};
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<InputContext>,
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<Item = &'static ProtocolSpeed> {
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)
}
+99 -90
View File
@@ -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<n>/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<n>/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<n>/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<n>/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<n>/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<n>/endpoints/<n> 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<n>/endpoints/<n>/<sub_endpoint> 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<u8>), // contents (ports)
Port(usize, Vec<u8>), // port, contents
PortDesc(usize, Vec<u8>), // port, contents
PortState(usize), // port
PortReq(usize, PortReqState), // port, state
Endpoints(usize, Vec<u8>), // port, contents
Endpoint(usize, u8, EndpointHandleTy), // port, endpoint, state
ConfigureEndpoints(usize), // port
TopLevel(Vec<u8>), // contents (ports)
Port(PortId, Vec<u8>), // port, contents
PortDesc(PortId, Vec<u8>), // port, contents
PortState(PortId), // port
PortReq(PortId, PortReqState), // port, state
Endpoints(PortId, Vec<u8>), // 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<n>
Port(usize), // port number
Port(PortId), // port number
/// /port<n>/descriptors
PortDesc(usize), // port number
PortDesc(PortId), // port number
/// /port<n>/state
PortState(usize), // port number
PortState(PortId), // port number
/// /port<n>/request
PortReq(usize), // port number
PortReq(PortId), // port number
/// /port<n>/endpoints
Endpoints(usize), // port number
Endpoints(PortId), // port number
/// /port<n>/endpoints/<n>/(data|ctl)
///
/// This can also represent
/// /port<n>/endpoints/<n>
Endpoint(usize, u8, String), // port number, endpoint number, handle type
Endpoint(PortId, u8, String), // port number, endpoint number, handle type
/// /port<n>/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<usize> {
) -> syscall::Result<PortId> {
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::<usize>() {
return Ok(integer);
if let Ok(port_id) = value.as_str().parse::<PortId>() {
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(&REGEX_PORT_CONFIGURE, scheme, 0)?;
let port_num = get_port_id_from_regex(&REGEX_PORT_CONFIGURE, scheme, 0)?;
Ok(Self::ConfigureEndpoints(port_num))
} else if REGEX_PORT_DESCRIPTORS.is_match(scheme) {
let port_num = get_usize_from_regex(&REGEX_PORT_DESCRIPTORS, scheme, 0)?;
let port_num = get_port_id_from_regex(&REGEX_PORT_DESCRIPTORS, scheme, 0)?;
Ok(Self::PortDesc(port_num))
} else if REGEX_PORT_STATE.is_match(scheme) {
let port_num = get_usize_from_regex(&REGEX_PORT_STATE, scheme, 0)?;
let port_num = get_port_id_from_regex(&REGEX_PORT_STATE, scheme, 0)?;
Ok(Self::PortState(port_num))
} else if REGEX_PORT_REQUEST.is_match(scheme) {
let port_num = get_usize_from_regex(&REGEX_PORT_REQUEST, scheme, 0)?;
let port_num = get_port_id_from_regex(&REGEX_PORT_REQUEST, scheme, 0)?;
Ok(Self::PortReq(port_num))
} else if REGEX_PORT_ENDPOINTS.is_match(scheme) {
let port_num = get_usize_from_regex(&REGEX_PORT_ENDPOINTS, scheme, 0)?;
let port_num = get_port_id_from_regex(&REGEX_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(&REGEX_PORT_SPECIFIC_ENDPOINT, scheme, 0)?;
let port_num = get_port_id_from_regex(&REGEX_PORT_SPECIFIC_ENDPOINT, scheme, 0)?;
let endpoint_num = get_u8_from_regex(&REGEX_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(&REGEX_PORT_SUB_ENDPOINT, scheme, 0)?;
let port_num = get_port_id_from_regex(&REGEX_PORT_SUB_ENDPOINT, scheme, 0)?;
let endpoint_num = get_u8_from_regex(&REGEX_PORT_SUB_ENDPOINT, scheme, 1)?;
let handle_type = get_string_from_regex(&REGEX_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<Item = EndpDesc>,
@@ -588,7 +588,7 @@ impl Xhci {
}
pub async fn execute_control_transfer<D>(
&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<D>(
&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<chashmap::ReadGuard<'_, usize, super::PortState>> {
fn port_state(
&self,
port: PortId,
) -> Result<chashmap::ReadGuard<'_, PortId, super::PortState>> {
self.port_states.get(&port).ok_or(Error::new(EBADF))
}
fn port_state_mut(
&self,
port: usize,
) -> Result<chashmap::WriteGuard<'_, usize, super::PortState>> {
port: PortId,
) -> Result<chashmap::WriteGuard<'_, PortId, super::PortState>> {
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<Dma<[u8]>>,
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<DevDesc> {
pub async fn get_desc(&self, port_id: PortId, slot: u8) -> Result<DevDesc> {
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<Vec<u8>> {
fn port_desc_json(&self, port_id: PortId) -> Result<Vec<u8>> {
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<PortReqState> {
fn port_req_init_st(&self, port_num: PortId, req: &PortReq) -> Result<PortReqState> {
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<usize> {
@@ -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<usize> {
@@ -1743,7 +1747,7 @@ impl Xhci {
/// implements open() for /port<n>/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<Handle> {
fn open_handle_port_descriptors(&self, port_num: PortId, flags: usize) -> Result<Handle> {
if flags & O_DIRECTORY != 0 && flags & O_STAT == 0 {
return Err(Error::new(ENOTDIR));
}
@@ -1763,7 +1767,7 @@ impl Xhci {
/// implements open() for /port<n>
///
/// # 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<Handle> {
fn open_handle_port(&self, port_num: PortId, flags: usize) -> Result<Handle> {
// 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<n>/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<Handle> {
fn open_handle_port_state(&self, port_num: PortId, flags: usize) -> Result<Handle> {
if flags & O_DIRECTORY != 0 && flags & O_STAT == 0 {
return Err(Error::new(ENOTDIR));
}
@@ -1819,7 +1823,7 @@ impl Xhci {
/// implements open() for /port<n>/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<Handle> {
fn open_handle_port_endpoints(&self, port_num: PortId, flags: usize) -> Result<Handle> {
if flags & O_DIRECTORY == 0 && flags & O_STAT == 0 {
return Err(Error::new(EISDIR));
};
@@ -1848,7 +1852,7 @@ impl Xhci {
/// implements open() for /port<n>/endpoints/<n>
///
/// # 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<Handle> {
@@ -1892,7 +1896,7 @@ impl Xhci {
/// implements open() for /port<n>/endpoints/<n>/data and /port<n>/endpoints/<n>/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<n>/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<Handle> {
fn open_handle_configure_endpoints(&self, port_num: PortId, flags: usize) -> Result<Handle> {
if flags & O_DIRECTORY != 0 && flags & O_STAT == 0 {
return Err(Error::new(ENOTDIR));
}
@@ -1965,7 +1969,7 @@ impl Xhci {
/// implements open() for /port<n>/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<Handle> {
fn open_handle_port_request(&self, port_num: PortId, flags: usize) -> Result<Handle> {
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<EndpointStatus> {
pub fn get_endp_status(&self, port_num: PortId, endp_num: u8) -> Result<EndpointStatus> {
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<EndpDirection> {
pub fn endp_direction(&self, port_num: PortId, endp_num: u8) -> Result<EndpDirection> {
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<u8> {
pub fn slot(&self, port_num: PortId) -> Result<u8> {
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<usize> {
@@ -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<usize> {
@@ -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<usize> {
pub fn on_read_endp_ctl(
&self,
port_num: PortId,
endp_num: u8,
buf: &mut [u8],
) -> Result<usize> {
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<usize> {