mjs513
Senior Member+
Just tried by adding a RAM and PROG disk - so got to 11. Think 16 is more than enough!Looks like Windows 11 can handle 16 MTP filesystems.
Just tried by adding a RAM and PROG disk - so got to 11. Think 16 is more than enough!Looks like Windows 11 can handle 16 MTP filesystems.
That is what I would suggest. You should probably change all the examples that will be part of the project to use these two classes.I forgot until just now that we have LittleFS_SPI which automatically tries NOR, NAND and FRAM, and also LittleFS_QSPI for Teensy 4.1's QSPI pads.
Maybe we should publish example programs with the instances like this?
Code:LittleFS_SPI sNand3; LittleFS_SPI sNand4; LittleFS_SPI sFlash5; LittleFS_SPI sFlash6;
Large code size, but will automatically work with any type of chip we support.
//=============================================================================
// Simple Sketch that initializes MTP and adds one SD drive as the only
// storage.
// Notes:
// If SD.h is included before MTP_Teensy.h, the code will automatically
// inert a handler callback that will try to detect when the SD is inserted
// or removed.
//
// The host often times will not automatically refresh to show the updated
// status of the drive after events such as this. However doing a refresh
// example F5 on Windows, will update and show the new status.
//
// If MTP_Teensy.h is included before SD.h, by default, this checking
// for drive insertions is not installed. You can tell the addFilesystem that
// the storage is an SD drive like:
// MTP.addFilesystem(SD, "SD Card", MTP_FSTYPE_SD);
//
//=============================================================================
#include <SD.h>
#include <MTP_Teensy.h>
#define SHOW_ALL_SD_OBJECTS
class SDWrapper : public FS {
public:
SDClass *_psd;
uint8_t _fat_type;
static uint8_t s_last_media_present_fat_type;
static elapsedMillis s_emLast_meda_check_time;
enum {MEDIA_PRESENT_CHECK_INTERVAL=100};
SDWrapper(SDClass &sd, uint8_t fattype)
: _psd(&sd), _fat_type(fattype){};
~SDWrapper() {}
virtual File open(const char *filename, uint8_t mode = FILE_READ) {
return _psd->open(filename, mode);
}
virtual bool exists(const char *filepath) {
return _psd->exists(filepath);
}
virtual bool mkdir(const char *filepath) {
return _psd->mkdir(filepath);
}
virtual bool rename(const char *oldfilepath, const char *newfilepath) {
return _psd->rename(oldfilepath, newfilepath);
}
virtual bool remove(const char *filepath) {
return _psd->remove(filepath);
}
virtual bool rmdir(const char *filepath) {
// if ( _fat_type != _last_media_present_fat_type) return false;
}
virtual uint64_t usedSize() {
if ( _fat_type != s_last_media_present_fat_type) return 0xfffffffffffffffful;
return _psd->usedSize();
}
virtual uint64_t totalSize() {
if ( _fat_type != s_last_media_present_fat_type) return 0xfffffffffffffffful;
return _psd->totalSize();
}
virtual bool format(int type = 0, char progressChar = 0, Print &pr = Serial) {
return _psd->format(type, progressChar, pr);
}
virtual bool mediaPresent() {
if ((s_last_media_present_fat_type == 0xff) || (s_emLast_meda_check_time > MEDIA_PRESENT_CHECK_INTERVAL)) {
if (!_psd->mediaPresent()) {
s_last_media_present_fat_type = 0xff;
return false;
}
s_last_media_present_fat_type = _psd->sdfs.vol()->fatType();
//Serial.printf("MP: this:%p FT=%u\n", this, s_last_media_present_fat_type);
s_emLast_meda_check_time = 0;
}
#ifdef SHOW_ALL_SD_OBJECTS
return s_last_media_present_fat_type != 0xff;
#else
return _fat_type == s_last_media_present_fat_type;
#endif
}
};
uint8_t SDWrapper::s_last_media_present_fat_type = 0xff;
elapsedMillis SDWrapper::s_emLast_meda_check_time = MEDIA_PRESENT_CHECK_INTERVAL;
SDWrapper sd1(SD, 12);
SDWrapper sd2(SD, 16);
SDWrapper sd3(SD, 32);
SDWrapper sd4(SD, 64);
#define CS_SD BUILTIN_SDCARD // Works on T_3.6 and T_4.1
//#define CS_SD 10 // Works on SPI with this CS pin
void setup() {
// mandatory to begin the MTP session.
MTP.begin();
while (!Serial && millis() < 5000) {}
Serial.begin(115200);
if (CrashReport) Serial.print(CrashReport);
// Add SD Card
SD.begin(CS_SD);
MTP.addFilesystem(sd1, "SDIO_FS_TYPE_12");
MTP.addFilesystem(sd2, "SDIO_FS_TYPE_16");
MTP.addFilesystem(sd3, "SDIO_FS_TYPE_32");
MTP.addFilesystem(sd4, "SDIO_FS_TYPE_64");
}
void loop() {
MTP.loop(); //This is mandatory to be placed in the loop code.
}
That is a good point. Detecting disk removal/insertion is one aspect, but content management on responder (teensy) is another one. The original MTP version had the index file on the disk, so it was easy to synchronize index file with disk related mtp actions and after reset, the file was simply wiped. From the MTP_Teensy code I see that the index file is now in memory. I'm not sure is upon removal of one of the many disks, all the content to relative disk is also removed from index file, which could be easily done, but was not in original code.Does all this testing involve removing one drive and replacing it with a different one instead? This was one of the major headaches I had when I played with it, because the disk contents was cached and MTP would present the wrong files to the host PC. Particularly when switching between FAT16/32 and EXFAT SD cards, it would usually crash.
I think the SD card in particular might be more prone to showing issues when switching cards, since there is only one static SD FS object that gets reused when a different card gets inserted. MTP would occasionally hold open the file handle of the last accessed file, which referenced the "stale" SD FS (the one that was removed) and only close it when a new file was accessed, by which time the SD FS had changed format internally due to switching from a FAT32 to EXFAT card (or vice versa).But on the USB stuff, normally I just plug the same drive back in. Will make a point to mix them up. I believe most of the USB drives, even the larger ones, are FAT32 format. Will look at reformatting some, and make sure the 1 smaller drive is FAT16.
Back when I was testing the index was on the first added disk by default, which caused an instant crash if that particular disk was removed. So I purposefully made it use memory instead, which made things a little bit better but there was still no "surefire" way to purge the index for a specific storage object when it was removed.That is a good point. Detecting disk removal/insertion is one aspect, but content management on responder (teensy) is another one. The original MTP version had the index file on the disk, so it was easy to synchronize index file with disk related mtp actions and after reset, the file was simply wiped. From the MTP_Teensy code I see that the index file is now in memory. I'm not sure is upon removal of one of the many disks, all the content to relative disk is also removed from index file, which could be easily done, but was not in original code.
Makes sense, as there was no mechanism in place to detect storage removal, or to 'error' handle the absence of a disk.Back when I was testing the index was on the first added disk by default, which caused an instant crash if that particular disk was removed. So I purposefully made it use memory instead, which made things a little bit better but there was still no "surefire" way to purge the index for a specific storage object when it was removed.
It has been a few years since I played with that part of the code. So there are lots of details that I foggy on.That is a good point. Detecting disk removal/insertion is one aspect, but content management on responder (teensy) is another one. The original MTP version had the index file on the disk, so it was easy to synchronize index file with disk related mtp actions and after reset, the file was simply wiped. From the MTP_Teensy code I see that the index file is now in memory. I'm not sure is upon removal of one of the many disks, all the content to relative disk is also removed from index file, which could be easily done, but was not in original code.
Yes, I know and there are some things better done in MTP-Teensy, but that is what progress is about and I'm happy that Paul, who kickstarted my interest in MTP, finally found some time to work on it to get rid of the experimental tag (@Paul: we still need some unique PID for MTP-Serial)It has been a few years since I played with that part of the code. So there are lots of details that I foggy on.
I remember the original code would fail if the first storage added was not in place or Read only or out of disk space... For example
if your sketch added both SD as well as USB drive and SD was missing it would fail.
There is/was code in place to try to detect when storages were removed, and notify the host, and handle messages back for a new session
(Probably wrong name) but doing from memory. At one point, I had both mechanisms in place, that, if necessary, it would hold so much of the index in memory and then fall back to index file. Not sure if that code is still there or was removed in an earlier code simplification pass.
Just a bit of warning about use of "Store" or StorageID.Right now I'm working on simplifying and cleaning up the examples to only use the public API (especially no use of "store" or StorageID by public functions), especially mtp-test-integrityV2.
// sets the storage for the index file
MTP.useFileSystemIndexFileStore(0);
#if useMemFile == 1
// Lets add the Program memory version:
// checks that the LittFS program has started with the disk size specified
MTP.useFileSystemIndexFileStore(MTPStorage::INDEX_STORE_MEM_FILE);
#endif
// lets initialize a RAM drive.
#if useExMem == 1
#if defined ARDUINO_TEENSY41
if (external_psram_size)
LFSRAM_SIZE = 4 * 1024 * 1024;
#endif
if (lfsram.begin(LFSRAM_SIZE)) {
DBGSerial.printf("Ram Drive of size: %u initialized\n", LFSRAM_SIZE);
uint32_t istore = MTP.addFilesystem(lfsram, "RAMindex");
if (istore != 0xFFFFFFFFUL)
MTP.useFileSystemIndexFileStore(istore);
DBGSerial.printf("Set Storage Index drive to %u\n", istore);
}
#endif
case '1':
// first dump list of storages:
fsCount = MTP.getFilesystemCount();
DBGSerial.printf("\nDump Storage list(%u)\n", fsCount);
for (uint32_t ii = 0; ii < fsCount; ii++) {
DBGSerial.printf("store:%u storage:%x name:%s fs:%x pn:", ii,
MTP.Store2Storage(ii), MTP.getFilesystemNameByIndex(ii),
(uint32_t)MTP.getFilesystemByIndex(ii));
DBGSerial.println(getFSPN(ii));
}
break;
case '2':
if (storage_index < MTP.getFilesystemCount()) {
DBGSerial.printf("Storage Index %u Name: %s Selected\n", storage_index,
MTP.getFilesystemNameByIndex(storage_index));
myfs = MTP.getFilesystemByIndex(storage_index);
current_store = storage_index;
} else {
DBGSerial.printf("Storage Index %u out of range\n", storage_index);
}
break;
Just a bit of warning about use of "Store" or StorageID.
its not meant for the faint of heart or beginners.
Makes sense to me...Hope this makes sense - maybe @KurtE can add something.
Again that V2 sketch was a catch all to demonstrate everything instead of having a million sketches by configuring the defines - its not meant for the faint of heart or beginners.
Personally, I would suggest that may be premature...Right now I'm working on simplifying and cleaning up the examples to only use the public API (especially no use of "store" or StorageID by public functions), especially mtp-test-integrityV2.
Ok will wait patiently to see how it gets handled in the new API oops just noticed the linkI added a list of user selectable filesystems to mtp-test-integrityV2, because the MTP public API won't be usable for that purpose anymore.
Going to address the index list configuration stuff soon. Complicated topic, so to save time now, will discuss details later.
Think if I/we realized this earlier probably would have opted to do this from the start.The list looks shorter only because I switched to using the LittleFS_SPI and LittleFS_QSPI rather than requiring explicit config for NOR vs FRAM vs NAND.
Actually think it was the other way around if I remember right.That is exactly what has happened with mtp-test-integrity and several other examples which probably began by copying mtp-test-integrity.
Would agree to a point but you also want to make it flexible enough for beginners and advanced users as @KurtE mentionedMaybe shrinking the public API feels like a loss if you're used to writing test code that uses the internal filesystem list for your test program's user interface? This is the huge challenge to designing public APIs. If an API exposes too much internal implementation detail,
RAMDISK Storage 46080 bytes
RAMDISK Storage 1536000 bytes failed
SD Storage, no card detected
Initializing USB drives...
USB initialized.
MTP internal filesystems info:
Storage List, 15 Filesystems
store:0 storage:10001 present:Yes fs:2000AFC8 name:"" fsname:"Untitled"
store:1 storage:20001 present:Yes fs:2000B094 name:"RAM1" fsname:"Untitled"
store:2 storage:30001 present:No fs:20009960 name:"SD Card" fsname:"Untitled"
store:3 storage:40001 present:Yes fs:2000A484 name:"" fsname:"Untitled"
store:4 storage:50001 present:Yes fs:2000A74C name:"" fsname:"Untitled"
store:5 storage:60001 present:Yes fs:2000AA14 name:"" fsname:"Untitled"
store:6 storage:70001 present:Yes fs:2000ACDC name:"" fsname:"Untitled"
store:7 storage:80001 present:Yes fs:2000F338 name:"USB1" fsname:"Untitled"
store:8 storage:90001 present:Yes fs:2000F7E0 name:"USB2" fsname:"Untitled"
store:9 storage:A0001 present:Yes fs:2000FC88 name:"USB3" fsname:"Untitled"
store:10 storage:B0001 present:Yes fs:20010130 name:"USB4" fsname:"Untitled"
store:11 storage:C0001 present:No fs:200105D8 name:"USB5" fsname:"Untitled"
store:12 storage:D0001 present:No fs:20010A80 name:"USB6" fsname:"Untitled"
store:13 storage:E0001 present:No fs:20010F28 name:"USB7" fsname:"Untitled"
store:14 storage:F0001 present:No fs:200113D0 name:"USB8" fsname:"Untitled"
Index List:
Filesystems Selected with '2 {number}' command:
FS #0 Present=Yes Size=640 kB Name=(null)
FS #1 Present=Yes Size=45 kB Name=(null)
FS #2 Present=No Size=0 kB Name=(null) Info=SD Card
FS #3 Present=Yes Size=126 MB Name=(null) Info=MEMBOARD CS pin 3
FS #4 Present=Yes Size=253 MB Name=(null) Info=MEMBOARD CS pin 4
FS #5 Present=Yes Size=64 MB Name=(null) Info=MEMBOARD CS pin 5
FS #6 Present=Yes Size=64 MB Name=(null) Info=MEMBOARD CS pin 6
FS #7 Present=Yes Size=8 GB Name=(null) Info=USB
FS #8 Present=Yes Size=115 GB Name=(null) Info=USB
FS #9 Present=Yes Size=58 GB Name=(null) Info=USB
FS #10 Present=Yes Size=57 GB Name=(null) Info=USB
FS #11 Present=No Size=0 kB Name=(null) Info=USB
FS #12 Present=No Size=0 kB Name=(null) Info=USB
FS #13 Present=No Size=0 kB Name=(null) Info=USB
FS #14 Present=No Size=0 kB Name=(null) Info=USB
Filesystem #3 "(null)" selected
Space Used = 2883584
Filesystem Size = 131596288
Directory
---------
1-s2.0-S0927650524001130-main.pdf 2584620
will give it a try:UpadateGrab the latest LittleFS and USBHost_t36 to get the volume names filled in. Media name improvements committed into LittleFS just a couple hours ago.
Tomorrow or Friday I'll probably package up a new beta, so it's easier to get all the other stuff. Still much testing I want to do, so time frame will depend on how things are looking...
MTP internal filesystems info:
Storage List, 15 Filesystems
store:0 storage:10001 present:Yes fs:2000AF78 name:"" fsname:"PROGRAM"
store:1 storage:20001 present:Yes fs:2000B044 name:"RAM1" fsname:"DMAMEM"
store:2 storage:30001 present:Yes fs:20009960 name:"SD Card" fsname:"Untitled"
store:3 storage:40001 present:Yes fs:2000A484 name:"" fsname:"W25N01GVZEIG"
store:4 storage:50001 present:Yes fs:2000A738 name:"" fsname:"W25N02KVZEIR"
store:5 storage:60001 present:Yes fs:2000A9EC name:"" fsname:"W25Q512JV*M (DTR)"
store:6 storage:70001 present:Yes fs:2000ACA0 name:"" fsname:"W25Q512JV*Q"
store:7 storage:80001 present:Yes fs:2000F2E8 name:"USB1" fsname:""
store:8 storage:90001 present:Yes fs:2000F79C name:"USB2" fsname:"Data"
store:9 storage:A0001 present:Yes fs:2000FC50 name:"USB3" fsname:"exFAT0"
store:10 storage:B0001 present:Yes fs:20010104 name:"USB4" fsname:""
store:11 storage:C0001 present:No fs:200105B8 name:"USB5" fsname:""
store:12 storage:D0001 present:No fs:20010A6C name:"USB6" fsname:""
store:13 storage:E0001 present:No fs:20010F20 name:"USB7" fsname:""
store:14 storage:F0001 present:No fs:200113D4 name:"USB8" fsname:""
Index List:
0: 0 1 1 65535 0 49 0 0 /
1: 1 1 1 65535 0 0 0 0 /
2: 2 1 0 65535 0 0 0 0 /
3: 3 1 0 65535 0 0 0 0 /
4: 4 1 0 65535 0 0 0 0 /
5: 5 1 0 65535 0 0 0 0 /
6: 6 1 0 65535 0 0 0 0 /
7: 7 1 0 65535 0 0 0 0 /
8: 8 1 0 65535 0 0 0 0 /
9: 9 1 1 65535 0 48 0 0 /
10: 10 1 1 65535 0 0 0 0 /
11: 11 1 0 65535 0 0 0 0 /
12: 12 1 0 65535 0 0 0 0 /
13: 13 1 0 65535 0 0 0 0 /
14: 14 1 0 65535 0 0 0 0 /
16: 9 1 0 9 0 0 1651585464 1651585464 System Volume Information
17: 9 0 0 9 16 135897 1651585478 1651046874 WM2204270371_invoice - LCSC.COM.pdf
18: 9 0 0 9 17 84305 1651585482 1651084098 613e-cy8JgL._AC_SL1000_.jpg
19: 9 0 0 9 18 33878 1651585484 1651084140 51ZIZAVX8ZL._AC_.jpg
20: 9 1 0 9 19 0 1664045018 1654685722 New folder (10)
21: 9 1 0 9 20 0 1664045040 1656490994 AvionicsInstrumentControlDemo
22: 9 1 0 9 21 0 1664045050 1650904550 New folder (8)
23: 9 1 0 9 22 0 1664045062 1651150636 erlin513
24: 9 0 0 9 23 1842 1664045068 1652085412 NAND_SDcard.txt
25: 9 0 0 9 24 343 1664045096 1653406350 token.txt
26: 9 1 0 9 25 0 1664045114 1650385930 lib
27: 9 0 0 9 26 1031 1664045118 1649408318 assignedI2Cpins.py
28: 9 1 0 9 27 0 1611226136 1611229004 Image2C
29: 9 0 0 9 28 377551 1632207658 1632207662 card11a_rev4_web.pdf
30: 9 1 0 9 29 0 1612916476 1642333848 T_4.1
31: 9 1 0 9 30 0 1664045310 1638185250 PRJC-PropShield-Practice-Sketches-master
32: 9 0 0 9 31 22023 1626435554 1626435556 Arduino Expansion V5 SCH.pdf
33: 9 0 0 9 32 396353 1632207650 1632207652 card11b_rev4_web.pdf
34: 9 1 0 9 33 0 1643175530 1643375132 test Images
35: 9 0 0 9 34 414861 1642783436 1642864614 Image Scaling With Bresenham.docx
36: 9 0 0 9 35 1037303 1628340932 1628340970 Picture1.png
37: 9 1 0 9 36 0 1633540270 1637071746 LFS_CPY
38: 9 1 0 9 37 0 1664045320 1623916864 Zenta_LSS_Phoenix_PhantomX_float
39: 9 1 0 9 38 0 1664045332 1642740438 extras
40: 9 0 0 9 39 3126044 1640620170 1640620172 SparkFun ProDriver Hookup Guide - learn.sparkfun.com.pdf
41: 9 1 0 9 40 0 1664045356 1622917450 Arduino_Hex_PS3
42: 9 0 0 9 41 13430 1664046686 1626286332 VirtualCommander.pde
43: 9 0 0 9 42 3008805 1664046692 1613422608 ZED-F9P_InterfaceDescription_(UBX-18010854).pdf
44: 9 0 0 9 43 133488 1664046700 1626330724 22AT Commands.pdf
45: 9 0 0 9 44 307693 1664046712 1627289590 If you are in EM0.docx
46: 9 0 0 9 45 909727 1664046734 1625511684 arduino_uno_drawing_5000x3515.png
47: 9 0 0 9 46 1439758 1664046776 1625736522 1809141331_Lyontek-Inc-LY68L6400SLIT_C261881.pdf
48: 9 0 0 9 47 964417 1664046788 1642840900 amt10.pdf
49: 0 0 0 0 0 0 1731501189 1731501189 mtpindex.dat
Filesystems Selected with '2 {number}' command:
FS #0 Present=Yes Size=640 kB Name=PROGRAM
FS #1 Present=Yes Size=45 kB Name=DMAMEM
FS #2 Present=Yes Size=29 GB Name=(null) Info=SD Card
FS #3 Present=Yes Size=126 MB Name=W25N01GVZEIG Info=MEMBOARD CS pin 3
FS #4 Present=Yes Size=253 MB Name=W25N02KVZEIR Info=MEMBOARD CS pin 4
FS #5 Present=Yes Size=64 MB Name=W25Q512JV*M (DTR) Info=MEMBOARD CS pin 5
FS #6 Present=Yes Size=64 MB Name=W25Q512JV*Q Info=MEMBOARD CS pin 6
FS #7 Present=Yes Size=8 GB Name= Info=USB
FS #8 Present=Yes Size=115 GB Name=Data Info=USB
FS #9 Present=Yes Size=58 GB Name=exFAT0 Info=USB
FS #10 Present=Yes Size=57 GB Name= Info=USB
FS #11 Present=No Size=0 kB Name= Info=USB
FS #12 Present=No Size=0 kB Name= Info=USB
FS #13 Present=No Size=0 kB Name= Info=USB
FS #14 Present=No Size=0 kB Name= Info=USB
Filesystem #3 "W25N01GVZEIG" selected
Space Used = 2883584
Filesystem Size = 131596288
Directory
---------
1-s2.0-S0927650524001130-main.pdf 2584620
Index List:
Filesystems Selected with '2 {number}' command:
FS #0 Present=Yes Size=640 kB Name=PROGRAM
FS #1 Present=Yes Size=45 kB Name=DMAMEM
FS #2 Present=Yes Size=29 GB Name=(null) Info=SD Card
FS #3 Present=Yes Size=512 kB Name=AT25SF041 Info=MEMBOARD CS pin 3
FS #4 Present=Yes Size=8 MB Name=W25Q64JV*Q/W25Q64FV Info=MEMBOARD CS pin 4
FS #5 Present=Yes Size=32 MB Name=W25Q256JW*M Info=MEMBOARD CS pin 5
FS #6 Present=Yes Size=8 GB Name= Info=USB
FS #7 Present=Yes Size=115 GB Name=Data Info=USB
FS #8 Present=Yes Size=58 GB Name=exFAT0 Info=USB
FS #9 Present=Yes Size=57 GB Name= Info=USB
FS #10 Present=No Size=0 kB Name= Info=USB
FS #11 Present=No Size=0 kB Name= Info=USB
FS #12 Present=No Size=0 kB Name= Info=USB
FS #13 Present=No Size=0 kB Name= Info=USB
Filesystem #3 "AT25SF041" selected
Space Used = 8192
Filesystem Size = 524288
Directory
---------
Filesystems Selected with '2 {number}' command:
FS #0 Present=Yes Size=640 kB Name=PROGRAM
FS #1 Present=Yes Size=45 kB Name=DMAMEM
FS #2 Present=Yes Size=29 GB Name=(null) Info=SD Card
FS #3 Present=Yes Size=1024 kB Name=CY15B108QN Info=MEMBOARD CS pin 3
FS #4 Present=Yes Size=512 kB Name=CY15B104Q Info=MEMBOARD CS pin 4
FS #5 Present=Yes Size=128 kB Name=MR45V100A Info=MEMBOARD CS pin 5
FS #6 Present=Yes Size=8 GB Name= Info=USB
FS #7 Present=Yes Size=115 GB Name=Data Info=USB
FS #8 Present=Yes Size=58 GB Name=exFAT0 Info=USB
Filesystem #3 "CY15B108QN" selected
Space Used = 256
Filesystem Size = 1048576
Directory
---------
Filesystem #4 "CY15B104Q" selected
Space Used = 256
Filesystem Size = 524288
Directory
---------
Filesystem #5 "MR45V100A" selected
Space Used = 256
Filesystem Size = 131072
Directory
---------