@@ -101,6 +101,9 @@ where
101
101
102
102
* state = UsbTaskState :: Running ( Some ( task) , WaitingForNextRequestState :: Idle ) ;
103
103
}
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.
104
107
_ => panic ! ( "spawn: wrong state" ) ,
105
108
}
106
109
}
@@ -149,7 +152,13 @@ pub fn spin() {
149
152
_ => None ,
150
153
} ;
151
154
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 {
153
162
Poll :: Ready ( result) => {
154
163
* USB_TASK_STATE . 0 . borrow_mut ( ) = UsbTaskState :: ResultAvailable ( result) ;
155
164
}
@@ -208,6 +217,11 @@ pub fn copy_response(dst: &mut [u8]) -> Result<usize, CopyResponseErr> {
208
217
209
218
/// Cancel and drop a running task. Returns true if a task was cancelled, false if no task was
210
219
/// 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()`
211
225
pub fn cancel ( ) -> bool {
212
226
let mut state = USB_TASK_STATE . 0 . borrow_mut ( ) ;
213
227
if let UsbTaskState :: Running ( _, _) = * state {
0 commit comments