diff options
Diffstat (limited to 'devices/src/usb/xhci/xhci.rs')
-rw-r--r-- | devices/src/usb/xhci/xhci.rs | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/devices/src/usb/xhci/xhci.rs b/devices/src/usb/xhci/xhci.rs index 55dd50e..47ebe85 100644 --- a/devices/src/usb/xhci/xhci.rs +++ b/devices/src/usb/xhci/xhci.rs @@ -30,6 +30,7 @@ pub enum Error { StartProvider, RingDoorbell(DeviceSlotError), CreateCommandRingController(CommandRingControllerError), + ResetPort, } type Result<T> = std::result::Result<T, Error>; @@ -52,6 +53,7 @@ impl Display for Error { CreateCommandRingController(e) => { write!(f, "failed to create command ring controller: {}", e) } + ResetPort => write!(f, "failed to reset port"), } } } @@ -267,17 +269,19 @@ impl Xhci { index, value ); + let port_id = (index + 1) as u8; // xHCI spec 4.19.5. Note: we might want to change this logic if we support USB 3.0. if (value & PORTSC_PORT_RESET) > 0 || (value & PORTSC_WARM_PORT_RESET) > 0 { - // Libusb onlys support blocking call to reset and "usually incurs a noticeable - // delay.". We are faking a reset now. + self.device_slots + .reset_port(port_id) + .map_err(|_| Error::ResetPort)?; value &= !PORTSC_PORT_LINK_STATE_MASK; value &= !PORTSC_PORT_RESET; value |= PORTSC_PORT_ENABLED; value |= PORTSC_PORT_RESET_CHANGE; self.interrupter .lock() - .send_port_status_change_trb((index + 1) as u8) + .send_port_status_change_trb(port_id) .map_err(Error::SendInterrupt)?; } Ok(value) |