@@ -78,7 +78,8 @@ def __init__(self):
78
78
descriptor_device_cb = self ._descriptor_device_cb ,
79
79
descriptor_config_cb = self ._descriptor_config_cb ,
80
80
descriptor_string_cb = self ._descriptor_string_cb ,
81
- open_driver_cb = self ._open_driver_cb ,
81
+ open_cb = self ._open_cb ,
82
+ reset_cb = self ._reset_cb ,
82
83
control_xfer_cb = self ._control_xfer_cb ,
83
84
xfer_cb = self ._xfer_cb ,
84
85
)
@@ -286,9 +287,37 @@ def _descriptor_string_cb(self, index):
286
287
except IndexError :
287
288
return None
288
289
289
- def _open_driver_cb (self , interface_desc_view ):
290
- # Singleton callback from TinyUSB custom class driver
291
- pass
290
+ def _open_cb (self , interface_desc_view ):
291
+ # Singleton callback from TinyUSB custom class driver, when USB host does
292
+ # Set Configuration. The "runtime class device" accepts all interfaces that
293
+ # it has sent in descriptors, and calls this callback.
294
+
295
+ # Walk the view of the "claimed" descriptor data provided in the
296
+ # callback and call handle_open() on each claimed interface
297
+ #
298
+ # ... this may be unnecessary at the moment, as only one configuration is supported so we
299
+ # can probably assume all the interfaces will be included.
300
+ i = 0
301
+ while i < len (interface_desc_view ):
302
+ # descriptor length, type, and index (if it's an interface descriptor)
303
+ dl , dt , di = interface_desc_view [i :i + 3 ]
304
+ if dt == _STD_DESC_INTERFACE_TYPE :
305
+ if di >= self ._usbd .static .itf_max :
306
+ di -= self ._usbd .static .itf_max
307
+ self ._itfs [di ].handle_open ()
308
+ i += dl
309
+ assert dl
310
+
311
+ def _reset_cb (self ):
312
+ # Callback when the USB device is reset by the host
313
+
314
+ # Cancel outstanding transfer callbacks
315
+ for k in self ._ep_cbs .keys ():
316
+ self ._ep_cbs [k ] = None
317
+
318
+ # Allow interfaces to respond to the reset
319
+ for itf in self ._itfs :
320
+ itf .handle_reset ()
292
321
293
322
def _submit_xfer (self , ep_addr , data , done_cb = None ):
294
323
# Singleton function to submit a USB transfer (of any type except control).
@@ -387,6 +416,7 @@ def __init__(
387
416
self .bInterfaceSubClass = bInterfaceSubClass
388
417
self .bInterfaceProtocol = bInterfaceProtocol
389
418
self .interface_str = interface_str
419
+ self ._open = False
390
420
391
421
def get_itf_descriptor (self , num_eps , itf_idx , str_idx ):
392
422
# Return the interface descriptor binary data and associated other
@@ -466,6 +496,27 @@ def get_endpoint_descriptors(self, ep_addr, str_idx):
466
496
# start from ep_addr, optionally with the utils.EP_IN_FLAG bit set.)
467
497
return (b"" , [], [])
468
498
499
+ def handle_open (self ):
500
+ # Callback called when the USB host accepts the device configuration.
501
+ #
502
+ # Override this function to initiate any operations that the USB interface
503
+ # should do when the USB device is configured to the host.
504
+ self ._open = True
505
+
506
+ def handle_reset (self ):
507
+ # Callback called on every registered interface when the USB device is
508
+ # reset by the host. This can happen when the USB device is unplugged,
509
+ # or if the host triggers a reset for some other reason.
510
+ #
511
+ # At this point, no USB functionality is available - handle_open() will
512
+ # be called later if/when the USB host re-enumerates and configures the
513
+ # interface.
514
+ self ._open = False
515
+
516
+ def is_open (self ):
517
+ # Returns True if the interface is in use
518
+ return self ._open
519
+
469
520
def handle_device_control_xfer (self , stage , request ):
470
521
# Control transfer callback. Override to handle a non-standard device
471
522
# control transfer where bmRequestType Recipient is Device, Type is
@@ -486,11 +537,11 @@ def handle_device_control_xfer(self, stage, request):
486
537
# The function can call split_bmRequestType() to split bmRequestType into
487
538
# (Recipient, Type, Direction).
488
539
#
489
- # Result:
540
+ # Result, any of :
490
541
#
491
- # - True to continue the request False to STALL the endpoint A buffer
492
- # - interface object to provide a buffer to the host as part of the
493
- # - transfer, if possible.
542
+ # - True to continue the request, False to STALL the endpoint.
543
+ # - Buffer interface object to provide a buffer to the host as part of the
544
+ # transfer, if possible.
494
545
return False
495
546
496
547
def handle_interface_control_xfer (self , stage , request ):
@@ -512,7 +563,8 @@ def handle_interface_control_xfer(self, stage, request):
512
563
def handle_endpoint_control_xfer (self , stage , request ):
513
564
# Control transfer callback. Override to handle a device
514
565
# control transfer where bmRequestType Recipient is Endpoint and
515
- # the lower byte of wIndex indicates an endpoint address associated with this interface.
566
+ # the lower byte of wIndex indicates an endpoint address associated
567
+ # with this interface.
516
568
#
517
569
# bmRequestType Type will generally have any value except
518
570
# utils.REQ_TYPE_STANDARD, as Standard endpoint requests are handled by
@@ -546,4 +598,6 @@ def submit_xfer(self, ep_addr, data, done_cb=None):
546
598
#
547
599
# Note that done_cb may be called immediately, possibly before this
548
600
# function has returned to the caller.
601
+ if not self ._open :
602
+ raise RuntimeError ()
549
603
return get_usbdevice ()._submit_xfer (ep_addr , data , done_cb )
0 commit comments