From 1b74f335b01a40689b89d7a73c9b8358fb68a27e Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 6 Feb 2020 21:45:44 +0100 Subject: [PATCH] Add a driver interface accessible to class drivers. --- usbscsid/src/main.rs | 2 + usbscsid/src/protocol/bot.rs | 47 +++ usbscsid/src/protocol/mod.rs | 12 + xhcid/Cargo.toml | 8 + xhcid/drivers.toml | 2 +- xhcid/src/driver_interface.rs | 135 +++++++ xhcid/src/lib.rs | 4 + xhcid/src/main.rs | 128 +++--- xhcid/src/usb/bos.rs | 16 +- xhcid/src/usb/mod.rs | 6 +- xhcid/src/usb/setup.rs | 7 +- xhcid/src/xhci/capability.rs | 5 +- xhcid/src/xhci/command.rs | 1 - xhcid/src/xhci/context.rs | 16 +- xhcid/src/xhci/mod.rs | 125 +++--- xhcid/src/xhci/operational.rs | 2 +- xhcid/src/xhci/port.rs | 8 +- xhcid/src/xhci/scheme.rs | 706 +++++++++++++++++++--------------- xhcid/src/xhci/trb.rs | 80 ++-- 19 files changed, 839 insertions(+), 471 deletions(-) create mode 100644 usbscsid/src/protocol/bot.rs create mode 100644 usbscsid/src/protocol/mod.rs create mode 100644 xhcid/src/driver_interface.rs create mode 100644 xhcid/src/lib.rs diff --git a/usbscsid/src/main.rs b/usbscsid/src/main.rs index b8733904ff..f78299fb27 100644 --- a/usbscsid/src/main.rs +++ b/usbscsid/src/main.rs @@ -1,5 +1,7 @@ use std::env; +pub mod protocol; + fn main() { let mut args = env::args().skip(1); diff --git a/usbscsid/src/protocol/bot.rs b/usbscsid/src/protocol/bot.rs new file mode 100644 index 0000000000..ab47b1a9a5 --- /dev/null +++ b/usbscsid/src/protocol/bot.rs @@ -0,0 +1,47 @@ +use super::Protocol; + +pub const CBW_SIGNATURE: u32 = 0x43425355; + +/// 0 means host to dev, 1 means dev to host +pub const CBW_FLAGS_DIRECTION_BIT: u8 = 1 << CBW_FLAGS_DIRECTION_SHIFT; +pub const CBW_FLAGS_DIRECTION_SHIFT: u8 = 7; + +#[repr(packed)] +pub struct CommandBlockWrapper { + pub signature: u32, + pub tag: u32, + pub data_transfer_len: u32, + pub flags: u8, // upper nibble reserved + pub lun: u8, // bits 7:5 reserved + pub cb_len: u8, + pub command_block: [u8; 16], +} + +pub const CSW_SIGNATURE: u32 = 0x53425355; + +#[repr(u8)] +pub enum CswStatus { + Passed = 0, + Failed = 1, + PhaseError = 2, + // the rest are reserved +} + +#[repr(packed)] +pub struct CommandStatusWrapper { + pub signature: u32, + pub tag: u32, + pub data_residue: u32, + pub status: u8, +} + +pub struct BulkOnlyTransport; + +impl Protocol for BulkOnlyTransport { + fn send_command_block(&mut self, cb: &[u8]) { + todo!() + } + fn recv_command_block(&mut self, cb: &mut [u8]) { + todo!() + } +} diff --git a/usbscsid/src/protocol/mod.rs b/usbscsid/src/protocol/mod.rs new file mode 100644 index 0000000000..ce63b4e4df --- /dev/null +++ b/usbscsid/src/protocol/mod.rs @@ -0,0 +1,12 @@ +pub trait Protocol { + fn send_command_block(&mut self, cb: &[u8]); + fn recv_command_block(&mut self, cb: &mut [u8]); +} + +/// Bulk-only transport +pub mod bot; + +/// Control-Bulk-Interface transpoint +mod cbi { + // TODO +} diff --git a/xhcid/Cargo.toml b/xhcid/Cargo.toml index a523d36367..a7a055459c 100644 --- a/xhcid/Cargo.toml +++ b/xhcid/Cargo.toml @@ -3,6 +3,14 @@ name = "xhcid" version = "0.1.0" edition = "2018" +[[bin]] +name = "xhcid" +path = "src/main.rs" + +[lib] +name = "xhcid_interface" +path = "src/lib.rs" + [dependencies] bitflags = "1" plain = "0.2" diff --git a/xhcid/drivers.toml b/xhcid/drivers.toml index 7376e52e70..426a19114e 100644 --- a/xhcid/drivers.toml +++ b/xhcid/drivers.toml @@ -2,4 +2,4 @@ name = "SCSI over USB" class = 8 # Mass Storage class subclass = 6 # SCSI transparent command set -command = ["usbscsid", "$SCHEME", "$PORT", "$IF_PROTO"] +command = ["/bin/usbscsid", "$SCHEME", "$PORT", "$IF_PROTO"] diff --git a/xhcid/src/driver_interface.rs b/xhcid/src/driver_interface.rs new file mode 100644 index 0000000000..1b2a158a91 --- /dev/null +++ b/xhcid/src/driver_interface.rs @@ -0,0 +1,135 @@ +pub extern crate serde; +pub extern crate smallvec; + +use serde::{Deserialize, Serialize}; +use smallvec::SmallVec; +use syscall::{Error, Result, EINVAL}; + +pub use crate::usb::{EndpointTy, ENDP_ATTR_TY_MASK}; + +#[derive(Serialize, Deserialize)] +pub struct ConfigureEndpointsReq { + /// Index into the configuration descriptors of the device descriptor. + pub config_desc: usize, + // TODO: Support multiple alternate interfaces as well. +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct DevDesc { + pub kind: u8, + pub usb: u16, + pub class: u8, + pub sub_class: u8, + pub protocol: u8, + pub packet_size: u8, + pub vendor: u16, + pub product: u16, + pub release: u16, + pub manufacturer_str: Option, + pub product_str: Option, + pub serial_str: Option, + pub config_descs: SmallVec<[ConfDesc; 1]>, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct ConfDesc { + pub kind: u8, + pub configuration_value: u8, + pub configuration: Option, + pub attributes: u8, + pub max_power: u8, + pub interface_descs: SmallVec<[IfDesc; 1]>, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub struct EndpDesc { + pub kind: u8, + pub address: u8, + pub attributes: u8, + pub max_packet_size: u16, + pub interval: u8, + pub ssc: Option, +} +pub enum EndpDirection { + Out, + In, + Bidirectional, +} + +impl EndpDesc { + pub fn ty(self) -> EndpointTy { + match self.attributes & ENDP_ATTR_TY_MASK { + 0 => EndpointTy::Ctrl, + 1 => EndpointTy::Interrupt, + 2 => EndpointTy::Bulk, + 3 => EndpointTy::Isoch, + _ => unreachable!(), + } + } + pub fn is_control(&self) -> bool { + self.ty() == EndpointTy::Ctrl + } + pub fn is_interrupt(&self) -> bool { + self.ty() == EndpointTy::Interrupt + } + pub fn is_bulk(&self) -> bool { + self.ty() == EndpointTy::Bulk + } + pub fn is_isoch(&self) -> bool { + self.ty() == EndpointTy::Isoch + } + pub fn direction(&self) -> EndpDirection { + if self.is_control() { + return EndpDirection::Bidirectional; + } + if self.address & 0x80 != 0 { + EndpDirection::In + } else { + EndpDirection::Out + } + } + pub fn xhci_ep_type(&self) -> Result { + Ok(match self.direction() { + EndpDirection::Out if self.is_isoch() => 1, + EndpDirection::Out if self.is_bulk() => 2, + EndpDirection::Out if self.is_interrupt() => 3, + EndpDirection::Bidirectional if self.is_control() => 4, + EndpDirection::In if self.is_isoch() => 5, + EndpDirection::In if self.is_bulk() => 6, + EndpDirection::In if self.is_interrupt() => 7, + _ => return Err(Error::new(EINVAL)), + }) + } +} +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct IfDesc { + pub kind: u8, + pub number: u8, + pub alternate_setting: u8, + pub class: u8, + pub sub_class: u8, + pub protocol: u8, + pub interface_str: Option, + pub endpoints: SmallVec<[EndpDesc; 4]>, + pub hid_descs: SmallVec<[HidDesc; 1]>, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub struct SuperSpeedCmp { + pub kind: u8, + pub max_burst: u8, + pub attributes: u8, + pub bytes_per_interval: u16, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub struct HidDesc { + pub kind: u8, + pub hid_spec_release: u16, + pub country: u8, + pub desc_count: u8, + pub desc_ty: u8, + pub desc_len: u16, + pub optional_desc_ty: u8, + pub optional_desc_len: u16, +} diff --git a/xhcid/src/lib.rs b/xhcid/src/lib.rs new file mode 100644 index 0000000000..e5e4b806ab --- /dev/null +++ b/xhcid/src/lib.rs @@ -0,0 +1,4 @@ +mod driver_interface; +mod usb; + +pub use driver_interface::*; diff --git a/xhcid/src/main.rs b/xhcid/src/main.rs index 9430af1eeb..2cc823886d 100644 --- a/xhcid/src/main.rs +++ b/xhcid/src/main.rs @@ -6,18 +6,19 @@ extern crate syscall; use event::{Event, EventQueue}; use std::cell::RefCell; -use std::{io, env}; use std::fs::File; -use std::io::{Result, Read, Write}; +use std::io::{Read, Result, Write}; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use std::sync::Arc; +use std::{env, io}; use syscall::data::Packet; -use syscall::flag::{CloneFlags, PHYSMAP_NO_CACHE, PHYSMAP_WRITE}; use syscall::error::EWOULDBLOCK; +use syscall::flag::{CloneFlags, PHYSMAP_NO_CACHE, PHYSMAP_WRITE}; use syscall::scheme::SchemeMut; use crate::xhci::Xhci; +mod driver_interface; mod usb; mod xhci; @@ -33,22 +34,38 @@ fn main() { let irq_str = args.next().expect("xhcid: no IRQ provided"); let irq = irq_str.parse::().expect("xhcid: failed to parse irq"); - print!("{}", format!(" + XHCI {} on: {:X} IRQ: {}\n", name, bar, irq)); + print!( + "{}", + format!(" + XHCI {} on: {:X} IRQ: {}\n", name, bar, irq) + ); // Daemonize if unsafe { syscall::clone(CloneFlags::empty()).unwrap() } == 0 { - let socket_fd = syscall::open(format!(":usb/{}", name), syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("xhcid: failed to create usb scheme"); - let socket = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd as RawFd) })); + let socket_fd = syscall::open( + format!(":usb/{}", name), + syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK, + ) + .expect("xhcid: failed to create usb scheme"); + let socket = Arc::new(RefCell::new(unsafe { + File::from_raw_fd(socket_fd as RawFd) + })); - let mut irq_file = File::open(format!("irq:{}", irq)).expect("xhcid: failed to open IRQ file"); + let mut irq_file = + File::open(format!("irq:{}", irq)).expect("xhcid: failed to open IRQ file"); - let address = unsafe { syscall::physmap(bar, 65536, PHYSMAP_WRITE | PHYSMAP_NO_CACHE).expect("xhcid: failed to map address") }; + let address = unsafe { + syscall::physmap(bar, 65536, PHYSMAP_WRITE | PHYSMAP_NO_CACHE) + .expect("xhcid: failed to map address") + }; { - let hci = Arc::new(RefCell::new(Xhci::new(name, address).expect("xhcid: failed to allocate device"))); + let hci = Arc::new(RefCell::new( + Xhci::new(name, address).expect("xhcid: failed to allocate device"), + )); hci.borrow_mut().probe().expect("xhcid: failed to probe"); - let mut event_queue = EventQueue::<()>::new().expect("xhcid: failed to create event queue"); + let mut event_queue = + EventQueue::<()>::new().expect("xhcid: failed to create event queue"); syscall::setrens(0, 0).expect("xhcid: failed to enter null namespace"); @@ -57,62 +74,67 @@ fn main() { let hci_irq = hci.clone(); let socket_irq = socket.clone(); let todo_irq = todo.clone(); - event_queue.add(irq_file.as_raw_fd(), move |_| -> Result> { - let mut irq = [0; 8]; - irq_file.read(&mut irq)?; + event_queue + .add(irq_file.as_raw_fd(), move |_| -> Result> { + let mut irq = [0; 8]; + irq_file.read(&mut irq)?; - if hci_irq.borrow_mut().trigger_irq() { - irq_file.write(&mut irq)?; + if hci_irq.borrow_mut().trigger_irq() { + irq_file.write(&mut irq)?; - let mut todo = todo_irq.borrow_mut(); - let mut i = 0; - while i < todo.len() { - let a = todo[i].a; - hci_irq.borrow_mut().handle(&mut todo[i]); - if todo[i].a == (-EWOULDBLOCK) as usize { - todo[i].a = a; - i += 1; - } else { - socket_irq.borrow_mut().write(&mut todo[i])?; - todo.remove(i); + let mut todo = todo_irq.borrow_mut(); + let mut i = 0; + while i < todo.len() { + let a = todo[i].a; + hci_irq.borrow_mut().handle(&mut todo[i]); + if todo[i].a == (-EWOULDBLOCK) as usize { + todo[i].a = a; + i += 1; + } else { + socket_irq.borrow_mut().write(&mut todo[i])?; + todo.remove(i); + } } } - } - Ok(None) - }).expect("xhcid: failed to catch events on IRQ file"); + Ok(None) + }) + .expect("xhcid: failed to catch events on IRQ file"); let socket_fd = socket.borrow().as_raw_fd(); let socket_packet = socket.clone(); - event_queue.add(socket_fd, move |_| -> Result> { - loop { - let mut packet = Packet::default(); - match socket_packet.borrow_mut().read(&mut packet) { - Ok(0) => break, - Err(err) if err.kind() == io::ErrorKind::WouldBlock => break, - Ok(_) => (), - Err(err) => return Err(err), - } + event_queue + .add(socket_fd, move |_| -> Result> { + loop { + let mut packet = Packet::default(); + match socket_packet.borrow_mut().read(&mut packet) { + Ok(0) => break, + Err(err) if err.kind() == io::ErrorKind::WouldBlock => break, + Ok(_) => (), + Err(err) => return Err(err), + } - let a = packet.a; - hci.borrow_mut().handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { - packet.a = a; - todo.borrow_mut().push(packet); - } else { - socket_packet.borrow_mut().write(&mut packet)?; + let a = packet.a; + hci.borrow_mut().handle(&mut packet); + if packet.a == (-EWOULDBLOCK) as usize { + packet.a = a; + todo.borrow_mut().push(packet); + } else { + socket_packet.borrow_mut().write(&mut packet)?; + } } - } - Ok(None) - }).expect("xhcid: failed to catch events on scheme file"); + Ok(None) + }) + .expect("xhcid: failed to catch events on scheme file"); - event_queue.trigger_all(Event { - fd: 0, - flags: 0 - }).expect("xhcid: failed to trigger events"); + event_queue + .trigger_all(Event { fd: 0, flags: 0 }) + .expect("xhcid: failed to trigger events"); event_queue.run().expect("xhcid: failed to handle events"); } - unsafe { let _ = syscall::physunmap(address); } + unsafe { + let _ = syscall::physunmap(address); + } } } diff --git a/xhcid/src/usb/bos.rs b/xhcid/src/usb/bos.rs index 2221b8e3a7..d2ef922288 100644 --- a/xhcid/src/usb/bos.rs +++ b/xhcid/src/usb/bos.rs @@ -57,9 +57,7 @@ pub struct BosDevDescIter<'a> { } impl<'a> BosDevDescIter<'a> { pub fn new(bytes: &'a [u8]) -> Self { - Self { - bytes, - } + Self { bytes } } } impl<'a> From<&'a [u8]> for BosDevDescIter<'a> { @@ -72,7 +70,9 @@ impl<'a> Iterator for BosDevDescIter<'a> { fn next(&mut self) -> Option { if let Some(desc) = plain::from_bytes::(self.bytes).ok() { - if desc.len as usize > self.bytes.len() { return None }; + if desc.len as usize > self.bytes.len() { + return None; + }; let bytes_ret = &self.bytes[..desc.len as usize]; self.bytes = &self.bytes[desc.len as usize..]; Some((*desc, bytes_ret)) @@ -129,6 +129,10 @@ impl<'a> Iterator for BosAnyDevDescIter<'a> { } } -pub fn bos_capability_descs<'a>(desc: BosDescriptor, data: &'a [u8]) -> impl Iterator + 'a { - BosAnyDevDescIter::from(&data[..desc.total_len as usize - std::mem::size_of_val(&desc)]).take(desc.cap_count as usize) +pub fn bos_capability_descs<'a>( + desc: BosDescriptor, + data: &'a [u8], +) -> impl Iterator + 'a { + BosAnyDevDescIter::from(&data[..desc.total_len as usize - std::mem::size_of_val(&desc)]) + .take(desc.cap_count as usize) } diff --git a/xhcid/src/usb/mod.rs b/xhcid/src/usb/mod.rs index bd441c82be..f6000a7843 100644 --- a/xhcid/src/usb/mod.rs +++ b/xhcid/src/usb/mod.rs @@ -1,7 +1,9 @@ -pub use self::bos::{BosDescriptor, BosAnyDevDesc, BosSuperSpeedDesc, bos_capability_descs}; +pub use self::bos::{bos_capability_descs, BosAnyDevDesc, BosDescriptor, BosSuperSpeedDesc}; pub use self::config::ConfigDescriptor; pub use self::device::DeviceDescriptor; -pub use self::endpoint::{EndpointDescriptor, HidDescriptor, SuperSpeedCompanionDescriptor, EndpointTy, ENDP_ATTR_TY_MASK}; +pub use self::endpoint::{ + EndpointDescriptor, EndpointTy, HidDescriptor, SuperSpeedCompanionDescriptor, ENDP_ATTR_TY_MASK, +}; pub use self::interface::InterfaceDescriptor; pub use self::setup::Setup; diff --git a/xhcid/src/usb/setup.rs b/xhcid/src/usb/setup.rs index ca26114f2f..3ba4462206 100644 --- a/xhcid/src/usb/setup.rs +++ b/xhcid/src/usb/setup.rs @@ -108,7 +108,12 @@ impl Setup { } } - pub const fn get_descriptor(kind: DescriptorKind, index: u8, language: u16, length: u16) -> Self { + pub const fn get_descriptor( + kind: DescriptorKind, + index: u8, + language: u16, + length: u16, + ) -> Self { Self { kind: 0b1000_0000, request: 0x06, diff --git a/xhcid/src/xhci/capability.rs b/xhcid/src/xhci/capability.rs index 66b8156310..d79d93d8f2 100644 --- a/xhcid/src/xhci/capability.rs +++ b/xhcid/src/xhci/capability.rs @@ -11,7 +11,7 @@ pub struct CapabilityRegs { pub hcc_params1: Mmio, pub db_offset: Mmio, pub rts_offset: Mmio, - pub hcc_params2: Mmio + pub hcc_params2: Mmio, } pub const HCC_PARAMS1_MAXPSASIZE_MASK: u32 = 0xF000; // 15:12 @@ -28,6 +28,7 @@ impl CapabilityRegs { self.hcc_params2.readf(HCC_PARAMS2_CIC_BIT) } pub fn max_psa_size(&self) -> u8 { - ((self.hcc_params1.read() & HCC_PARAMS1_MAXPSASIZE_MASK) >> HCC_PARAMS1_MAXPSASIZE_SHIFT) as u8 + ((self.hcc_params1.read() & HCC_PARAMS1_MAXPSASIZE_MASK) >> HCC_PARAMS1_MAXPSASIZE_SHIFT) + as u8 } } diff --git a/xhcid/src/xhci/command.rs b/xhcid/src/xhci/command.rs index 56449a66e3..41c539fe2e 100644 --- a/xhcid/src/xhci/command.rs +++ b/xhcid/src/xhci/command.rs @@ -1,6 +1,5 @@ use syscall::error::Result; - use super::event::EventRing; use super::ring::Ring; use super::trb::Trb; diff --git a/xhcid/src/xhci/context.rs b/xhcid/src/xhci/context.rs index 95c86d6e4a..0e7c882e0b 100644 --- a/xhcid/src/xhci/context.rs +++ b/xhcid/src/xhci/context.rs @@ -1,5 +1,5 @@ use syscall::error::Result; -use syscall::io::{Dma, Mmio, Io}; +use syscall::io::{Dma, Io, Mmio}; #[repr(packed)] pub struct SlotContext { @@ -55,7 +55,17 @@ pub struct InputContext { } impl InputContext { pub fn dump_control(&self) { - println!("INPUT CONTEXT: {} {} [{} {} {} {} {}] {}", self.drop_context.read(), self.add_context.read(), self._rsvd[0].read(), self._rsvd[1].read(), self._rsvd[2].read(), self._rsvd[3].read(), self._rsvd[4].read(), self.control.read()); + println!( + "INPUT CONTEXT: {} {} [{} {} {} {} {}] {}", + self.drop_context.read(), + self.add_context.read(), + self._rsvd[0].read(), + self._rsvd[1].read(), + self._rsvd[2].read(), + self._rsvd[3].read(), + self._rsvd[4].read(), + self.control.read() + ); } } @@ -78,7 +88,7 @@ impl DeviceContextList { Ok(DeviceContextList { dcbaa: dcbaa, - contexts: contexts + contexts: contexts, }) } diff --git a/xhcid/src/xhci/mod.rs b/xhcid/src/xhci/mod.rs index 250cb32207..640254b880 100644 --- a/xhcid/src/xhci/mod.rs +++ b/xhcid/src/xhci/mod.rs @@ -1,11 +1,11 @@ -use std::{mem, slice, process, sync::atomic, task}; use std::collections::BTreeMap; use std::ffi::OsStr; use std::pin::Pin; -use std::sync::{Arc, Mutex, Weak, atomic::AtomicBool}; +use std::sync::{atomic::AtomicBool, Arc, Mutex, Weak}; +use std::{mem, process, slice, sync::atomic, task}; use serde::Deserialize; -use syscall::error::{EBADF, EBADMSG, ENOENT, Error, Result}; +use syscall::error::{Error, Result, EBADF, EBADMSG, ENOENT}; use syscall::io::{Dma, Io}; use crate::usb; @@ -17,8 +17,8 @@ mod doorbell; mod event; mod operational; mod port; -mod runtime; mod ring; +mod runtime; mod scheme; mod trb; @@ -29,9 +29,11 @@ use self::doorbell::Doorbell; use self::operational::OperationalRegs; use self::port::Port; use self::ring::Ring; -use self::runtime::{RuntimeRegs, Interrupter}; +use self::runtime::{Interrupter, RuntimeRegs}; use self::trb::{TransferKind, TrbCompletionCode, TrbType}; +use crate::driver_interface::*; + struct Device<'a> { ring: &'a mut Ring, cmd: &'a mut CommandRing, @@ -47,7 +49,8 @@ impl<'a> Device<'a> { let (cmd, cycle) = self.ring.next(); cmd.setup( usb::Setup::get_descriptor(kind, index, 0, len as u16), - TransferKind::In, cycle + TransferKind::In, + cycle, ); } @@ -75,45 +78,29 @@ impl<'a> Device<'a> { fn get_device(&mut self) -> Result { let mut desc = Dma::::zeroed()?; - self.get_desc( - usb::DescriptorKind::Device, - 0, - &mut desc - ); + self.get_desc(usb::DescriptorKind::Device, 0, &mut desc); Ok(*desc) } fn get_config(&mut self, config: u8) -> Result<(usb::ConfigDescriptor, [u8; 4087])> { let mut desc = Dma::<(usb::ConfigDescriptor, [u8; 4087])>::zeroed()?; - self.get_desc( - usb::DescriptorKind::Configuration, - config, - &mut desc - ); + self.get_desc(usb::DescriptorKind::Configuration, config, &mut desc); Ok(*desc) } fn get_bos(&mut self) -> Result<(usb::BosDescriptor, [u8; 4087])> { let mut desc = Dma::<(usb::BosDescriptor, [u8; 4087])>::zeroed()?; - self.get_desc( - usb::DescriptorKind::BinaryObjectStorage, - 0, - &mut desc, - ); + self.get_desc(usb::DescriptorKind::BinaryObjectStorage, 0, &mut desc); Ok(*desc) } fn get_string(&mut self, index: u8) -> Result { let mut sdesc = Dma::<(u8, u8, [u16; 127])>::zeroed()?; - self.get_desc( - usb::DescriptorKind::String, - index, - &mut sdesc - ); + self.get_desc(usb::DescriptorKind::String, index, &mut sdesc); let len = sdesc.0 as usize; if len > 2 { - Ok(String::from_utf16(&sdesc.2[.. (len - 2)/2]).unwrap_or(String::new())) + Ok(String::from_utf16(&sdesc.2[..(len - 2) / 2]).unwrap_or(String::new())) } else { Ok(String::new()) } @@ -150,7 +137,7 @@ pub struct Xhci { struct PortState { slot: u8, input_context: Dma, - dev_desc: scheme::DevDesc, + dev_desc: DevDesc, endpoint_states: BTreeMap, } @@ -197,7 +184,7 @@ impl Xhci { println!(" - Wait for not running"); // Wait until controller not running - while ! op.usb_sts.readf(1) { + while !op.usb_sts.readf(1) { println!(" - Waiting for XHCI stopped"); } @@ -217,7 +204,8 @@ impl Xhci { } let port_base = op_base + 0x400; - let ports = unsafe { slice::from_raw_parts_mut(port_base as *mut Port, max_ports as usize) }; + let ports = + unsafe { slice::from_raw_parts_mut(port_base as *mut Port, max_ports as usize) }; println!(" - PORT {:X}", port_base); let db_base = address + cap.db_offset.read() as usize; @@ -331,14 +319,12 @@ impl Xhci { for i in 0..self.ports.len() { let (data, state, speed, flags) = { let port = &self.ports[i]; - ( - port.read(), - port.state(), - port.speed(), - port.flags(), - ) + (port.read(), port.state(), port.speed(), port.flags()) }; - println!(" + XHCI Port {}: {:X}, State {}, Speed {}, Flags {:?}", i, data, state, speed, flags); + println!( + " + XHCI Port {}: {:X}, State {}, Speed {}, Flags {:?}", + i, data, state, speed, flags + ); if flags.contains(port::PortFlags::PORT_CCS) { //TODO: Link TRB when running to the end of the ring buffer @@ -362,7 +348,9 @@ impl Xhci { input.device.slot.b.write(((i as u32 + 1) & 0xFF) << 16); // control endpoint? - input.device.endpoints[0].b.write(4096 << 16 | 4 << 3 | 3 << 1); // packet size | control endpoint | allowed error count + input.device.endpoints[0] + .b + .write(4096 << 16 | 4 << 3 | 3 << 1); // packet size | control endpoint | allowed error count let tr = ring.register(); input.device.endpoints[0].trh.write((tr >> 32) as u32); input.device.endpoints[0].trl.write(tr as u32); @@ -379,7 +367,9 @@ impl Xhci { println!(" - Waiting for event"); } - if event.completion_code() != TrbCompletionCode::Success as u8 || event.trb_type() != TrbType::CommandCompletion as u8 { + if event.completion_code() != TrbCompletionCode::Success as u8 + || event.trb_type() != TrbType::CommandCompletion as u8 + { panic!("ADDRESS DEVICE FAILED"); } @@ -387,14 +377,24 @@ impl Xhci { event.reserved(false); } - let dev_desc = Self::get_dev_desc_raw(&mut self.ports, &mut self.run, &mut self.cmd, &mut self.dbs, i, slot, &mut ring)?; + let dev_desc = Self::get_dev_desc_raw( + &mut self.ports, + &mut self.run, + &mut self.cmd, + &mut self.dbs, + i, + slot, + &mut ring, + )?; let mut port_state = PortState { slot, input_context: input, dev_desc, - endpoint_states: std::iter::once((0, EndpointState::Ready( - RingOrStreams::Ring(ring), - ))).collect::>(), + endpoint_states: std::iter::once(( + 0, + EndpointState::Ready(RingOrStreams::Ring(ring)), + )) + .collect::>(), }; match self.spawn_drivers(i, &mut port_state) { @@ -431,7 +431,7 @@ impl Xhci { } pub(crate) fn irq(&self) -> IrqFuture { IrqFuture { - state: IrqFutureState::Pending(Arc::downgrade(&self.irq_state)) + state: IrqFutureState::Pending(Arc::downgrade(&self.irq_state)), } } fn spawn_drivers(&mut self, port: usize, ps: &mut PortState) -> Result<()> { @@ -440,16 +440,39 @@ impl Xhci { // TODO: Now that there are some good error crates, I don't think errno.h error codes are // suitable here. - let ifdesc = &ps.dev_desc.config_descs.first().ok_or(Error::new(EBADF))?.interface_descs.first().ok_or(Error::new(EBADF))?; + let ifdesc = &ps + .dev_desc + .config_descs + .first() + .ok_or(Error::new(EBADF))? + .interface_descs + .first() + .ok_or(Error::new(EBADF))?; let drivers_usercfg: &DriversConfig = &DRIVERS_CONFIG; - if let Some(driver) = drivers_usercfg.drivers.iter().find(|driver| driver.class == ifdesc.class && driver.subclass == ifdesc.sub_class) { + if let Some(driver) = drivers_usercfg + .drivers + .iter() + .find(|driver| driver.class == ifdesc.class && driver.subclass == ifdesc.sub_class) + { println!("Loading driver \"{}\"", driver.name); let (command, args) = driver.command.split_first().ok_or(Error::new(EBADMSG))?; let if_proto = ifdesc.protocol; - let process = process::Command::new(command).args(args.into_iter().map(|arg| arg.replace("$SCHEME", &self.scheme_name).replace("$PORT", &format!("{}", port)).replace("$IF_PROTO", &format!("{}", if_proto))).collect::>()).stdin(process::Stdio::null()).spawn().or(Err(Error::new(ENOENT)))?; + let process = process::Command::new(command) + .args( + args.into_iter() + .map(|arg| { + arg.replace("$SCHEME", &self.scheme_name) + .replace("$PORT", &format!("{}", port)) + .replace("$IF_PROTO", &format!("{}", if_proto)) + }) + .collect::>(), + ) + .stdin(process::Stdio::null()) + .spawn() + .or(Err(Error::new(ENOENT)))?; self.drivers.insert(port, process); } else { return Err(Error::new(ENOENT)); @@ -481,7 +504,9 @@ lazy_static! { }; } -pub(crate) struct IrqFuture { state: IrqFutureState } +pub(crate) struct IrqFuture { + state: IrqFutureState, +} struct IrqState { triggered: AtomicBool, @@ -503,7 +528,9 @@ impl std::future::Future for IrqFuture { match &mut this.state { // TODO: Ordering? IrqFutureState::Pending(state_weak) => { - let state = state_weak.upgrade().expect("IRQ futures keep getting polled even after the driver has been deinitialized"); + let state = state_weak.upgrade().expect( + "IRQ futures keep getting polled even after the driver has been deinitialized", + ); if state.triggered.load(atomic::Ordering::SeqCst) { this.state = IrqFutureState::Finished; diff --git a/xhcid/src/xhci/operational.rs b/xhcid/src/xhci/operational.rs index 3f3d6001ae..213cae4185 100644 --- a/xhcid/src/xhci/operational.rs +++ b/xhcid/src/xhci/operational.rs @@ -1,4 +1,4 @@ -use syscall::io::{Mmio, Io}; +use syscall::io::{Io, Mmio}; #[repr(packed)] pub struct OperationalRegs { diff --git a/xhcid/src/xhci/port.rs b/xhcid/src/xhci/port.rs index 0f62d66140..1745a793bd 100644 --- a/xhcid/src/xhci/port.rs +++ b/xhcid/src/xhci/port.rs @@ -28,10 +28,10 @@ bitflags! { #[repr(packed)] pub struct Port { - pub portsc : Mmio, - pub portpmsc : Mmio, - pub portli : Mmio, - pub porthlpmc : Mmio, + pub portsc: Mmio, + pub portpmsc: Mmio, + pub portli: Mmio, + pub porthlpmc: Mmio, } impl Port { diff --git a/xhcid/src/xhci/scheme.rs b/xhcid/src/xhci/scheme.rs index c28f8992b3..287f78b534 100644 --- a/xhcid/src/xhci/scheme.rs +++ b/xhcid/src/xhci/scheme.rs @@ -1,38 +1,39 @@ -use std::{cmp, mem, path, str}; use std::convert::TryFrom; use std::io::prelude::*; +use std::{cmp, mem, path, str}; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use smallvec::SmallVec; use syscall::io::{Dma, Io}; use syscall::scheme::SchemeMut; use syscall::{ - EACCES, EBADF, EBADMSG, EEXIST, EINVAL, EIO, EISDIR, ENOENT, ENOSYS, ENOTDIR, ENXIO, ESPIPE, - O_CREAT, O_DIRECTORY, O_STAT, O_RDWR, O_RDONLY, O_WRONLY, - MODE_CHR, MODE_DIR, MODE_FILE, - SEEK_CUR, SEEK_END, SEEK_SET, - Stat, - Error, Result + Error, Result, Stat, EACCES, EBADF, EBADMSG, EEXIST, EINVAL, EIO, EISDIR, ENOENT, ENOSYS, + ENOTDIR, ENXIO, ESPIPE, MODE_CHR, MODE_DIR, MODE_FILE, O_CREAT, O_DIRECTORY, O_RDONLY, O_RDWR, + O_STAT, O_WRONLY, SEEK_CUR, SEEK_END, SEEK_SET, }; -use super::{Device, EndpointState, Xhci}; use super::{port, usb}; +use super::{Device, EndpointState, Xhci}; use super::command::CommandRing; -use super::context::{ENDPOINT_CONTEXT_STATUS_MASK, InputContext, SlotState, StreamContextArray, StreamContext}; +use super::context::{ + InputContext, SlotState, StreamContext, StreamContextArray, ENDPOINT_CONTEXT_STATUS_MASK, +}; use super::doorbell::Doorbell; use super::operational::OperationalRegs; use super::ring::Ring; use super::runtime::RuntimeRegs; use super::trb::{TransferKind, TrbCompletionCode, TrbType}; -use super::usb::endpoint::{ENDP_ATTR_TY_MASK, EndpointTy}; +use super::usb::endpoint::{EndpointTy, ENDP_ATTR_TY_MASK}; + +use crate::driver_interface::*; /// Subdirs of an endpoint pub enum EndpointHandleTy { /// portX/endpoints/Y/transfer. Write calls transfer data to the device, and read calls /// transfer data from the device. - Transfer, + Transfer, /// portX/endpoints/Y/status Status(usize), // offset @@ -42,104 +43,19 @@ pub enum EndpointHandleTy { } pub enum Handle { - TopLevel(usize, Vec), // offset, contents (ports) - Port(usize, usize, Vec), // port, offset, contents - PortDesc(usize, usize, Vec), // port, offset, contents - PortState(usize, usize), // port, offset - PortReq(usize), // port - Endpoints(usize, usize, Vec), // port, offset, contents + TopLevel(usize, Vec), // offset, contents (ports) + Port(usize, usize, Vec), // port, offset, contents + PortDesc(usize, usize, Vec), // port, offset, contents + PortState(usize, usize), // port, offset + PortReq(usize), // port + Endpoints(usize, usize, Vec), // port, offset, contents Endpoint(usize, u8, EndpointHandleTy), // port, endpoint, offset, state - ConfigureEndpoints(usize), // port + ConfigureEndpoints(usize), // port } -#[derive(Serialize)] -struct PortDesc(DevDesc); - -// TODO: Even though these descriptors are originally intended for JSON, they should suffice... for +// TODO: Even though the driver interface descriptors are originally intended for JSON, they should suffice... for // now. -#[derive(Clone, Debug, Serialize)] -pub(crate) struct DevDesc { - pub(crate) kind: u8, - pub(crate) usb: u16, - pub(crate) class: u8, - pub(crate) sub_class: u8, - pub(crate) protocol: u8, - pub(crate) packet_size: u8, - pub(crate) vendor: u16, - pub(crate) product: u16, - pub(crate) release: u16, - pub(crate) manufacturer_str: Option, - pub(crate) product_str: Option, - pub(crate) serial_str: Option, - pub(crate) config_descs: SmallVec<[ConfDesc; 1]>, -} - -#[derive(Clone, Debug, Serialize)] -pub(crate) struct ConfDesc { - pub(crate) kind: u8, - pub(crate) configuration_value: u8, - pub(crate) configuration: Option, - pub(crate) attributes: u8, - pub(crate) max_power: u8, - pub(crate) interface_descs: SmallVec<[IfDesc; 1]>, -} - -#[derive(Clone, Copy, Debug, Serialize)] -pub(crate) struct EndpDesc { - pub(crate) kind: u8, - pub(crate) address: u8, - pub(crate) attributes: u8, - pub(crate) max_packet_size: u16, - pub(crate) interval: u8, - pub(crate) ssc: Option, -} - -enum EndpDirection { - Out, - In, - Bidirectional, -} - -impl EndpDesc { - fn ty(self) -> EndpointTy { - match self.attributes & ENDP_ATTR_TY_MASK { - 0 => EndpointTy::Ctrl, - 1 => EndpointTy::Interrupt, - 2 => EndpointTy::Bulk, - 3 => EndpointTy::Isoch, - _ => unreachable!(), - } - } - fn is_control(&self) -> bool { - self.ty() == EndpointTy::Ctrl - } - fn is_interrupt(&self) -> bool { - self.ty() == EndpointTy::Interrupt - } - fn is_bulk(&self) -> bool { - self.ty() == EndpointTy::Bulk - } - fn is_isoch(&self) -> bool { - self.ty() == EndpointTy::Isoch - } - fn direction(&self) -> EndpDirection { - if self.is_control() { return EndpDirection::Bidirectional } - if self.address & 0x80 != 0 { EndpDirection::In } else { EndpDirection::Out } - } - fn xhci_ep_type(&self) -> Result { - Ok(match self.direction() { - EndpDirection::Out if self.is_isoch() => 1, - EndpDirection::Out if self.is_bulk() => 2, - EndpDirection::Out if self.is_interrupt() => 3, - EndpDirection::Bidirectional if self.is_control() => 4, - EndpDirection::In if self.is_isoch() => 5, - EndpDirection::In if self.is_bulk() => 6, - EndpDirection::In if self.is_interrupt() => 7, - _ => return Err(Error::new(EINVAL)), - }) - } -} impl From for EndpDesc { fn from(d: usb::EndpointDescriptor) -> Self { Self { @@ -152,53 +68,6 @@ impl From for EndpDesc { } } } -#[derive(Clone, Debug, Serialize)] -pub(crate) struct IfDesc { - pub(crate) kind: u8, - pub(crate) number: u8, - pub(crate) alternate_setting: u8, - pub(crate) class: u8, - pub(crate) sub_class: u8, - pub(crate) protocol: u8, - pub(crate) interface_str: Option, - pub(crate) endpoints: SmallVec<[EndpDesc; 4]>, - pub(crate) hid_descs: SmallVec<[HidDesc; 1]>, -} -impl IfDesc { - fn new(dev: &mut Device, desc: usb::InterfaceDescriptor, endps: impl IntoIterator, hid_descs: impl IntoIterator) -> Result { - Ok(Self { - alternate_setting: desc.alternate_setting, - class: desc.class, - interface_str: if desc.interface_str > 0 { Some(dev.get_string(desc.interface_str)?) } else { None }, - kind: desc.kind, - number: desc.number, - protocol: desc.protocol, - sub_class: desc.sub_class, - endpoints: endps.into_iter().collect(), - hid_descs: hid_descs.into_iter().collect(), - }) - } -} - -#[derive(Clone, Copy, Debug, Serialize)] -pub(crate) struct SuperSpeedCmp { - pub(crate) kind: u8, - pub(crate) max_burst: u8, - pub(crate) attributes: u8, - pub(crate) bytes_per_interval: u16, -} - -#[derive(Clone, Copy, Debug, Serialize)] -pub(crate) struct HidDesc { - pub(crate) kind: u8, - pub(crate) hid_spec_release: u16, - pub(crate) country: u8, - pub(crate) desc_count: u8, - pub(crate) desc_ty: u8, - pub(crate) desc_len: u16, - pub(crate) optional_desc_ty: u8, - pub(crate) optional_desc_len: u16, -} impl From for HidDesc { fn from(d: usb::HidDescriptor) -> Self { @@ -225,10 +94,34 @@ impl From for SuperSpeedCmp { } } } +impl IfDesc { + fn new( + dev: &mut Device, + desc: usb::InterfaceDescriptor, + endps: impl IntoIterator, + hid_descs: impl IntoIterator, + ) -> Result { + Ok(Self { + alternate_setting: desc.alternate_setting, + class: desc.class, + interface_str: if desc.interface_str > 0 { + Some(dev.get_string(desc.interface_str)?) + } else { + None + }, + kind: desc.kind, + number: desc.number, + protocol: desc.protocol, + sub_class: desc.sub_class, + endpoints: endps.into_iter().collect(), + hid_descs: hid_descs.into_iter().collect(), + }) + } +} /// Any descriptor that can be stored in the config desc "data" area. #[derive(Debug)] -enum AnyDescriptor { +pub enum AnyDescriptor { // These are the ones that I have found, but there are more. Device(usb::DeviceDescriptor), Config(usb::ConfigDescriptor), @@ -240,46 +133,51 @@ enum AnyDescriptor { impl AnyDescriptor { fn parse(bytes: &[u8]) -> Option<(Self, usize)> { - if bytes.len() < 2 { return None } + if bytes.len() < 2 { + return None; + } let len = bytes[0]; let kind = bytes[1]; - if bytes.len() < len.into() { return None } + if bytes.len() < len.into() { + return None; + } - Some((match kind { - 1 => Self::Device(*plain::from_bytes(bytes).ok()?), - 2 => Self::Config(*plain::from_bytes(bytes).ok()?), - 4 => Self::Interface(*plain::from_bytes(bytes).ok()?), - 5 => Self::Endpoint(*plain::from_bytes(bytes).ok()?), - 33 => Self::Hid(*plain::from_bytes(bytes).ok()?), - 48 => Self::SuperSpeedCompanion(*plain::from_bytes(bytes).ok()?), - _ => { - //panic!("Descriptor unknown {}: bytes {:#0x?}", kind, bytes); - return None; - } - }, len.into())) + Some(( + match kind { + 1 => Self::Device(*plain::from_bytes(bytes).ok()?), + 2 => Self::Config(*plain::from_bytes(bytes).ok()?), + 4 => Self::Interface(*plain::from_bytes(bytes).ok()?), + 5 => Self::Endpoint(*plain::from_bytes(bytes).ok()?), + 33 => Self::Hid(*plain::from_bytes(bytes).ok()?), + 48 => Self::SuperSpeedCompanion(*plain::from_bytes(bytes).ok()?), + _ => { + //panic!("Descriptor unknown {}: bytes {:#0x?}", kind, bytes); + return None; + } + }, + len.into(), + )) } } -#[derive(Deserialize)] -struct ConfigureEndpointsJson { - /// Index into the configuration descriptors of the device descriptor. - config_desc: usize, - - // TODO: Support multiple interfaces as well. -} - impl Xhci { fn set_configuration(&mut self, port: usize, config: u16) -> Result<()> { let ps = self.port_states.get_mut(&port).ok_or(Error::new(EIO))?; - let ring = ps.endpoint_states.get_mut(&0).ok_or(Error::new(EIO))?.ring().ok_or(Error::new(EIO))?; + let ring = ps + .endpoint_states + .get_mut(&0) + .ok_or(Error::new(EIO))? + .ring() + .ok_or(Error::new(EIO))?; { let (cmd, cycle) = ring.next(); cmd.setup( usb::Setup::set_configuration(config), - TransferKind::NoData, cycle, + TransferKind::NoData, + cycle, ); } { @@ -297,10 +195,18 @@ impl Xhci { let control = event.control.read(); if (status >> 24) != TrbCompletionCode::Success as u32 { - println!("SET_CONFIGURATION ERROR, COMPLETION CODE {:#0x}", (status >> 24)); + println!( + "SET_CONFIGURATION ERROR, COMPLETION CODE {:#0x}", + (status >> 24) + ); } - println!("SET_CONFIGURATION EVENT {:#0x} {:#0x} {:#0x}", event.data.read(), status, control); + println!( + "SET_CONFIGURATION EVENT {:#0x} {:#0x} {:#0x}", + event.data.read(), + status, + control + ); } self.run.ints[0].erdp.write(self.cmd.erdp()); @@ -309,8 +215,8 @@ impl Xhci { } fn configure_endpoints(&mut self, port: usize, json_buf: &[u8]) -> Result<()> { - - let req: ConfigureEndpointsJson = serde_json::from_slice(json_buf).or(Err(Error::new(EBADMSG)))?; + let req: ConfigureEndpointsReq = + serde_json::from_slice(json_buf).or(Err(Error::new(EBADMSG)))?; let port_state = self.port_states.get_mut(&port).ok_or(Error::new(ENOENT))?; let input_context: &mut Dma = &mut port_state.input_context; @@ -323,9 +229,11 @@ impl Xhci { const CONTEXT_ENTRIES_SHIFT: u8 = 27; let current_slot_a = input_context.device.slot.a.read(); - let current_context_entries = ((current_slot_a & CONTEXT_ENTRIES_MASK) >> CONTEXT_ENTRIES_SHIFT) as u8; + let current_context_entries = + ((current_slot_a & CONTEXT_ENTRIES_MASK) >> CONTEXT_ENTRIES_SHIFT) as u8; - let endpoints = &port_state.dev_desc.config_descs[req.config_desc].interface_descs[0].endpoints; + let endpoints = + &port_state.dev_desc.config_descs[req.config_desc].interface_descs[0].endpoints; if endpoints.len() >= 31 { return Err(Error::new(EIO)); @@ -333,7 +241,11 @@ impl Xhci { let new_context_entries = 1 + endpoints.len() as u32; - input_context.device.slot.a.write((current_slot_a & !CONTEXT_ENTRIES_MASK) | ((u32::from(new_context_entries) << CONTEXT_ENTRIES_SHIFT) & CONTEXT_ENTRIES_MASK)); + input_context.device.slot.a.write( + (current_slot_a & !CONTEXT_ENTRIES_MASK) + | ((u32::from(new_context_entries) << CONTEXT_ENTRIES_SHIFT) + & CONTEXT_ENTRIES_MASK), + ); let lec = self.cap.lec(); @@ -342,18 +254,33 @@ impl Xhci { input_context.add_context.writef(1 << (endp_num + 1), true); - let endp_ctx = input_context.device.endpoints.get_mut(endp_num as usize).ok_or(Error::new(EIO))?; + let endp_ctx = input_context + .device + .endpoints + .get_mut(endp_num as usize) + .ok_or(Error::new(EIO))?; let endp_desc = endpoints.get(index as usize).ok_or(Error::new(EIO))?; let superspeed_companion = endp_desc.ssc; - // TODO: Check if streams are actually supported. - let max_streams = superspeed_companion.map(|ssc| if endp_desc.is_bulk() { 1 << (ssc.attributes & 0x1F) } else { 0 }).unwrap_or(0); + let max_streams = superspeed_companion + .map(|ssc| { + if endp_desc.is_bulk() { + 1 << (ssc.attributes & 0x1F) + } else { + 0 + } + }) + .unwrap_or(0); let max_psa_size = self.cap.max_psa_size(); // TODO: Secondary streams. - let primary_streams = if max_streams != 0 { cmp::min(max_streams, max_psa_size) } else { 0 }; + let primary_streams = if max_streams != 0 { + cmp::min(max_streams, max_psa_size) + } else { + 0 + }; let linear_stream_array = if primary_streams != 0 { true } else { false }; // TODO: Interval related fields @@ -376,7 +303,7 @@ impl Xhci { } else { 0 }; - + let interval = endp_desc.interval; let max_error_count = 3; let ep_ty = endp_desc.xhci_ep_type()?; @@ -387,8 +314,8 @@ impl Xhci { // for control, 1KiB for interrupt and 3KiB for bulk and isoch. let avg_trb_len: u16 = match endp_desc.ty() { EndpointTy::Ctrl => return Err(Error::new(EIO)), // only endpoint zero is of type control, and is configured separately with the address device command. - EndpointTy::Bulk | EndpointTy::Isoch => 3072, // 3 KiB - EndpointTy::Interrupt => 1024, // 1 KiB + EndpointTy::Bulk | EndpointTy::Isoch => 3072, // 3 KiB + EndpointTy::Interrupt => 1024, // 1 KiB }; assert_eq!(ep_ty & 0x7, ep_ty); @@ -401,26 +328,51 @@ impl Xhci { let array = StreamContextArray::new(1 << (max_streams + 1))?; let array_ptr = array.register(); - assert_eq!(array_ptr & 0xFFFF_FFFF_FFFF_FF81, array_ptr, "stream ctx ptr not aligned to 16 bytes"); + assert_eq!( + array_ptr & 0xFFFF_FFFF_FFFF_FF81, + array_ptr, + "stream ctx ptr not aligned to 16 bytes" + ); - port_state.endpoint_states.insert(endp_num, EndpointState::Ready(super::RingOrStreams::Streams(array))); + port_state.endpoint_states.insert( + endp_num, + EndpointState::Ready(super::RingOrStreams::Streams(array)), + ); array_ptr } else { let ring = Ring::new(true)?; let ring_ptr = ring.register(); - assert_eq!(ring_ptr & 0xFFFF_FFFF_FFFF_FF81, ring_ptr, "ring pointer not aligned to 16 bytes"); + assert_eq!( + ring_ptr & 0xFFFF_FFFF_FFFF_FF81, + ring_ptr, + "ring pointer not aligned to 16 bytes" + ); - port_state.endpoint_states.insert(endp_num, EndpointState::Ready(super::RingOrStreams::Ring(ring))); + port_state.endpoint_states.insert( + endp_num, + EndpointState::Ready(super::RingOrStreams::Ring(ring)), + ); ring_ptr }; assert_eq!(primary_streams & 0x1F, primary_streams); - endp_ctx.a.write(u32::from(mult) << 8 | u32::from(interval) << 16 | u32::from(primary_streams) << 10 | u32::from(linear_stream_array) << 15); - endp_ctx.b.write(max_error_count << 1 | u32::from(ep_ty) << 3 | u32::from(host_initiate_disable) << 7 | u32::from(max_burst_size) << 8 | u32::from(max_packet_size) << 16); + endp_ctx.a.write( + u32::from(mult) << 8 + | u32::from(interval) << 16 + | u32::from(primary_streams) << 10 + | u32::from(linear_stream_array) << 15, + ); + endp_ctx.b.write( + max_error_count << 1 + | u32::from(ep_ty) << 3 + | u32::from(host_initiate_disable) << 7 + | u32::from(max_burst_size) << 8 + | u32::from(max_packet_size) << 16, + ); endp_ctx.trl.write(ring_ptr as u32); endp_ctx.trh.write((ring_ptr >> 32) as u32); endp_ctx.c.write(u32::from(avg_trb_len)); @@ -429,7 +381,7 @@ impl Xhci { input_context.dump_control(); self.run.ints[0].erdp.write(self.cmd.erdp()); - + { let (cmd, cycle, event) = self.cmd.next(); cmd.configure_endpoint(port_state.slot, input_context.physical(), cycle); @@ -440,7 +392,9 @@ impl Xhci { println!(" - Waiting for event"); } - if event.completion_code() != TrbCompletionCode::Success as u8 || event.trb_type() != TrbType::CommandCompletion as u8 { + if event.completion_code() != TrbCompletionCode::Success as u8 + || event.trb_type() != TrbType::CommandCompletion as u8 + { println!("CONFIGURE_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)); } @@ -451,7 +405,12 @@ impl Xhci { // Tell the device about this configuration. - let configuration_value = port_state.dev_desc.config_descs.get(req.config_desc).ok_or(Error::new(EIO))?.configuration_value; + let configuration_value = port_state + .dev_desc + .config_descs + .get(req.config_desc) + .ok_or(Error::new(EIO))? + .configuration_value; self.set_configuration(port, configuration_value.into())?; Ok(()) @@ -463,10 +422,33 @@ impl Xhci { Err(Error::new(ENOSYS)) } pub(crate) fn get_dev_desc(&mut self, port_id: usize) -> Result { - let st = self.port_states.get_mut(&port_id).ok_or(Error::new(ENOENT))?; - Self::get_dev_desc_raw(&mut self.ports, &mut self.run, &mut self.cmd, &mut self.dbs, port_id, st.slot, st.endpoint_states.get_mut(&0).ok_or(Error::new(EIO))?.ring().ok_or(Error::new(EIO))?) + let st = self + .port_states + .get_mut(&port_id) + .ok_or(Error::new(ENOENT))?; + Self::get_dev_desc_raw( + &mut self.ports, + &mut self.run, + &mut self.cmd, + &mut self.dbs, + port_id, + st.slot, + st.endpoint_states + .get_mut(&0) + .ok_or(Error::new(EIO))? + .ring() + .ok_or(Error::new(EIO))?, + ) } - pub(crate) fn get_dev_desc_raw(ports: &mut [port::Port], run: &mut RuntimeRegs, cmd: &mut CommandRing, dbs: &mut [Doorbell], port_id: usize, slot: u8, ring: &mut Ring) -> Result { + pub(crate) fn get_dev_desc_raw( + ports: &mut [port::Port], + run: &mut RuntimeRegs, + cmd: &mut CommandRing, + dbs: &mut [Doorbell], + port_id: usize, + slot: u8, + ring: &mut Ring, + ) -> Result { let port = ports.get(port_id).ok_or(Error::new(ENOENT))?; if !port.flags().contains(port::PortFlags::PORT_CCS) { return Err(Error::new(ENOENT)); @@ -488,77 +470,90 @@ impl Xhci { let (manufacturer_str, product_str, serial_str) = ( if raw_dd.manufacturer_str > 0 { Some(dev.get_string(raw_dd.manufacturer_str)?) - } else { None }, + } else { + None + }, if raw_dd.product_str > 0 { Some(dev.get_string(raw_dd.product_str)?) - } else { None }, + } else { + None + }, if raw_dd.serial_str > 0 { Some(dev.get_string(raw_dd.serial_str)?) - } else { None }, + } else { + None + }, ); let (bos_desc, bos_data) = dev.get_bos()?; - let has_superspeed = usb::bos_capability_descs(bos_desc, &bos_data).any(|desc| desc.is_superspeed()); + let has_superspeed = + usb::bos_capability_descs(bos_desc, &bos_data).any(|desc| desc.is_superspeed()); - let config_descs = (0..raw_dd.configurations).map(|index| -> Result<_> { - let (desc, data) = dev.get_config(index)?; + let config_descs = (0..raw_dd.configurations) + .map(|index| -> Result<_> { + let (desc, data) = dev.get_config(index)?; - let extra_length = desc.total_length as usize - mem::size_of_val(&desc); - let data = &data[..extra_length]; + let extra_length = desc.total_length as usize - mem::size_of_val(&desc); + let data = &data[..extra_length]; - let mut i = 0; - let mut descriptors = Vec::new(); + let mut i = 0; + let mut descriptors = Vec::new(); - while let Some((descriptor, len)) = AnyDescriptor::parse(&data[i..]) { - descriptors.push(descriptor); - i += len; - } + while let Some((descriptor, len)) = AnyDescriptor::parse(&data[i..]) { + descriptors.push(descriptor); + i += len; + } - let mut interface_descs = SmallVec::new(); - let mut iter = descriptors.into_iter(); + let mut interface_descs = SmallVec::new(); + let mut iter = descriptors.into_iter(); - while let Some(item) = iter.next() { - if let AnyDescriptor::Interface(idesc) = item { - let mut endpoints = SmallVec::<[EndpDesc; 4]>::new(); - let mut hid_descs = SmallVec::<[HidDesc; 1]>::new(); + while let Some(item) = iter.next() { + if let AnyDescriptor::Interface(idesc) = item { + let mut endpoints = SmallVec::<[EndpDesc; 4]>::new(); + let mut hid_descs = SmallVec::<[HidDesc; 1]>::new(); - for _ in 0..idesc.endpoints { - let next = match iter.next() { - Some(AnyDescriptor::Endpoint(n)) => n, - Some(AnyDescriptor::Hid(h)) if idesc.class == 3 => { - hid_descs.push(h.into()); - break; - } - _ => break, - }; - let mut endp = EndpDesc::from(next); - - if has_superspeed { + for _ in 0..idesc.endpoints { let next = match iter.next() { - Some(AnyDescriptor::SuperSpeedCompanion(n)) => n, + Some(AnyDescriptor::Endpoint(n)) => n, + Some(AnyDescriptor::Hid(h)) if idesc.class == 3 => { + hid_descs.push(h.into()); + break; + } _ => break, }; - endp.ssc = Some(SuperSpeedCmp::from(next)); + let mut endp = EndpDesc::from(next); + + if has_superspeed { + let next = match iter.next() { + Some(AnyDescriptor::SuperSpeedCompanion(n)) => n, + _ => break, + }; + endp.ssc = Some(SuperSpeedCmp::from(next)); + } + endpoints.push(endp); } - endpoints.push(endp); + + interface_descs.push(IfDesc::new(&mut dev, idesc, endpoints, hid_descs)?); + } else { + // TODO + break; } - - interface_descs.push(IfDesc::new(&mut dev, idesc, endpoints, hid_descs)?); - } else { - // TODO - break; } - } - Ok(ConfDesc { - kind: desc.kind, - configuration: if desc.configuration_str > 0 { Some(dev.get_string(desc.configuration_str)?) } else { None }, - configuration_value: desc.configuration_value, - attributes: desc.attributes, - max_power: desc.max_power, - interface_descs, + Ok(ConfDesc { + kind: desc.kind, + configuration: if desc.configuration_str > 0 { + Some(dev.get_string(desc.configuration_str)?) + } else { + None + }, + configuration_value: desc.configuration_value, + attributes: desc.attributes, + max_power: desc.max_power, + interface_descs, + }) }) - }).collect::>>()?; + .collect::>>()?; Ok(DevDesc { kind: raw_dd.kind, @@ -577,7 +572,11 @@ impl Xhci { }) } fn write_port_desc(&mut self, port_id: usize, contents: &mut Vec) -> Result<()> { - let dev_desc = &self.port_states.get(&port_id).ok_or(Error::new(ENOENT))?.dev_desc; + let dev_desc = &self + .port_states + .get(&port_id) + .ok_or(Error::new(ENOENT))? + .dev_desc; serde_json::to_writer_pretty(contents, dev_desc).unwrap(); Ok(()) } @@ -631,15 +630,24 @@ impl Xhci { } as u8; let setup = Setup { - kind: (direction << USB_SETUP_DIR_SHIFT) | (ty << USB_SETUP_REQ_TY_SHIFT) | (recipient << USB_SETUP_RECIPIENT_SHIFT), + kind: (direction << USB_SETUP_DIR_SHIFT) + | (ty << USB_SETUP_REQ_TY_SHIFT) + | (recipient << USB_SETUP_RECIPIENT_SHIFT), request: req.request, value: req.value, index: req.index, length: req.length, }; - let port_state = self.port_states.get_mut(&port_num).ok_or(Error::new(EBADF))?; - let ring = match port_state.endpoint_states.get_mut(&0).ok_or(Error::new(EIO))? { + let port_state = self + .port_states + .get_mut(&port_num) + .ok_or(Error::new(EBADF))?; + let ring = match port_state + .endpoint_states + .get_mut(&0) + .ok_or(Error::new(EIO))? + { EndpointState::Ready(super::RingOrStreams::Ring(ref mut ring)) => ring, // Control endpoints never use streams @@ -675,28 +683,43 @@ impl Xhci { impl SchemeMut for Xhci { fn open(&mut self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - if uid != 0 { return Err(Error::new(EACCES)) } + if uid != 0 { + return Err(Error::new(EACCES)); + } - let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?.trim_start_matches('/'); + let path_str = str::from_utf8(path) + .or(Err(Error::new(ENOENT)))? + .trim_start_matches('/'); - let components = path::Path::new(path_str).components().map(|component| -> Option<_> { - match component { - path::Component::Normal(n) => Some(n.to_str()?), - _ => None, - } - }).collect::>>().ok_or(Error::new(ENOENT))?; + let components = path::Path::new(path_str) + .components() + .map(|component| -> Option<_> { + match component { + path::Component::Normal(n) => Some(n.to_str()?), + _ => None, + } + }) + .collect::>>() + .ok_or(Error::new(ENOENT))?; let handle = match &components[..] { - &[] => if flags & O_DIRECTORY != 0 || flags & O_STAT != 0 { - let mut contents = Vec::new(); + &[] => { + if flags & O_DIRECTORY != 0 || flags & O_STAT != 0 { + let mut contents = Vec::new(); - for (index, _) in self.ports.iter().enumerate().filter(|(_, port)| port.flags().contains(port::PortFlags::PORT_CCS)) { - write!(contents, "port{}\n", index).unwrap(); + for (index, _) in self + .ports + .iter() + .enumerate() + .filter(|(_, port)| port.flags().contains(port::PortFlags::PORT_CCS)) + { + write!(contents, "port{}\n", index).unwrap(); + } + + Handle::TopLevel(0, contents) + } else { + return Err(Error::new(EISDIR)); } - - Handle::TopLevel(0, contents) - } else { - return Err(Error::new(EISDIR)); } &[port, port_tl] if port.starts_with("port") => { let port_num = port[4..].parse::().or(Err(Error::new(ENOENT)))?; @@ -760,7 +783,6 @@ impl SchemeMut for Xhci { } _ => return Err(Error::new(ENOENT)), } - } &[port, "endpoints", endpoint_num_str] if port.starts_with("port") => { let port_num = port[4..].parse::().or(Err(Error::new(ENOENT)))?; @@ -770,15 +792,24 @@ impl SchemeMut for Xhci { return Err(Error::new(EISDIR)); } - let port_state = self.port_states.get_mut(&port_num).ok_or(Error::new(ENOENT))?; + let port_state = self + .port_states + .get_mut(&port_num) + .ok_or(Error::new(ENOENT))?; /*if self.dev_ctx.contexts[port_state.slot as usize].endpoints.get(endpoint_num as usize).ok_or(Error::new(ENOENT))?.a.read() & 0b111 != 1 { return Err(Error::new(ENXIO)); // TODO: Find a proper error code for "endpoint not initialized". }*/ - let contents = match port_state.endpoint_states.get(&endpoint_num).ok_or(Error::new(ENOENT))? { + let contents = match port_state + .endpoint_states + .get(&endpoint_num) + .ok_or(Error::new(ENOENT))? + { EndpointState::Init => "status\n", EndpointState::Ready { .. } => "transfer\nstatus\n", - }.as_bytes().to_owned(); + } + .as_bytes() + .to_owned(); Handle::Endpoint(port_num, endpoint_num, EndpointHandleTy::Root(0, contents)) } @@ -786,9 +817,18 @@ impl SchemeMut for Xhci { let port_num = port[4..].parse::().or(Err(Error::new(ENOENT)))?; let endpoint_num = endpoint_num_str.parse::().or(Err(Error::new(ENOENT)))?; - if flags & O_DIRECTORY != 0 && flags & O_STAT == 0 { return Err(Error::new(EISDIR)) } + if flags & O_DIRECTORY != 0 && flags & O_STAT == 0 { + return Err(Error::new(EISDIR)); + } - if self.port_states.get(&port_num).ok_or(Error::new(ENOENT))?.endpoint_states.get(&endpoint_num).is_none() { + if self + .port_states + .get(&port_num) + .ok_or(Error::new(ENOENT))? + .endpoint_states + .get(&endpoint_num) + .is_none() + { return Err(Error::new(ENOENT)); } @@ -805,19 +845,27 @@ impl SchemeMut for Xhci { }; Handle::Endpoint(port_num, endpoint_num, st) } - &[port] if port.starts_with("port") => if flags & O_DIRECTORY != 0 || flags & O_STAT != 0 { - let port_num = port[4..].parse::().or(Err(Error::new(ENOENT)))?; - let mut contents = Vec::new(); + &[port] if port.starts_with("port") => { + if flags & O_DIRECTORY != 0 || flags & O_STAT != 0 { + let port_num = port[4..].parse::().or(Err(Error::new(ENOENT)))?; + let mut contents = Vec::new(); - write!(contents, "descriptors\nendpoints\n").unwrap(); - - if dbg!(self.slot_state(self.port_states.get(&port_num).ok_or(Error::new(ENOENT))?.slot as usize)) != SlotState::Configured as u8 { - write!(contents, "configure\n").unwrap(); + write!(contents, "descriptors\nendpoints\n").unwrap(); + + if dbg!(self.slot_state( + self.port_states + .get(&port_num) + .ok_or(Error::new(ENOENT))? + .slot as usize + )) != SlotState::Configured as u8 + { + write!(contents, "configure\n").unwrap(); + } + + Handle::Port(port_num, 0, contents) + } else { + return Err(Error::new(EISDIR)); } - - Handle::Port(port_num, 0, contents) - } else { - return Err(Error::new(EISDIR)); } _ => return Err(Error::new(ENOENT)), }; @@ -831,7 +879,9 @@ impl SchemeMut for Xhci { fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result { match self.handles.get(&id).ok_or(Error::new(EBADF))? { - Handle::TopLevel(_, ref buf) | Handle::Port(_, _, ref buf) | Handle::Endpoints(_, _, ref buf) => { + Handle::TopLevel(_, ref buf) + | Handle::Port(_, _, ref buf) + | Handle::Endpoints(_, _, ref buf) => { stat.st_mode = MODE_DIR; stat.st_size = buf.len() as u64; } @@ -846,7 +896,7 @@ impl SchemeMut for Xhci { stat.st_mode = MODE_DIR; stat.st_size = buf.len() as u64; } - } + }, Handle::ConfigureEndpoints(_) | Handle::PortReq(_) => { stat.st_mode = MODE_CHR | 0o200; // write only } @@ -860,16 +910,29 @@ impl SchemeMut for Xhci { match self.handles.get(&fd).ok_or(Error::new(EBADF))? { Handle::TopLevel(_, _) => write!(src, "/").unwrap(), Handle::Port(port_num, _, _) => write!(src, "/port{}/", port_num).unwrap(), - Handle::PortDesc(port_num, _, _) => write!(src, "/port{}/descriptors", port_num).unwrap(), + Handle::PortDesc(port_num, _, _) => { + write!(src, "/port{}/descriptors", port_num).unwrap() + } Handle::PortState(port_num, _) => write!(src, "/port{}/state", port_num).unwrap(), Handle::PortReq(port_num) => write!(src, "/port{}/request", port_num).unwrap(), - Handle::Endpoints(port_num, _, _) => write!(src, "/port{}/endpoints/", port_num).unwrap(), - Handle::Endpoint(port_num, endp_num, st) => write!(src, "/port{}/endpoints/{}/{}", port_num, endp_num, match st { - EndpointHandleTy::Root(_, _) => "", - EndpointHandleTy::Status(_) => "status", - EndpointHandleTy::Transfer => "transfer", - }).unwrap(), - Handle::ConfigureEndpoints(port_num) => write!(src, "/port{}/configure", port_num).unwrap(), + Handle::Endpoints(port_num, _, _) => { + write!(src, "/port{}/endpoints/", port_num).unwrap() + } + Handle::Endpoint(port_num, endp_num, st) => write!( + src, + "/port{}/endpoints/{}/{}", + port_num, + endp_num, + match st { + EndpointHandleTy::Root(_, _) => "", + EndpointHandleTy::Status(_) => "status", + EndpointHandleTy::Transfer => "transfer", + } + ) + .unwrap(), + Handle::ConfigureEndpoints(port_num) => { + write!(src, "/port{}/configure", port_num).unwrap() + } } let bytes_to_read = cmp::min(src.len(), buffer.len()); buffer[..bytes_to_read].copy_from_slice(&src[..bytes_to_read]); @@ -879,7 +942,11 @@ impl SchemeMut for Xhci { fn seek(&mut self, fd: usize, pos: usize, whence: usize) -> Result { match self.handles.get_mut(&fd).ok_or(Error::new(EBADF))? { // Directories, or fixed files - Handle::TopLevel(ref mut offset, ref buf) | Handle::Port(_, ref mut offset, ref buf) | Handle::PortDesc(_, ref mut offset, ref buf) | Handle::Endpoints(_, ref mut offset, ref buf) | Handle::Endpoint(_, _, EndpointHandleTy::Root(ref mut offset, ref buf)) => { + Handle::TopLevel(ref mut offset, ref buf) + | Handle::Port(_, ref mut offset, ref buf) + | Handle::PortDesc(_, ref mut offset, ref buf) + | Handle::Endpoints(_, ref mut offset, ref buf) + | Handle::Endpoint(_, _, EndpointHandleTy::Root(ref mut offset, ref buf)) => { *offset = match whence { SEEK_SET => cmp::max(0, cmp::min(pos, buf.len())), SEEK_CUR => cmp::max(0, cmp::min(*offset + pos, buf.len())), @@ -889,7 +956,8 @@ impl SchemeMut for Xhci { Ok(*offset) } // Read-only unknown-length status strings - Handle::Endpoint(_, _, EndpointHandleTy::Status(ref mut offset)) | Handle::PortState(_, ref mut offset) => { + Handle::Endpoint(_, _, EndpointHandleTy::Status(ref mut offset)) + | Handle::PortState(_, ref mut offset) => { *offset = match whence { SEEK_SET => cmp::max(0, pos), SEEK_CUR => cmp::max(0, *offset + pos), @@ -899,13 +967,19 @@ impl SchemeMut for Xhci { Ok(*offset) } // Write-once configure or transfer - Handle::Endpoint(_, _, _) | Handle::ConfigureEndpoints(_) | Handle::PortReq(_) => return Err(Error::new(ESPIPE)), + Handle::Endpoint(_, _, _) | Handle::ConfigureEndpoints(_) | Handle::PortReq(_) => { + return Err(Error::new(ESPIPE)) + } } } fn read(&mut self, fd: usize, buf: &mut [u8]) -> Result { match self.handles.get_mut(&fd).ok_or(Error::new(EBADF))? { - Handle::TopLevel(ref mut offset, ref src_buf) | Handle::Port(_, ref mut offset, ref src_buf) | Handle::PortDesc(_, ref mut offset, ref src_buf) | Handle::Endpoints(_, ref mut offset, ref src_buf) | Handle::Endpoint(_, _, EndpointHandleTy::Root(ref mut offset, ref src_buf)) => { + Handle::TopLevel(ref mut offset, ref src_buf) + | Handle::Port(_, ref mut offset, ref src_buf) + | Handle::PortDesc(_, ref mut offset, ref src_buf) + | Handle::Endpoints(_, ref mut offset, ref src_buf) + | Handle::Endpoint(_, _, EndpointHandleTy::Root(ref mut offset, ref src_buf)) => { let max_bytes_to_read = cmp::min(src_buf.len(), buf.len()); let bytes_to_read = cmp::max(max_bytes_to_read, *offset) - *offset; @@ -925,7 +999,17 @@ impl SchemeMut for Xhci { } EndpointHandleTy::Status(ref mut offset) => { let ps = self.port_states.get(&port_num).ok_or(Error::new(EBADF))?; - let status = self.dev_ctx.contexts.get(ps.slot as usize).ok_or(Error::new(EBADF))?.endpoints.get(endp_num as usize).ok_or(Error::new(EBADF))?.a.read() & ENDPOINT_CONTEXT_STATUS_MASK; + let status = self + .dev_ctx + .contexts + .get(ps.slot as usize) + .ok_or(Error::new(EBADF))? + .endpoints + .get(endp_num as usize) + .ok_or(Error::new(EBADF))? + .a + .read() + & ENDPOINT_CONTEXT_STATUS_MASK; let string = match status { // TODO: Give this its own enum. @@ -935,7 +1019,8 @@ impl SchemeMut for Xhci { 3 => "stopped", 4 => "error", _ => "unknown", - }.as_bytes(); + } + .as_bytes(); Ok(Self::write_dyn_string(string, buf, offset)) } @@ -943,7 +1028,13 @@ impl SchemeMut for Xhci { }, &mut Handle::PortState(port_num, ref mut offset) => { let ps = self.port_states.get(&port_num).ok_or(Error::new(EBADF))?; - let state = self.dev_ctx.contexts.get(ps.slot as usize).ok_or(Error::new(EBADF))?.slot.state(); + let state = self + .dev_ctx + .contexts + .get(ps.slot as usize) + .ok_or(Error::new(EBADF))? + .slot + .state(); let string = match state { // TODO: Give this its own enum. @@ -952,7 +1043,8 @@ impl SchemeMut for Xhci { 2 => "addressed", 3 => "configured", _ => "unknown", - }.as_bytes(); + } + .as_bytes(); Ok(Self::write_dyn_string(string, buf, offset)) } diff --git a/xhcid/src/xhci/trb.rs b/xhcid/src/xhci/trb.rs index 53cf648a6a..6eb6169b28 100644 --- a/xhcid/src/xhci/trb.rs +++ b/xhcid/src/xhci/trb.rs @@ -1,6 +1,6 @@ +use crate::usb; use std::{fmt, mem}; use syscall::io::{Io, Mmio}; -use crate::usb; #[repr(u8)] pub enum TrbType { @@ -127,12 +127,7 @@ impl Trb { } pub fn reserved(&mut self, cycle: bool) { - self.set( - 0, - 0, - ((TrbType::Reserved as u32) << 10) | - (cycle as u32) - ); + self.set(0, 0, ((TrbType::Reserved as u32) << 10) | (cycle as u32)); } pub fn completion_code(&self) -> u8 { @@ -149,28 +144,21 @@ impl Trb { self.set( address as u64, 0, - ((TrbType::Link as u32) << 10) | - ((toggle as u32) << 1) | - (cycle as u32) + ((TrbType::Link as u32) << 10) | ((toggle as u32) << 1) | (cycle as u32), ); } pub fn no_op_cmd(&mut self, cycle: bool) { - self.set( - 0, - 0, - ((TrbType::NoOpCmd as u32) << 10) | - (cycle as u32) - ); + self.set(0, 0, ((TrbType::NoOpCmd as u32) << 10) | (cycle as u32)); } pub fn enable_slot(&mut self, slot_type: u8, cycle: bool) { self.set( 0, 0, - (((slot_type as u32) & 0x1F) << 16) | - ((TrbType::EnableSlot as u32) << 10) | - (cycle as u32) + (((slot_type as u32) & 0x1F) << 16) + | ((TrbType::EnableSlot as u32) << 10) + | (cycle as u32), ); } @@ -178,21 +166,23 @@ impl Trb { self.set( input as u64, 0, - ((slot_id as u32) << 24) | - ((TrbType::AddressDevice as u32) << 10) | - (cycle as u32) + ((slot_id as u32) << 24) | ((TrbType::AddressDevice as u32) << 10) | (cycle as u32), ); } // Synchronizes the input context endpoints with the device context endpoints, I think. pub fn configure_endpoint(&mut self, slot_id: u8, input_ctx_ptr: usize, cycle: bool) { - assert_eq!(input_ctx_ptr & 0xFFFF_FFFF_FFFF_FF80, input_ctx_ptr, "unaligned input context ptr"); + assert_eq!( + input_ctx_ptr & 0xFFFF_FFFF_FFFF_FF80, + input_ctx_ptr, + "unaligned input context ptr" + ); self.set( input_ctx_ptr as u64, 0, - (u32::from(slot_id) << 24) | - ((TrbType::ConfigureEndpoint as u32) << 10) | - (cycle as u32), + (u32::from(slot_id) << 24) + | ((TrbType::ConfigureEndpoint as u32) << 10) + | (cycle as u32), ) } @@ -200,10 +190,10 @@ impl Trb { self.set( unsafe { mem::transmute(setup) }, 8, - ((transfer as u32) << 16) | - ((TrbType::SetupStage as u32) << 10) | - (1 << 6) | - (cycle as u32) + ((transfer as u32) << 16) + | ((TrbType::SetupStage as u32) << 10) + | (1 << 6) + | (cycle as u32), ); } @@ -211,9 +201,7 @@ impl Trb { self.set( buffer as u64, length as u32, - ((input as u32) << 16) | - ((TrbType::DataStage as u32) << 10) | - (cycle as u32) + ((input as u32) << 16) | ((TrbType::DataStage as u32) << 10) | (cycle as u32), ); } @@ -221,24 +209,34 @@ impl Trb { self.set( 0, 0, - ((input as u32) << 16) | - ((TrbType::StatusStage as u32) << 10) | - (1 << 5) | - (cycle as u32) + ((input as u32) << 16) + | ((TrbType::StatusStage as u32) << 10) + | (1 << 5) + | (cycle as u32), ); } } impl fmt::Debug for Trb { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Trb {{ data: {:>016X}, status: {:>08X}, control: {:>08X} }}", - self.data.read(), self.status.read(), self.control.read()) + write!( + f, + "Trb {{ data: {:>016X}, status: {:>08X}, control: {:>08X} }}", + self.data.read(), + self.status.read(), + self.control.read() + ) } } impl fmt::Display for Trb { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "({:>016X}, {:>08X}, {:>08X})", - self.data.read(), self.status.read(), self.control.read()) + write!( + f, + "({:>016X}, {:>08X}, {:>08X})", + self.data.read(), + self.status.read(), + self.control.read() + ) } }