diff --git a/src/control_pipe.rs b/src/control_pipe.rs index e447b91..fc4c7dd 100644 --- a/src/control_pipe.rs +++ b/src/control_pipe.rs @@ -84,6 +84,10 @@ impl ControlPipe<'_, B> { }, }; + // Now that we have properly parsed the setup packet, ensure the end-point is no longer in + // a stalled state. + self.ep_out.unstall(); + /*sprintln!("SETUP {:?} {:?} {:?} req:{} val:{} idx:{} len:{} {:?}", req.direction, req.request_type, req.recipient, req.request, req.value, req.index, req.length, diff --git a/src/device.rs b/src/device.rs index 6b0bab3..9620cbf 100644 --- a/src/device.rs +++ b/src/device.rs @@ -169,6 +169,23 @@ impl UsbDevice<'_, B> { // Pending events for endpoint 0? if (eps & 1) != 0 { + // Handle EP0-IN conditions first. When both EP0-IN and EP0-OUT have completed, + // it is possible that EP0-OUT is a zero-sized out packet to complete the STATUS + // phase of the control transfer. We have to process EP0-IN first to update our + // internal state properly. + if (ep_in_complete & 1) != 0 { + let completed = self.control.handle_in_complete(); + + if !B::QUIRK_SET_ADDRESS_BEFORE_STATUS { + if completed && self.pending_address != 0 { + self.bus.set_device_address(self.pending_address); + self.pending_address = 0; + + self.device_state = UsbDeviceState::Addressed; + } + } + } + let req = if (ep_setup & 1) != 0 { self.control.handle_setup() } else if (ep_out & 1) != 0 { @@ -185,19 +202,6 @@ impl UsbDevice<'_, B> { _ => (), }; - if (ep_in_complete & 1) != 0 { - let completed = self.control.handle_in_complete(); - - if !B::QUIRK_SET_ADDRESS_BEFORE_STATUS { - if completed && self.pending_address != 0 { - self.bus.set_device_address(self.pending_address); - self.pending_address = 0; - - self.device_state = UsbDeviceState::Addressed; - } - } - } - eps &= !1; }