USBHost_t36 USB Mass Storage Driver Experiments

@defragster

I included T4_PowerButton.h. What else do I need to do to show hard faults if they happen? This is new to me:)

Thanks
 
@KurtE
Was just looking over your code snippet so this is a question - it may be buried but I don't see where you are setting up expartVol/partVol .begin for the different partitions and then setting a mscfs based on that?

EDIT: You may need a modified addfilesystem in MTP where you pass each partition based on type and do the begins accordingly in MTP. Forming idea in head but its giving me a headache.
 
@mjs513 which code fragment... MSC or MTP... So far in MTP I have not converted the main code to try to do anything with partitions, other than so far I am printing them out and I am able to get the first volume ID.

So far I am not having any luck with anyone actually doing anything with the volume ID. I updated storage class to have the string which I pass off to the data back to the PC along with the name.

On PC I don't so far see anywhere where it shows up. On Linux I am having issues of dynamically adding volumes and have them show up...

Still looking. I think Linux still have issues with speed of startup. I think the linux times out after the USB starts that I we don't respond quickly enough probably to the start session or...

Will play more!
 
Just an FYI: I updated the Volume name sketch to also print out the total size and used size sort of plus elapsed time to get them for the different partitions:
Code:
//  VolumeName.ino
//  An example of how to retrieve Fat32 and ExFat volume names using SdFat.
//  Works with SD cards and USB mass storage drives.

#include "Arduino.h"
#include "mscFS.h"

// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);

//#define SHOW_CLOCK_CARAT 1
IntervalTimer clocked100ms;
volatile int32_t cmsReport = -1;

// Setup MSC for the number of USB Drives you are using. (Two for this example)
// Mutiple  USB drives can be used. Hot plugging is supported. There is a slight
// delay after a USB MSC device is plugged in. This is waiting for initialization
// but after it is initialized ther should be no delay.
msController msDrive1(myusb);
msController msDrive2(myusb);

#define SD_DRIVE 1
#define MS_DRIVE 2

#define SD_CONFIG SdioConfig(FIFO_SDIO)

// set up variables using the mscFS utility library functions:
UsbFs msc1;
UsbFs msc2;

SdFs sd;
//FatVolume partVol;

//create holding array for partions
uint8_t partitionTable[4];
int32_t dataStart[4];

// Get ExFat volume name.

bool getExFatVolumeLabel(uint8_t  drvType, uint8_t part, UsbFs *myMsc) {
  uint8_t buf[32];
  UsbExFat volName;
  SdExFat volName1;
  ExFatFile root;
  //msController *mscDrive;
  DirLabel_t *dir;

  ExFatVolume expartVol;

  if (drvType == MS_DRIVE) {
    //mscDrive = &msDrive1;
    //if (!volName.begin(&msDrive1)) {
    //   Serial.println("EXFat volName.begin failed");
    //   return false;
    // }
    expartVol.begin(myMsc->usbDrive(), true, part);
    expartVol.chvol();
    if (!root.openRoot(&expartVol)) {
      Serial.println("openRoot failed");
      return false;
    }
  }
  if (drvType == SD_DRIVE) {
    if (!volName1.begin(SD_CONFIG)) {
      return false;
    }
    if (!root.openRoot(&volName1)) {
      Serial.println("openRoot failed");
      return false;
    }
  }

  root.read(buf, 32);
  dir = reinterpret_cast<DirLabel_t*>(buf);
  Serial.print(F("Volume Name: "));
  for (size_t i = 0; i < dir->labelLength; i++) {
    Serial.write(dir->unicode[2 * i]);
  }
  Serial.println();
  expartVol.ls(LS_SIZE | LS_DATE | LS_R);
  return true;
}

// Get Fat32 volume name.
bool getFat32VolumeLabel(uint8_t  drvType, uint8_t part, UsbFs *myMsc) {
  FatVolume partVol;

  uint8_t buf[512];

  partVol.begin(myMsc->usbDrive(), true, part);
  partVol.chvol();
  if (drvType == MS_DRIVE) {
    myMsc->usbDrive()->readSector(partVol.dataStartSector(), buf);
  }

  if (drvType == SD_DRIVE) {
    sd.card()->readSector(sd.dataStartSector(), buf);
  }
  Serial.print(F("Volume Name: "));
  for (size_t i = 0; i < 11; i++) {
    if ( buf[i] > 0 && buf[i] < 127 )
      Serial.write(buf[i]);
  }
  Serial.println();
  partVol.ls(LS_SIZE | LS_DATE | LS_R);

  return true;
}

// Get Fat16 volume name.
// Get Fat16 volume name.
bool getFat16VolumeLabel(uint8_t  drvType, uint8_t part, UsbFs *myMsc) {
  FatVolume partVol;

  uint8_t buf[512];

  partVol.begin(myMsc->usbDrive(), true, part);
  partVol.chvol();
  if (drvType == MS_DRIVE) {
    myMsc->usbDrive()->readSector(partVol.rootDirStart(), buf);
  }

  if (drvType == SD_DRIVE) {
    sd.card()->readSector(sd.dataStartSector(), buf);
    print_hexbytes(buf, 512);
  }
  Serial.print(F("Volume Name: "));
  for (size_t i = 0; i < 11; i++) {
    Serial.write(buf[i]);
  }
  Serial.println();
  partVol.ls(LS_SIZE | LS_DATE | LS_R);

  return true;
}


bool getUSBPartitionVolumeLabel(UsbFs *myMsc, uint8_t part, uint8_t *pszVolName, uint16_t cb) {
  MbrSector_t mbr;
  uint8_t buf[512];
  if (!pszVolName || (cb < 12)) return false; // don't want to deal with it
  myMsc->usbDrive()->readSector(0, (uint8_t*)&mbr);
  MbrPart_t *pt = &mbr.part[part - 1];
  switch (pt->type) {
    case 4:
    case 6:
    case 0xe:
      {
        FatVolume partVol;
        Serial.print("FAT16:\t");

        partVol.begin(myMsc->usbDrive(), true, part);
        partVol.chvol();
        myMsc->usbDrive()->readSector(partVol.rootDirStart(), buf);

        size_t i;
        for (i = 0; i < 11; i++) {
          pszVolName[i]  = buf[i];
        }
        while ((i > 0) && (pszVolName[i - 1] == ' ')) i--; // trim off trailing blanks
        pszVolName[i] = 0;
      }
      break;
    case 11:
    case 12:
      {
        FatVolume partVol;
        Serial.print("FAT32:\t");
        partVol.begin(myMsc->usbDrive(), true, part);
        partVol.chvol();
        myMsc->usbDrive()->readSector(partVol.dataStartSector(), buf);

        size_t i;
        for (i = 0; i < 11; i++) {
          pszVolName[i]  = buf[i];
        }
        while ((i > 0) && (pszVolName[i - 1] == ' ')) i--; // trim off trailing blanks
        pszVolName[i] = 0;
      }
      break;
    case 7:
      {
        Serial.print("exFAT:\t");
        ExFatFile root;
        DirLabel_t *dir;

        ExFatVolume expartVol;

        expartVol.begin(myMsc->usbDrive(), true, part);
        expartVol.chvol();
        if (!root.openRoot(&expartVol)) {
          Serial.println("openRoot failed");
          return false;
        }
        root.read(buf, 32);
        dir = reinterpret_cast<DirLabel_t*>(buf);

        size_t i;
        for (i = 0; i < dir->labelLength; i++) {
          pszVolName[i] = dir->unicode[2 * i];
        }
        pszVolName[i] = 0;
      }

      break;
    default:
      return false;
  }
  return true;
}



bool mbrDmp(UsbFs *myMsc) {
  MbrSector_t mbr;
  // bool valid = true;
  if (!myMsc->usbDrive()->readSector(0, (uint8_t*)&mbr)) {
    Serial.print("\nread MBR failed.\n");
    //errorPrint();
    return false;
  }
  Serial.print("\nmsc # Partition Table\n");
  Serial.print("\tpart,boot,bgnCHS[3],type,endCHS[3],start,length\n");
  for (uint8_t ip = 1; ip < 5; ip++) {
    MbrPart_t *pt = &mbr.part[ip - 1];
    //    if ((pt->boot != 0 && pt->boot != 0X80) ||
    //        getLe32(pt->relativeSectors) > sdCardCapacity(&m_csd)) {
    //      valid = false;
    //    }
    switch (pt->type) {
      case 4:
      case 6:
      case 0xe:
        Serial.print("FAT16:\t");
        break;
      case 11:
      case 12:
        Serial.print("FAT32:\t");
        break;
      case 7:
        Serial.print("exFAT:\t");
        break;
      default:
        Serial.print("pt_#");
        Serial.print(pt->type);
        Serial.print(":\t");
        break;
    }
    partitionTable[ip - 1] = pt->type;
    dataStart[ip - 1] = getLe32(pt->relativeSectors);
    Serial.print( int(ip)); Serial.print( ',');
    Serial.print(int(pt->boot), HEX); Serial.print( ',');
    for (int i = 0; i < 3; i++ ) {
      Serial.print("0x"); Serial.print(int(pt->beginCHS[i]), HEX); Serial.print( ',');
    }
    Serial.print("0x"); Serial.print(int(pt->type), HEX); Serial.print( ',');
    for (int i = 0; i < 3; i++ ) {
      Serial.print("0x"); Serial.print(int(pt->endCHS[i]), HEX); Serial.print( ',');
    }
    Serial.print(getLe32(pt->relativeSectors), DEC); Serial.print(',');
    Serial.println(getLe32(pt->totalSectors));
  }
  return true;
}

void setup()
{
#if 0 // easy test to check HardFault Detection response
  int *pp = 0;
  *pp = 5;
#endif
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    SysCall::yield(); // wait for serial port to connect.
  }

  // Start USBHost_t36, HUB(s) and USB devices.
  myusb.begin();

#ifdef SHOW_CLOCK_CARAT
  clocked100ms.begin(clock_isr, 100000);
#endif

}

void clock_isr() {
  if (cmsReport >= 0 ) {
    if (cmsReport > 0 ) {
      if (cmsReport < 10 )
        Serial.print( "^");
      else if ( cmsReport < 50 && !(cmsReport % 10) )
        Serial.print( "~");
      else if ( !(cmsReport % 50) )
        Serial.print( ":(");
    }
    cmsReport++;
  }
}

void print_hexbytes(const void *ptr, int len)
{
  if (ptr == NULL || len <= 0) return;
  const uint8_t *p = (const uint8_t *)ptr;
  while (len) {
    for (uint8_t i = 0; i < 32; i++) {
      if (i > len) break;
      Serial.printf("%02X ", p[i]);
    }
    Serial.print(":");
    for (uint8_t i = 0; i < 32; i++) {
      if (i > len) break;
      Serial.printf("%c", ((p[i] >= ' ') && (p[i] <= '~')) ? p[i] : '.');
    }
    Serial.println();
    p += 32;
    len -= 32;
  }
}



// Function to handle one MS Drive...
void procesMSDrive(uint8_t drive_number, msController &msDrive, UsbFs &msc)
{
  Serial.printf("Initialize USB drive...");
  cmsReport = 0;
  if (!msc.begin(&msDrive)) {
    Serial.println("");
    msc.errorPrint(&Serial);
    Serial.printf("initialization drive %u failed.\n", drive_number);
  } else {
    Serial.printf("USB drive %u is present.\n", drive_number);
  }
  cmsReport = -1;

  mbrDmp( &msc );
  for (uint8_t i = 1; i < 5; i++) {

    switch (partitionTable[i - 1]) {
      case 11:
      case 12:
        Serial.printf("\nFat Type: Fat32\n");
        if (!getFat32VolumeLabel(MS_DRIVE, i, &msc))
          Serial.printf("Failed to get volume label\n");
        break;
      case 4:
      case 6:
      case 0xe:
        Serial.printf("\nFat Type: Fat16\n");
        if (!getFat16VolumeLabel(MS_DRIVE, i, &msc))
          Serial.printf("Failed to get volume label\n");
        break;
      case 7:
        Serial.printf("\nFat Type: ExFat\n");
        if (!getExFatVolumeLabel(MS_DRIVE, i, &msc))
          Serial.printf("Failed to get volume label\n");
        break;
      default:
        Serial.println("No or Not Supported Partition");
    }
    // lets see if our all in one works
    uint8_t volName[32];
    Serial.println("Try calling getUSBPartitionVolumeLabel");
    if (getUSBPartitionVolumeLabel(&msc, i, volName, sizeof(volName))) {
      Serial.printf(">> Volume name:(%s)\n", volName);
    }
    elapsedMicros em_sizes = 0;
    uint64_t used_size =  (uint64_t)(msc.clusterCount() - msc.freeClusterCount())
                          * (uint64_t)msc.bytesPerCluster();
    uint64_t total_size = (uint64_t)msc.clusterCount() * (uint64_t)msc.bytesPerCluster();
    Serial.printf("Total Size:%llu Used:%llu time us: %u\n", total_size, used_size,
                  (uint32_t)em_sizes);
  }
}

//================================================================
void loop(void) {
  //--------------------------------------------------
  cmsReport = 0;
  myusb.Task();
  if (!msDrive1) {
    Serial.println("Waiting up to 5 seconds for USB drive 1");
    elapsedMillis em = 0;
    while (!msDrive1 && (em < 5000) )  myusb.Task();
  }
  if (!msDrive2) {
    Serial.println("Waiting up to 5 seconds for USB drive 2");
    elapsedMillis em = 0;
    while (!msDrive2 && (em < 5000) )  myusb.Task();
  }
  if (msDrive1) {
    procesMSDrive(1, msDrive1, msc1);
  }
  if (msDrive2) {
    procesMSDrive(2, msDrive2, msc2);
  }
  cmsReport = -1;
  //--------------------------------------------------
  Serial.printf("\nInitialize SD card...");

  if (!sd.begin(SD_CONFIG)) {
    Serial.println("initialization failed.\n");
  } else {
    Serial.println("SD card is present.\n");

    if (sd.fatType() == 32) {
      Serial.printf("Fat Type: Fat32\n");
      if (!getFat32VolumeLabel(SD_DRIVE, 1, &msc2))
        Serial.printf("Failed to get volume label\n");
    } else {
      Serial.printf("Fat Type: ExFAT\n");
      if (!getExFatVolumeLabel(SD_DRIVE, 1, &msc2)) {
        Serial.printf("Failed to get volume label\n");
      }
    }
    //sd.ls(LS_SIZE | LS_DATE | LS_R);
  }

  Serial.println("done...");

  Serial.println("Press any key to run again");
  while (Serial.read() == -1);
  while (Serial.read() != -1);
}
Output with two SD cards one with 3 partitions:
Code:
Waiting up to 5 seconds for USB drive 1
Waiting up to 5 seconds for USB drive 2
Initialize USB drive...FsVolume::begin(20001fe0)
ExFatPartition::init(20001fe0, 1)
FatPartition::init(20001fe0, 1)
USB drive 1 is present.

msc # Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT16:	1,0,0x3,0x37,0x0,0xE,0xFE,0x3F,0x7C,243,2013741
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

Fat Type: Fat16
FatPartition::init(20001fe0, 1)
Volume Name: CRUZER     
                     393481 T4.1-Cardlike.jpg
                    3355221 DSC03356.JPG
Try calling getUSBPartitionVolumeLabel
FAT16:	FatPartition::init(20001fe0, 1)
>> Volume name:(CRUZER)
Total Size:1030750208 Used:3817472 time us: 95999
No or Not Supported Partition
Try calling getUSBPartitionVolumeLabel
Total Size:1030750208 Used:3817472 time us: 95501
No or Not Supported Partition
Try calling getUSBPartitionVolumeLabel
Total Size:1030750208 Used:3817472 time us: 96001
No or Not Supported Partition
Try calling getUSBPartitionVolumeLabel
Total Size:1030750208 Used:3817472 time us: 95751
Initialize USB drive...FsVolume::begin(2000247c)
ExFatPartition::init(2000247c, 1)
FatPartition::init(2000247c, 1)
USB drive 2 is present.

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

Fat Type: Fat32
FatPartition::init(2000247c, 1)
Volume Name: VOLFAT32   
2010-03-22 07:11    3343737 DSC03357.JPG
2021-01-01 00:00          0 example.txt
2021-02-24 16:35          0 OnFat32.txt
Try calling getUSBPartitionVolumeLabel
FAT32:	FatPartition::init(2000247c, 1)
>> Volume name:(VOLFAT32)
Total Size:4186095616 Used:3362816 time us: 6018748

Fat Type: Fat16
FatPartition::init(2000247c, 2)
Volume Name: VOLFAT16   
2021-01-13 17:56     340510 T4-Cardlike.jpg
2021-02-24 16:34          0 OnFat16.txt
Try calling getUSBPartitionVolumeLabel
FAT16:	FatPartition::init(2000247c, 2)
>> Volume name:(VOLFAT16)
Total Size:4186095616 Used:3362816 time us: 6020248

Fat Type: ExFat
ExFatPartition::init(2000247c, 3)
Volume Name: VolEXFAT
2021-01-24 06:23       393481 T4.1-Cardlike.jpg
2021-02-24 16:35            0 OnExFat.txt
Try calling getUSBPartitionVolumeLabel
exFAT:	ExFatPartition::init(2000247c, 3)
>> Volume name:(VolEXFAT)
Total Size:4186095616 Used:3362816 time us: 6019873
No or Not Supported Partition
Try calling getUSBPartitionVolumeLabel
Total Size:4186095616 Used:3362816 time us: 6020500

Initialize SD card...initialization failed.

done...
Press any key to run again

Or the interesting stuff:
Code:
>> Volume name:(CRUZER)
Total Size:1030750208 Used:3817472 time us: 95999


>> Volume name:(VOLFAT32)
Total Size:4186095616 Used:3362816 time us: 6018748
>> Volume name:(VOLFAT16)
Total Size:4186095616 Used:3362816 time us: 6020248
>> Volume name:(VolEXFAT)
Total Size:4186095616 Used:3362816 time us: 6019873

It is interesting that the one smaller CRUZER didk took about .1 seconds.

And the larger one with three partitions, each one took over 6 seconds...

Wonder why? Or if it takes that long on other OS?

WIll play more tomorrow.
 
@defragster

I figured out how to install it from FrankB's cores. Locked up without info still:(

Glad you got it - there is an #if 0 in setup that will quickly confirm Faults are trapped as configured.

Locked up? Does it do the CARAT printing from timer with "#define SHOW_CLOCK_CARAT 1"? If not then it is locked up and not faulting.

@KurtE - you leap frogged some minor edits - merged below. With your changes I see this:
Code:
...
msc # Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
exFAT:	1,0,0x20,0x21,0x0,0x7,0xFE,0xFF,0xFF,2048,234436608
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

USB Fat Type: ExFat
Volume Name: 120GB_Ext
2020-01-23 17:04     32768000 A_00001.dat
2020-01-23 17:04     32768000 A_00002.dat
2020-01-23 17:04     32768000 A_00003.dat
2020-01-23 17:04     32768000 A_00004.dat
2020-01-23 17:04     32768000 A_00005.dat
2020-01-23 17:04     32768000 A_00006.dat
                            0 A_00007.dat
Try calling getUSBPartitionVolumeLabel
exFAT:	>> Volume name:(120GB_Ext)
Total Size:120026300416 Used:197394432 time us: 84001
0 is No or Not Supported USB Partition
Total Size:120026300416 Used:197394432 time us: 83990
0 is No or Not Supported USB Partition
Total Size:120026300416 Used:197394432 time us: 83990
0 is No or Not Supported USB Partition
Total Size:120026300416 Used:197394432 time us: 83990
Initialize USB drive...^^^^USB drive 2 is present.

msc # Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT32:	1,80,0x20,0x21,0x0,0xC,0xFE,0xFF,0xFF,2048,67108864
FAT32:	2,0,0xFE,0xFF,0xFF,0xC,0xFE,0xFF,0xFF,67110912,54128640
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

USB Fat Type: Fat32
Volume Name: B Info
...
Try calling getUSBPartitionVolumeLabel
FAT32:	>> Volume name:(B )
Total Size:34347155456 Used:28836429824 time us: 3071498

USB Fat Type: Fat32
Volume Name: 64G_PT#2   
2021-02-24 09:01          0 FPartTwo.txt
Try calling getUSBPartitionVolumeLabel
FAT32:	>> Volume name:(64G_PT#2)
Total Size:34347155456 Used:28836429824 time us: 3071623
0 is No or Not Supported USB Partition
Total Size:34347155456 Used:28836429824 time us: 3071489
0 is No or Not Supported USB Partition
Total Size:34347155456 Used:28836429824 time us: 3071489
...

Current code - Merged:
Code:
//  VolumeName.ino
// VER: P494, p498, p506, p507
//  An example of how to retrieve Fat32 and ExFat volume names using SdFat.
//  Works with SD cards and USB mass storage drives.

#include "Arduino.h"
#include "mscFS.h"

// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);

#define SHOW_CLOCK_CARAT 1
IntervalTimer clocked100ms;
volatile int32_t cmsReport = -1;

// Setup MSC for the number of USB Drives you are using. (Two for this example)
// Mutiple  USB drives can be used. Hot plugging is supported. There is a slight
// delay after a USB MSC device is plugged in. This is waiting for initialization
// but after it is initialized ther should be no delay.
msController msDrive1(myusb);
msController msDrive2(myusb);

#define SD_DRIVE 1
#define MS_DRIVE 2

#define SD_CONFIG SdioConfig(FIFO_SDIO)

// set up variables using the mscFS utility library functions:
UsbFs msc1;
UsbFs msc2;

SdFs sd;
//FatVolume partVol;

//create holding array for partions
uint8_t partitionTable[4];
int32_t dataStart[4];

// Get ExFat volume name.

bool getExFatVolumeLabel(uint8_t  drvType, uint8_t part, UsbFs *myMsc) {
  uint8_t buf[32];
  UsbExFat volName;
  SdExFat volName1;
  ExFatFile root;
  //msController *mscDrive;
  DirLabel_t *dir;

  ExFatVolume expartVol;

  if (drvType == MS_DRIVE) {
    //mscDrive = &msDrive1;
    //if (!volName.begin(&msDrive1)) {
    //   Serial.println("EXFat volName.begin failed");
    //   return false;
    // }
    expartVol.begin(myMsc->usbDrive(), true, part);
    expartVol.chvol();
    if (!root.openRoot(&expartVol)) {
      Serial.println("openRoot failed");
      return false;
    }
  }
  if (drvType == SD_DRIVE) {
    if (!volName1.begin(SD_CONFIG)) {
      return false;
    }
    if (!root.openRoot(&volName1)) {
      Serial.println("openRoot failed");
      return false;
    }
  }

  root.read(buf, 32);
  dir = reinterpret_cast<DirLabel_t*>(buf);
  Serial.print(F("Volume Name: "));
  for (size_t i = 0; i < dir->labelLength; i++) {
    Serial.write(dir->unicode[2 * i]);
  }
  Serial.println();
  expartVol.ls(LS_SIZE | LS_DATE | LS_R);
  return true;
}

// Get Fat32 volume name.
bool getFat32VolumeLabel(uint8_t  drvType, uint8_t part, UsbFs *myMsc) {
  FatVolume partVol;

  uint8_t buf[512];

  if (drvType == MS_DRIVE) {
    partVol.begin(myMsc->usbDrive(), true, part);
    partVol.chvol();
    myMsc->usbDrive()->readSector(partVol.dataStartSector(), buf);
  }

  if (drvType == SD_DRIVE) {
    sd.card()->readSector(sd.dataStartSector(), buf);
  }
  Serial.print(F("Volume Name: "));
  for (size_t i = 0; i < 11; i++) {
    if ( buf[i] > 0 && buf[i] < 127 )
      Serial.write(buf[i]);
  }
  Serial.println();
  partVol.ls(LS_SIZE | LS_DATE | LS_R);

  return true;
}

// Get Fat16 volume name.
// Get Fat16 volume name.
bool getFat16VolumeLabel(uint8_t  drvType, uint8_t part, UsbFs *myMsc) {
  FatVolume partVol;

  uint8_t buf[512];

  if (drvType == MS_DRIVE) {
    partVol.begin(myMsc->usbDrive(), true, part);
    partVol.chvol();
    myMsc->usbDrive()->readSector(partVol.rootDirStart(), buf);
  }

  if (drvType == SD_DRIVE) {
    sd.card()->readSector(sd.dataStartSector(), buf);
    print_hexbytes(buf, 512);
  }
  Serial.print(F("Volume Name: "));
  for (size_t i = 0; i < 11; i++) {
    Serial.write(buf[i]);
  }
  Serial.println();
  partVol.ls(LS_SIZE | LS_DATE | LS_R);

  return true;
}


bool getUSBPartitionVolumeLabel(UsbFs *myMsc, uint8_t part, uint8_t *pszVolName, uint16_t cb) {
  MbrSector_t mbr;
  uint8_t buf[512];
  if (!pszVolName || (cb < 12)) return false; // don't want to deal with it
  myMsc->usbDrive()->readSector(0, (uint8_t*)&mbr);
  MbrPart_t *pt = &mbr.part[part - 1];
  switch (pt->type) {
  case 4:
  case 6:
  case 0xe:
  {
    FatVolume partVol;
    Serial.print("FAT16:\t");

    partVol.begin(myMsc->usbDrive(), true, part);
    partVol.chvol();
    myMsc->usbDrive()->readSector(partVol.rootDirStart(), buf);

    size_t i;
    for (i = 0; i < 11; i++) {
      pszVolName[i]  = buf[i];
    }
    while ((i > 0) && (pszVolName[i - 1] == ' ')) i--; // trim off trailing blanks
    pszVolName[i] = 0;
  }
  break;
  case 11:
  case 12:
  {
    FatVolume partVol;
    Serial.print("FAT32:\t");
    partVol.begin(myMsc->usbDrive(), true, part);
    partVol.chvol();
    myMsc->usbDrive()->readSector(partVol.dataStartSector(), buf);

    size_t i;
    for (i = 0; i < 11; i++) {
      pszVolName[i]  = buf[i];
    }
    while ((i > 0) && (pszVolName[i - 1] == ' ')) i--; // trim off trailing blanks
    pszVolName[i] = 0;
  }
  break;
  case 7:
  {
    Serial.print("exFAT:\t");
    ExFatFile root;
    DirLabel_t *dir;

    ExFatVolume expartVol;

    expartVol.begin(myMsc->usbDrive(), true, part);
    expartVol.chvol();
    if (!root.openRoot(&expartVol)) {
      Serial.println("openRoot failed");
      return false;
    }
    root.read(buf, 32);
    dir = reinterpret_cast<DirLabel_t*>(buf);

    size_t i;
    for (i = 0; i < dir->labelLength; i++) {
      pszVolName[i] = dir->unicode[2 * i];
    }
    pszVolName[i] = 0;
  }

  break;
  default:
    return false;
  }
  return true;
}



bool mbrDmp(UsbFs *myMsc) {
  MbrSector_t mbr;
  // bool valid = true;
  if (!myMsc->usbDrive()->readSector(0, (uint8_t*)&mbr)) {
    Serial.print("\nread MBR failed.\n");
    //errorPrint();
    return false;
  }
  Serial.print("\nmsc # Partition Table\n");
  Serial.print("\tpart,boot,bgnCHS[3],type,endCHS[3],start,length\n");
  for (uint8_t ip = 1; ip < 5; ip++) {
    MbrPart_t *pt = &mbr.part[ip - 1];
    //    if ((pt->boot != 0 && pt->boot != 0X80) ||
    //        getLe32(pt->relativeSectors) > sdCardCapacity(&m_csd)) {
    //      valid = false;
    //    }
    switch (pt->type) {
    case 4:
    case 6:
    case 0xe:
      Serial.print("FAT16:\t");
      break;
    case 11:
    case 12:
      Serial.print("FAT32:\t");
      break;
    case 7:
      Serial.print("exFAT:\t");
      break;
    default:
      Serial.print("pt_#");
      Serial.print(pt->type);
      Serial.print(":\t");
      break;
    }
    partitionTable[ip - 1] = pt->type;
    dataStart[ip - 1] = getLe32(pt->relativeSectors);
    Serial.print( int(ip)); Serial.print( ',');
    Serial.print(int(pt->boot), HEX); Serial.print( ',');
    for (int i = 0; i < 3; i++ ) {
      Serial.print("0x"); Serial.print(int(pt->beginCHS[i]), HEX); Serial.print( ',');
    }
    Serial.print("0x"); Serial.print(int(pt->type), HEX); Serial.print( ',');
    for (int i = 0; i < 3; i++ ) {
      Serial.print("0x"); Serial.print(int(pt->endCHS[i]), HEX); Serial.print( ',');
    }
    Serial.print(getLe32(pt->relativeSectors), DEC); Serial.print(',');
    Serial.println(getLe32(pt->totalSectors));
  }
  return true;
}

void setup()
{
#if 0 // easy test to check HardFault Detection response
  int *pp = 0;
  *pp = 5;
#endif
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    SysCall::yield(); // wait for serial port to connect.
  }

  // Start USBHost_t36, HUB(s) and USB devices.
  myusb.begin();

#ifdef SHOW_CLOCK_CARAT
  clocked100ms.begin(clock_isr, 100000);
#endif

}

void clock_isr() {
  if (cmsReport >= 0 ) {
    if (cmsReport > 0 ) {
      if (cmsReport < 10 )
        Serial.print( "^");
      else if ( cmsReport < 50 && !(cmsReport % 10) )
        Serial.print( "~");
      else if ( !(cmsReport % 50) )
        Serial.print( ":(");
    }
    cmsReport++;
  }
}

void print_hexbytes(const void *ptr, int len)
{
  if (ptr == NULL || len <= 0) return;
  const uint8_t *p = (const uint8_t *)ptr;
  while (len) {
    for (uint8_t i = 0; i < 32; i++) {
      if (i > len) break;
      Serial.printf("%02X ", p[i]);
    }
    Serial.print(":");
    for (uint8_t i = 0; i < 32; i++) {
      if (i > len) break;
      Serial.printf("%c", ((p[i] >= ' ') && (p[i] <= '~')) ? p[i] : '.');
    }
    Serial.println();
    p += 32;
    len -= 32;
  }
}



// Function to handle one MS Drive...
void procesMSDrive(uint8_t drive_number, msController &msDrive, UsbFs &msc)
{
  Serial.printf("Initialize USB drive...");
  cmsReport = 0;
  if (!msc.begin(&msDrive)) {
    Serial.println("");
    msc.errorPrint(&Serial);
    Serial.printf("initialization drive %u failed.\n", drive_number);
  } else {
    Serial.printf("USB drive %u is present.\n", drive_number);
  }
  cmsReport = -1;

  mbrDmp( &msc );
  for (uint8_t i = 1; i < 5; i++) {

    switch (partitionTable[i - 1]) {
    case 11:
    case 12:
      Serial.printf("\nUSB Fat Type: Fat32\n");
      if (!getFat32VolumeLabel(MS_DRIVE, i, &msc))
        Serial.printf("Failed to get volume label\n");
      break;
    case 4:
    case 6:
    case 0xe:
      Serial.printf("\nUSB Fat Type: Fat16\n");
      if (!getFat16VolumeLabel(MS_DRIVE, i, &msc))
        Serial.printf("Failed to get volume label\n");
      break;
    case 7:
      Serial.printf("\nUSB Fat Type: ExFat\n");
      if (!getExFatVolumeLabel(MS_DRIVE, i, &msc))
        Serial.printf("Failed to get volume label\n");
      break;
    default:
      Serial.print( partitionTable[i - 1] );
      Serial.println(" is No or Not Supported USB Partition");
    }
    // lets see if our all in one works
    uint8_t volName[32];
    if ( 0 != partitionTable[i - 1] ) {
      Serial.println("Try calling getUSBPartitionVolumeLabel");
      if (getUSBPartitionVolumeLabel(&msc, i, volName, sizeof(volName))) {
        Serial.printf(">> Volume name:(%s)\n", volName);
      }
    }
    elapsedMicros em_sizes = 0;
    uint64_t used_size =  (uint64_t)(msc.clusterCount() - msc.freeClusterCount())
                          * (uint64_t)msc.bytesPerCluster();
    uint64_t total_size = (uint64_t)msc.clusterCount() * (uint64_t)msc.bytesPerCluster();
    Serial.printf("Total Size:%llu Used:%llu time us: %u\n", total_size, used_size,
                  (uint32_t)em_sizes);
  }
}

//================================================================
void loop(void) {
  //--------------------------------------------------
  cmsReport = 0;
  myusb.Task();
  if (!msDrive1) {
    Serial.println("Waiting up to 5 seconds for USB drive 1");
    elapsedMillis em = 0;
    while (!msDrive1 && (em < 5000) )  myusb.Task();
  }
  if (!msDrive2) {
    Serial.println("Waiting up to 5 seconds for USB drive 2");
    elapsedMillis em = 0;
    while (!msDrive2 && (em < 5000) )  myusb.Task();
  }
  if (msDrive1) {
    procesMSDrive(1, msDrive1, msc1);
  }
  if (msDrive2) {
    procesMSDrive(2, msDrive2, msc2);
  }
  cmsReport = -1;
  //--------------------------------------------------
  Serial.printf("\nInitialize SD card...");

  if (!sd.begin(SD_CONFIG)) {
    Serial.println("initialization failed.\n");
  } else {
    Serial.println("SD card is present.\n");

    if (sd.fatType() == 32) {
      Serial.printf("SD Fat Type: Fat32\n");
      if (!getFat32VolumeLabel(SD_DRIVE, 1, nullptr))
        Serial.printf("Failed to get volume label\n");
    } else {
      Serial.printf("SD Fat Type: ExFAT\n");
      if (!getExFatVolumeLabel(SD_DRIVE, 1, nullptr)) {
        Serial.printf("Failed to get volume label\n");
      }
    }
    //sd.ls(LS_SIZE | LS_DATE | LS_R);
  }

  Serial.println("done...");

  Serial.println("Press any key to run again");
  while (Serial.read() == -1);
  while (Serial.read() != -1);
}
 
Thanks @defragster,

I updated to your version.

I ran again, still real slow on my older thumb drives:
Code:
Waiting up to 5 seconds for USB drive 1
^^Waiting up to 5 seconds for USB drive 2
^^^^Initialize USB drive...^^^^FsVolume::begin(20002000)
ExFatPartition::init(20002000, 1)
FatPartition::init(20002000, 1)
USB drive 1 is present.

msc # Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT16:	1,0,0x3,0x37,0x0,0xE,0xFE,0x3F,0x7C,243,2013741
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

USB Fat Type: Fat16
FatPartition::init(20002000, 1)
Volume Name: CRUZER     
                     393481 T4.1-Cardlike.jpg
                    3355221 DSC03356.JPG
Try calling getUSBPartitionVolumeLabel
FAT16:	FatPartition::init(20002000, 1)
>> Volume name:(CRUZER)
Total Size:1030750208 Used:3817472 time us: 96749
0 is No or Not Supported USB Partition
Total Size:1030750208 Used:3817472 time us: 96116
0 is No or Not Supported USB Partition
Total Size:1030750208 Used:3817472 time us: 96241
0 is No or Not Supported USB Partition
Total Size:1030750208 Used:3817472 time us: 94741
Initialize USB drive...^^^^^^^^FsVolume::begin(2000249c)
ExFatPartition::init(2000249c, 1)
FatPartition::init(2000249c, 1)
USB drive 2 is present.

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

USB Fat Type: Fat32
FatPartition::init(2000249c, 1)
Volume Name: VOLFAT32   
2010-03-22 07:11    3343737 DSC03357.JPG
2021-01-01 00:00          0 example.txt
2021-02-24 16:35          0 OnFat32.txt
Try calling getUSBPartitionVolumeLabel
FAT32:	FatPartition::init(2000249c, 1)
>> Volume name:(VOLFAT32)
Total Size:4186095616 Used:3362816 time us: 6019373

USB Fat Type: Fat16
FatPartition::init(2000249c, 2)
Volume Name: VOLFAT16   
2021-01-13 17:56     340510 T4-Cardlike.jpg
2021-02-24 16:34          0 OnFat16.txt
Try calling getUSBPartitionVolumeLabel
FAT16:	FatPartition::init(2000249c, 2)
>> Volume name:(VOLFAT16)
Total Size:4186095616 Used:3362816 time us: 6022123

USB Fat Type: ExFat
ExFatPartition::init(2000249c, 3)
Volume Name: VolEXFAT
2021-01-24 06:23       393481 T4.1-Cardlike.jpg
2021-02-24 16:35            0 OnExFat.txt
Try calling getUSBPartitionVolumeLabel
exFAT:	ExFatPartition::init(2000249c, 3)
>> Volume name:(VolEXFAT)
Total Size:4186095616 Used:3362816 time us: 6019873
0 is No or Not Supported USB Partition
Total Size:4186095616 Used:3362816 time us: 6018365

Initialize SD card...initialization failed.

done...

I reran without the older USB Hub and I think it did speed some on these slower drives like:
Code:
>> Volume name:(VOLFAT32)
Total Size:4186095616 Used:3362816 time us: 5897998

For the heck of it I tried plugging in a portable hard disk (WD My Passport) which is USB3 cable but used USB2... It failed to read in the MBR...
Code:
Waiting up to 5 seconds for USB drive 1
^^^^^^^^^~~~~Initialize USB drive...^^^^^^^^^~~
mscError: 0X23
initialization drive 2 failed.

read MBR failed.

USB Fat Type: Fat32
FatPartition::init(2000249c, 1)
Volume Name: 
Try calling getUSBPartitionVolumeLabel
Total Size:4186095616 Used:4186099712 time us: 1500000

First up, wondering why the getting used space is so slow! Wondering how many reads does it need to do?

Then if can not significantly speed up. May see about adding option to MSC to say load these drives fast, tell the host they have some bogus free/used space and then come back around and see after the host is not asking a lot of questions if I can then go back around and fill in the slow drives data... Probably will take that part up more under the MTP thread.
 
Morning all
Decided to start playing. Ran @defragster's updated sketch on 3 devices: (1) an old 2GB thumb drive (FAT16 only), (2) a 32GB Sandisk thumb and (3) my HP 120GB SSD.

One thing I noticed is that the used/totals are for the whole disk not just the partition. Other and obvious one is the times are proportional to the number of items on the disk.

Code:
Waiting up to 5 seconds for USB drive 2
^^^^^^^^^~~~~Initialize USB drive...^^^^USB drive 1 is present.

msc # Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT32:	1,0,0x0,0x21,0x0,0xC,0xFE,0xFF,0xFF,32,62530592
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

USB Fat Type: Fat32
Volume Name: LOST    DIR
...... long list of files 

Try calling getUSBPartitionVolumeLabel
FAT32:	>> Volume name:(LOST    DIR)
Total Size:32000016384 Used:10393780224 time us: 9531498
0 is No or Not Supported USB Partition
Total Size:32000016384 Used:10393780224 time us: 9532739
0 is No or Not Supported USB Partition
Total Size:32000016384 Used:10393780224 time us: 9533114
0 is No or Not Supported USB Partition
Total Size:32000016384 Used:10393780224 time us: 9532989

Initialize SD card...initialization failed.

done...
Press any key to run 

=======================================================

Waiting up to 5 seconds for USB drive 2
^^^^^^^^^~~~~Initialize USB drive...^^^^^USB drive 1 is present.

msc # Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT16:	1,80,0x1,0x1,0x0,0xE,0xFE,0x3F,0x79,63,1974208
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

USB Fat Type: Fat16
Volume Name: NEW VOLUME 
2020-11-17 13:56     220021 T4.1-Cardlike0.jpg
Try calling getUSBPartitionVolumeLabel
FAT16:	>> Volume name:(NEW VOLUME)
Total Size:1010515968 Used:278528 time us: 90374
0 is No or Not Supported USB Partition
Total Size:1010515968 Used:278528 time us: 119492
0 is No or Not Supported USB Partition
Total Size:1010515968 Used:278528 time us: 90367
0 is No or Not Supported USB Partition
Total Size:1010515968 Used:278528 time us: 90367

Initialize SD card...initialization failed.

done...
Press any key to run again

=============================================
msc # Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
exFAT:	1,0,0x20,0x21,0x0,0x7,0xFE,0xFF,0xFF,2048,204800000
FAT32:	2,0,0xFE,0xFF,0xFF,0xC,0xFE,0xFF,0xFF,204802048,29634560
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

USB Fat Type: ExFat
Volume Name: New Volume
Try calling getUSBPartitionVolumeLabel
exFAT:	>> Volume name:(New Volume)
Total Size:104852357120 Used:43811733504 time us: 73499

USB Fat Type: Fat32
Volume Name: NEW VOLUME 
2020-12-27 14:47    5725283 VSLAM_and_Navigation_System_of_Unmanned_Ground_Vehicle_Based_on_RGB-D_Camera.pdf
Try calling getUSBPartitionVolumeLabel
FAT32:	>> Volume name:(NEW VOLUME)
Total Size:104852357120 Used:43811733504 time us: 73499
0 is No or Not Supported USB Partition
Total Size:104852357120 Used:43811733504 time us: 73489
0 is No or Not Supported USB Partition
Total Size:104852357120 Used:43811733504 time us: 73489

Initialize SD card...initialization failed.

done...
Press any key to run again
 
@KurtE
Just tried your updated MTP and this is what I am seeing. Look like it works for SSD:
Code:
MTP_test
sd_addFilesystem: 0 20006328 RAM1
RAM Storage 0 RAM1 199936 512
sd_addFilesystem: 1 200063f0 RAM2
RAM Storage 1 RAM2 3999744 4096
sd_addFilesystem: 2 20006260 PROGM
Program Storage 0 PROGM 983040 8192
sd_addFilesystem: 3 20003a68 QSPI
QSPI Storage 0 QSPI 16777216 8192
sd_addFilesystem: 4 20003b64 sflash5
SPIFlash Storage 0 5 sflash5 67108864 8192
sd_addFilesystem: 5 20003c3c sflash6
SPIFlash Storage 1 6 sflash6 67108864 8192
SPIFlash Storage 2 7 prop failed or missing
sd_addFilesystem: 6 20006e80 WINBOND1G
Storage 0 3 WINBOND1G 131596288 9175040
sd_addFilesystem: 7 20006f70 WINBOND2G
Storage 1 4 WINBOND2G 265289728 9306112

Initializing USB MSC drives...

Setup done
CMD: 1002(OPEN_SESSION)l: 16 T:0 : 1
RESP:2001(RSP:OK)l: 16 T:0 : 1
USB Drive Inserted

msc # Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
exFAT:	1,0,0x20,0x21,0x0,0x7,0xFE,0xFF,0xFF,2048,204800000
FAT32:	2,0,0xFE,0xFF,0xFF,0xC,0xFE,0xFF,0xFF,204802048,29634560
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
exFAT:	>> USB partition 0 valume ID: New Volume
sd_addFilesystem: 8 200071b4 MSC0
new Storage 0 MSC0 104852357120(0) 43811733504(73496)
*MTPD::send_Event(4004) 9
*MTPD::send_Event(400b)
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: 1005(GET_STORAGE_INFO)l: 16 T:3 : 9
9 8 name:MSC0 vol:New Volume
9 8 name:MSC0 vol:New Volume
RESP:2001(RSP:OK)l: 16 T:3 : 9
CMD: 1004(GET_STORAGE_IDS)l: 12 T:4
RESP:2001(RSP:OK)l: 12 T:4
CMD: 1005(GET_STORAGE_INFO)l: 16 T:5 : 1
1 0 name:RAM1 vol:
1 0 name:RAM1 vol:
RESP:2001(RSP:OK)l: 16 T:5 : 1
CMD: 1005(GET_STORAGE_INFO)l: 16 T:6 : 2
2 1 name:RAM2 vol:
2 1 name:RAM2 vol:
RESP:2001(RSP:OK)l: 16 T:6 : 2
CMD: 1005(GET_STORAGE_INFO)l: 16 T:7 : 3
3 2 name:PROGM vol:
3 2 name:PROGM vol:
RESP:2001(RSP:OK)l: 16 T:7 : 3
CMD: 1005(GET_STORAGE_INFO)l: 16 T:8 : 4
4 3 name:QSPI vol:
4 3 name:QSPI vol:
RESP:2001(RSP:OK)l: 16 T:8 : 4
CMD: 1005(GET_STORAGE_INFO)l: 16 T:9 : 5
5 4 name:sflash5 vol:
5 4 name:sflash5 vol:
RESP:2001(RSP:OK)l: 16 T:9 : 5
CMD: 1005(GET_STORAGE_INFO)l: 16 T:a : 6
6 5 name:sflash6 vol:
6 5 name:sflash6 vol:
RESP:2001(RSP:OK)l: 16 T:a : 6
CMD: 1005(GET_STORAGE_INFO)l: 16 T:b : 7
7 6 name:WINBOND1G vol:
7 6 name:WINBOND1G vol:
RESP:2001(RSP:OK)l: 16 T:b : 7
CMD: 1005(GET_STORAGE_INFO)l: 16 T:c : 8
8 7 name:WINBOND2G vol:
8 7 name:WINBOND2G vol:
RESP:2001(RSP:OK)l: 16 T:c : 8
CMD: 9801(GET_OBJECT_PROPS_SUPPORTED)l: 16 T:d : 3000
RESP:2001(RSP:OK)l: 16 T:d : 3000
CMD: 9801(GET_OBJECT_PROPS_SUPPORTED)l: 16 T:e : 3001
RESP:2001(RSP:OK)l: 16 T:e : 3001
but seems to be timing out if I use a 32GB Sandisk Thumb Drive:
Code:
MTP_test
sd_addFilesystem: 0 20006328 RAM1
RAM Storage 0 RAM1 199936 512
sd_addFilesystem: 1 200063f0 RAM2
RAM Storage 1 RAM2 3999744 4096
sd_addFilesystem: 2 20006260 PROGM
Program Storage 0 PROGM 983040 8192
sd_addFilesystem: 3 20003a68 QSPI
QSPI Storage 0 QSPI 16777216 8192
sd_addFilesystem: 4 20003b64 sflash5
SPIFlash Storage 0 5 sflash5 67108864 8192
sd_addFilesystem: 5 20003c3c sflash6
SPIFlash Storage 1 6 sflash6 67108864 8192
SPIFlash Storage 2 7 prop failed or missing
sd_addFilesystem: 6 20006e80 WINBOND1G
Storage 0 3 WINBOND1G 131596288 9175040
sd_addFilesystem: 7 20006f70 WINBOND2G
Storage 1 4 WINBOND2G 265289728 9306112

Initializing USB MSC drives...

Setup done
CMD: 1002(OPEN_SESSION)l: 16 T:0 : 1
RESP:2001(RSP:OK)l: 16 T:0 : 1
USB Drive Inserted

msc # Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT32:	1,0,0x0,0x21,0x0,0xC,0xFE,0xFF,0xFF,32,62530592
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
FAT32:	>> USB partition 0 valume ID: LOST    DIR
sd_addFilesystem: 8 200071b4 MSC0
new Storage 0 MSC0 32000016384(0) 10393780224(9532495)
*MTPD::send_Event(4004) 9
*MTPD::send_Event(400b)
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: 1005(GET_STORAGE_INFO)l: 16 T:3 : 9
9 8 name:MSC0 vol:LOST    DIR
9 8 name:MSC0 vol:LOST    DIR
RESP:2001(RSP:OK)l: 16 T:3 : 9

In the case of the thumb drive a Win Explorer opens but no devices are shown for the Teensy. In the case of the SSD all devices appear including MSC0.
 
Morning,

Try picking up the latest UsbMSCFat project - I added a hack into it that if you ask for the Used size, twice (or more) it remembers the first call to it, which we do as a debug message at the time we add the drive, but then when windows actually sees the drive list and asks for information, we give them the cached data, which allowed my drives to come up.

But on Linux, I think the delay at startup (the time it took after the host sees the new device before we respond to a new session request or the like, it times out still...

Now to maybe look at why the whole disk?

Edit: looking at your data:
new Storage 0 MSC0 32000016384(0) 10393780224(9,532,495)
Slightly edited, it took over 9.5 seconds to compute the free/used data 8)
 
Morning,

Try picking up the latest UsbMSCFat project - I added a hack into it that if you ask for the Used size, twice (or more) it remembers the first call to it, which we do as a debug message at the time we add the drive, but then when windows actually sees the drive list and asks for information, we give them the cached data, which allowed my drives to come up.

But on Linux, I think the delay at startup (the time it took after the host sees the new device before we respond to a new session request or the like, it times out still...

Now to maybe look at why the whole disk?

Thanks will pull down the latest changes and give it a go. Not even going to touch linux - having enough problems :)
 
Quick note: I am thinking it might make sense to add the VolumeName.ino as an example sketch to maybe MscFS.h project. That way we can all keep track of it?

Make sense?
 
@all - Another quick question: while starting to look at why the free space is TAKING SOOOOOOOO LLLLOOONNNGGG

I noticed in the SDFat code:
Code:
//------------------------------------------------------------------------------
/**
 * Set MAINTAIN_FREE_CLUSTER_COUNT nonzero to keep the count of free clusters
 * updated.  This will increase the speed of the freeClusterCount() call
 * after the first call.  Extra flash will be required.
 */
#define MAINTAIN_FREE_CLUSTER_COUNT 0

Sort of like, If we turn this on, I don't need the last changes I made to the UsbMSCFat which sort of does a poor subset...

But again it still would be slow for the first call through...

Now to see what that call is doing!
 
@all - Another quick question: while starting to look at why the free space is TAKING SOOOOOOOO LLLLOOONNNGGG

I noticed in the SDFat code:
Code:
//------------------------------------------------------------------------------
/**
 * Set MAINTAIN_FREE_CLUSTER_COUNT nonzero to keep the count of free clusters
 * updated.  This will increase the speed of the freeClusterCount() call
 * after the first call.  Extra flash will be required.
 */
#define MAINTAIN_FREE_CLUSTER_COUNT 0

Sort of like, If we turn this on, I don't need the last changes I made to the UsbMSCFat which sort of does a poor subset...

But again it still would be slow for the first call through...

Now to see what that call is doing!

Very cool = I just gave you last set of chances a try and they worked = both thumb drives came up - even the SD Card.
 
Quick note: I am thinking it might make sense to add the VolumeName.ino as an example sketch to maybe MscFS.h project. That way we can all keep track of it?

Make sense?

Makes absolute sense to me - that sketch is coming in handy for testing.
 
Something does not appear to be working correctly at all with the freeClusterCount:

Code:
int32_t FatPartition::freeClusterCount() {
#if MAINTAIN_FREE_CLUSTER_COUNT
  if (m_freeClusterCount >= 0) {
    return m_freeClusterCount;
  }
#endif  // MAINTAIN_FREE_CLUSTER_COUNT
  uint32_t free = 0;
  uint32_t sector;
  uint32_t todo = m_lastCluster + 1;
  uint16_t n;

  if (FAT12_SUPPORT && fatType() == 12) {
    for (unsigned i = 2; i < todo; i++) {
      uint32_t c;
      int8_t fg = fatGet(i, &c);
      if (fg < 0) {
        DBG_FAIL_MACRO;
        goto fail;
      }
      if (fg && c == 0) {
        free++;
      }
    }
  } else if (fatType() == 16 || fatType() == 32) {
    [COLOR="#B22222"]Serial.printf("###FatPartition::freeClusterCount: FT:%u start:%u todo:%u\n", fatType(), m_fatStartSector, todo);[/COLOR]
    sector = m_fatStartSector;
    while (todo) {
...
Note: it will read the number todo sectors... I aded the Serial.printf

I ran with just the one thumb drive with 3 partitions on it, without hub... Extract
Code:
Waiting up to 5 seconds for USB drive 1
^^Waiting up to 5 seconds for USB drive 2
^^^^^^^~~~~:(Initialize USB drive...^^^^^^^^FsVolume::begin(20002040)
ExFatPartition::init(20002040, 1)
FatPartition::init(20002040, 1)
USB drive 1 is present.

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

USB Fat Type: Fat32
FatPartition::init(20002040, 1)
>> Volume name:(VOLFAT32)
###FatPartition::freeClusterCount: FT:32 start:2094 todo:1021998
Total Size:4186095616 Used:3362816 time us: 5899873

USB Fat Type: Fat16
>> Volume name:(VOLFAT16)
###FatPartition::freeClusterCount: FT:32 start:2094 todo:1021998
Total Size:4186095616 Used:3362816 time us: 5897623

USB Fat Type: ExFat
>> Volume name:(VolEXFAT)
###FatPartition::freeClusterCount: FT:32 start:2094 todo:1021998
Total Size:4186095616 Used:3362816 time us: 5899498
As mentioned it looks like it is reading the whole disk for each one... Now to figure out where those values for the clusters and the like are coming from...
 
@KurtE
Was toying with something like this for MTP but don;t think I am passing the right things:
Code:
    uint32_t sd_addFilesystem(FS &fs, const char *name, const char *volumeID) {
      if (fsCount < MTPD_MAX_FILESYSTEMS) {
        sd_name[fsCount] = name;
        sd_volumeID[fsCount] = volumeID;
        sdx[fsCount] = &fs;
        Serial.printf("sd_addFilesystem: %d %x %s\n", fsCount, (uint32_t)&fs, name);
        return fsCount++;
      }
      return 0xFFFFFFFFUL;  // no room left
    }
	
    uint32_t sd_addUsbFilesystem(FS &fs, const char *name, const char *volumeID, uint16_t part) {
      if (fsCount < MTPD_MAX_FILESYSTEMS) {
        sd_name[fsCount] = name;
        sd_volumeID[fsCount] = volumeID;
        
        Serial.printf("sd_addFilesystem: %d %x %s\n", fsCount, (uint32_t)&fs, name);
		
  switch (part) {
    case 4:
    case 6:
    case 0xe:
      {
        FatVolume partVol;
        Serial.print("FAT16:\t");

        partVol.begin(&fs, true, part);
        //partVol.chvol();
		sdx[fsCount] = &partVol;
       }
      break;
    case 11:
    case 12:
      {
        FatVolume partVol;
        partVol.begin(&fs true, part);
        //partVol.chvol();
		sdx[fsCount] = &partVol;

      }
      break;
    case 7:
      {
        Serial.print("exFAT:\t");

        ExFatVolume expartVol;

        expartVol.begin(&fs true, part);
        //expartVol.chvol();
		sdx[fsCount] = &expartVol;

  
      }
      break;
    default:
      //return false;
  }
 
KurtE said:
As mentioned it looks like it is reading the whole disk for each one... Now to figure out where those values for the clusters and the like are coming from...
Maybe using the drive as the pointer instead of the volume so everything in MTP going to associated with the drive not the vol?
 
Maybe the code in the sketch is wrong...

It is not applying the partition... I am going to move those calls into the sections by partition type and see what I get...

Looks like we crossed posted.

I am going to hack up the test sketch above first to see if setting the active partition gets us reasonable data or not...

And if so in MTP should do the same.

However: I would think that the FS by default should always set the partition 0(1) as active as default?
 
So I tried adding in the above test sketch currently just to the FAT16 and FAT32 section code like:
Code:
   for (uint8_t i = 1; i < 5; i++) {

    switch (partitionTable[i - 1]) {
    case 11:
    case 12:
      {
        Serial.printf("\nUSB Fat Type: Fat32\n");
        if (!getFat32VolumeLabel(MS_DRIVE, i, &msc))
          Serial.printf("Failed to get volume label\n");
[COLOR="#FF0000"]          FatVolume partVol;
          partVol.begin(msc.usbDrive(), true, i);
          partVol.chvol();
          elapsedMicros em_sizes = 0;
          uint64_t used_size =  (uint64_t)(partVol.clusterCount() - partVol.freeClusterCount())
                                * (uint64_t)partVol.bytesPerCluster();
          uint64_t total_size = (uint64_t)partVol.clusterCount() * (uint64_t)partVol.bytesPerCluster();
          Serial.printf("FAT16 Partition Total Size:%llu Used:%llu time us: %u\n", total_size, used_size,
                        (uint32_t)em_sizes);
[/COLOR]
      }
      break;
    case 4:
    case 6:
    case 0xe:
      {
        Serial.printf("\nUSB Fat Type: Fat16\n");
        if (!getFat16VolumeLabel(MS_DRIVE, i, &msc))
          Serial.printf("Failed to get volume label\n");

[COLOR="#FF0000"]          FatVolume partVol;
          partVol.begin(msc.usbDrive(), true, i);
          partVol.chvol();
          elapsedMicros em_sizes = 0;
          uint64_t used_size =  (uint64_t)(partVol.clusterCount() - partVol.freeClusterCount())
                                * (uint64_t)partVol.bytesPerCluster();
          uint64_t total_size = (uint64_t)partVol.clusterCount() * (uint64_t)partVol.bytesPerCluster();
          Serial.printf("FAT32 Partition Total Size:%llu Used:%llu time us: %u\n", total_size, used_size,
                        (uint32_t)em_sizes);
[/COLOR]
      }
      break;
    case 7:
      Serial.printf("\nUSB Fat Type: ExFat\n");
      if (!getExFatVolumeLabel(MS_DRIVE, i, &msc))
        Serial.printf("Failed to get volume label\n");
      break;
    default:
      Serial.print( partitionTable[i - 1] );
      Serial.println(" is No or Not Supported USB Partition");
      continue; // don't try to get the other stuff here...
    }

And for the first partition is is running over the same data, but for second partition it helps:
Code:
^^^^~~~~:(Initialize USB drive...^^^^^^^^FsVolume::begin(20002080)
ExFatPartition::init(20002080, 1)
FatPartition::init(20002080, 1)
USB drive 1 is present.

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

USB Fat Type: Fat32
FatPartition::init(20002080, 1)
Volume Name: VOLFAT32   
2010-03-22 07:11    3343737 DSC03357.JPG
2021-01-01 00:00          0 example.txt
2021-02-24 16:35          0 OnFat32.txt
FatPartition::init(20002080, 1)
[COLOR="#FF0000"]###FatPartition::freeClusterCount: FT:32 start:2094 todo:1021998[/COLOR]
FAT16 Partition Total Size:4186095616 Used:3362816 time us: 5899625
Try calling getUSBPartitionVolumeLabel
FAT32:	FatPartition::init(20002080, 1)
>> Volume name:(VOLFAT32)
[COLOR="#FF0000"]###FatPartition::freeClusterCount: FT:32 start:2094 todo:1021998[/COLOR]
Total Size:4186095616 Used:3362816 time us: 5898498

USB Fat Type: Fat16
FatPartition::init(20002080, 2)
Volume Name: VOLFAT16   
2021-01-13 17:56     340510 T4-Cardlike.jpg
2021-02-24 16:34          0 OnFat16.txt
FatPartition::init(20002080, 2)
[COLOR="#FF0000"]###FatPartition::freeClusterCount: FT:16 start:8194056 todo:65520[/COLOR]
FAT32 Partition Total Size:1073446912 Used:393216 time us: 187501
Try calling getUSBPartitionVolumeLabel
FAT16:	FatPartition::init(20002080, 2)
>> Volume name:(VOLFAT16)
[COLOR="#FF0000"]###FatPartition::freeClusterCount: FT:32 start:2094 todo:1021998[/COLOR]
Total Size:4186095616 Used:3362816 time us: 5901373

USB Fat Type: ExFat
ExFatPartition::init(20002080, 3)
Volume Name: VolEXFAT
2021-01-24 06:23       393481 T4.1-Cardlike.jpg
2021-02-24 16:35            0 OnExFat.txt
Try calling getUSBPartitionVolumeLabel
exFAT:	ExFatPartition::init(20002080, 3)
>> Volume name:(VolEXFAT)
###FatPartition::freeClusterCount: FT:32 start:2094 todo:1021998
Total Size:4186095616 Used:3362816 time us: 5894748
0 is No or Not Supported USB Partition

Initialize SD card...FsVolume::begin(200039f0)
ExFatPartition::init(200039f0, 1)
SD card is present.

SD Fat Type: ExFAT
ExFatPartition::init(2006ff94, 1)
Volume Name: EXFat_Vol
done...
Press any key to run again
So now curious on what the Fat system actually says are the correct counts...
 
Full current sketch, Note I commented out the earlier calls to get sizes...
Code:
Waiting up to 5 seconds for USB drive 1
^^Waiting up to 5 seconds for USB drive 2
^^^^^^^~~~~:(Initialize USB drive...^^^^^^^^FsVolume::begin(20002100)
ExFatPartition::init(20002100, 1)
FatPartition::init(20002100, 1)
USB drive 1 is present.

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

USB Fat Type: Fat32
FatPartition::init(20002100, 1)
Volume Name: VOLFAT32   
2010-03-22 07:11    3343737 DSC03357.JPG
2021-01-01 00:00          0 example.txt
2021-02-24 16:35          0 OnFat32.txt
FatPartition::init(20002100, 1)
###FatPartition::freeClusterCount: FT:32 start:2094 todo:1021998
FAT16 Partition Total Size:4186095616 Used:3362816 time us: 5900875
Try calling getUSBPartitionVolumeLabel
FAT32:	FatPartition::init(20002100, 1)
>> Volume name:(VOLFAT32)

USB Fat Type: Fat16
FatPartition::init(20002100, 2)
Volume Name: VOLFAT16   
2021-01-13 17:56     340510 T4-Cardlike.jpg
2021-02-24 16:34          0 OnFat16.txt
FatPartition::init(20002100, 2)
###FatPartition::freeClusterCount: FT:16 start:8194056 todo:65520
FAT32 Partition Total Size:1073446912 Used:393216 time us: 187877
Try calling getUSBPartitionVolumeLabel
FAT16:	FatPartition::init(20002100, 2)
>> Volume name:(VOLFAT16)

USB Fat Type: ExFat
ExFatPartition::init(20002100, 3)
Volume Name: VolEXFAT
2021-01-24 06:23       393481 T4.1-Cardlike.jpg
2021-02-24 16:35            0 OnExFat.txt
ExFatPartition::init(20002100, 3)
###ExFatPartition::freeClusterCount: FT:10292096 start:84914 cluster count:0
ExFat Partition Total Size:2782461952 Used:622592 time us: 17004
Try calling getUSBPartitionVolumeLabel
exFAT:	ExFatPartition::init(20002100, 3)
>> Volume name:(VolEXFAT)
0 is No or Not Supported USB Partition

Initialize SD card...FsVolume::begin(20003a70)
ExFatPartition::init(20003a70, 1)
SD card is present.

SD Fat Type: ExFAT
ExFatPartition::init(2006ff94, 1)
Volume Name: EXFat_Vol
done...
Press any key to run again
And note output lines like: ###ExFatPartition::freeClusterCount: FT:10292096 start:84914 cluster count:0
Were from edits of the SDFat library functions... Will play more...
Code:
//  VolumeName.ino
// VER: P494, p498, p506, p507. [B][COLOR="#FF0000"]p522[/COLOR][/B]
//  An example of how to retrieve Fat32 and ExFat volume names using SdFat.
//  Works with SD cards and USB mass storage drives.

#include "Arduino.h"
#include "mscFS.h"

// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);

#define SHOW_CLOCK_CARAT 1
IntervalTimer clocked100ms;
volatile int32_t cmsReport = -1;

// Setup MSC for the number of USB Drives you are using. (Two for this example)
// Mutiple  USB drives can be used. Hot plugging is supported. There is a slight
// delay after a USB MSC device is plugged in. This is waiting for initialization
// but after it is initialized ther should be no delay.
msController msDrive1(myusb);
msController msDrive2(myusb);

#define SD_DRIVE 1
#define MS_DRIVE 2

#define SD_CONFIG SdioConfig(FIFO_SDIO)

// set up variables using the mscFS utility library functions:
UsbFs msc1;
UsbFs msc2;

SdFs sd;
//FatVolume partVol;

//create holding array for partions
uint8_t partitionTable[4];
int32_t dataStart[4];

// Get ExFat volume name.

bool getExFatVolumeLabel(uint8_t  drvType, uint8_t part, UsbFs *myMsc) {
  uint8_t buf[32];
  UsbExFat volName;
  SdExFat volName1;
  ExFatFile root;
  //msController *mscDrive;
  DirLabel_t *dir;

  ExFatVolume expartVol;

  if (drvType == MS_DRIVE) {
    //mscDrive = &msDrive1;
    //if (!volName.begin(&msDrive1)) {
    //   Serial.println("EXFat volName.begin failed");
    //   return false;
    // }
    expartVol.begin(myMsc->usbDrive(), true, part);
    expartVol.chvol();
    if (!root.openRoot(&expartVol)) {
      Serial.println("openRoot failed");
      return false;
    }
  }
  if (drvType == SD_DRIVE) {
    if (!volName1.begin(SD_CONFIG)) {
      return false;
    }
    if (!root.openRoot(&volName1)) {
      Serial.println("openRoot failed");
      return false;
    }
  }

  root.read(buf, 32);
  dir = reinterpret_cast<DirLabel_t*>(buf);
  Serial.print(F("Volume Name: "));
  for (size_t i = 0; i < dir->labelLength; i++) {
    Serial.write(dir->unicode[2 * i]);
  }
  Serial.println();
  expartVol.ls(LS_SIZE | LS_DATE | LS_R);
  return true;
}

// Get Fat32 volume name.
bool getFat32VolumeLabel(uint8_t  drvType, uint8_t part, UsbFs *myMsc) {
  FatVolume partVol;

  uint8_t buf[512];

  if (drvType == MS_DRIVE) {
    partVol.begin(myMsc->usbDrive(), true, part);
    partVol.chvol();
    myMsc->usbDrive()->readSector(partVol.dataStartSector(), buf);
  }

  if (drvType == SD_DRIVE) {
    sd.card()->readSector(sd.dataStartSector(), buf);
  }
  Serial.print(F("Volume Name: "));
  for (size_t i = 0; i < 11; i++) {
    if ( buf[i] > 0 && buf[i] < 127 )
      Serial.write(buf[i]);
  }
  Serial.println();
  partVol.ls(LS_SIZE | LS_DATE | LS_R);

  return true;
}

// Get Fat16 volume name.
// Get Fat16 volume name.
bool getFat16VolumeLabel(uint8_t  drvType, uint8_t part, UsbFs *myMsc) {
  FatVolume partVol;

  uint8_t buf[512];

  if (drvType == MS_DRIVE) {
    partVol.begin(myMsc->usbDrive(), true, part);
    partVol.chvol();
    myMsc->usbDrive()->readSector(partVol.rootDirStart(), buf);
  }

  if (drvType == SD_DRIVE) {
    sd.card()->readSector(sd.dataStartSector(), buf);
    print_hexbytes(buf, 512);
  }
  Serial.print(F("Volume Name: "));
  for (size_t i = 0; i < 11; i++) {
    Serial.write(buf[i]);
  }
  Serial.println();
  partVol.ls(LS_SIZE | LS_DATE | LS_R);

  return true;
}


bool getUSBPartitionVolumeLabel(UsbFs *myMsc, uint8_t part, uint8_t *pszVolName, uint16_t cb) {
  MbrSector_t mbr;
  uint8_t buf[512];
  if (!pszVolName || (cb < 12)) return false; // don't want to deal with it
  myMsc->usbDrive()->readSector(0, (uint8_t*)&mbr);
  MbrPart_t *pt = &mbr.part[part - 1];
  switch (pt->type) {
    case 4:
    case 6:
    case 0xe:
      {
        FatVolume partVol;
        Serial.print("FAT16:\t");

        partVol.begin(myMsc->usbDrive(), true, part);
        partVol.chvol();
        myMsc->usbDrive()->readSector(partVol.rootDirStart(), buf);

        size_t i;
        for (i = 0; i < 11; i++) {
          pszVolName[i]  = buf[i];
        }
        while ((i > 0) && (pszVolName[i - 1] == ' ')) i--; // trim off trailing blanks
        pszVolName[i] = 0;
      }
      break;
    case 11:
    case 12:
      {
        FatVolume partVol;
        Serial.print("FAT32:\t");
        partVol.begin(myMsc->usbDrive(), true, part);
        partVol.chvol();
        myMsc->usbDrive()->readSector(partVol.dataStartSector(), buf);

        size_t i;
        for (i = 0; i < 11; i++) {
          pszVolName[i]  = buf[i];
        }
        while ((i > 0) && (pszVolName[i - 1] == ' ')) i--; // trim off trailing blanks
        pszVolName[i] = 0;
      }
      break;
    case 7:
      {
        Serial.print("exFAT:\t");
        ExFatFile root;
        DirLabel_t *dir;

        ExFatVolume expartVol;

        expartVol.begin(myMsc->usbDrive(), true, part);
        expartVol.chvol();
        if (!root.openRoot(&expartVol)) {
          Serial.println("openRoot failed");
          return false;
        }
        root.read(buf, 32);
        dir = reinterpret_cast<DirLabel_t*>(buf);

        size_t i;
        for (i = 0; i < dir->labelLength; i++) {
          pszVolName[i] = dir->unicode[2 * i];
        }
        pszVolName[i] = 0;
      }

      break;
    default:
      return false;
  }
  return true;
}



bool mbrDmp(UsbFs *myMsc) {
  MbrSector_t mbr;
  // bool valid = true;
  if (!myMsc->usbDrive()->readSector(0, (uint8_t*)&mbr)) {
    Serial.print("\nread MBR failed.\n");
    //errorPrint();
    return false;
  }
  Serial.print("\nmsc # Partition Table\n");
  Serial.print("\tpart,boot,bgnCHS[3],type,endCHS[3],start,length\n");
  for (uint8_t ip = 1; ip < 5; ip++) {
    MbrPart_t *pt = &mbr.part[ip - 1];
    //    if ((pt->boot != 0 && pt->boot != 0X80) ||
    //        getLe32(pt->relativeSectors) > sdCardCapacity(&m_csd)) {
    //      valid = false;
    //    }
    switch (pt->type) {
      case 4:
      case 6:
      case 0xe:
        Serial.print("FAT16:\t");
        break;
      case 11:
      case 12:
        Serial.print("FAT32:\t");
        break;
      case 7:
        Serial.print("exFAT:\t");
        break;
      default:
        Serial.print("pt_#");
        Serial.print(pt->type);
        Serial.print(":\t");
        break;
    }
    partitionTable[ip - 1] = pt->type;
    dataStart[ip - 1] = getLe32(pt->relativeSectors);
    Serial.print( int(ip)); Serial.print( ',');
    Serial.print(int(pt->boot), HEX); Serial.print( ',');
    for (int i = 0; i < 3; i++ ) {
      Serial.print("0x"); Serial.print(int(pt->beginCHS[i]), HEX); Serial.print( ',');
    }
    Serial.print("0x"); Serial.print(int(pt->type), HEX); Serial.print( ',');
    for (int i = 0; i < 3; i++ ) {
      Serial.print("0x"); Serial.print(int(pt->endCHS[i]), HEX); Serial.print( ',');
    }
    Serial.print(getLe32(pt->relativeSectors), DEC); Serial.print(',');
    Serial.println(getLe32(pt->totalSectors));
  }
  return true;
}

void setup()
{
#if 0 // easy test to check HardFault Detection response
  int *pp = 0;
  *pp = 5;
#endif
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    SysCall::yield(); // wait for serial port to connect.
  }

  // Start USBHost_t36, HUB(s) and USB devices.
  myusb.begin();

#ifdef SHOW_CLOCK_CARAT
  clocked100ms.begin(clock_isr, 100000);
#endif

}

void clock_isr() {
  if (cmsReport >= 0 ) {
    if (cmsReport > 0 ) {
      if (cmsReport < 10 )
        Serial.print( "^");
      else if ( cmsReport < 50 && !(cmsReport % 10) )
        Serial.print( "~");
      else if ( !(cmsReport % 50) )
        Serial.print( ":(");
    }
    cmsReport++;
  }
}

void print_hexbytes(const void *ptr, int len)
{
  if (ptr == NULL || len <= 0) return;
  const uint8_t *p = (const uint8_t *)ptr;
  while (len) {
    for (uint8_t i = 0; i < 32; i++) {
      if (i > len) break;
      Serial.printf("%02X ", p[i]);
    }
    Serial.print(":");
    for (uint8_t i = 0; i < 32; i++) {
      if (i > len) break;
      Serial.printf("%c", ((p[i] >= ' ') && (p[i] <= '~')) ? p[i] : '.');
    }
    Serial.println();
    p += 32;
    len -= 32;
  }
}



// Function to handle one MS Drive...
void procesMSDrive(uint8_t drive_number, msController &msDrive, UsbFs &msc)
{
  Serial.printf("Initialize USB drive...");
  cmsReport = 0;
  if (!msc.begin(&msDrive)) {
    Serial.println("");
    msc.errorPrint(&Serial);
    Serial.printf("initialization drive %u failed.\n", drive_number);
  } else {
    Serial.printf("USB drive %u is present.\n", drive_number);
  }
  cmsReport = -1;

  mbrDmp( &msc );
  for (uint8_t i = 1; i < 5; i++) {

    switch (partitionTable[i - 1]) {
      case 11:
      case 12:
        {
          Serial.printf("\nUSB Fat Type: Fat32\n");
          if (!getFat32VolumeLabel(MS_DRIVE, i, &msc))
            Serial.printf("Failed to get volume label\n");
          FatVolume partVol;
          partVol.begin(msc.usbDrive(), true, i);
          partVol.chvol();
          elapsedMicros em_sizes = 0;
          uint64_t used_size =  (uint64_t)(partVol.clusterCount() - partVol.freeClusterCount())
                                * (uint64_t)partVol.bytesPerCluster();
          uint64_t total_size = (uint64_t)partVol.clusterCount() * (uint64_t)partVol.bytesPerCluster();
          Serial.printf("FAT16 Partition Total Size:%llu Used:%llu time us: %u\n", total_size, used_size,
                        (uint32_t)em_sizes);
        }
        break;
      case 4:
      case 6:
      case 0xe:
        {
          Serial.printf("\nUSB Fat Type: Fat16\n");
          if (!getFat16VolumeLabel(MS_DRIVE, i, &msc))
            Serial.printf("Failed to get volume label\n");

          FatVolume partVol;
          partVol.begin(msc.usbDrive(), true, i);
          partVol.chvol();
          elapsedMicros em_sizes = 0;
          uint64_t used_size =  (uint64_t)(partVol.clusterCount() - partVol.freeClusterCount())
                                * (uint64_t)partVol.bytesPerCluster();
          uint64_t total_size = (uint64_t)partVol.clusterCount() * (uint64_t)partVol.bytesPerCluster();
          Serial.printf("FAT32 Partition Total Size:%llu Used:%llu time us: %u\n", total_size, used_size,
                        (uint32_t)em_sizes);

        }
        break;
      case 7:
        {
          Serial.printf("\nUSB Fat Type: ExFat\n");
          if (!getExFatVolumeLabel(MS_DRIVE, i, &msc))
            Serial.printf("Failed to get volume label\n");
          ExFatVolume partVol;
          partVol.begin(msc.usbDrive(), true, i);
          partVol.chvol();
          elapsedMicros em_sizes = 0;
          uint64_t used_size =  (uint64_t)(partVol.clusterCount() - partVol.freeClusterCount())
                                * (uint64_t)partVol.bytesPerCluster();
          uint64_t total_size = (uint64_t)partVol.clusterCount() * (uint64_t)partVol.bytesPerCluster();
          Serial.printf("ExFat Partition Total Size:%llu Used:%llu time us: %u\n", total_size, used_size,
                        (uint32_t)em_sizes);
        }
        break;
      default:
        Serial.print( partitionTable[i - 1] );
        Serial.println(" is No or Not Supported USB Partition");
        continue; // don't try to get the other stuff here...
    }
    // lets see if our all in one works
    uint8_t volName[32];
    if ( 0 != partitionTable[i - 1] ) {
      Serial.println("Try calling getUSBPartitionVolumeLabel");
      if (getUSBPartitionVolumeLabel(&msc, i, volName, sizeof(volName))) {
        Serial.printf(">> Volume name:(%s)\n", volName);
      }
    }
#if 0
    elapsedMicros em_sizes = 0;
    uint64_t used_size =  (uint64_t)(msc.clusterCount() - msc.freeClusterCount())
                          * (uint64_t)msc.bytesPerCluster();
    uint64_t total_size = (uint64_t)msc.clusterCount() * (uint64_t)msc.bytesPerCluster();
    Serial.printf("Total Size:%llu Used:%llu time us: %u\n", total_size, used_size,
                  (uint32_t)em_sizes);
#endif
  }
}

//================================================================
void loop(void) {
  //--------------------------------------------------
  cmsReport = 0;
  myusb.Task();
  if (!msDrive1) {
    Serial.println("Waiting up to 5 seconds for USB drive 1");
    elapsedMillis em = 0;
    while (!msDrive1 && (em < 5000) )  myusb.Task();
  }
  if (!msDrive2) {
    Serial.println("Waiting up to 5 seconds for USB drive 2");
    elapsedMillis em = 0;
    while (!msDrive2 && (em < 5000) )  myusb.Task();
  }
  if (msDrive1) {
    procesMSDrive(1, msDrive1, msc1);
  }
  if (msDrive2) {
    procesMSDrive(2, msDrive2, msc2);
  }
  cmsReport = -1;
  //--------------------------------------------------
  Serial.printf("\nInitialize SD card...");

  if (!sd.begin(SD_CONFIG)) {
    Serial.println("initialization failed.\n");
  } else {
    Serial.println("SD card is present.\n");

    if (sd.fatType() == 32) {
      Serial.printf("SD Fat Type: Fat32\n");
      if (!getFat32VolumeLabel(SD_DRIVE, 1, nullptr))
        Serial.printf("Failed to get volume label\n");
    } else {
      Serial.printf("SD Fat Type: ExFAT\n");
      if (!getExFatVolumeLabel(SD_DRIVE, 1, nullptr)) {
        Serial.printf("Failed to get volume label\n");
      }
    }
    //sd.ls(LS_SIZE | LS_DATE | LS_R);
  }

  Serial.println("done...");

  Serial.println("Press any key to run again");
  while (Serial.read() == -1);
  while (Serial.read() != -1);
}
 
Last edited by a moderator:
Just plugged in my 5 TB external - yesterday's code - doesn't matter given the part ID #238:
Code:
msc # Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
pt_#238:	1,0,0x0,0x2,0x0,0xEE,0xFF,0xFF,0xFF,1,4294967295

We could add a set of Known Unknown part ID's :)

I have one disk that came up 0us reading the sizes - will run again when up p#520 updates post
Code here still dislikes Fat16 part it seems?:
Code:
Initialize USB drive...^^^^^^^
Check USB drive format.
initialization drive 2 failed.

msc # Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT16:	1,0,0x20,0x21,0x0,0xE,0xE8,0x27,0x1,2048,28672
exFAT:	2,0,0xA,0x9,0x2,0x7,0xFE,0xFF,0xFF,32768,242450176
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

USB Fat Type: Fat16
Volume Name: FATVOL16M  
Try calling getUSBPartitionVolumeLabel
FAT16:	>> Volume name:(FATVOL16M)
Total Size:0 Used:0 time us: 0

USB Fat Type: ExFat
Volume Name: 
2021-02-24 18:40           34 ExFat.txt
2021-02-24 18:41       131072 ExFatFldr/
  2021-02-24 18:40           34 Folder_ExFat.txt
Try calling getUSBPartitionVolumeLabel
exFAT:	>> Volume name:()
Total Size:0 Used:0 time us: 0
0 is No or Not Supported USB Partition
Total Size:0 Used:0 time us: 0
0 is No or Not Supported USB Partition
Total Size:0 Used:0 time us: 0
 
p#523 crosspost ...

Windows view of USB Hub Drive >> H: << and Flash drives >> F: and G: << as below:
p524Drives.png

Here is run on p#522 updated code - now has ExFat drive size:
Code:
Waiting up to 5 seconds for USB drive 1
^^Waiting up to 5 seconds for USB drive 2
^Initialize USB drive...^^^^USB drive 1 is present.

msc # Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
exFAT:	1,0,0x20,0x21,0x0,0x7,0xFE,0xFF,0xFF,2048,234436608
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

USB Fat Type: ExFat
Volume Name: 120GB_Ext
2020-01-23 17:04     32768000 A_00001.dat
2020-01-23 17:04     32768000 A_00002.dat
2020-01-23 17:04     32768000 A_00003.dat
2020-01-23 17:04     32768000 A_00004.dat
2020-01-23 17:04     32768000 A_00005.dat
2020-01-23 17:04     32768000 A_00006.dat
                            0 A_00007.dat
ExFat Partition Total Size:120026300416 Used:[B][COLOR="#FF0000"]197394432 [/COLOR][/B]time us: 83983
Try calling getUSBPartitionVolumeLabel
exFAT:	>> Volume name:(120GB_Ext)
0 is No or Not Supported USB Partition
0 is No or Not Supported USB Partition
0 is No or Not Supported USB Partition
Initialize USB drive...^^^^^^^
Check USB drive format.
initialization drive 2 failed.

msc # Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT16:	1,0,0x20,0x21,0x0,0xE,0xE8,0x27,0x1,2048,28672
exFAT:	2,0,0xA,0x9,0x2,0x7,0xFE,0xFF,0xFF,32768,242450176
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

USB Fat Type: Fat16
Volume Name: FATVOL16M  
FAT32 Partition Total Size:14651392 Used:[B][COLOR="#FF0000"]14655488 [/COLOR][/B]time us: 0
Try calling getUSBPartitionVolumeLabel
FAT16:	>> Volume name:(FATVOL16M)

USB Fat Type: ExFat
Volume Name: 
2021-02-24 18:40           34 ExFat.txt
2021-02-24 18:41       131072 ExFatFldr/
  2021-02-24 18:40           34 Folder_ExFat.txt
ExFat Partition Total Size:124117712896 Used:[B][COLOR="#FF0000"]1179648 [/COLOR][/B]time us: 243251
Try calling getUSBPartitionVolumeLabel
exFAT:	>> Volume name:()
0 is No or Not Supported USB Partition
0 is No or Not Supported USB Partition

Initialize SD card...SD card is present.

SD Fat Type: Fat32
Volume Name: SD1_8GB_AD 
done...
Press any key to run again
 
Last edited:
@defragster and @mjs513 I am sort of curious about fragmentation works ;)

For the Fat32 volume:
I mucked up the beginning of the method most all of the class variables
Code:
int32_t FatPartition::freeClusterCount() {
#if MAINTAIN_FREE_CLUSTER_COUNT
  if (m_freeClusterCount >= 0) {
    return m_freeClusterCount;
  }
#endif  // MAINTAIN_FREE_CLUSTER_COUNT
  uint32_t free = 0;
  uint32_t sector;
  uint32_t todo = m_lastCluster + 1;
  uint16_t n;

  if (FAT12_SUPPORT && fatType() == 12) {
    for (unsigned i = 2; i < todo; i++) {
      uint32_t c;
      int8_t fg = fatGet(i, &c);
      if (fg < 0) {
        DBG_FAIL_MACRO;
        goto fail;
      }
      if (fg && c == 0) {
        free++;
      }
    }
  } else if (fatType() == 16 || fatType() == 32) {
    Serial.printf("###FatPartition::freeClusterCount: FT:%u start:%u todo:%u\n", fatType(), m_fatStartSector, todo);
    Serial.printf("    m_sectorsPerCluster:%u\n", m_sectorsPerCluster);
    Serial.printf("    m_clusterSectorMask:%u\n", m_clusterSectorMask);
    Serial.printf("    m_sectorsPerClusterShift:%u\n", m_sectorsPerClusterShift);
    Serial.printf("    m_fatType:%u\n", m_fatType);
    Serial.printf("    m_rootDirEntryCount:%u\n", m_rootDirEntryCount);
    Serial.printf("    m_allocSearchStart:%u\n", m_allocSearchStart);
    Serial.printf("    m_sectorsPerFat:%u\n", m_sectorsPerFat);
    Serial.printf("    m_dataStartSector:%u\n", m_dataStartSector);
    Serial.printf("    m_fatStartSector:%u\n", m_fatStartSector);
    Serial.printf("    m_lastCluster:%u\n", m_lastCluster);
    Serial.printf("    m_rootDirStart:%u\n", m_rootDirStart);
    Serial.printf("    m_bytesPerSector:%u\n", m_bytesPerSector);
    sector = m_fatStartSector;
    while (todo) {
      cache_t* pc = cacheFetchFat(sector++, FsCache::CACHE_FOR_READ);
      if (!pc) {
        DBG_FAIL_MACRO;
        goto fail;
      }
      n =  fatType() == 16 ? m_bytesPerSector/2 : m_bytesPerSector/4;
      if (todo < n) {
        n = todo;
      }
      if (fatType() == 16) {
        for (uint16_t i = 0; i < n; i++) {
          if (pc->fat16[i] == 0) {
            free++;
          }
        }
      } else {
        for (uint16_t i = 0; i < n; i++) {
          if (pc->fat32[i] == 0) {
            free++;
          }
        }
      }
      todo -= n;
    }
  } else {
    // invalid FAT type
    DBG_FAIL_MACRO;
    goto fail;
  }
  setFreeClusterCount(free);
  return free;

 fail:
  return -1;
}
From the header file:
Code:
  uint8_t  m_sectorsPerCluster;       // Cluster size in sectors.
  uint8_t  m_clusterSectorMask;       // Mask to extract sector of cluster.
  uint8_t  m_sectorsPerClusterShift;  // Cluster count to sector count shift.
  uint8_t  m_fatType = 0;             // Volume type (12, 16, OR 32).
  uint16_t m_rootDirEntryCount;       // Number of entries in FAT16 root dir.
  uint32_t m_allocSearchStart;        // Start cluster for alloc search.
  uint32_t m_sectorsPerFat;           // FAT size in sectors
  uint32_t m_dataStartSector;         // First data sector number.
  uint32_t m_fatStartSector;          // Start sector for first FAT.
  uint32_t m_lastCluster;             // Last cluster number in FAT.
  uint32_t m_rootDirStart;            // Start sector FAT16, cluster FAT32.

Some of the Debug output
Code:
USB Fat Type: Fat32
FatPartition::init(20002220, 1)
Volume Name: VOLFAT32   
2010-03-22 07:11    3343737 DSC03357.JPG
2021-01-01 00:00          0 example.txt
2021-02-24 16:35          0 OnFat32.txt
FatPartition::init(20002220, 1)
###FatPartition::freeClusterCount: FT:32 start:2094 todo:1021998
    m_sectorsPerCluster:8
    m_clusterSectorMask:7
    m_sectorsPerClusterShift:3
    m_fatType:32
    m_rootDirEntryCount:0
    m_allocSearchStart:1
    m_sectorsPerFat:7993
    m_dataStartSector:18080
    m_fatStartSector:2094
    m_lastCluster:1021997
    m_rootDirStart:2
    m_bytesPerSector:512
FAT16 Partition Total Size:4186095616 Used:3362816 time us: 5896750
Try calling getUSBPartitionVolumeLabel
FAT32:	FatPartition::init(20002220, 1)
>> Volume name:(VOLFAT32)

USB Fat Type: Fat16
FatPartition::init(20002220, 2)
Volume Name: VOLFAT16   
2021-01-13 17:56     340510 T4-Cardlike.jpg
2021-02-24 16:34          0 OnFat16.txt
FatPartition::init(20002220, 2)
###FatPartition::freeClusterCount: FT:16 start:8194056 todo:65520
    m_sectorsPerCluster:32
    m_clusterSectorMask:31
    m_sectorsPerClusterShift:5
    m_fatType:16
    m_rootDirEntryCount:512
    m_allocSearchStart:1
    m_sectorsPerFat:256
    m_dataStartSector:8194600
    m_fatStartSector:8194056
    m_lastCluster:65519
    m_rootDirStart:8194568
    m_bytesPerSector:512
FAT32 Partition Total Size:1073446912 Used:393216 time us: 188377

So if I am reading this correct: in the Fat32 case:
n = fatType() == 16 ? m_bytesPerSector/2 : m_bytesPerSector/4; So 512/4 = 128 per fat directory...
SO I think we would read: 1021998/128=7985 Fat sectors?
So the m_sectorsPerFat:7993 makes sense...

so 2094+7993 =10087 as last sector...

So if our read of the FAT took 5896750us and we did about 7990 reads, each read took 738us
 
Back
Top