summary refs log tree commit diff
path: root/devices
diff options
context:
space:
mode:
Diffstat (limited to 'devices')
-rw-r--r--devices/src/usb/host_backend/host_backend_device_provider.rs6
-rw-r--r--devices/src/usb/xhci/command_ring_controller.rs3
-rw-r--r--devices/src/usb/xhci/device_slot.rs55
-rw-r--r--devices/src/usb/xhci/ring_buffer.rs5
4 files changed, 28 insertions, 41 deletions
diff --git a/devices/src/usb/host_backend/host_backend_device_provider.rs b/devices/src/usb/host_backend/host_backend_device_provider.rs
index 8d39d80..01fd84c 100644
--- a/devices/src/usb/host_backend/host_backend_device_provider.rs
+++ b/devices/src/usb/host_backend/host_backend_device_provider.rs
@@ -244,6 +244,12 @@ impl ProviderInner {
                             }
                         }
                     };
+
+                    // Resetting the device is used to make sure it is in a known state, but it may
+                    // still function if the reset fails.
+                    if let Err(e) = device_handle.reset() {
+                        error!("failed to reset device after attach: {:?}", e);
+                    }
                     (device, device_handle)
                 };
 
diff --git a/devices/src/usb/xhci/command_ring_controller.rs b/devices/src/usb/xhci/command_ring_controller.rs
index 83582dd..6c84fc6 100644
--- a/devices/src/usb/xhci/command_ring_controller.rs
+++ b/devices/src/usb/xhci/command_ring_controller.rs
@@ -29,6 +29,7 @@ pub enum Error {
     StopEndpoint(DeviceSlotError),
     ConfigEndpoint(DeviceSlotError),
     SetAddress(DeviceSlotError),
+    SetDequeuePointer(DeviceSlotError),
     EvaluateContext(DeviceSlotError),
     DisableSlot(DeviceSlotError),
     ResetSlot(DeviceSlotError),
@@ -48,6 +49,7 @@ impl Display for Error {
             StopEndpoint(e) => write!(f, "failed to stop endpoint: {}", e),
             ConfigEndpoint(e) => write!(f, "failed to config endpoint: {}", e),
             SetAddress(e) => write!(f, "failed to set address: {}", e),
+            SetDequeuePointer(e) => write!(f, "failed to set dequeue pointer: {}", e),
             EvaluateContext(e) => write!(f, "failed to evaluate context: {}", e),
             DisableSlot(e) => write!(f, "failed to disable slot: {}", e),
             ResetSlot(e) => write!(f, "failed to reset slot: {}", e),
@@ -314,6 +316,7 @@ impl CommandRingTrbHandler {
             if valid_slot_id(slot_id) {
                 self.slot(slot_id)?
                     .set_tr_dequeue_ptr(endpoint_id, dequeue_ptr)
+                    .map_err(Error::SetDequeuePointer)?
             } else {
                 error!("stop endpoint trb has invalid slot id {}", slot_id);
                 TrbCompletionCode::TrbError
diff --git a/devices/src/usb/xhci/device_slot.rs b/devices/src/usb/xhci/device_slot.rs
index ef58edb..d3d556a 100644
--- a/devices/src/usb/xhci/device_slot.rs
+++ b/devices/src/usb/xhci/device_slot.rs
@@ -514,23 +514,6 @@ impl DeviceSlot {
         if !self.enabled.load(Ordering::SeqCst) {
             return Ok(TrbCompletionCode::SlotNotEnabledError);
         }
-
-        let device_context = self.get_device_context()?;
-        let state = device_context
-            .slot_context
-            .state()
-            .map_err(Error::GetSlotContextState)?;
-        if state == DeviceSlotState::Default
-            || state == DeviceSlotState::Addressed
-            || state == DeviceSlotState::Configured
-        {
-            error!(
-                "wrong context state on evaluate context. state = {:?}",
-                state
-            );
-            return Ok(TrbCompletionCode::ContextStateError);
-        }
-
         // TODO(jkwang) verify this
         // The spec has multiple contradictions about validating context parameters in sections
         // 4.6.7, 6.2.3.3. To keep things as simple as possible we do no further validation here.
@@ -581,13 +564,6 @@ impl DeviceSlot {
         slot: &Arc<DeviceSlot>,
         mut callback: C,
     ) -> Result<()> {
-        let state = slot.state()?;
-        if state != DeviceSlotState::Addressed && state != DeviceSlotState::Configured {
-            error!("reset slot failed due to context state error {:?}", state);
-            return callback(TrbCompletionCode::ContextStateError)
-                .map_err(|_| Error::CallbackFailed);
-        }
-
         let weak_s = Arc::downgrade(&slot);
         let auto_callback =
             RingBufferStopCallback::new(fallible_closure(fail_handle, move || -> Result<()> {
@@ -650,20 +626,23 @@ impl DeviceSlot {
     }
 
     /// Set transfer ring dequeue pointer.
-    pub fn set_tr_dequeue_ptr(&self, endpoint_id: u8, ptr: u64) -> TrbCompletionCode {
+    pub fn set_tr_dequeue_ptr(&self, endpoint_id: u8, ptr: u64) -> Result<TrbCompletionCode> {
         if !valid_endpoint_id(endpoint_id) {
             error!("trb indexing wrong endpoint id");
-            return TrbCompletionCode::TrbError;
+            return Ok(TrbCompletionCode::TrbError);
         }
-        let index = endpoint_id - 1;
-        match self.get_trc(index as usize) {
+        let index = (endpoint_id - 1) as usize;
+        match self.get_trc(index) {
             Some(trc) => {
                 trc.set_dequeue_pointer(GuestAddress(ptr));
-                TrbCompletionCode::Success
+                let mut ctx = self.get_device_context()?;
+                ctx.endpoint_context[index].set_tr_dequeue_pointer(ptr >> 4);
+                self.set_device_context(ctx)?;
+                Ok(TrbCompletionCode::Success)
             }
             None => {
                 error!("set tr dequeue ptr failed due to no trc started");
-                TrbCompletionCode::ContextStateError
+                Ok(TrbCompletionCode::ContextStateError)
             }
         }
     }
@@ -718,9 +697,12 @@ impl DeviceSlot {
     }
 
     fn get_device_context(&self) -> Result<DeviceContext> {
-        self.mem
+        let ctx = self
+            .mem
             .read_obj_from_addr(self.get_device_context_addr()?)
-            .map_err(Error::ReadGuestMemory)
+            .map_err(Error::ReadGuestMemory)?;
+        usb_debug!("read device ctx: {:?}", ctx);
+        Ok(ctx)
     }
 
     fn set_device_context(&self, device_context: DeviceContext) -> Result<()> {
@@ -768,15 +750,6 @@ impl DeviceSlot {
         Ok(GuestAddress(addr))
     }
 
-    // Returns the current state of the device slot.
-    fn state(&self) -> Result<DeviceSlotState> {
-        let context = self.get_device_context()?;
-        context
-            .slot_context
-            .state()
-            .map_err(Error::GetSlotContextState)
-    }
-
     fn set_state(&self, state: DeviceSlotState) -> Result<()> {
         let mut ctx = self.get_device_context()?;
         ctx.slot_context.set_state(state);
diff --git a/devices/src/usb/xhci/ring_buffer.rs b/devices/src/usb/xhci/ring_buffer.rs
index 5e2c570..72c9ec0 100644
--- a/devices/src/usb/xhci/ring_buffer.rs
+++ b/devices/src/usb/xhci/ring_buffer.rs
@@ -85,6 +85,11 @@ impl RingBuffer {
                 }
             };
 
+            usb_debug!(
+                "{}: adding trb to td {}",
+                self.name.as_str(),
+                addressed_trb.trb
+            );
             td.push(addressed_trb);
             if !addressed_trb.trb.get_chain_bit().map_err(Error::TrbChain)? {
                 usb_debug!("trb chain is false returning");