99
1010#include "tusb_config.h"
1111
12+ #include "lib/tinyusb/src/tusb.h"
1213#include "lib/tinyusb/src/host/hcd.h"
1314#include "lib/tinyusb/src/host/usbh.h"
1415#include "py/runtime.h"
@@ -31,9 +32,24 @@ void tuh_umount_cb(uint8_t dev_addr) {
3132 _mounted_devices &= ~(1 << dev_addr );
3233}
3334
35+ static void _force_tinyusb_tasks_to_run (void ) {
36+ // TinyUSB uses state machines and task queues that require tud_task()
37+ // and tuh_task() to be called very frequently. If you try to use tuh_* API
38+ // functions when something interesting has happened (device unplugged, etc),
39+ // things can go badly wrong if you wait too long to call the task runners.
40+ // For example, although RUN_BACKGROUND_TASKS schedules TinyUSB background
41+ // tasks at 1024 Hz, that doesn't seem to be sufficient if you're rapidly
42+ // polling usb.core.Device.read().
43+ #if CIRCUITPY_USB_DEVICE
44+ tud_task ();
45+ #endif
46+ tuh_task ();
47+ }
48+
3449static xfer_result_t _xfer_result ;
3550static size_t _actual_len ;
3651bool common_hal_usb_core_device_construct (usb_core_device_obj_t * self , uint8_t device_address ) {
52+ _force_tinyusb_tasks_to_run ();
3753 if (!tuh_inited ()) {
3854 mp_raise_RuntimeError (MP_ERROR_TEXT ("No usb host port initialized" ));
3955 }
@@ -58,6 +74,7 @@ void common_hal_usb_core_device_deinit(usb_core_device_obj_t *self) {
5874 if (common_hal_usb_core_device_deinited (self )) {
5975 return ;
6076 }
77+ _force_tinyusb_tasks_to_run ();
6178 size_t open_size = sizeof (self -> open_endpoints );
6279 for (size_t i = 0 ; i < open_size ; i ++ ) {
6380 if (self -> open_endpoints [i ] != 0 ) {
@@ -66,11 +83,13 @@ void common_hal_usb_core_device_deinit(usb_core_device_obj_t *self) {
6683 }
6784 }
6885 self -> device_address = 0 ;
86+ _force_tinyusb_tasks_to_run ();
6987}
7088
7189uint16_t common_hal_usb_core_device_get_idVendor (usb_core_device_obj_t * self ) {
7290 uint16_t vid ;
7391 uint16_t pid ;
92+ _force_tinyusb_tasks_to_run ();
7493 if (!tuh_vid_pid_get (self -> device_address , & vid , & pid )) {
7594 mp_raise_usb_core_USBError (NULL );
7695 }
@@ -80,6 +99,7 @@ uint16_t common_hal_usb_core_device_get_idVendor(usb_core_device_obj_t *self) {
8099uint16_t common_hal_usb_core_device_get_idProduct (usb_core_device_obj_t * self ) {
81100 uint16_t vid ;
82101 uint16_t pid ;
102+ _force_tinyusb_tasks_to_run ();
83103 if (!tuh_vid_pid_get (self -> device_address , & vid , & pid )) {
84104 mp_raise_usb_core_USBError (NULL );
85105 }
@@ -97,8 +117,8 @@ static void _transfer_done_cb(tuh_xfer_t *xfer) {
97117static bool _wait_for_callback (void ) {
98118 while (!mp_hal_is_interrupted () &&
99119 _xfer_result == XFER_RESULT_INVALID ) {
100- // The background tasks include TinyUSB which will call the function
101- // we provided above. In other words, the callback isn't in an interrupt.
120+ // The background tasks include TinyUSB which will call _transfer_done_cb().
121+ // In other words, the callback isn't in an interrupt.
102122 RUN_BACKGROUND_TASKS ;
103123 }
104124 if (mp_hal_is_interrupted ()) {
@@ -142,8 +162,8 @@ static size_t _handle_timed_transfer_callback(tuh_xfer_t *xfer, mp_int_t timeout
142162 while ((timeout == 0 || supervisor_ticks_ms32 () - start_time < (uint32_t )timeout ) &&
143163 !mp_hal_is_interrupted () &&
144164 _xfer_result == XFER_RESULT_INVALID ) {
145- // The background tasks include TinyUSB which will call the function
146- // we provided above. In other words, the callback isn't in an interrupt.
165+ // The background tasks include TinyUSB which will call _transfer_done_cb().
166+ // In other words, the callback isn't in an interrupt.
147167 RUN_BACKGROUND_TASKS ;
148168 }
149169 if (mp_hal_is_interrupted ()) {
@@ -203,6 +223,7 @@ static void _get_langid(usb_core_device_obj_t *self) {
203223mp_obj_t common_hal_usb_core_device_get_serial_number (usb_core_device_obj_t * self ) {
204224 uint16_t temp_buf [127 ];
205225 tusb_desc_device_t descriptor ;
226+ _force_tinyusb_tasks_to_run ();
206227 // First, be sure not to ask TinyUSB for a non-existent string (avoid error)
207228 if (!tuh_descriptor_get_device_local (self -> device_address , & descriptor )) {
208229 return mp_const_none ;
@@ -224,6 +245,7 @@ mp_obj_t common_hal_usb_core_device_get_serial_number(usb_core_device_obj_t *sel
224245mp_obj_t common_hal_usb_core_device_get_product (usb_core_device_obj_t * self ) {
225246 uint16_t temp_buf [127 ];
226247 tusb_desc_device_t descriptor ;
248+ _force_tinyusb_tasks_to_run ();
227249 // First, be sure not to ask TinyUSB for a non-existent string (avoid error)
228250 if (!tuh_descriptor_get_device_local (self -> device_address , & descriptor )) {
229251 return mp_const_none ;
@@ -245,6 +267,7 @@ mp_obj_t common_hal_usb_core_device_get_product(usb_core_device_obj_t *self) {
245267mp_obj_t common_hal_usb_core_device_get_manufacturer (usb_core_device_obj_t * self ) {
246268 uint16_t temp_buf [127 ];
247269 tusb_desc_device_t descriptor ;
270+ _force_tinyusb_tasks_to_run ();
248271 // First, be sure not to ask TinyUSB for a non-existent string (avoid error)
249272 if (!tuh_descriptor_get_device_local (self -> device_address , & descriptor )) {
250273 return mp_const_none ;
@@ -266,6 +289,7 @@ mp_obj_t common_hal_usb_core_device_get_manufacturer(usb_core_device_obj_t *self
266289
267290mp_int_t common_hal_usb_core_device_get_bus (usb_core_device_obj_t * self ) {
268291 tuh_bus_info_t bus_info ;
292+ _force_tinyusb_tasks_to_run ();
269293 if (!tuh_bus_info_get (self -> device_address , & bus_info )) {
270294 return 0 ;
271295 }
@@ -274,6 +298,7 @@ mp_int_t common_hal_usb_core_device_get_bus(usb_core_device_obj_t *self) {
274298
275299mp_obj_t common_hal_usb_core_device_get_port_numbers (usb_core_device_obj_t * self ) {
276300 tuh_bus_info_t bus_info ;
301+ _force_tinyusb_tasks_to_run ();
277302 if (!tuh_bus_info_get (self -> device_address , & bus_info )) {
278303 return mp_const_none ;
279304 }
@@ -297,6 +322,7 @@ mp_obj_t common_hal_usb_core_device_get_port_numbers(usb_core_device_obj_t *self
297322
298323mp_int_t common_hal_usb_core_device_get_speed (usb_core_device_obj_t * self ) {
299324 tuh_bus_info_t bus_info ;
325+ _force_tinyusb_tasks_to_run ();
300326 if (!tuh_bus_info_get (self -> device_address , & bus_info )) {
301327 return 0 ;
302328 }
@@ -315,6 +341,7 @@ mp_int_t common_hal_usb_core_device_get_speed(usb_core_device_obj_t *self) {
315341void common_hal_usb_core_device_set_configuration (usb_core_device_obj_t * self , mp_int_t configuration ) {
316342 // We assume that the config index is one less than the value.
317343 uint8_t config_index = configuration - 1 ;
344+ _force_tinyusb_tasks_to_run ();
318345 // Get the configuration descriptor and cache it. We'll use it later to open
319346 // endpoints.
320347
@@ -395,6 +422,7 @@ static bool _open_endpoint(usb_core_device_obj_t *self, mp_int_t endpoint) {
395422}
396423
397424mp_int_t common_hal_usb_core_device_write (usb_core_device_obj_t * self , mp_int_t endpoint , const uint8_t * buffer , mp_int_t len , mp_int_t timeout ) {
425+ _force_tinyusb_tasks_to_run ();
398426 if (!_open_endpoint (self , endpoint )) {
399427 mp_raise_usb_core_USBError (NULL );
400428 return 0 ;
@@ -408,6 +436,7 @@ mp_int_t common_hal_usb_core_device_write(usb_core_device_obj_t *self, mp_int_t
408436}
409437
410438mp_int_t common_hal_usb_core_device_read (usb_core_device_obj_t * self , mp_int_t endpoint , uint8_t * buffer , mp_int_t len , mp_int_t timeout ) {
439+ _force_tinyusb_tasks_to_run ();
411440 if (!_open_endpoint (self , endpoint )) {
412441 mp_raise_usb_core_USBError (NULL );
413442 return 0 ;
@@ -441,6 +470,7 @@ mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self,
441470 .complete_cb = _transfer_done_cb ,
442471 };
443472
473+ _force_tinyusb_tasks_to_run ();
444474 _prepare_for_transfer ();
445475 if (!tuh_control_xfer (& xfer )) {
446476 mp_raise_usb_core_USBError (NULL );
@@ -450,6 +480,7 @@ mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self,
450480}
451481
452482bool common_hal_usb_core_device_is_kernel_driver_active (usb_core_device_obj_t * self , mp_int_t interface ) {
483+ _force_tinyusb_tasks_to_run ();
453484 #if CIRCUITPY_USB_KEYBOARD_WORKFLOW
454485 if (usb_keyboard_in_use (self -> device_address , interface )) {
455486 return true;
@@ -459,12 +490,14 @@ bool common_hal_usb_core_device_is_kernel_driver_active(usb_core_device_obj_t *s
459490}
460491
461492void common_hal_usb_core_device_detach_kernel_driver (usb_core_device_obj_t * self , mp_int_t interface ) {
493+ _force_tinyusb_tasks_to_run ();
462494 #if CIRCUITPY_USB_KEYBOARD_WORKFLOW
463495 usb_keyboard_detach (self -> device_address , interface );
464496 #endif
465497}
466498
467499void common_hal_usb_core_device_attach_kernel_driver (usb_core_device_obj_t * self , mp_int_t interface ) {
500+ _force_tinyusb_tasks_to_run ();
468501 #if CIRCUITPY_USB_KEYBOARD_WORKFLOW
469502 usb_keyboard_attach (self -> device_address , interface );
470503 #endif
0 commit comments