@@ -101,6 +101,59 @@ static bool _wait_for_callback(void) {
101101 return result == XFER_RESULT_SUCCESS ;
102102}
103103
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+
104157static mp_obj_t _get_string (const uint16_t * temp_buf ) {
105158 size_t utf16_len = ((temp_buf [0 ] & 0xff ) - 2 ) / sizeof (uint16_t );
106159 if (utf16_len == 0 ) {
@@ -225,38 +278,13 @@ void common_hal_usb_core_device_set_configuration(usb_core_device_obj_t *self, m
225278}
226279
227280static size_t _xfer (tuh_xfer_t * xfer , mp_int_t timeout ) {
228- _xfer_result = XFER_RESULT_INVALID ;
281+ _prepare_for_transfer () ;
229282 xfer -> complete_cb = _transfer_done_cb ;
230283 if (!tuh_edpt_xfer (xfer )) {
231284 mp_raise_usb_core_USBError (NULL );
232285 return 0 ;
233286 }
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 );
260288}
261289
262290static 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,
355383 .complete_cb = _transfer_done_cb ,
356384 };
357385
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 ();
364387 if (!tuh_control_xfer (& xfer )) {
365388 mp_raise_usb_core_USBError (NULL );
366389 return 0 ;
367390 }
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 );
406392}
407393
408394bool common_hal_usb_core_device_is_kernel_driver_active (usb_core_device_obj_t * self , mp_int_t interface ) {
0 commit comments