Use the real DCIs instead of driver-level numbers.
Sidenote: instead of STALLing because the driver didn't configure the endpoints properly, regular transfers now work. Thus, QEMU was able to recognize that it received a Bulk-Only Transport CBW. Yay! Additionally, to make life easier when debugging, usbctl was added; now it can get endpoint statuses which were previously non-accessible from shell scripts, after the transition to the new ctl+data endpoint interface.
This commit is contained in:
Generated
+70
@@ -21,6 +21,14 @@ dependencies = [
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arg_parser"
|
||||
version = "0.1.0"
|
||||
@@ -34,6 +42,16 @@ dependencies = [
|
||||
"nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.7"
|
||||
@@ -114,6 +132,20 @@ name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
@@ -1054,6 +1086,11 @@ dependencies = [
|
||||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.14"
|
||||
@@ -1075,6 +1112,14 @@ dependencies = [
|
||||
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.10"
|
||||
@@ -1308,6 +1353,11 @@ dependencies = [
|
||||
"smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
@@ -1328,6 +1378,14 @@ dependencies = [
|
||||
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "usbctl"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xhcid 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "usbhidd"
|
||||
version = "0.1.0"
|
||||
@@ -1375,6 +1433,11 @@ dependencies = [
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.1.5"
|
||||
@@ -1472,8 +1535,10 @@ dependencies = [
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum arg_parser 0.1.0 (git+https://gitlab.redox-os.org/redox-os/arg-parser.git)" = "<none>"
|
||||
"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
|
||||
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
|
||||
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||
"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
||||
@@ -1486,6 +1551,7 @@ dependencies = [
|
||||
"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
|
||||
"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
|
||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
|
||||
"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c"
|
||||
@@ -1585,8 +1651,10 @@ dependencies = [
|
||||
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
|
||||
"checksum stb_truetype 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9d1bec4382294c5a680fcebd29f8451e8d8c04479a026f6909004e2ab1cb425d"
|
||||
"checksum stb_truetype 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f77b6b07e862c66a9f3e62a07588fee67cd90a9135a2b942409f195507b4fb51"
|
||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
|
||||
"checksum termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c22cec9d8978d906be5ac94bceb5a010d885c626c4c8855721a4dbd20e3ac905"
|
||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
"checksum thiserror 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "205684fd018ca14432b12cce6ea3d46763311a571c3d294e71ba3f01adcf1aad"
|
||||
"checksum thiserror-impl 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "57e4d2e50ca050ed44fb58309bdce3efa79948f84f9993ad1978de5eebdce5a7"
|
||||
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||
@@ -1609,12 +1677,14 @@ dependencies = [
|
||||
"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
|
||||
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
||||
"checksum unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4"
|
||||
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
|
||||
"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
|
||||
"checksum utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d"
|
||||
"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"
|
||||
"checksum ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dfeb711b61ce620c0cb6fd9f8e3e678622f0c971da2a63c4b3e25e88ed012f"
|
||||
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
||||
"checksum vte 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f42f536e22f7fcbb407639765c8fd78707a33109301f834a594758bedd6e8cf"
|
||||
"checksum webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "17d7967316d8411ca3b01821ee6c332bde138ba4363becdb492f12e514daa17f"
|
||||
|
||||
@@ -15,6 +15,7 @@ members = [
|
||||
"vboxd",
|
||||
"vesad",
|
||||
"xhcid",
|
||||
"usbctl",
|
||||
"usbhidd",
|
||||
"usbscsid",
|
||||
]
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/target
|
||||
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "usbctl"
|
||||
version = "0.1.0"
|
||||
authors = ["4lDO2 <4lDO2@protonmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33"
|
||||
xhcid = { path = "../xhcid" }
|
||||
@@ -0,0 +1,35 @@
|
||||
use clap::{Arg, App};
|
||||
use xhcid_interface::XhciClientHandle;
|
||||
|
||||
fn main() {
|
||||
let matches = App::new("usbctl")
|
||||
.arg(Arg::with_name("SCHEME").takes_value(true).required(true).long("scheme").short("s"))
|
||||
.subcommand(App::new("port")
|
||||
.arg(Arg::with_name("PORT").takes_value(true).required(true))
|
||||
.subcommand(App::new("status")
|
||||
)
|
||||
.subcommand(App::new("endpoint")
|
||||
.arg(Arg::with_name("ENDPOINT_NUM").takes_value(true).required(true))
|
||||
.subcommand(App::new("status"))
|
||||
)
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
let scheme = matches.value_of("SCHEME").expect("no scheme");
|
||||
|
||||
if let Some(port_scmd_matches) = matches.subcommand_matches("port") {
|
||||
let port = port_scmd_matches.value_of("PORT").expect("invalid utf-8 for PORT argument").parse::<usize>().expect("expected PORT to be an integer");
|
||||
|
||||
let handle = XhciClientHandle::new(scheme.to_owned(), port);
|
||||
|
||||
if let Some(_status_scmd_matches) = port_scmd_matches.subcommand_matches("status") {
|
||||
let state = handle.port_state().expect("Failed to get port state");
|
||||
println!("{}", state.as_str());
|
||||
} else if let Some(endp_scmd_matches) = port_scmd_matches.subcommand_matches("endpoint") {
|
||||
let endp_num = endp_scmd_matches.value_of("ENDPOINT_NUM").expect("no valid ENDPOINT_NUM").parse::<u8>().expect("expected ENDPOINT_NUM to be an 8-bit integer");
|
||||
let mut endp_handle = handle.open_endpoint(endp_num).expect("Failed to open endpoint");
|
||||
let state = endp_handle.status().expect("Failed to get endpoint state");
|
||||
println!("{}", state.as_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,8 +95,6 @@ impl<'a> BulkOnlyTransport<'a> {
|
||||
let bulk_in_num = (endpoints.iter().position(|endpoint| endpoint.direction() == EndpDirection::In).unwrap() + 1) as u8;
|
||||
let bulk_out_num = (endpoints.iter().position(|endpoint| endpoint.direction() == EndpDirection::Out).unwrap() + 1) as u8;
|
||||
|
||||
bulk_only_mass_storage_reset(handle, if_desc.number.into())?;
|
||||
|
||||
let max_lun = get_max_lun(handle, 0)?;
|
||||
println!("BOT_MAX_LUN {}", max_lun);
|
||||
|
||||
@@ -147,6 +145,8 @@ impl<'a> Protocol for BulkOnlyTransport<'a> {
|
||||
|
||||
dbg!(self.bulk_in.status()?, self.bulk_out.status()?);
|
||||
|
||||
bulk_only_mass_storage_reset(&self.handle, self.interface_num.into())?;
|
||||
|
||||
match self.bulk_out.transfer_write(&cbw_bytes)? {
|
||||
PortTransferStatus::ShortPacket(31) => (),
|
||||
PortTransferStatus::Stalled => {
|
||||
@@ -154,7 +154,7 @@ impl<'a> Protocol for BulkOnlyTransport<'a> {
|
||||
self.clear_stall_out()?;
|
||||
dbg!(self.bulk_in.status()?, self.bulk_out.status()?);
|
||||
}
|
||||
_ => panic!("invalid number of CBW bytes written; expected a short packed of length 31 (0x1F)"),
|
||||
_ => (),//panic!("invalid number of CBW bytes written; expected a short packet of length 31 (0x1F)"),
|
||||
}
|
||||
|
||||
match data {
|
||||
|
||||
@@ -388,6 +388,9 @@ impl Xhci {
|
||||
}
|
||||
|
||||
pub fn update_default_control_pipe(&mut self, input_context: &mut Dma<InputContext>, slot_id: u8, dev_desc: &DevDesc) -> Result<()> {
|
||||
input_context.add_context.write(1 << 1);
|
||||
input_context.drop_context.write(0);
|
||||
|
||||
let new_max_packet_size = if dev_desc.major_version() == 2 {
|
||||
u32::from(dev_desc.packet_size)
|
||||
} else {
|
||||
|
||||
+83
-40
@@ -217,7 +217,7 @@ impl Xhci {
|
||||
let (cmd, cycle) = ring.next();
|
||||
cmd.status(false, cycle);
|
||||
}
|
||||
self.dbs[ps.slot as usize].write(1);
|
||||
self.dbs[ps.slot as usize].write(Self::def_control_endp_doorbell());
|
||||
|
||||
{
|
||||
let event = self.cmd.next_event();
|
||||
@@ -259,33 +259,34 @@ impl Xhci {
|
||||
}
|
||||
|
||||
fn reset_endpoint(&mut self, port_num: usize, endp_num: u8, tsp: bool) -> Result<()> {
|
||||
let endp_num_xhc = Self::endp_num_to_dci(endp_num, self.endp_desc(port_num, endp_num)?);
|
||||
|
||||
let slot = self
|
||||
.port_states
|
||||
.get(&port_num)
|
||||
.ok_or(Error::new(EBADF))?
|
||||
.slot;
|
||||
{
|
||||
let (cmd, cycle, event) = self.cmd.next();
|
||||
cmd.reset_endpoint(slot, endp_num + 1, tsp, cycle);
|
||||
|
||||
self.dbs[0].write(0);
|
||||
let (cmd, cycle, event) = self.cmd.next();
|
||||
cmd.reset_endpoint(slot, endp_num_xhc, tsp, cycle);
|
||||
|
||||
while event.data.read() == 0 {
|
||||
println!(" - Waiting for event");
|
||||
}
|
||||
self.dbs[0].write(0);
|
||||
|
||||
if event.completion_code() != TrbCompletionCode::Success as u8
|
||||
|| event.trb_type() != TrbType::CommandCompletion as u8
|
||||
{
|
||||
println!("RESET_ENDPOINT failed with event TRB ({:#0x} {:#0x} {:#0x}) and command TRB ({:#0x} {:#0x} {:#0x})", event.data.read(), event.status.read(), event.control.read(), cmd.data.read(), cmd.status.read(), cmd.control.read());
|
||||
return Err(Error::new(EIO));
|
||||
}
|
||||
|
||||
cmd.reserved(false);
|
||||
event.reserved(false);
|
||||
|
||||
self.run.ints[0].erdp.write(self.cmd.erdp());
|
||||
while event.data.read() == 0 {
|
||||
println!(" - Waiting for event");
|
||||
}
|
||||
|
||||
if event.completion_code() != TrbCompletionCode::Success as u8
|
||||
|| event.trb_type() != TrbType::CommandCompletion as u8
|
||||
{
|
||||
println!("RESET_ENDPOINT failed with event TRB ({:#0x} {:#0x} {:#0x}) and command TRB ({:#0x} {:#0x} {:#0x})", event.data.read(), event.status.read(), event.control.read(), cmd.data.read(), cmd.status.read(), cmd.control.read());
|
||||
return Err(Error::new(EIO));
|
||||
}
|
||||
|
||||
cmd.reserved(false);
|
||||
event.reserved(false);
|
||||
|
||||
self.run.ints[0].erdp.write(self.cmd.erdp());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -391,7 +392,10 @@ impl Xhci {
|
||||
return Err(Error::new(EIO));
|
||||
}
|
||||
|
||||
let new_context_entries = 1 + endpoints.len() as u32;
|
||||
let new_context_entries = match endpoints.last() {
|
||||
Some(l) => Self::endp_num_to_dci(endpoints.len() as u8, l),
|
||||
None => 1,
|
||||
} + 1;
|
||||
|
||||
input_context.device.slot.a.write(
|
||||
(current_slot_a & !CONTEXT_ENTRIES_MASK)
|
||||
@@ -406,18 +410,19 @@ impl Xhci {
|
||||
|
||||
let lec = self.cap.lec();
|
||||
|
||||
for index in 0..endpoints.len() as u8 {
|
||||
let endp_num = index + 1;
|
||||
let xhc_endp_num = endp_num + 1;
|
||||
for endp_idx in 0..endpoints.len() as u8 {
|
||||
let endp_num = endp_idx + 1;
|
||||
|
||||
input_context.add_context.writef(1 << xhc_endp_num, true);
|
||||
let endp_desc = endpoints.get(endp_idx as usize).ok_or(Error::new(EIO))?;
|
||||
let endp_num_xhc = Self::endp_num_to_dci(endp_num, endp_desc);
|
||||
|
||||
input_context.add_context.writef(1 << endp_num_xhc, true);
|
||||
|
||||
let endp_ctx = input_context
|
||||
.device
|
||||
.endpoints
|
||||
.get_mut(endp_num as usize)
|
||||
.get_mut(endp_num_xhc as usize - 1)
|
||||
.ok_or(Error::new(EIO))?;
|
||||
let endp_desc = endpoints.get(index as usize).ok_or(Error::new(EIO))?;
|
||||
|
||||
let max_streams = endp_desc.max_streams();
|
||||
let max_psa_size = self.cap.max_psa_size();
|
||||
@@ -589,6 +594,30 @@ impl Xhci {
|
||||
},
|
||||
)
|
||||
}
|
||||
const fn def_control_endp_doorbell() -> u32 {
|
||||
1
|
||||
}
|
||||
// TODO: Wrap DCIs and driver-level endp_num into distinct types, due to the high chance of
|
||||
// mixing the two up.
|
||||
fn endp_num_to_dci(endp_num: u8, desc: &EndpDesc) -> u8 {
|
||||
if endp_num == 0 { unreachable!("EndpDesc cannot be obtained from the default control endpoint") }
|
||||
|
||||
if desc.is_control() || desc.direction() == EndpDirection::In {
|
||||
endp_num * 2 + 1
|
||||
} else if desc.direction() == EndpDirection::Out {
|
||||
endp_num * 2
|
||||
} else { unreachable!() }
|
||||
}
|
||||
fn endp_desc(&self, port_num: usize, endp_num: u8) -> Result<&EndpDesc> {
|
||||
self.port_states.get(&port_num).ok_or(Error::new(EIO))?.dev_desc.config_descs.first().ok_or(Error::new(EIO))?.interface_descs.first().ok_or(Error::new(EIO))?.endpoints.get(endp_num as usize - 1).ok_or(Error::new(EIO))
|
||||
}
|
||||
fn endp_doorbell(endp_num: u8, desc: &EndpDesc, stream_id: u16) -> u32 {
|
||||
let db_target = Self::endp_num_to_dci(endp_num, desc);
|
||||
let db_task_id: u16 = stream_id;
|
||||
|
||||
(u32::from(db_task_id) << 16)
|
||||
| u32::from(db_target)
|
||||
}
|
||||
// TODO: Rename DeviceReqData to something more general.
|
||||
fn transfer(
|
||||
&mut self,
|
||||
@@ -598,7 +627,6 @@ impl Xhci {
|
||||
) -> Result<(u8, u32)> {
|
||||
// TODO: Check that only readable enpoints are read, etc.
|
||||
let endp_num = endp_idx + 1;
|
||||
let xhc_endp_num = endp_num + 1;
|
||||
// TODO: Check that buf has a nonzero size, otherwise (at least for Rust's GlobalAlloc),
|
||||
// UB.
|
||||
let dma_buffer = match buf {
|
||||
@@ -629,12 +657,13 @@ impl Xhci {
|
||||
.get(endp_idx as usize)
|
||||
.ok_or(Error::new(EBADFD))?;
|
||||
|
||||
let direction = endp_desc.direction();
|
||||
|
||||
if endp_desc.is_isoch() {
|
||||
return Err(Error::new(ENOSYS));
|
||||
}
|
||||
|
||||
if EndpDirection::from(buf.direction()) != endp_desc.direction() {
|
||||
dbg!(buf.direction(), endp_desc.direction());
|
||||
return Err(Error::new(EBADF));
|
||||
}
|
||||
|
||||
@@ -688,8 +717,7 @@ impl Xhci {
|
||||
}
|
||||
|
||||
let stream_id = 1u16;
|
||||
self.dbs[port_state.slot as usize]
|
||||
.write(u32::from(xhc_endp_num) | (u32::from(stream_id) << 16));
|
||||
self.dbs[port_state.slot as usize].write(Self::endp_doorbell(endp_num, self.endp_desc(port_num, endp_num)?, stream_id));
|
||||
|
||||
let (completion_code, bytes_transferred) = {
|
||||
let event = self.cmd.next_event();
|
||||
@@ -953,7 +981,7 @@ impl Xhci {
|
||||
let (cmd, cycle) = ring.next();
|
||||
cmd.status(transfer_kind == TransferKind::In, cycle);
|
||||
}
|
||||
self.dbs[port_state.slot as usize].write(1);
|
||||
self.dbs[port_state.slot as usize].write(Self::def_control_endp_doorbell());
|
||||
|
||||
{
|
||||
let event = self.cmd.next_event();
|
||||
@@ -1441,7 +1469,12 @@ impl SchemeMut for Xhci {
|
||||
impl Xhci {
|
||||
pub fn get_endp_status(&mut self, port_num: usize, endp_num: u8) -> Result<EndpointStatus> {
|
||||
let slot = self.port_states.get(&port_num).ok_or(Error::new(EBADFD))?.slot;
|
||||
let raw = self.dev_ctx.contexts.get(slot as usize).ok_or(Error::new(EBADFD))?.endpoints.get(endp_num as usize).ok_or(Error::new(EBADFD))?.a.read() & super::context::ENDPOINT_CONTEXT_STATUS_MASK;
|
||||
let endp_num_xhc = if endp_num != 0 {
|
||||
Self::endp_num_to_dci(endp_num, self.endp_desc(port_num, endp_num)?)
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let raw = self.dev_ctx.contexts.get(slot as usize).ok_or(Error::new(EBADFD))?.endpoints.get(endp_num_xhc as usize - 1).ok_or(Error::new(EBADFD))?.a.read() & super::context::ENDPOINT_CONTEXT_STATUS_MASK;
|
||||
Ok(match raw {
|
||||
0 => EndpointStatus::Disabled,
|
||||
1 => EndpointStatus::Enabled,
|
||||
@@ -1473,6 +1506,12 @@ impl Xhci {
|
||||
}
|
||||
pub fn restart_endpoint(&mut self, port_num: usize, endp_num: u8) -> Result<()> {
|
||||
let port_state = self.port_states.get_mut(&port_num).ok_or(Error::new(EBADFD))?;
|
||||
let direction = if endp_num != 0 {
|
||||
let endp_desc = port_state.dev_desc.config_descs.get(0).ok_or(Error::new(EIO))?.interface_descs.get(0).ok_or(Error::new(EIO))?.endpoints.get(endp_num as usize - 1).ok_or(Error::new(EBADFD))?;
|
||||
endp_desc.direction()
|
||||
} else {
|
||||
EndpDirection::Bidirectional
|
||||
};
|
||||
let endpoint_state: &mut EndpointState = port_state.endpoint_states.get_mut(&endp_num).ok_or(Error::new(EBADFD))?;
|
||||
let ring = match &mut endpoint_state.transfer {
|
||||
&mut super::RingOrStreams::Ring(ref mut ring) => ring,
|
||||
@@ -1483,17 +1522,21 @@ impl Xhci {
|
||||
let deque_ptr_and_cycle = ring.register();
|
||||
let slot = port_state.slot;
|
||||
|
||||
self.set_tr_deque_ptr(slot, endp_num, deque_ptr_and_cycle)?;
|
||||
self.set_tr_deque_ptr(port_num, endp_num, deque_ptr_and_cycle)?;
|
||||
|
||||
let endp_num_xhc = endp_num + 1;
|
||||
self.dbs[slot as usize].write(
|
||||
(1 << 16) // stream id
|
||||
| u32::from(endp_num_xhc)
|
||||
);
|
||||
let stream_id = 1u16;
|
||||
self.dbs[slot as usize].write(Self::endp_doorbell(endp_num, self.endp_desc(port_num, endp_num)?, stream_id));
|
||||
Ok(())
|
||||
}
|
||||
pub fn set_tr_deque_ptr(&mut self, slot: u8, endp_num: u8, deque_ptr_and_cycle: u64) -> Result<()> {
|
||||
let endp_num_xhc = endp_num + 1;
|
||||
pub fn endp_direction(&self, port_num: usize, endp_num: u8) -> Result<EndpDirection> {
|
||||
Ok(self.port_states.get(&port_num).ok_or(Error::new(EIO))?.dev_desc.config_descs.first().ok_or(Error::new(EIO))?.interface_descs.first().ok_or(Error::new(EIO))?.endpoints.get(endp_num as usize).ok_or(Error::new(EIO))?.direction())
|
||||
}
|
||||
pub fn slot(&self, port_num: usize) -> Result<u8> {
|
||||
Ok(self.port_states.get(&port_num).ok_or(Error::new(EIO))?.slot)
|
||||
}
|
||||
pub fn set_tr_deque_ptr(&mut self, port_num: usize, endp_num: u8, deque_ptr_and_cycle: u64) -> Result<()> {
|
||||
let slot = self.slot(port_num)?;
|
||||
let endp_num_xhc = Self::endp_num_to_dci(endp_num, self.endp_desc(port_num, endp_num)?);
|
||||
|
||||
// TODO: Merge these command boilerplates into a single function.
|
||||
self.run.ints[0].erdp.write(self.cmd.erdp());
|
||||
|
||||
Reference in New Issue
Block a user