Some updates on MTP and MSC (USBDrive/USBFilesystem):
I have been playing with some of the what I think of as missing pieces within the MTP and USB Filesystem code. In particular how to make it easier for Sketch to "Just use it"
Note: These changes are not in the main branches of USBHost_t36 (
https://github.com/KurtE/USBHost_t36/tree/format_cleanup)
or MTP_Teensy (
https://github.com/KurtE/MTP_Teensy/tree/try_auto_detect_sd_media)
I have not yet issued a Pull Request on these as still testing them out and also making sure they pass the smell test
USBHost_t36 changes:
a) Cleanup format code a little bit - what the branch was originally created for...
b) I did not like having the sketches have to call something, that when we detect a drive was plugged in or removed to then have the drive enumerate all of the partitions and if appropriate claim one or more
USBFilesystem objects to handle any Fat/ExFat partitions contained in the MBR, or GPT list...
So now the code is hooked up using the USBDrive.Task() method, which before was using the default {}... So this part is take care of by calls like: myUSB.Task();
c) I moved some of the stuff out of the USBFilesystem class to be within the base class, including being derived by the FS class. I also no longer link/unlink the objects depending on if they are claimed or not. I can teel if they are claimed as the device member variable is set or not...
d) Also cleaned up the code to know the connection state and the state of has the drive been formatted. Again part of the base class with a query and set function. Also a query/set function for has any device changed state since I last checked/cleared it...
e) probably a few other things, like rename some variables...
MTP_Teensy
a) Extended the MTP_class::loop() functionality... Actually MTPStorage.loop() which is already called by the MTP_class code. In here it allows one to register a callback function, to be called, either once per call for a logical type or once per instance of logical type... Currently just (unknown, SD (instance), USBFS(class))...
b) updated the MTP_class::addFilesystem to allow you to pass in optional parameter saying which one it is... default to unknown and callbacks won't be used... (except...)
c) Hacked MTP_Teensy.h header file in the class that if SD.h had been included in the sketch (before this header file was included), it added a simple method override for the SDClass object and if so, when
you add an SD it will automatically call off to the main one with the optional parameter...
Note: I wanted to simply use __has_include(<SD.h> but as I pointed out in another sketch if your code has something like:
if MTP_Teensy.h started off like:
Code:
...
#include "MTP_Storage.h"
#if defined(__has_include) && __has_include(<SD.h>)
#include <SD.h>
#endif
...
And your sketch had:
Code:
#include <SD.H>
#include <MTP_Teensy.h>
It build fine.
However if you had:
Code:
#include <MTP_Teensy.h>
#include <SD.H>
The code will fail to build as SD.h will be never be included... Other thread, but simply put Arduino builder will not include the directory that contains SD.h into the -I search list...
Turns out issue with GCC compilers...
d) I added two .cpp files, one each for SD and USBFilesystem...
Both start off something like:
Code:
#include "MTP_Teensy.h"
#include "MTP_Storage.h"
// This code should only be build and run if the SD library was included in the sketch
#if defined(__has_include) && __has_include(<SD.h>)
#include <SD.h>
// I am going to create a simple class with a constructor and maybe some simple data.
// that can be associated with the SD...
// This is sort of a prototype, could expand to something more later.
class MTP_SD_Callback {
public:
// constructor
MTP_SD_Callback() {
MTP.storage()->registerClassLoopCallback(MTP_FSTYPE_SD, &checkMediaPresent);
}
// static callback for device check (media present)
static bool checkMediaPresent(uint8_t storage_index, FS *pfs);
static uint8_t media_present_prev_[MTPD_MAX_FILESYSTEMS];
};
uint8_t MTP_SD_Callback::media_present_prev_[MTPD_MAX_FILESYSTEMS] = {0};
// define one here so it's constructor will be called.
static MTP_SD_Callback mtsdcb;
So in this case if the sketch includes SD.h somewhere, this code will be included and it defines a dummy class, whose constructor will call off to register the callback
function with Storage. So again this code will not be added unless SD was already going to be included.
And then the rest of the code in these files, take care of either checking for SD media present or not, and checks when a USBDrive is plugged in and the code went through and
enumerated and updated one or more USBFilesystems, this code will then see about adding/removing the drives from the MTP storage...
What does all of this mean
Here is a pretty simple sketch:
Code:
/*
Simple MTP example that will add a RAM and Flash drive plus handles allowing you to insert one or more USB drives
and shows those as well.
*/
#include <USBHost_t36.h>
#include <SD.h>
#include <MTP_Teensy.h>
// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);
// Instances for the number of USB drives you are using.
USBDrive myDrive1(myusb);
// Instances for accessing the files on each drive
USBFilesystem pf1(myusb);
USBFilesystem pf2(myusb);
USBFilesystem pf3(myusb);
USBFilesystem pf4(myusb);
void setup() {
// Open serial communications and wait for port to open:
// setup to do quick and dirty ram stream until Serial or like is up...
MTP.begin();
SD.begin(BUILTIN_SDCARD);
MTP.addFilesystem(SD, "SD Card");
while (!Serial && millis() < 5000) { }
if (CrashReport) Serial.print(CrashReport);
Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
myusb.begin();
}
void loop() {
myusb.Task();
MTP.loop();
}
With it, it will add the SD card to MTP... If the media is not present, if you plug in card it should detect it and update the MTP status.
Note: In this case the MTP window is not automatically refreshed. but if you hit F5 you will see the updated status.
And if a USB drive is detected, the File systems will be added automatically.
It ain't perfect, but...