@@ -101,6 +101,59 @@ static bool _wait_for_callback(void) {
101
101
return result == XFER_RESULT_SUCCESS ;
102
102
}
103
103
104
+ static void _prepare_for_transfer (void ) {
105
+ // Prepare for transfer. Unless there is a timeout, these static globals will
106
+ // get modified by the _transfer_done_cb() callback when tinyusb finishes the
107
+ // transfer or encounters an error condition.
108
+ _xfer_result = XFER_RESULT_INVALID ;
109
+ _actual_len = 0 ;
110
+ }
111
+
112
+ static size_t _handle_timed_transfer_callback (tuh_xfer_t * xfer , mp_int_t timeout ) {
113
+ if (xfer == NULL ) {
114
+ mp_raise_usb_core_USBError (NULL );
115
+ return 0 ;
116
+ }
117
+ uint32_t start_time = supervisor_ticks_ms32 ();
118
+ while ((timeout == 0 || supervisor_ticks_ms32 () - start_time < (uint32_t )timeout ) &&
119
+ !mp_hal_is_interrupted () &&
120
+ _xfer_result == XFER_RESULT_INVALID ) {
121
+ // The background tasks include TinyUSB which will call the function
122
+ // we provided above. In other words, the callback isn't in an interrupt.
123
+ RUN_BACKGROUND_TASKS ;
124
+ }
125
+ if (mp_hal_is_interrupted ()) {
126
+ // Handle case of VM being interrupted by Ctrl-C or autoreload
127
+ tuh_edpt_abort_xfer (xfer -> daddr , xfer -> ep_addr );
128
+ return 0 ;
129
+ }
130
+ // Handle control transfer result code from TinyUSB
131
+ xfer_result_t result = _xfer_result ;
132
+ _xfer_result = XFER_RESULT_INVALID ;
133
+ switch (result ) {
134
+ case XFER_RESULT_SUCCESS :
135
+ return _actual_len ;
136
+ case XFER_RESULT_FAILED :
137
+ mp_raise_usb_core_USBError (NULL );
138
+ break ;
139
+ case XFER_RESULT_STALLED :
140
+ mp_raise_usb_core_USBError (MP_ERROR_TEXT ("Pipe error" ));
141
+ break ;
142
+ case XFER_RESULT_TIMEOUT :
143
+ // This timeout comes from TinyUSB, so assume that it has stopped the
144
+ // transfer (note: timeout logic may be unimplemented on TinyUSB side)
145
+ mp_raise_usb_core_USBTimeoutError ();
146
+ break ;
147
+ case XFER_RESULT_INVALID :
148
+ // This timeout comes from CircuitPython, not TinyUSB, so tell TinyUSB
149
+ // to stop the transfer
150
+ tuh_edpt_abort_xfer (xfer -> daddr , xfer -> ep_addr );
151
+ mp_raise_usb_core_USBTimeoutError ();
152
+ break ;
153
+ }
154
+ return 0 ;
155
+ }
156
+
104
157
static mp_obj_t _get_string (const uint16_t * temp_buf ) {
105
158
size_t utf16_len = ((temp_buf [0 ] & 0xff ) - 2 ) / sizeof (uint16_t );
106
159
if (utf16_len == 0 ) {
@@ -225,38 +278,13 @@ void common_hal_usb_core_device_set_configuration(usb_core_device_obj_t *self, m
225
278
}
226
279
227
280
static size_t _xfer (tuh_xfer_t * xfer , mp_int_t timeout ) {
228
- _xfer_result = XFER_RESULT_INVALID ;
281
+ _prepare_for_transfer () ;
229
282
xfer -> complete_cb = _transfer_done_cb ;
230
283
if (!tuh_edpt_xfer (xfer )) {
231
284
mp_raise_usb_core_USBError (NULL );
232
285
return 0 ;
233
286
}
234
- uint32_t start_time = supervisor_ticks_ms32 ();
235
- while ((timeout == 0 || supervisor_ticks_ms32 () - start_time < (uint32_t )timeout ) &&
236
- !mp_hal_is_interrupted () &&
237
- _xfer_result == XFER_RESULT_INVALID ) {
238
- // The background tasks include TinyUSB which will call the function
239
- // we provided above. In other words, the callback isn't in an interrupt.
240
- RUN_BACKGROUND_TASKS ;
241
- }
242
- if (mp_hal_is_interrupted ()) {
243
- tuh_edpt_abort_xfer (xfer -> daddr , xfer -> ep_addr );
244
- return 0 ;
245
- }
246
- xfer_result_t result = _xfer_result ;
247
- _xfer_result = XFER_RESULT_INVALID ;
248
- if (result == XFER_RESULT_STALLED ) {
249
- mp_raise_usb_core_USBError (MP_ERROR_TEXT ("Pipe error" ));
250
- }
251
- if (result == XFER_RESULT_INVALID ) {
252
- tuh_edpt_abort_xfer (xfer -> daddr , xfer -> ep_addr );
253
- mp_raise_usb_core_USBTimeoutError ();
254
- }
255
- if (result == XFER_RESULT_SUCCESS ) {
256
- return _actual_len ;
257
- }
258
-
259
- return 0 ;
287
+ return _handle_timed_transfer_callback (xfer , timeout );
260
288
}
261
289
262
290
static bool _open_endpoint (usb_core_device_obj_t * self , mp_int_t endpoint ) {
@@ -355,54 +383,12 @@ mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self,
355
383
.complete_cb = _transfer_done_cb ,
356
384
};
357
385
358
- // Prepare for transfer. Unless there is a timeout, these static globals will
359
- // get modified by the _transfer_done_cb() callback when tinyusb finishes the
360
- // transfer or encounters an error condition.
361
- _xfer_result = XFER_RESULT_INVALID ;
362
- _actual_len = 0 ;
363
-
386
+ _prepare_for_transfer ();
364
387
if (!tuh_control_xfer (& xfer )) {
365
388
mp_raise_usb_core_USBError (NULL );
366
389
return 0 ;
367
390
}
368
- uint32_t start_time = supervisor_ticks_ms32 ();
369
- while ((timeout == 0 || supervisor_ticks_ms32 () - start_time < (uint32_t )timeout ) &&
370
- !mp_hal_is_interrupted () &&
371
- _xfer_result == XFER_RESULT_INVALID ) {
372
- // The background tasks include TinyUSB which will call the function
373
- // we provided above. In other words, the callback isn't in an interrupt.
374
- RUN_BACKGROUND_TASKS ;
375
- }
376
- if (mp_hal_is_interrupted ()) {
377
- // Handle case of VM being interrupted by Ctrl-C or autoreload
378
- tuh_edpt_abort_xfer (xfer .daddr , xfer .ep_addr );
379
- return 0 ;
380
- }
381
- // Handle control transfer result code from TinyUSB
382
- xfer_result_t result = _xfer_result ;
383
- _xfer_result = XFER_RESULT_INVALID ;
384
- switch (result ) {
385
- case XFER_RESULT_SUCCESS :
386
- return _actual_len ;
387
- case XFER_RESULT_FAILED :
388
- mp_raise_usb_core_USBError (NULL );
389
- break ;
390
- case XFER_RESULT_STALLED :
391
- mp_raise_usb_core_USBError (MP_ERROR_TEXT ("Pipe error" ));
392
- break ;
393
- case XFER_RESULT_TIMEOUT :
394
- // This timeout comes from TinyUSB, so assume that it has stopped the
395
- // transfer (note: timeout logic may be unimplemented on TinyUSB side)
396
- mp_raise_usb_core_USBTimeoutError ();
397
- break ;
398
- case XFER_RESULT_INVALID :
399
- // This timeout comes from CircuitPython, not TinyUSB, so tell TinyUSB
400
- // to stop the transfer
401
- tuh_edpt_abort_xfer (xfer .daddr , xfer .ep_addr );
402
- mp_raise_usb_core_USBTimeoutError ();
403
- break ;
404
- }
405
- return 0 ;
391
+ return (mp_int_t )_handle_timed_transfer_callback (& xfer , timeout );
406
392
}
407
393
408
394
bool common_hal_usb_core_device_is_kernel_driver_active (usb_core_device_obj_t * self , mp_int_t interface ) {
0 commit comments