Yet another new day
I have been playing with the MTP stuff, with partitions... And pulling out a fair percentage of the few hairs I have left
I have hacked my way through to try to support N USB drives with M partitions...
Code:
#define USE_MSC_FAT 2 // set to > 0 experiment with MTP (USBHost.t36 + mscFS)
#define USE_MSC_FAT_VOL 8 // Max MSC FAT Volumes.
Data associated with this some I can probably get rid of once I understand what I am doing... Note it also handles pressing in SD Card after program starts...
Code:
#if USE_MSC_FAT > 0
#if defined(__IMXRT1062__) || defined(ARDUINO_TEENSY36)
#include <mscFS.h>
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
#ifndef USE_MSC_FAT_VOL
#define USE_MSC_FAT_VOL USE_MSC_FAT
#endif
// start off with one controller.
msController msDrive[USE_MSC_FAT](myusb);
bool msDrive_previous[USE_MSC_FAT]; // Was this drive there the previous time through?
MSCClass msc[USE_MSC_FAT];
char nmsc_str[USE_MSC_FAT_VOL][20];
uint16_t msc_storage_index[USE_MSC_FAT_VOL];
uint8_t msc_drive_index[USE_MSC_FAT_VOL]; // probably can find easy way not to need this.
The helper function I have to add the drives and partitions:
Code:
void checkUSBandSDIOStatus(bool fInit) {
#if USE_MSC_FAT > 0
bool usb_drive_changed_state = false;
myusb.Task(); // make sure we are up to date.
if (fInit) {
// make sure all of the indexes are -1..
for (int ii = 0; ii < USE_MSC_FAT_VOL; ii++) {msc_storage_index[ii] = (uint16_t)-1; msc_drive_index[ii] = -1;}
for (int ii = 0; ii < USE_MSC_FAT; ii++) msDrive_previous[ii] = false;
}
for (int index_usb_drive = 0; index_usb_drive < USE_MSC_FAT; index_usb_drive++)
{
msController *pdriver = &msDrive[index_usb_drive];
if (*pdriver != msDrive_previous[index_usb_drive]) {
// Drive status changed.
msDrive_previous[index_usb_drive] = *pdriver;
usb_drive_changed_state = true; // something changed
if (*pdriver)
{
Serial.println("USB Drive Inserted");
mbrDmp(pdriver);
// Now lets see if we can iterate over all of the possible parititions of this drive
for (int index_drive_partition=1; index_drive_partition < 5; index_drive_partition++) {
// lets see if we can find an available msc object to use...
for (int index_msc = 0; index_msc < USE_MSC_FAT_VOL; index_msc++) {
if (msc_storage_index[index_msc] == (uint16_t)-1)
{
// lets try to open a partition.
Serial.printf(" Try Partiton:%d on MSC Index:%d\n", index_drive_partition, index_msc);
if (msc[index_msc].begin(pdriver, false, index_drive_partition))
{
Serial.println(" ** SUCCEEDED **");
// now see if we can get the volume label.
uint8_t volName[20];
if (getPartitionVolumeLabel(msc[index_msc].mscfs, volName, sizeof(volName))) {
Serial.printf(">> USB partition %d valume ID: %s\n", index_drive_partition, volName);
snprintf(nmsc_str[index_msc], sizeof(nmsc_str[index_msc]), "MSC%d-%s", index_usb_drive, volName);
}
else snprintf(nmsc_str[index_msc], sizeof(nmsc_str[index_msc]), "MSC%d-%d", index_usb_drive, index_drive_partition);
msc_drive_index[index_msc] = index_usb_drive;
msc_storage_index[index_msc] = storage.addFilesystem(msc[index_msc], nmsc_str[index_msc]);
#if 0
elapsedMicros emmicro = 0;
uint64_t totalSize = msc[index_usb_drive].totalSize();
uint32_t elapsed_totalSize = emmicro;
uint64_t usedSize = msc[index_usb_drive].usedSize();
Serial.printf("new Storage %d %s %llu(%u) %llu(%u)\n", index_msc, nmsc_str[index_msc], totalSize, elapsed_totalSize, usedSize, (uint32_t)emmicro - elapsed_totalSize);
#endif
if (!fInit) mtpd.send_StoreAddedEvent(msc_storage_index[index_msc]);
}
break;
}
}
}
}
else
{
// drive went away...
for (int index_msc = 0; index_msc < USE_MSC_FAT_VOL; index_msc++) {
// check for any indexes that were in use that were associated with that drive
// Don't need to check for fInit here as we wont be removing drives during init...
if (msc_drive_index[index_msc]== index_usb_drive) {
mtpd.send_StoreRemovedEvent(msc_storage_index[index_msc]);
storage.removeFilesystem(msc_storage_index[index_msc]);
msc_storage_index[index_msc] = (uint16_t)-1;
msc_drive_index[index_msc] = -1;
}
}
}
}
}
if (usb_drive_changed_state && !fInit) {
delay(10); // give some time to handle previous one
mtpd.send_DeviceResetEvent();
}
#endif
#ifdef _SD_DAT3
if (BUILTIN_SDCARD_missing_index != -1)
{
// delayMicroseconds(5);
bool r = digitalReadFast(_SD_DAT3);
if (r)
{
// looks like SD Inserted. so disable the pin for now...
pinMode(_SD_DAT3, INPUT_DISABLE);
delay(1);
Serial.printf("\n*** SDIO Card Inserted ***");
if(!sdx[BUILTIN_SDCARD_missing_index].sdfs.begin(SdioConfig(FIFO_SDIO)))
{ Serial.printf("SDIO Storage %d %d %s failed or missing",BUILTIN_SDCARD_missing_index,cs[BUILTIN_SDCARD_missing_index],sd_str[BUILTIN_SDCARD_missing_index]); Serial.println();
}
else
{
// The SD is valid now...
uint32_t store = storage.getStoreID(sd_str[BUILTIN_SDCARD_missing_index]);
if (store != 0xFFFFFFFFUL)
{
mtpd.send_StoreRemovedEvent(store);
delay(50);
//mtpd.send_StorageInfoChangedEvent(store);
mtpd.send_StoreAddedEvent(store);
} else {
// not in our list, try adding it
store = storage.addFilesystem(sdx[BUILTIN_SDCARD_missing_index], sd_str[BUILTIN_SDCARD_missing_index]);
mtpd.send_StoreAddedEvent(store);
}
uint64_t totalSize = sdx[BUILTIN_SDCARD_missing_index].totalSize();
uint64_t usedSize = sdx[BUILTIN_SDCARD_missing_index].usedSize();
Serial.printf("SDIO Storage %d %d %s ",BUILTIN_SDCARD_missing_index,cs[BUILTIN_SDCARD_missing_index],sd_str[BUILTIN_SDCARD_missing_index]);
Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
}
BUILTIN_SDCARD_missing_index = -1; // only try this once
}
}
#endif
}
Note I currently have changes to MTP and MSC projects, plus some hacks in the SDFat (more debug code) trying to understand why things are doing what they are doing.
Right now testing with just one USB drive, the one that has 3 partitions... But only two show up...

Debug output:
Code:
MTP_test
FsVolume::begin(20004250)
ExFatVolume::begin(20004250 0 1
ExFatPartition::init(20004250, 1)
after part>4
after boot test
after EXFAT
Return true
After init
After chdir
sd_addFilesystem: 0 20003dbc sdio
SDIO Storage 0 254 sdio 32017219584 4653056
SD Storage 1 10 sd1 failed or missing
sd_addFilesystem: 1 20006bb8 RAM1
RAM Storage 0 RAM1 199936 512
sd_addFilesystem: 2 20006c80 RAM2
RAM Storage 1 RAM2 3999744 4096
sd_addFilesystem: 3 20003520 PROGM
Program Storage 0 PROGM 983040 8192
QSPI Storage 0 QSPI failed or missing
SPIFlash Storage 0 5 sflash5 failed or missing
SPIFlash Storage 1 6 sflash6 failed or missing
SPIFlash Storage 2 7 prop failed or missing
Flash ID: 00 00 00
SPIFlash NAND Storage 0 3 WINBOND1G failed or missing
Flash ID: 00 00 00
SPIFlash NAND Storage 1 4 WINBOND2G failed or missing
Initializing USB MSC drives...
USB Drive Inserted
msc # Partition Table
part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT32: 1,0,0x4,0x1,0x4,0xB,0xFE,0xC2,0xFF,2048,8192000
FAT16: 2,0,0xE,0x51,0xFE,0xE,0x98,0x98,0x80,8194048,2097152
exFAT: 3,0,0x98,0x99,0x80,0x7,0xEE,0xDC,0xD2,10291200,5435392
pt_#0: 4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
Try Partiton:1 on MSC Index:0
UsbBase::mscBegin called 20006d60 0 1
After usbDriveBegin
PFsVolume::begin(20007eec)
ExFatVolume::begin(20007eec 0 1
ExFatPartition::init(20007eec, 1)
after part>4
after boot test
FatVolume::Begin 20007eec 0 1
*** Return true
** SUCCEEDED **
>> USB partition 1 valume ID: VOLFAT32
sd_addFilesystem: 4 20007a58 MSC0-VOLFAT32
Try Partiton:2 on MSC Index:1
UsbBase::mscBegin called 20006d60 0 2
After usbDriveBegin
PFsVolume::begin(2000839c)
ExFatVolume::begin(2000839c 0 2
ExFatPartition::init(2000839c, 2)
after part>4
after boot test
FatVolume::Begin 2000839c 0 2
*** Return true
** SUCCEEDED **
>> USB partition 2 valume ID: VOLFAT16
sd_addFilesystem: 5 20007f08 MSC0-VOLFAT16
Try Partiton:3 on MSC Index:2
UsbBase::mscBegin called 20006d60 0 3
After usbDriveBegin
PFsVolume::begin(2000884c)
ExFatVolume::begin(2000884c 0 3
ExFatPartition::init(2000884c, 3)
after part>4
FatVolume::Begin 2000884c 0 3
Try Partiton:4 on MSC Index:2
UsbBase::mscBegin called 20006d60 0 4
After usbDriveBegin
PFsVolume::begin(2000884c)
ExFatVolume::begin(2000884c 0 4
ExFatPartition::init(2000884c, 4)
after part>4
FatVolume::Begin 2000884c 0 4
**** dir of sd[0] ****
T4.1-Cardlike.jpg
T4-Cardlike.jpg
DSC03355.JPG
test1.txt
mtpindex.dat
Setup done
CMD: 1002(OPEN_SESSION)l: 16 T:0 : 1
RESP:2001(RSP:OK)l: 16 T:0 : 1
CMD: 1001(GET_DEVICE_INFO)l: 12 T:1
RESP:2001(RSP:OK)l: 12 T:1
CMD: 1014(GET_DEVICE_PROP_DESC)l: 16 T:2 : d402
RESP:2001(RSP:OK)l: 16 T:2 : d402
CMD: 1004(GET_STORAGE_IDS)l: 12 T:3
RESP:2001(RSP:OK)l: 12 T:3
CMD: 1005(GET_STORAGE_INFO)l: 16 T:4 : 1
1 0 name:sdio vol:
1 0 name:sdio vol:
RESP:2001(RSP:OK)l: 16 T:4 : 1
CMD: 1005(GET_STORAGE_INFO)l: 16 T:5 : 2
2 1 name:RAM1 vol:
2 1 name:RAM1 vol:
RESP:2001(RSP:OK)l: 16 T:5 : 2
CMD: 1005(GET_STORAGE_INFO)l: 16 T:6 : 3
3 2 name:RAM2 vol:
3 2 name:RAM2 vol:
RESP:2001(RSP:OK)l: 16 T:6 : 3
CMD: 1005(GET_STORAGE_INFO)l: 16 T:7 : 4
4 3 name:PROGM vol:
4 3 name:PROGM vol:
RESP:2001(RSP:OK)l: 16 T:7 : 4
CMD: 1005(GET_STORAGE_INFO)l: 16 T:8 : 5
5 4 name:MSC0-VOLFAT32 vol:
5 4 name:MSC0-VOLFAT32 vol:
RESP:2001(RSP:OK)l: 16 T:8 : 5
CMD: 1005(GET_STORAGE_INFO)l: 16 T:9 : 6
6 5 name:MSC0-VOLFAT16 vol:
6 5 name:MSC0-VOLFAT16 vol:
RESP:2001(RSP:OK)l: 16 T:9 : 6
CMD: 9801(GET_OBJECT_PROPS_SUPPORTED)l: 16 T:a : 3000
RESP:2001(RSP:OK)l: 16 T:a : 3000
CMD: 9801(GET_OBJECT_PROPS_SUPPORTED)l: 16 T:b : 3001
RESP:2001(RSP:OK)l: 16 T:b : 3001
The part in RED is where it should have gone through and detected the ExFat partition, but the ExFat code bailed on:
Code:
bool ExFatPartition::init(BlockDevice* dev, uint8_t part) {
uint32_t volStart = 0;
uint8_t* cache;
pbs_t* pbs;
BpbExFat_t* bpb;
MbrSector_t* mbr;
MbrPart_t* mp;
Serial.printf("ExFatPartition::init(%x, %u)\n",(uint32_t)dev, part);
m_fatType = 0;
m_blockDev = dev;
cacheInit(m_blockDev);
cache = dataCacheGet(0, FsCache::CACHE_FOR_READ);
if (part > 4 || !cache) {
DBG_FAIL_MACRO;
goto fail;
}
Serial.println(" after part>4");
if (part >= 1) {
mbr = reinterpret_cast<MbrSector_t*>(cache);
mp = &mbr->part[part - 1];
if ((mp->boot != 0 && mp->boot != 0X80) || mp->type == 0) {
DBG_FAIL_MACRO;
goto fail;
}
Serial.println(" after boot test");
volStart = getLe32(mp->relativeSectors);
cache = dataCacheGet(volStart, FsCache::CACHE_FOR_READ);
if (!cache) {
DBG_FAIL_MACRO;
goto fail;
}
}
pbs = reinterpret_cast<pbs_t*>(cache);
if (strncmp(pbs->oemName, "EXFAT", 5)) {
DBG_FAIL_MACRO;
goto fail;
}
Serial.println(" after EXFAT");
bpb = reinterpret_cast<BpbExFat_t*>(pbs->bpb);
if (bpb->bytesPerSectorShift != m_bytesPerSectorShift) {
DBG_FAIL_MACRO;
goto fail;
}
m_fatStartSector = volStart + getLe32(bpb->fatOffset);
m_fatLength = getLe32(bpb->fatLength);
m_clusterHeapStartSector = volStart + getLe32(bpb->clusterHeapOffset);
m_clusterCount = getLe32(bpb->clusterCount);
m_rootDirectoryCluster = getLe32(bpb->rootDirectoryCluster);
m_sectorsPerClusterShift = bpb->sectorsPerClusterShift;
m_bytesPerCluster = 1UL << (m_bytesPerSectorShift + m_sectorsPerClusterShift);
m_clusterMask = m_bytesPerCluster - 1;
// Set m_bitmapStart to first free cluster.
m_bitmapStart = 0;
bitmapFind(0, 1);
m_fatType = FAT_TYPE_EXFAT;
Serial.println(" Return true");
return true;
fail:
return false;
}
I showed the debug code that I put in the ExVolume and you can see the last output was the >4 messages... So it bailed in the boot test... Not sure why in this case as it works with the VolumeLabel sketch...
More debugging! I could create new temporary branches of any of this if anyone wants to play along.
Kurt
EDIT: Forgot to mention that current hack in MTP get storage info that if partition > 3gb I just return half free and not ask for it to crunch through all of the sectors... only temporary need to find better solution, but...