@@ -101,6 +101,9 @@ where
101101
102102 * state = UsbTaskState :: Running ( Some ( task) , WaitingForNextRequestState :: Idle ) ;
103103 }
104+ // This panic could happen e.g. if someone reconnects to the BitBox while a task is running,
105+ // before the 500ms timeout cancels the task. The proper way to handle would be to let the
106+ // host know we are busy so the host can re-retry after some time.
104107 _ => panic ! ( "spawn: wrong state" ) ,
105108 }
106109}
@@ -149,7 +152,13 @@ pub fn spin() {
149152 _ => None ,
150153 } ;
151154 if let Some ( ref mut task) = popped_task {
152- match spin_task ( task) {
155+ let spin_result = spin_task ( task) ;
156+ if matches ! ( * USB_TASK_STATE . 0 . borrow( ) , UsbTaskState :: Nothing ) {
157+ // The task was cancelled while it was running, so there is nothing to do with the
158+ // result.
159+ return ;
160+ }
161+ match spin_result {
153162 Poll :: Ready ( result) => {
154163 * USB_TASK_STATE . 0 . borrow_mut ( ) = UsbTaskState :: ResultAvailable ( result) ;
155164 }
@@ -208,6 +217,11 @@ pub fn copy_response(dst: &mut [u8]) -> Result<usize, CopyResponseErr> {
208217
209218/// Cancel and drop a running task. Returns true if a task was cancelled, false if no task was
210219/// running.
220+ ///
221+ /// Call this inside a running task only if you expect that the host may not be able to read the
222+ /// result (e.g. when resetting the BLE chip as part of a task), so another task can spawn
223+ /// afterwards immediately (before the timeout auto-cancles it), which currently would run into a
224+ /// panic until the response was read and the current task concluded. See the comment in `spawn()`
211225pub fn cancel ( ) -> bool {
212226 let mut state = USB_TASK_STATE . 0 . borrow_mut ( ) ;
213227 if let UsbTaskState :: Running ( _, _) = * state {
0 commit comments