xhcid and friends: use newtype PortId to ensure route string can be passed where needed
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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();
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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(®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<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> {
|
||||
|
||||
Reference in New Issue
Block a user