USBHost_t36 USB Mass Storage Driver Experiments

@defragster
Wondering if its an issue with MSFT formatted drive. I put a 128GB SD Card in a usb adapter with 2 FAT32 and 1 extFAT. But looks like the exFAT is failing for some reason;
Code:
Initialize USB drive...USB drive 1 is present.


msc1 Partition Table
part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT32: 1,80,0x0,0x1,0x10,0xC,0x3,0xE0,0xFF,2048,524288
FAT32: 2,0,0xC2,0x23,0x20,0xC,0xFE,0xFF,0xFF,526336,16564224
exFAT: 3,0,0xFE,0xFF,0xFF,0x7,0xFE,0xFF,0xFF,17092608,232642560
4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

Fat Type: Fat32
Volume Name: system-boot
2021-01-01 00:00     128890 bench0.txt
2021-01-01 00:00     128890 bench1.txt
2021-01-01 00:00     200000 bench2.txt
2021-01-01 00:00     200000 bench3.txt
2021-01-01 00:00     149000 bench4.txt
2021-01-01 00:00     149000 bench5.txt

Fat Type: Fat32
Volume Name: NEW VOLUME1
2021-01-01 00:00     128890 bench0.txt
2021-01-01 00:00     128890 bench1.txt
2021-01-01 00:00     200000 bench2.txt
2021-01-01 00:00     200000 bench3.txt
2021-01-01 00:00     149000 bench4.txt
2021-01-01 00:00     149000 bench5.txt

Fat Type: ExFat
EXFat volName.begin failed
Failed to get volume label
No or Not Supported Partition
 
@defragster
Wondering if its an issue with MSFT formatted drive. I put a 128GB SD Card in a usb adapter with 2 FAT32 and 1 extFAT. But looks like the exFAT is failing for some reason;
...

Turns out BOTH of these drives are MSFT formatted :) One for recover 64GB with 2nd partition now formatted where they image it with one of 32GB

The second 16GB drive they format when putting on the WIN 10 install MEDIA program.

But the HANG is only on the 16GB drive when the 'Write Protect' switch is ON - drive is write protected.

With the (1) usb time change the other drive comes up fine - though it does take extra time I just saw based on the '^':
Code:
Waiting up to 5 seconds for USB drive
^^^^^^^^^^^^^Initialize USB drive...^USB drive 1 is present.

Okay it was coming through fine - now three fails in a row ... 64GB with two parts recovery drive::
Though quick code change to help counting seconds by changing the '^' to a '~' on the end of the first second - shows it failing twice after 5 seconds:
Code:
Waiting up to 5 seconds for USB drive
^^^^^^^^^~~~~
Initialize SD card...initialization failed.

Fat Type: ExFAT
Failed to get volume label
done...
Press any key to run again

Failing again after Upload or Power on ... 64GB Recovery

Back to the Write Protect disk when OFF - no problem to start:
Code:
Waiting up to 5 seconds for USB drive
^^Initialize USB drive...^^^^^^^~USB drive 1 is present.


msc1 Partition Table
 
Ok here is the fix for extFat:
Code:
Waiting up to 5 seconds for USB drive
Initialize USB drive...USB drive 1 is present.


msc1 Partition Table
part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT32: 1,80,0x0,0x1,0x10,0xC,0x3,0xE0,0xFF,2048,524288
FAT32: 2,0,0xC2,0x23,0x20,0xC,0xFE,0xFF,0xFF,526336,16564224
exFAT: 3,0,0xFE,0xFF,0xFF,0x7,0xFE,0xFF,0xFF,17092608,232642560
4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

Fat Type: Fat32
Volume Name: system-boot
2021-01-01 00:00     128890 bench0.txt
2021-01-01 00:00     128890 bench1.txt
2021-01-01 00:00     200000 bench2.txt
2021-01-01 00:00     200000 bench3.txt
2021-01-01 00:00     149000 bench4.txt
2021-01-01 00:00     149000 bench5.txt

Fat Type: Fat32
Volume Name: NEW VOLUME1
2021-01-01 00:00     128890 bench0.txt
2021-01-01 00:00     128890 bench1.txt
2021-01-01 00:00     200000 bench2.txt
2021-01-01 00:00     200000 bench3.txt
2021-01-01 00:00     149000 bench4.txt
2021-01-01 00:00     149000 bench5.txt

Fat Type: ExFat
Volume Name: New Volume2
2021-01-27 05:36       429216 CommandStation-EX-Arch-v1-0.pdf
2020-12-27 14:47      5725283 VSLAM_and_Navigation_System_of_Unmanned_Ground_Vehicle_Based_on_RGB-D_Camera.pdf
No or Not Supported Partition

Initialize SD card...initialization failed.

Fat Type: ExFAT
Failed to get volume label
done...
Press any key to run again

Code:
[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);

// 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 sdDrive 1
#define msDrive 2

#define SD_CONFIG SdioConfig(FIFO_SDIO)

// set up variables using the mscFS utility library functions:
UsbFs msc1;
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) {
  uint8_t buf[32];
  UsbExFat volName;
  SdExFat volName1;
  ExFatFile root;
  msController *mscDrive;
  DirLabel_t *dir;

  ExFatVolume expartVol;

  if (drvType == msDrive) {
    mscDrive = &msDrive1;
    //if (!volName.begin(&msDrive1)) {
   //   Serial.println("EXFat volName.begin failed");
   //   return false;
   // }
    expartVol.begin(msc1.usbDrive(), true, part);
    expartVol.chvol();
    if (!root.openRoot(&expartVol)) {
      Serial.println("openRoot failed");
      return false;
    }
  }
  if (drvType == sdDrive) {
    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) {
  FatVolume partVol;

  uint8_t buf[512];

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

  if (drvType == sdDrive) {
    sd.card()->readSector(sd.dataStartSector(), buf);
  }
  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;
}

// Get Fat16 volume name.
bool getFat16VolumeLabel(uint8_t  drvType, uint8_t part) {
  FatVolume partVol;
  MbrSector_t mbr;

  uint8_t buf[512];

  partVol.begin(msc1.usbDrive(), true, part);
  partVol.chvol();
  if (drvType == msDrive) {
    msc1.usbDrive()->readSector(partVol.rootDirStart(), buf);
//    print_hexbytes(buf, 512);
  }

  if (drvType == sdDrive) {
    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 mbrDmp() {
  MbrSector_t mbr;
  bool valid = true;
  if (!msc1.usbDrive()->readSector(0, (uint8_t*)&mbr)) {
    Serial.print("\nread MBR failed.\n");
    //errorPrint();
    return false;
  }
  Serial.print("\nmsc1 Partition Table\n");
  Serial.print("part,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: ");
        break;
      case 11:
      case 12:
        Serial.print("FAT32: ");
        break;
      case 7:
        Serial.print("exFAT: ");
        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()
{
  // 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();


}

void loop(void) {
  //--------------------------------------------------
  myusb.Task();
  if (!msDrive1) {
    Serial.println("Waiting up to 5 seconds for USB drive");
    elapsedMillis em = 0;
    while (!msDrive1 && (em < 5000) )  myusb.Task();
  }
  if (msDrive1) {
    Serial.printf("Initialize USB drive...");

    if (!msc1.begin(&msDrive1)) {
      msc1.errorPrint(&Serial);
      Serial.println("initialization failed.\n");
    } else {
      Serial.println("USB drive 1 is present.\n");
    }

    mbrDmp();
    /*
      if(msc1.fatType() == 32) {
        Serial.printf("Fat Type: Fat32\n");
        if(!getFat32VolumeLabel(msDrive))
          Serial.printf("Failed to get volume label\n");
      } else {
        Serial.printf("Fat Type: ExFat\n");
      if(!getExFatVolumeLabel(msDrive,1))
        Serial.printf("Failed to get volume label\n");
      }
      msc1.ls(LS_SIZE | LS_DATE | LS_R);
    */

    for (uint8_t i = 1; i < 5; i++) {
      switch (partitionTable[i - 1]) {
        case 11:
        case 12:
          Serial.printf("\nFat Type: Fat32\n");
          if (!getFat32VolumeLabel(msDrive, i))
            Serial.printf("Failed to get volume label\n");
          break;
        case 4:
        case 6:
        case 0xe:
          Serial.printf("\nFat Type: Fat16\n");
          if (!getFat16VolumeLabel(msDrive, i))
            Serial.printf("Failed to get volume label\n");
          break;
        case 7:
          Serial.printf("\nFat Type: ExFat\n");
          if (!getExFatVolumeLabel(msDrive, i))
            Serial.printf("Failed to get volume label\n");
          break;
        default:
          Serial.println("No or Not Supported Partition");
      }
    }
  }
  //--------------------------------------------------
  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(sdDrive, 1))
      Serial.printf("Failed to get volume label\n");
  } else {
    Serial.printf("Fat Type: ExFAT\n");
    if (!getExFatVolumeLabel(sdDrive, 1)) {
      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);
}

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;
  }
}
[/CODE]
 
Argh - that p#479 doesn't have my edits in :(

I have another drive : Flash 128 GB that was seen to FAIL using to backup PC data.

I just went to MSC ExFatFormatter - here is Format okay and startup okay ... then maybe the exFat problem where it just stalls?:
Code:
Type any character to begin

Your SD will be formated exFAT.
All data on the SD will be lost.
Type 'Y' to continue.

Formatting USB drive to ExFat. Please wait...
Writing FAT .................................
Writing upcase table
Writing root
Format done
Bytes per cluster: 131072
Done
Waiting up to 5 seconds for USB drive
^^^^Initialize USB drive...^^^^^~USB drive 1 is present.


msc1 Partition Table
part,boot,bgnCHS[3],type,endCHS[3],start,length
exFAT: 1,0,0x1,0x1,0x0,0x7,0xFE,0xFF,0xFF,32768,242450176
2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

Fat Type: ExFat

Need to take a timeout here ... then will Merge to @mjs513 with my current posted code ... unless @mjs513 does it ...
 
My exfat was failing as well, will look tomorrow unless someone beats me to it.
Damn - thought I posted the fix:
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);

// 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 sdDrive 1
#define msDrive 2

#define SD_CONFIG SdioConfig(FIFO_SDIO)

// set up variables using the mscFS utility library functions:
UsbFs msc1;
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) {
  uint8_t buf[32];
  UsbExFat volName;
  SdExFat volName1;
  ExFatFile root;
  msController *mscDrive;
  DirLabel_t *dir;

  ExFatVolume expartVol;

  if (drvType == msDrive) {
    mscDrive = &msDrive1;
[COLOR="#FF0000"]    //if (!volName.begin(&msDrive1)) {  just delete these lines
   //   Serial.println("EXFat volName.begin failed");
   //   return false;
   // }[/COLOR]
    expartVol.begin(msc1.usbDrive(), true, part);
    expartVol.chvol();
    if (!root.openRoot(&expartVol)) {
      Serial.println("openRoot failed");
      return false;
    }
  }
  if (drvType == sdDrive) {
    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) {
  FatVolume partVol;

  uint8_t buf[512];

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

  if (drvType == sdDrive) {
    sd.card()->readSector(sd.dataStartSector(), buf);
  }
  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;
}

// Get Fat16 volume name.
bool getFat16VolumeLabel(uint8_t  drvType, uint8_t part) {
  FatVolume partVol;
  MbrSector_t mbr;

  uint8_t buf[512];

  partVol.begin(msc1.usbDrive(), true, part);
  partVol.chvol();
  if (drvType == msDrive) {
    msc1.usbDrive()->readSector(partVol.rootDirStart(), buf);
//    print_hexbytes(buf, 512);
  }

  if (drvType == sdDrive) {
    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 mbrDmp() {
  MbrSector_t mbr;
  bool valid = true;
  if (!msc1.usbDrive()->readSector(0, (uint8_t*)&mbr)) {
    Serial.print("\nread MBR failed.\n");
    //errorPrint();
    return false;
  }
  Serial.print("\nmsc1 Partition Table\n");
  Serial.print("part,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: ");
        break;
      case 11:
      case 12:
        Serial.print("FAT32: ");
        break;
      case 7:
        Serial.print("exFAT: ");
        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()
{
  // 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();


}

void loop(void) {
  //--------------------------------------------------
  myusb.Task();
  if (!msDrive1) {
    Serial.println("Waiting up to 5 seconds for USB drive");
    elapsedMillis em = 0;
    while (!msDrive1 && (em < 5000) )  myusb.Task();
  }
  if (msDrive1) {
    Serial.printf("Initialize USB drive...");

    if (!msc1.begin(&msDrive1)) {
      msc1.errorPrint(&Serial);
      Serial.println("initialization failed.\n");
    } else {
      Serial.println("USB drive 1 is present.\n");
    }

    mbrDmp();
    /*
      if(msc1.fatType() == 32) {
        Serial.printf("Fat Type: Fat32\n");
        if(!getFat32VolumeLabel(msDrive))
          Serial.printf("Failed to get volume label\n");
      } else {
        Serial.printf("Fat Type: ExFat\n");
      if(!getExFatVolumeLabel(msDrive,1))
        Serial.printf("Failed to get volume label\n");
      }
      msc1.ls(LS_SIZE | LS_DATE | LS_R);
    */

    for (uint8_t i = 1; i < 5; i++) {
      switch (partitionTable[i - 1]) {
        case 11:
        case 12:
          Serial.printf("\nFat Type: Fat32\n");
          if (!getFat32VolumeLabel(msDrive, i))
            Serial.printf("Failed to get volume label\n");
          break;
        case 4:
        case 6:
        case 0xe:
          Serial.printf("\nFat Type: Fat16\n");
          if (!getFat16VolumeLabel(msDrive, i))
            Serial.printf("Failed to get volume label\n");
          break;
        case 7:
          Serial.printf("\nFat Type: ExFat\n");
          if (!getExFatVolumeLabel(msDrive, i))
            Serial.printf("Failed to get volume label\n");
          break;
        default:
          Serial.println("No or Not Supported Partition");
      }
    }
  }
  //--------------------------------------------------
  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(sdDrive, 1))
      Serial.printf("Failed to get volume label\n");
  } else {
    Serial.printf("Fat Type: ExFAT\n");
    if (!getExFatVolumeLabel(sdDrive, 1)) {
      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);
}

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;
  }
}
 
Code Merged - ExFat 128GB Flash lives:
Code:
Waiting up to 5 seconds for USB drive
^^^^Initialize USB drive...^^^^^~USB drive 1 is present.


msc1 Partition Table
part,boot,bgnCHS[3],type,endCHS[3],start,length
exFAT: 1,0,0x1,0x1,0x0,0x7,0xFE,0xFF,0xFF,32768,242450176
2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

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
No or Not Supported Partition
No or Not Supported Partition
No or Not Supported Partition

Initialize SD card...initialization failed.

done...
Press any key to run again
Initialize USB drive...^^^^^^^^^~~~~:(:(:(

LOOKS GOOD:
> Just one root file and a folder with another file - oppps - no known volume name added
> Works ON Upload, Reset, Power On

PROBLEM - after it works ONCE:
> Press Any Key and then ... HANG with frowny :: Initialize USB drive...^^^^^^^^^~~~~:(:(:(

Merged Code with ExFat working:
- with file for spare "Fat Type: ExFAT" that shows when SD not present - was outside the } close of the else { // success case
- remove two warnings of unused
- shows timer ticks during USB init { cmsReport [ -1 OFF, 0 ON to count ] }
- should not print unprintable chars in Vol Name
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);

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 sdDrive 1
#define msDrive 2

#define SD_CONFIG SdioConfig(FIFO_SDIO)

// set up variables using the mscFS utility library functions:
UsbFs msc1;
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) {
  uint8_t buf[32];
  UsbExFat volName;
  SdExFat volName1;
  ExFatFile root;
  //msController *mscDrive;
  DirLabel_t *dir;

  ExFatVolume expartVol;

  if (drvType == msDrive) {
    //mscDrive = &msDrive1;
    //if (!volName.begin(&msDrive1)) {
    //   Serial.println("EXFat volName.begin failed");
    //   return false;
    // }
    expartVol.begin(msc1.usbDrive(), true, part);
    expartVol.chvol();
    if (!root.openRoot(&expartVol)) {
      Serial.println("openRoot failed");
      return false;
    }
  }
  if (drvType == sdDrive) {
    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) {
  FatVolume partVol;

  uint8_t buf[512];

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

  if (drvType == sdDrive) {
    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.
bool getFat16VolumeLabel(uint8_t  drvType, uint8_t part) {
  FatVolume partVol;
  MbrSector_t mbr;

  uint8_t buf[512];

  partVol.begin(msc1.usbDrive(), true, part);
  partVol.chvol();
  if (drvType == msDrive) {
    // lets read in the Master boot record...
    msc1.usbDrive()->readSector(0, (uint8_t*)&mbr);
    MbrPart_t *pt = &mbr.part[part - 1];
    uint32_t starting_sector = getLe32(pt->relativeSectors);
    msc1.usbDrive()->readSector(starting_sector, buf);
    Serial.printf("\nFAT first sector:(%x)\n", starting_sector);
    print_hexbytes(buf, 512);
    pbs_t* pbs = (pbs_t*)&buf;
    BpbFat16_t *bpt16 = reinterpret_cast<BpbFat16_t*>(pbs->bpb);

    Serial.print(F("Volume Name: "));
    for (size_t i = 0; i < 11; i++) {
      Serial.write(bpt16->volumeLabel[i]);
    }
  }

  if (drvType == sdDrive) {
    sd.card()->readSector(sd.dataStartSector(), buf);
    print_hexbytes(buf, 512);

    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;
}



bool mbrDmp() {
  MbrSector_t mbr;
  // bool valid = true;
  if (!msc1.usbDrive()->readSector(0, (uint8_t*)&mbr)) {
    Serial.print("\nread MBR failed.\n");
    //errorPrint();
    return false;
  }
  Serial.print("\nmsc1 Partition Table\n");
  Serial.print("part,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: ");
      break;
    case 11:
    case 12:
      Serial.print("FAT32: ");
      break;
    case 7:
      Serial.print("exFAT: ");
      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();

#define SHOW_CLOCK_CARAT 1
#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 loop(void) {
  //--------------------------------------------------
  cmsReport = 0;
  myusb.Task();
  if (!msDrive1) {
    Serial.println("Waiting up to 5 seconds for USB drive");
    elapsedMillis em = 0;
    while (!msDrive1 && (em < 5000) )  myusb.Task();
  }
  if (msDrive1) {
    Serial.printf("Initialize USB drive...");

    if (!msc1.begin(&msDrive1)) {
      msc1.errorPrint(&Serial);
      Serial.println("initialization failed.\n");
    } else {
      Serial.println("USB drive 1 is present.\n");
    }
    cmsReport = -1;

    mbrDmp();
    /*
      if(msc1.fatType() == 32) {
        Serial.printf("Fat Type: Fat32\n");
        if(!getFat32VolumeLabel(msDrive))
          Serial.printf("Failed to get volume label\n");
      } else {
        Serial.printf("Fat Type: ExFat\n");
      if(!getExFatVolumeLabel(msDrive,1))
        Serial.printf("Failed to get volume label\n");
      }
      msc1.ls(LS_SIZE | LS_DATE | LS_R);
    */

    for (uint8_t i = 1; i < 5; i++) {
      switch (partitionTable[i - 1]) {
      case 11:
      case 12:
        Serial.printf("\nFat Type: Fat32\n");
        if (!getFat32VolumeLabel(msDrive, i))
          Serial.printf("Failed to get volume label\n");
        break;
      case 4:
      case 6:
      case 0xe:
        Serial.printf("\nFat Type: Fat16\n");
        if (!getFat16VolumeLabel(msDrive, i))
          Serial.printf("Failed to get volume label\n");
        break;
      case 7:
        Serial.printf("\nFat Type: ExFat\n");
        if (!getExFatVolumeLabel(msDrive, i))
          Serial.printf("Failed to get volume label\n");
        break;
      default:
        Serial.println("No or Not Supported Partition");
      }
    }
  }
  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(sdDrive, 1))
        Serial.printf("Failed to get volume label\n");
    } else {
      Serial.printf("Fat Type: ExFAT\n");
      if (!getExFatVolumeLabel(sdDrive, 1)) {
        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);
}

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;
  }
}
 
@All

When you guy's go for something, it always amazes me. I learn so much from your testing:)

There are two timeouts in 'msc.h' located in the 'USBHost_t36/utility' folder that you can tweak at the driver level.
Code:
// These two defines are timeouts for detecting a connected drive
// and waiting for it to be operational.
#define MEDIA_READY_TIMEOUT  1000
#define MSC_CONNECT_TIMEOUT 4000

I have discovered that some USB drives can take several seconds to come up before detection by the driver and before they internally initialize. USB to SATA HDD is a good example. Some drives take 30 seconds or more to come up. A PNY 64 GB thumb drive took over a minute to initialize. How long to wait?

I think having a mount and unmount method is needed. This was the next thing I wanted to try. What I have not figured out is memory allocation for mounting a drive and how to free any said allocation when attempting to unmount a drive. USB or SD card. The unmounting part has me confused still.

'checkConnectedInitialized()' that is used for hot plugging USB drives. Obviously you want to sync a drive and free allocated memory before you unplug a USB drive, unmount it. Any time a USB drive is accessed checkConnectedInitialized()' is called to make sure the USB drive is connected and initialized else returns an error code with the appropriate failure code. Even device failure.

Do not understand this yet with SdFat. How do you unmount a USB drive or SD card?
 
Put the Teensy MSC formatted ExFat drive on Windows - looks good.

Had 16 MB Unallocated before the ExFat Partition. Made that space into a FAT drive.

Both Volumes have usable names - NOT SHOWN, and it sees the FAT - but not anything on it.
After success again - still PAKey rescan Hangs ... forever :(:(:(:(:(
Code:
Waiting up to 5 seconds for USB drive
^^^^Initialize USB drive...^^^^^~Check USB drive format.
initialization failed.


msc1 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
3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0

Fat Type: Fat16

FAT first sector:(800)
EB 3C 90 4D 53 44 4F 53 35 2E 30 00 02 08 02 00 02 00 02 00 70 F8 0B 00 3F 00 FF 00 00 08 00 00 :.<.MSDOS5.0.........p...?.......
00 00 00 00 80 00 29 B1 3C 16 8C 4E 4F 20 4E 41 4D 45 20 20 20 20 46 41 54 31 32 20 20 20 33 C9 :......).<..NO NAME    FAT12   3.
8E D1 BC F0 7B 8E D9 B8 00 20 8E C0 FC BD 00 7C 38 4E 24 7D 24 8B C1 99 E8 3C 01 72 1C 83 EB 3A :....{.... .....|8N$}$....<.r...:
66 A1 1C 7C 26 66 3B 07 26 8A 57 FC 75 06 80 CA 02 88 56 02 80 C3 10 73 EB 33 C9 8A 46 10 98 F7 :f..|&f;.&.W.u.....V....s.3..F...
66 16 03 46 1C 13 56 1E 03 46 0E 13 D1 8B 76 11 60 89 46 FC 89 56 FE B8 20 00 F7 E6 8B 5E 0B 03 :f..F..V..F....v.`.F..V.. ....^..
C3 48 F7 F3 01 46 FC 11 4E FE 61 BF 00 00 E8 E6 00 72 39 26 38 2D 74 17 60 B1 0B BE A1 7D F3 A6 :.H...F..N.a......r9&8-t.`....}..
61 74 32 4E 74 09 83 C7 20 3B FB 72 E6 EB DC A0 FB 7D B4 7D 8B F0 AC 98 40 74 0C 48 74 13 B4 0E :at2Nt... ;.r.....}.}....@t.Ht...
BB 07 00 CD 10 EB EF A0 FD 7D EB E6 A0 FC 7D EB E1 CD 16 CD 19 26 8B 55 1A 52 B0 01 BB 00 00 E8 :.........}....}......&.U.R......
3B 00 72 E8 5B 8A 56 24 BE 0B 7C 8B FC C7 46 F0 3D 7D C7 46 F4 29 7D 8C D9 89 4E F2 89 4E F6 C6 :;.r.[.V$..|...F.=}.F.)}...N..N..
06 96 7D CB EA 03 00 00 20 0F B6 C8 66 8B 46 F8 66 03 46 1C 66 8B D0 66 C1 EA 10 EB 5E 0F B6 C8 :..}..... ...f.F.f.F.f..f....^...
4A 4A 8A 46 0D 32 E4 F7 E2 03 46 FC 13 56 FE EB 4A 52 50 06 53 6A 01 6A 10 91 8B 46 18 96 92 33 :JJ.F.2....F..V..JRP.Sj.j...F...3
D2 F7 F6 91 F7 F6 42 87 CA F7 76 1A 8A F2 8A E8 C0 CC 02 0A CC B8 01 02 80 7E 02 0E 75 04 B4 42 :......B...v..............~..u..B
8B F4 8A 56 24 CD 13 61 61 72 0B 40 75 01 42 03 5E 0B 49 75 06 F8 C3 41 BB 00 00 60 66 6A 00 EB :...V$..aar.@u.B.^.Iu...A...`fj..
B0 42 4F 4F 54 4D 47 52 20 20 20 20 0D 0A 52 65 6D 6F 76 65 20 64 69 73 6B 73 20 6F 72 20 6F 74 :.BOOTMGR    ..Remove disks or ot
68 65 72 20 6D 65 64 69 61 2E FF 0D 0A 44 69 73 6B 20 65 72 72 6F 72 FF 0D 0A 50 72 65 73 73 20 :her media....Disk error...Press 
61 6E 79 20 6B 65 79 20 74 6F 20 72 65 73 74 61 72 74 0D 0A 00 00 00 00 00 00 00 AC CB D8 55 AA :any key to restart............U.
Volume Name: NO NAME    

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
No or Not Supported Partition
No or Not Supported Partition

Initialize SD card...initialization failed.

done...
Press any key to run again
Initialize USB drive...^^^^^^^^^~~~~:(:(

<edit> Here is how Windows see's this 128GB drive:
Fl128dual.png
 
Last edited:
Turned on USB DEBUG

This is the inital case on power up where ExFat works:
Code:
new_Pipe
new_Pipe
Descriptor 5 = ENDPOINT
Descriptor 5 = ENDPOINT
[B]Initialize USB drive...control CallbackIn (msController)[/B]
00 00 00 00 00 00 00 00 
^^^^^control CallbackIn (msController)
00 00 00 00 00 00 00 00 
msController CallbackOut (static)
transfer->qtd.token = 0
msController dataOut (static)31
55 53 42 43 01 00 00 00 00 00 00 00 80 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
[B][COLOR="#FF0000"]~msController CallbackIn (static)[/COLOR][/B]
transfer->qtd.token = 0
msController dataIn (static): 13
55 53 42 53 01 00 00 00 00 00 00 00 00 
msController CallbackOut (static)
transfer->qtd.token = 0
msController dataOut (static)31

Then Press Any Key to run again case the hangs ... :)
Code:
Initialize SD card...initialization failed.

done...
Press any key to run again
[B]Initialize USB drive...control CallbackIn (msController)[/B]
00 00 00 00 00 00 00 00 
^^^^control CallbackIn (msController)
00 00 00 00 00 00 00 00 
msController CallbackOut (static)
transfer->qtd.token = 0
msController dataOut (static)31
55 53 42 43 01 00 00 00 00 00 00 00 80 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
^^^^^~~~~:(:(

Funny it was HUNG there - then PULLED that ExFat drive and Get USB SPEW for HOST - still hung:
Code:
msController dataOut (static)31
55 53 42 43 01 00 00 00 00 00 00 00 80 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
^^^^^~~~~:(:(HUB Callback (member)  [B][COLOR="#FF0000"]// << PULLED DRIVE [/COLOR][/B]
status = 4
getstatus, port = 2
USBHub control callback
00 01 01 00 
New Port Status
  status=10100  port=2
  state=9
  Has Power
disconnect_Device:
USBDriver (available_drivers) list: 200034E0 -> 200038A0 -> 20002D60 -> 20004600
USBDriver (dev->drivers) list: 20004120
disconnect driver 20004120
Device Disconnected...
USBDriver (available_drivers) list: 20004120 -> 200034E0 -> 200038A0 -> 20002D60 -> 20004600
delete_Pipe 20004780
  remove QH from async schedule
  Free transfers
    * 536892672 * remove * free
    * 536889696
  Free transfers attached to QH
    * 536892608
* Delete Pipe completed
delete_Pipe 20004360
  remove QH from async schedule
  Free transfers
    * 536889696
  Free transfers attached to QH
    * 536892544
* Delete Pipe completed
delete_Pipe 200047E0
  remove QH from async schedule
  Free transfers
    * 536889696
  Free transfers attached to QH
    * 536889632
* Delete Pipe completed
removed Device_t from devlist
USBHub control callback
Port Status Cleared, port=2
:(:(:(:(:(:(:(:(:(:(:(:(

>> Plug in another drive and USB brings it onboard ... but still leaving it HUNG ... :(:(:(

Then repowering Teensy with that WP_16GB that hangs - full Spew:
Code:
USB2 PLL running
 reset waited 6
USBHS_ASYNCLISTADDR = 0
USBHS_PERIODICLISTBASE = 20005000
periodictable = 20005000
Waiting up to 5 seconds for USB drive
port change: 10001803
    connect
  begin reset
port change: 18001205
  port enabled
  end recovery
new_Device: 480 Mbit/sec
new_Pipe
enumeration:
enumeration:
enumeration:
Device Descriptor:
  12 01 00 02 09 00 01 40 40 1A 01 01 11 01 00 01 00 01 
    VendorID = 1A40, ProductID = 0101, Version = 0111
    Class/Subclass/Protocol = 9(Hub) / 0 / 1(Single-TT)
    Number of Configurations = 1
enumeration:
enumeration:
Product: USB 2.0 Hub
enumeration:
Config data length = 25
enumeration:
Configuration Descriptor:
  09 02 19 00 01 01 00 E0 32 
    NumInterfaces = 1
    ConfigurationValue = 1
  09 04 00 00 01 09 00 00 00 
    Interface = 0
    Number of endpoints = 1
    Class/Subclass/Protocol = 9(Hub) / 0 / 0
  07 05 81 03 01 00 0C 
    Endpoint = 1 IN
    Type = Interrupt
    Max Size = 1
    Polling Interval = 12
enumeration:
USBHub memory usage = 960
USBHub claim_device this=20003120
found possible interface, altsetting=0
number of interfaces found = 1
USBHub control callback
09 29 04 00 00 32 64 00 FF 00 00 00 00 00 00 00 
Hub ports = 4
USBHub control callback
USBHub control callback
USBHub control callback
USBHub control callback
power turned on to all ports
device addr = 1
new_Pipe
allocate_interrupt_pipe_bandwidth
  ep interval = 12
  interval = 256
 best_bandwidth = 2, at offset = 0
pipe cap1 = F0012101
HUB Callback (member)
status = 4
getstatus, port = 2
USBHub control callback
01 01 01 00 
New Port Status
  status=10101  port=2
  state=0
  Device is present: 
  Has Power
USBHub control callback
Port Status Cleared, port=2
^timer event (19999 us): Debounce Timer, this = 20003120, timer = 20003438
ports in use bitmask = 4
getstatus, port = 2
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=2
  state=2
  Device is present: 
  Has Power
timer event (19999 us): Debounce Timer, this = 20003120, timer = 20003438
ports in use bitmask = 4
getstatus, port = 2
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=2
  state=3
  Device is present: 
  Has Power
timer event (19999 us): Debounce Timer, this = 20003120, timer = 20003438
ports in use bitmask = 4
getstatus, port = 2
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=2
  state=4
  Device is present: 
  Has Power
timer event (19999 us): Debounce Timer, this = 20003120, timer = 20003438
ports in use bitmask = 4
getstatus, port = 2
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=2
  state=5
  Device is present: 
  Has Power
timer event (19999 us): Debounce Timer, this = 20003120, timer = 20003438
ports in use bitmask = 4
getstatus, port = 2
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=2
  state=6
  Device is present: 
  Has Power
sending reset
send_setreset
USBHub control callback
unhandled setup, message = 40323
^timer event (19999 us): Debounce Timer, this = 20003120, timer = 20003438
ports in use bitmask = 0
HUB Callback (member)
status = 4
getstatus, port = 2
USBHub control callback
03 05 10 00 
New Port Status
  status=100503  port=2
  state=7
  Device is present: 
  Enabled, speed = 480 Mbit/sec
  Has Power
USBHub control callback
unhandled setup, message = 140123
timer event (24999 us): Hello, I'm resettimer, this = 20003120, timer = 20003458
port_doing_reset = 2
PORT_RECOVERY
new_Device: 480 Mbit/sec
new_Pipe
enumeration:
enumeration:
enumeration:
Device Descriptor:
  12 01 10 02 00 00 00 40 1D 1E 04 11 00 01 01 02 03 01 
    VendorID = 1E1D, ProductID = 1104, Version = 0100
    Class/Subclass/Protocol = 0 / 0 / 0
    Number of Configurations = 1
enumeration:
enumeration:
Manufacturer: Kanguru
enumeration:
Product: FlashBlu 30
enumeration:
Serial Number: 0708784EA61B9727
enumeration:
Config data length = 32
enumeration:
Configuration Descriptor:
  09 02 20 00 01 01 00 80 96 
    NumInterfaces = 1
    ConfigurationValue = 1
  09 04 00 00 02 08 06 50 00 
    Interface = 0
    Number of endpoints = 2
    Class/Subclass/Protocol = 8(Mass Storage) / 6(SCSI) / 80(Bulk Only)
  07 05 81 02 00 02 00 
    Endpoint = 1 IN
    Type = Bulk
    Max Size = 512
    Polling Interval = 0
  07 05 02 02 00 02 00 
    Endpoint = 2 OUT
    Type = Bulk
    Max Size = 512
    Polling Interval = 0
enumeration:
USBHub memory usage = 960
USBHub claim_device this=200034E0
USBHub memory usage = 960
USBHub claim_device this=200038A0
USBHub memory usage = 960
USBHub claim_device this=20002D60
msController claim this=20004120
msController claim this=20004600
Descriptor 4 = INTERFACE
msController claim this=20004120
09 04 00 00 02 08 06 50 00 07 05 81 02 00 02 00 07 05 02 02 00 02 00 
numendpoint=2
endpointIn=81
endpointOut=2
packet size in (msController) = 512
packet size out (msController) = 512
polling intervalIn = 0
polling intervalOut = 0
new_Pipe
new_Pipe
Descriptor 5 = ENDPOINT
Descriptor 5 = ENDPOINT
Initialize USB drive...control CallbackIn (msController)
00 00 00 00 00 00 00 00 
^^^^^control CallbackIn (msController)
00 00 00 00 00 00 00 00 
msController CallbackOut (static)
transfer->qtd.token = 0
msController dataOut (static)31
55 53 42 43 01 00 00 00 00 00 00 00 80 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
^^~msController CallbackIn (static)
transfer->qtd.token = 0
msController dataIn (static): 13
55 53 42 53 01 00 00 00 00 00 00 00 00 
msController CallbackOut (static)
transfer->qtd.token = 0
msController dataOut (static)31
55 53 42 43 02 00 00 00 24 00 00 00 80 00 06 12 00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 
msController CallbackIn (static)
transfer->qtd.token = 0
msController dataIn (static): 36
00 80 06 02 39 00 00 00 4B 61 6E 67 75 72 75 20 46 6C 61 73 68 42 6C 75 20 33 30 20 20 20 20 20 
msController CallbackIn (static)
transfer->qtd.token = 0
msController dataIn (static): 13
55 53 42 53 02 00 00 00 00 00 00 00 00 
msController CallbackOut (static)
transfer->qtd.token = 0
msController dataOut (static)31
55 53 42 43 03 00 00 00 08 00 00 00 80 00 0A 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
msController CallbackIn (static)
transfer->qtd.token = 64
msController dataIn (static): 0
ERROR Followup
~~~:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(
 
Last edited:
GOOD NEWS! Looks like it was used a year ago for USBHost testing.

Now it just needs to be coded to bring up a second drive as well.

My 120GB HUB DRIVE is ExFat and now works - seems to have Vol Label - and it works again with Press Any Key:
Code:
Waiting up to 5 seconds for USB drive
^^Initialize USB drive...^^^^^USB drive 1 is present.


msc1 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

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
No or Not Supported Partition
No or Not Supported Partition
No or Not Supported Partition

Initialize SD card...initialization failed.

done...
Press any key to run again
Initialize USB drive...^^^^USB drive 1 is present.


msc1 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

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
No or Not Supported Partition
No or Not Supported Partition
No or Not Supported Partition

Initialize SD card...initialization failed.

done...
Press any key to run again
 
Done for now - Got Twin Drives Hacked in and working!!!!

Duplicated setup code for msDrive 1 and 2 in loop() - and pass ptr to msc1 or msc2 to the func( UsbFs *myMsc )'s that need it ( mbrDump and volLabel()'s )
>> Did this because I like my powered HUB with enclosed HDD ( used DigiStump USB power cut dongle to prevent Teensy powered back from Hub )
> Mounts TWO drives and gets proper partition tables and works with Device#1:HDD and any one of 3 flash drives plugged into it
> Fails to decipher the Fat16 first part on 2nd drive - as it does when it is the first drive on other hub - HexDump commented below
> Doing Press Any Key finds first ExFat HDD ( with volume label ) - but HANGS as before/above when it hits : "Initialize USB drive 2..." - SHOW_CLOCK_CARAT commented below
- > second ExFat never gets right Volume Label ???
> added \tab formatting to partition table with 'default' case showing the "pt_#0:" when unknown - in this case zero
> I have new empty SD card in shop - will get that next time - all the ones on my desk are lost or have TONS of data on - in these tests to date : Not Present
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.


[B]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
[/B]
[B]Fat Type: ExFat
Volume Name: 120GB_Ext
[/B]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
No or Not Supported Partition
No or Not Supported Partition
No or Not Supported Partition
Initialize USB drive 2...
Check USB drive format.
[B][COLOR="#FF0000"]initialization failed.[/COLOR][/B]


[B]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
[/B]
[B][COLOR="#FF0000"]Fat Type: Fat16[/COLOR][/B]

FAT first sector:(800)
Volume Name: NO NAME    

[B]Fat Type: ExFat[/B]
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
No or Not Supported Partition
No or Not Supported Partition

Initialize SD card...initialization failed.

done...
Press any key to run again

This Code also working (on HDD HUB) with the 16GB Write protected Flash - even on Power up (or Reset) and Press Any Key with the HUB's 120GB ExFat also working. - { this is the WP_Flash that HANGS when powered up connected )
This Code also working (on HDD HUB) with the 64GB Flash with TWO FAT32 partitions ( and hundreds of pages of FILE data on first RECOVERY partition) - even on Power up (or Reset) and Press Any Key with the HUB's 120GB ExFat also working.


Here is the code as I have it :
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 sdDrive 1
#define msDrive 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 == msDrive) {
    //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 == sdDrive) {
    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 == msDrive) {
    myMsc->usbDrive()->readSector(partVol.dataStartSector(), buf);
  }

  if (drvType == sdDrive) {
    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.
bool getFat16VolumeLabel(uint8_t  drvType, uint8_t part, UsbFs *myMsc) {
  FatVolume partVol;
  MbrSector_t mbr;

  uint8_t buf[512];

  partVol.begin(myMsc->usbDrive(), true, part);
  partVol.chvol();
  if (drvType == msDrive) {
    // lets read in the Master boot record...
    myMsc->usbDrive()->readSector(0, (uint8_t*)&mbr);
    MbrPart_t *pt = &mbr.part[part - 1];
    uint32_t starting_sector = getLe32(pt->relativeSectors);
    myMsc->usbDrive()->readSector(starting_sector, buf);
    Serial.printf("\nFAT first sector:(%x)\n", starting_sector);
    //print_hexbytes(buf, 512);
    pbs_t* pbs = (pbs_t*)&buf;
    BpbFat16_t *bpt16 = reinterpret_cast<BpbFat16_t*>(pbs->bpb);

    Serial.print(F("Volume Name: "));
    for (size_t i = 0; i < 11; i++) {
      Serial.write(bpt16->volumeLabel[i]);
    }
  }

  if (drvType == sdDrive) {
    sd.card()->readSector(sd.dataStartSector(), buf);
    print_hexbytes(buf, 512);

    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;
}



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 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) {
    Serial.printf("Initialize USB drive...");
    cmsReport = 0;

    if (!msc1.begin(&msDrive1)) {
      Serial.println("");
      msc1.errorPrint(&Serial);
      Serial.println("initialization failed.\n");
    } else {
      Serial.println("USB drive 1 is present.\n");
    }
    cmsReport = -1;

    mbrDmp( &msc1 );
    for (uint8_t i = 1; i < 5; i++) {
      switch (partitionTable[i - 1]) {
      case 11:
      case 12:
        Serial.printf("\nFat Type: Fat32\n");
        if (!getFat32VolumeLabel(msDrive, i, &msc1))
          Serial.printf("Failed to get volume label\n");
        break;
      case 4:
      case 6:
      case 0xe:
        Serial.printf("\nFat Type: Fat16\n");
        if (!getFat16VolumeLabel(msDrive, i, &msc1))
          Serial.printf("Failed to get volume label\n");
        break;
      case 7:
        Serial.printf("\nFat Type: ExFat\n");
        if (!getExFatVolumeLabel(msDrive, i, &msc1))
          Serial.printf("Failed to get volume label\n");
        break;
      default:
        Serial.println("No or Not Supported Partition");
      }
    }
  }
  if (msDrive2) {
    Serial.printf("Initialize USB drive 2...");
    cmsReport = 0;

    if (!msc2.begin(&msDrive2)) {
      Serial.println("");
      msc2.errorPrint(&Serial);
      Serial.println("initialization failed.\n");
    } else {
      Serial.println("USB drive 2 is present.\n");
    }
    cmsReport = -1;

    mbrDmp( &msc2 );
    for (uint8_t i = 1; i < 5; i++) {
      switch (partitionTable[i - 1]) {
      case 11:
      case 12:
        Serial.printf("\nFat Type: Fat32\n");
        if (!getFat32VolumeLabel(msDrive, i, &msc2))
          Serial.printf("Failed to get volume label\n");
        break;
      case 4:
      case 6:
      case 0xe:
        Serial.printf("\nFat Type: Fat16\n");
        if (!getFat16VolumeLabel(msDrive, i, &msc2))
          Serial.printf("Failed to get volume label\n");
        break;
      case 7:
        Serial.printf("\nFat Type: ExFat\n");
        if (!getExFatVolumeLabel(msDrive, i, &msc2))
          Serial.printf("Failed to get volume label\n");
        break;
      default:
        Serial.println("No or Not Supported Partition");
      }
    }
  }
  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(sdDrive, 1, &msc2))
        Serial.printf("Failed to get volume label\n");
    } else {
      Serial.printf("Fat Type: ExFAT\n");
      if (!getExFatVolumeLabel(sdDrive, 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);
}

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;
  }
}

Minor note: The 128GB Flash reformatted with MSC that left 16GB first partition space WAS NOT the Bad Flash drive - That is another untried 64GB disk marked Bad.
 
Morning all
@defragster - gave your mods a go and all seems to be working.

1. SSD 120GB - 2parts, extFAT/FAT32
2. SD CARD in adapter - 32GB - 2 FAT32 parts
3. 2 GB Thumb drive - 1 FAT16

All worked without a problem to get vol name and display contents.
 
Good Morning all:

Sounds like we have things coming along well here, to understand some about partitions and getting the volume label. :D
But our test has not handled SD Cards with multiple partitions ;) For example RPI sd cards have multiple, luckily it is the first one that typically is some form of FAT.

@mjs513 you probably already found it, but you asked me how I found out about rootDirStart...

In one of my versions of test, I tried some of the FatPartition debug functions, including: dmpRootDir...
And then looked at the code:
Code:
void FatPartition::dmpRootDir(print_t* pr) {
  uint32_t sector;
  if (fatType() == 16) {
    sector = rootDirStart();
  } else if (fatType() == 32) {
    sector = clusterStartSector(rootDirStart());
  } else {
    pr->println(F("dmpRootDir failed"));
    return;
  }
  dmpDirSector(pr, sector);
}

This has been a great learning sketch as it shows we can handle multiple devices with multiple partitions and now get the volume label :D

But now it would be interesting to again try to figure out how to put all of the pieces together, again across multiple libraries, with different owners, and ...

Things like:
a) FatVolume or FatPartition would be nice if they had a member to read the Volume label, something like: bool volumeLabel(char *vol, size_t cb);
dito for ExFatVolume...

b) Is there a unifying FAT/EXFat partition class? That is each sketch doing something like:
Code:
    for (uint8_t i = 1; i < 5; i++) {
      switch (partitionTable[i - 1]) {
        case 11:
        case 12:
          Serial.printf("\nFat Type: Fat32\n");
          if (!getFat32VolumeLabel(msDrive, i))
            Serial.printf("Failed to get volume label\n");
          break;
        case 4:
        case 6:
        case 0xe:
          Serial.printf("\nFat Type: Fat16\n");
          if (!getFat16VolumeLabel(msDrive, i))
            Serial.printf("Failed to get volume label\n");
          break;
        case 7:
          Serial.printf("\nFat Type: ExFat\n");
          if (!getExFatVolumeLabel(msDrive, i))
            Serial.printf("Failed to get volume label\n");
          break;
        default:
          Serial.println("No or Not Supported Partition");
      }
    }
  }
Does not feel ideal. Would be nice if there was wrapper that cased it all for you, like we do for the first partition.... Most of the time you don't care what type of Fat FS...
Maybe in one of the UsbMscFat classes? Like probably first look might be: MSCClass? Would need to ripple through things like partition number...

c) MTP - I want to play and integrate some of this. That is if I now plug in the USB stick with 3 partitions, Maybe want all three to show up... Need to figure out the objects
Currently I have in my branch:
Code:
#if USE_MSC_FAT > 0
#if defined(__IMXRT1062__) || defined(ARDUINO_TEENSY36)
#include <mscFS.h>
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);

// start off with one controller. 
msController msDrive[USE_MSC_FAT](myusb);
MSCClass msc[USE_MSC_FAT];
char *nmsc_str[USE_MSC_FAT] = {nullptr};
uint32_t msc_storage_index[USE_MSC_FAT] = {(uint32_t)-1};
But with this new stuff I am guessing that our usage of msDrive (USB Device) and msc (File systems) will not necessarily be one to one. So I may want lets say max of 2 USB devices and 6 or volumes...

Also with MTP I want to experiment with telling host the volume label to see if they come through...

...

But probably first more coffee!
 
Morning all
@mjs513 you probably already found it, but you asked me how I found out about rootDirStart...
Actually no, didn't get a chance to look - too many other distractions last couple of days :)

This has been a great learning sketch as it shows we can handle multiple devices with multiple partitions and now get the volume label

But now it would be interesting to again try to figure out how to put all of the pieces together, again across multiple libraries, with different owners, and ...

Things like:
a) FatVolume or FatPartition would be nice if they had a member to read the Volume label, something like: bool volumeLabel(char *vol, size_t cb);
dito for ExFatVolume...

b) Is there a unifying FAT/EXFat partition class? That is each sketch doing something like:

------
Does not feel ideal. Would be nice if there was wrapper that cased it all for you, like we do for the first partition.... Most of the time you don't care what type of Fat FS...
Maybe in one of the UsbMscFat classes? Like probably first look might be: MSCClass? Would need to ripple through things like partition number...
I agree with you Kurt 100%.

Oh - one thing I noticed is that if you put in a SD Card in a USB adapter it works with out having to deal with starting sd.card. So no extra coding if you use SD with USB Host!
 
Some More not fleshed out thoughts on MSC and Partitions and FS...

I first off think it will be great all of the pieces in place and part of Teensyduino!

What I am sort of wondering is if it makes sense to have a lot of the processing for Partitions be part of the USBHost code. Again I don't know enough about all of the usages of the msController classes.

But IF in most cases all of usages will read the master boot record, to grab the partition table and use the partition table to control their access.

Then maybe some of the low level code could be part of the msController code.

Then maybe there are another class of objects with some name like: MSCPartition that works sort of like HID devices or Bluetooth devices...
Where you can have different implementations of: and maybe this interface has a member like: claimPartition where you pass to it, some/all of the partition information, like index, file system type,
starting sector, sector count... and this class could decide to claim the partition or not. Maybe there is another member or parameter pass, where for those who want the whole thing, say I claim this whole device.

Then we could have one or more implementations of this class. Like could just be Fat or just ExFat or either ... And who knows maybe someone has a linux EXTn implementation they wish to use...

Again don't know if this at all makes sense or would be worth the time?
 
Another quick note: I updated my sketch to the last one @defragster and found it was using the old non working Fat16 code. i.e. the one that was reading the boot sector and appears to always be: NO NAME

Will fix and post again, right now playing with another function: bool getUSBPartitionVolumeLabel(UsbFs *myMsc, uint8_t part, uint8_t *pszVolName, uint16_t cb) {

Where it figures out which one... Once it is working I will lift it from here and add to the MTP sketch...
 
Updated to fix the Fat16, also implemented a one call to find volume label.

And did some more gratuitous changes to have a function called by loop to process a drive, as to not need to reproduce it for more drives...
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);
    }
  }
}

//================================================================
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);
}
 
p#494 sketch looks Great!

Grabbed a fresh 128GB SD card and will make it Multi Partition.

I thought to do something like procesMSDrive(1, msDrive1, msc1); rather than Dupe - but time was limited and wanted to get the (UsbFs *myMsc) part done - and then with multi drive testing that was the safer start. And didn't want to get sketch leap frogged again as I had done the UsbFs *myMsc change once before and lost it.

This second Drive below still HANGS on 'Press Any Key" {PAK}

I see FAT16 Vol Name - but still not liking init drive 2:
Code:
Check USB drive format.
[B]initialization drive 2 failed.[/B]

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

Fat Type: Fat16
[B]Volume Name: FATVOL16M [/B] 
Try calling getUSBPartitionVolumeLabel
FAT16:	>> Volume name:(FATVOL16M)

Fresh from package 128GB Flash seems to add this on SerMon:
Note: Win shows no Vol Label from factory
Note: This 128GB SD ( like the MSC formatted 128 Flash stick ) shows 16MB unallocated at start of media ??? Formatted are is 116MB.
Code:
Try calling getUSBPartitionVolumeLabel
exFAT:	>> Volume name:(120GB_Ext)
No or Not Supported Partition
Try calling getUSBPartitionVolumeLabel
No or Not Supported Partition
Try calling getUSBPartitionVolumeLabel
No or Not Supported Partition
Try calling getUSBPartitionVolumeLabel

Initialize SD card...SD card is present.

Fat Type: ExFAT
Volume Name: 
done...
Press any key to run again
 
Last edited:
Fun News: Fresh 128GB SD - as noted with 116GB primary ExFat.

Week old Windows 10 i7 - running next release of Windows 21H1 insider build:

On SD Deleted Factory Partition - Created one of 8GB { after format : BSOD - REBOOT } - Created one of 16GB { before format : BSOD - REBOOT } : posting this before making the third Partition.

Note: BSOD is now Green
 
@All

Took the rest of the day off and tried out the latest sketch. Everything works great:) I had one little problem that was my fault when I was creating two partitions on a 16G thumb drive I accidentally formated one partition as NTFS instead of ExFat. The result:
Code:
Waiting up to 5 seconds for USB drive 1
Waiting up to 5 seconds for USB drive 2
Initialize USB drive...
Check USB drive format.
initialization drive 1 failed.

msc # Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
exFAT:	1,0,0x20,0x21,0x0,0x7,0x1,0xF1,0x90,2048,14649344
exFAT:	2,0,0x1,0xF2,0x90,0x7,0xFE,0xFF,0xFF,14651392,15566848
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: ExFat
Volume Name: tvstbo><... etc.
Try calling getUSBPartitionVolumeLabel
exFAT:	locked up here

Does not like NTFS I guess. I am not sure of how to detect that to avoid lock ups. Maybe @KurtE knows.

I first off think it will be great all of the pieces in place and part of Teensyduino!

What I am sort of wondering is if it makes sense to have a lot of the processing for Partitions be part of the USBHost code. Again I don't know enough about all of the usages of the msController classes.

But IF in most cases all of usages will read the master boot record, to grab the partition table and use the partition table to control their access.

Then maybe some of the low level code could be part of the msController code.

Then maybe there are another class of objects with some name like: MSCPartition that works sort of like HID devices or Bluetooth devices...
Where you can have different implementations of: and maybe this interface has a member like: claimPartition where you pass to it, some/all of the partition information, like index, file system type,
starting sector, sector count... and this class could decide to claim the partition or not. Maybe there is another member or parameter pass, where for those who want the whole thing, say I claim this whole device.

This is why I did not want to go any further than i did with UsbMSCFat. I was not sure how all of these different drivers would be put together.

Then we could have one or more implementations of this class. Like could just be Fat or just ExFat or either ... And who knows maybe someone has a linux EXTn implementation they wish to use...
A while back I had started exploring lwext4. The examples were for Linux and Windows and used ext4 files images. But I saw that it to is using a block device as an interface. Going to see if there is way to adapt it to the T4.1. Maybe, maybe not:)

I updated UsbMSCFat to get rid of some compiler warnings in 'USBmscDevice.cpp' on GitHub.
 
@wwatson - perhaps with line #16 on in UPDATE sketch below : //#define SHOW_CLOCK_CARAT 1
That will show MCU running but USB msgs stalled. Have you hacked in the PR for HardFaults just to know if any hang results from a Fault.

> Minor SerMon print adds to note SD versus USB to clarify output on multi drives Partitions
> Moved myMsc usage under MS_DRIVE when same func handles SD_DRIVE type so passing nullptr wouldn't Fault for calls from SD code.

Four Partitions on NEW 128 GB SD - and FOUR Windows system Faults :(:
SD128in4.png
Partitions created and formatted and named.
p#494 sketch only show Vol Name of first Part:
Code:
Initialize SD card...SD card is present.

SD Fat Type: Fat32
Volume Name: SD1_8GB_AD

SD only looking as far as first Partition, And not showing directory of disk?

Updated p494 code - added version comment line to track where changed:
Code:
//  VolumeName.ino
// VER: P494, p498
//  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);
      }
    }
  }
}

//================================================================
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);
}
 
@wwatson - not sure, about NTFS here. It looks like both partitions have type=7 which I believe is exfat. although looking at:https://en.wikipedia.org/wiki/Partition_type

It looks like type of 7 could be either. Not sure yet how one would detect an NTFS partition here?

@all - not sure where is best place to ask something like this: but playing with changing some of the stuff in my MTP version that works with MSC... But running into timeout issues... What else is new!

But in my test version the code I have that adds a USB drive when it plug it in.. So far only the first partition... But for debug I copied in the stuff to dump partition table, plus my code to get the volume label..

Again hard to know what thread to talk in... But will mention it here.

Code:
void checkUSBandSDIOStatus() {
#if USE_MSC_FAT > 0
  bool usb_drive_changed_state = false;
  myusb.Task(); // make sure we are up to date.
  for (int ii = 0; ii < USE_MSC_FAT; ii++)
  {
    USBDriver *pdriver = &msDrive[ii];
    if (*pdriver) 
    {
      if (msc_storage_index[ii] == (uint32_t)-1) 
      {
        // lets try to add this storage...
        Serial.println("USB Drive Inserted");
        if (msc[ii].begin(&msDrive[ii]))
        {
          // experiment to see if we can get some additional information. 
          mbrDmp(&msc[ii].mscfs);
          uint8_t volName[32];
          if (getUSBPartitionVolumeLabel(&msc[ii].mscfs,1, volName, sizeof(volName))) {
            Serial.printf(">> USB partition 0 valume ID: %s\n", volName);
          }

          msc_storage_index[ii] = storage.addFilesystem(msc[ii], nmsc_str[ii]);
[COLOR="#006400"]          elapsedMicros emmicro = 0;
          uint64_t totalSize = msc[ii].totalSize();
          uint32_t elapsed_totalSize = emmicro;
          uint64_t usedSize  = msc[ii].usedSize();
          Serial.printf("new Storage %d %s %llu(%u) %llu(%u)\n", ii, nmsc_str[ii], totalSize, elapsed_totalSize, usedSize, (uint32_t)emmicro - elapsed_totalSize); 
[/COLOR]          usb_drive_changed_state = true;
          mtpd.send_StoreAddedEvent(msc_storage_index[ii]);
        }
      }
Sometimes I was finding that it would not work when it added the MSC drive.

So I tried plugging in one of the two drives at at time after it started up...
Code:
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
RESP:2001(RSP:OK)l: 16 T:4 : 1
CMD: 1005(GET_STORAGE_INFO)l: 16 T:5 : 2
RESP:2001(RSP:OK)l: 16 T:5 : 2
CMD: 1005(GET_STORAGE_INFO)l: 16 T:6 : 3
RESP:2001(RSP:OK)l: 16 T:6 : 3
CMD: 1005(GET_STORAGE_INFO)l: 16 T:7 : 4
RESP:2001(RSP:OK)l: 16 T:7 : 4
CMD: 9801(GET_OBJECT_PROPS_SUPPORTED)l: 16 T:8 : 3000
RESP:2001(RSP:OK)l: 16 T:8 : 3000
CMD: 9801(GET_OBJECT_PROPS_SUPPORTED)l: 16 T:9 : 3001
RESP:2001(RSP:OK)l: 16 T:9 : 3001
USB Drive Inserted
FsVolume::begin(20007cb8)
ExFatPartition::init(20007cb8, 1)
FatPartition::init(20007cb8, 1)

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
FAT32:	FatPartition::init(20007cb8, 1)
>> USB partition 0 valume ID: VOLFAT32
sd_addFilesystem: 4 20007824 MSC0
new Storage 0 MSC0 4186095616(0) 3362816(5888495)
*MTPD::send_Event(4004) 5
*MTPD::send_Event(400b)
[COLOR="#FF0000"]CMD: 1005(GET_STORAGE_INFO)l: 16 T:a : 5
RESP:2001(RSP:OK)l: 16 T:a : 5
[/COLOR]USB Drive Inserted
FsVolume::begin(20008158)
ExFatPartition::init(20008158, 1)
FatPartition::init(20008158, 1)

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
FAT16:	FatPartition::init(20008158, 1)
>> USB partition 0 valume ID: CRUZER
sd_addFilesystem: 5 20007cc4 MSC1
new Storage 1 MSC1 1030750208(0) 3817472(93496)
*MTPD::send_Event(4004) 6
*MTPD::send_Event(400b)

But during this time, I would see that on the first drive I would get the expected message from host when I told them there was a new drive:

Code:
*MTPD::send_Event(4004) 5
*MTPD::send_Event(400b)
CMD: 1005(GET_STORAGE_INFO)l: 16 T:a : 5
RESP:2001(RSP:OK)l: 16 T:a : 5
That it would take a long time between when saw the request for storage info and when I responded... So that is when I instrumented the debug code that prints out data about the drive I am adding:
Green code up above: So the one debug message I output:
new Storage 0 MSC0 4186095616(0) 3362816(5888495)
looks like the call: uint64_t usedSize = msc[ii].usedSize()
Took almost 6 seconds to complete 8)

Need to figure out what to do about that... I may try some hacks and see if your FS class maybe I will try to cache that data in there, at startup and see what that does...
 
@KurtE
It looks like type of 7 could be either. Not sure yet how one would detect an NTFS partition here?

That is what I was thinking. In the Linux disks formatting program it lists the partition type as 'NTFS/exFAT/HPFS' but shows NTFS and exFAT as two different format types. Possibly NTFS has a different type of file access that SdFat does not support. Not that familiar with NTFS.

I want to get back to playing with MTP. I know a lot has changed. Has it been able to be used with Linux yet? Last time I played with it I was still getting permission error on everything except the SDIO card. It would show the directory and I could copy files back and forth. Oh, and it would show the stores 1... for the other storages. That's about as far as I got with it.

I am now working with lwext4. Hopefully not in vain:) Starting with modifying the base ext4 file system. I'm sunk if it needs a MM:)

Need to figure out what to do about that... I may try some hacks and see if your FS class maybe I will try to cache that data in there, at startup and see what that does...

'mscFS.h' was based on 'SD.h' a couple of betas back. If there were changes to 'SD.h' they were probably not incorperated into 'mscFS.h'. I need to compare them if that is the case.
 
Last edited:
Back
Top