adafruit / Adafruit_TinyUSB_Arduino

Arduino library for TinyUSB
MIT License
470 stars 124 forks source link

Exposure of `tud_msc_start_stop_cb` for detecting media ejections on (at least) Windows systems #177

Closed masonova1 closed 2 years ago

masonova1 commented 2 years ago

Under the hood of TinyUSB for mass storage class devices, there exists the tud_msc_start_stop_cb callback. Setting, using, and modifying this callback from within Adafruit's high-level TinyUSB API would enable me to detect mass storage ejections on my Windows machine (in theory). I have looked quite hard for other ways to access this weak callback; Simply defining it does not seem to work, as the test callback was never invoked in my runs:

bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) { digitalWrite(LED_BUILTIN, HIGH); return true; }

I suggest adding a simple mutator method, like Adafruit_USBD_MSC::setStartStopCallback(...) and storing the callback pointer in the LUN info for the TinyUSB stack.

Presently, I use the following code to detect whether I am connected to a computer in setup, and then disable the mass storage class as soon as the user is done modifying FAT contents of a SPI SD card from their PC (I am using SdFat and Adafruit_USBD_MSC::setReadWriteCallback for this):

usb_msc.setUnitReady(true); sleep_ms(1000); while(TinyUSBDevice.mounted()) { // Connected to computer, let file I/O happen delay(1); // Arduino delay so we don't go into a different power mode } usb_msc.setUnitReady(false);

However, this is not my desired behavior. I would like to be able to detect and then respond to a SCSI start/stop so that I can disable the mass storage interface and continue with my sketch when an ejection occurs.

I need to disable the mass storage class after FAT I/O over USB is complete, because I then want to launch immediately into a real-time data processing loop where constant, uninterrupted SD card access is required. I am using the Raspberry Pi Pico RP2040 with Philhower's board spec 2.1.1, in case the hardware is relevant.

hathach commented 2 years ago

have you tried to extern "C" to your callback in the sketch, to address C and C++ linking symbol

masonova1 commented 2 years ago

Making the symbol visible to C did the trick, the system detects host ejections now.https://github.com/adafruit/Adafruit_TinyUSB_Arduino/pull/138 This PR seems to implement the functionality I describe practically verbatim, but its merging failure logs have since been lost, it seems.

hathach commented 2 years ago

implemented by #179 , @masonova1 you may want to try it out.

bassjansson commented 1 year ago

Great that this got added, but unfortunately the callback isn't being called in my current setup. I am using an ESP32-S2 together with Arduino 1.8.19, Arduino-ESP32 2.0.5 and Adafruit-TinyUSB 1.14.4 on MacOS 11.7 using an SD Card as mass storage. Everything else works fine, like mounting, reading and writing to the mass storage.

I am pointing this out here, because after trying the USBMSC class which comes together with the Arduino-ESP32 core, I found out that the start/stop callback is being called without a problem. After digging into the libraries and testing some code, I can see that the USBMSC class is using the exact same TinyUSB files from the Arduino-ESP32 core as this library (Adafruit_TinyUSB) is using. I tried to find the difference to fix it, but unfortunately I failed and gave up. Though, I don't think it's a too big of a change to make this work, so someone else is maybe able to find the difference and fix it!