USB Host Port hotplug MIDI Device issue

yeahtuna

Well-known member
I'm reporting a bug with the USB Host library. The setup uses 2 Teensy 3.6 devices running the exact same code shown below. USB Type is MIDI. Tested with 3 different USB hubs.


Description of problem
When hot hotplugging a Teensy USB MIDI device, plugged into a USB hub connected to the host port of a Teensy 3.6, the USB Hub driver goes into an endless loop and eventually crashes the host teensy.

If the MIDIDevice driver is removed from the sketch, the problem goes away.

Test Setup
Connect a USB hub to the host port of one of the Teensys. Connect / disconnect the second Teensy to the hub. I sure way to trigger the problem is to press the program button on the teensy connected to the hub.


Simplest Sketch to Reproduce (USB Type MIDI)
Code:
#include <USBHost_t36.h>

USBHost myusb;
USBHub usbHub(myusb);
MIDIDevice midi1(myusb); // if removed from the shetch, the problem goes away!

bool ledOn = false;
#define LEDPIN 5

void setup() {
  Serial.begin(9600);
  while (!Serial && millis() < 5000) {
    // wait for serial port to connect.
  }
  myusb.begin();
}

void loop() {

}


Sample Debugging Output (truncated)
Code:
sizeof Device = 36
sizeof Pipe = 96
sizeof Transfer = 64
power up USBHS PHY
 reset waited 5
USBHS_ASYNCLISTADDR = 0
USBHS_PERIODICLISTBASE = 1FFF3000
periodictable = 1FFF3000
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 E3 05 05 06 0B 06 00 01 00 01 
    VendorID = 05E3, ProductID = 0605, Version = 060B
    Class/Subclass/Protocol = 9(Hub) / 0 / 1(Single-TT)
    Number of Configurations = 1
enumeration:
enumeration:
Product: USB2.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=1FFF2720
found possible interface, altsetting=0
number of interfaces found = 1
USBHub control callback
09 29 04 E9 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 = 10
getstatus, port = 4
USBHub control callback
01 01 01 00 
New Port Status
  status=10101  port=4
  state=0
  Device is present: 
  Has Power
USBHub control callback
Port Status Cleared, port=4
timer event (199999 us): Debounce Timer, this = 1FFF2720, timer = 1FFF2A38
ports in use bitmask = 10
getstatus, port = 4
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=4
  state=2
  Device is present: 
  Has Power
timer event (19999 us): Debounce Timer, this = 1FFF2720, timer = 1FFF2A38
ports in use bitmask = 10
getstatus, port = 4
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=4
  state=3
  Device is present: 
  Has Power
timer event (19999 us): Debounce Timer, this = 1FFF2720, timer = 1FFF2A38
ports in use bitmask = 10
getstatus, port = 4
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=4
  state=4
  Device is present: 
  Has Power
timer event (19999 us): Debounce Timer, this = 1FFF2720, timer = 1FFF2A38
ports in use bitmask = 10
getstatus, port = 4
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=4
  state=5
  Device is present: 
  Has Power
timer event (20000 us): Debounce Timer, this = 1FFF2720, timer = 1FFF2A38
ports in use bitmask = 10
getstatus, port = 4
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=4
  state=6
  Device is present: 
  Has Power
sending reset
send_setreset
USBHub control callback
unhandled setup, message = 40323
timer event (20000 us): Debounce Timer, this = 1FFF2720, timer = 1FFF2A38
ports in use bitmask = 0
HUB Callback (member)
status = 10
getstatus, port = 4
USBHub control callback
03 01 10 00 
New Port Status
  status=100103  port=4
  state=7
  Device is present: 
  Enabled, speed = 12 Mbit/sec
  Has Power
USBHub control callback
unhandled setup, message = 140123
timer event (25000 us): Hello, I'm resettimer, this = 1FFF2720, timer = 1FFF2A58
port_doing_reset = 4
PORT_RECOVERY
new_Device: 12 Mbit/sec
new_Pipe
enumeration:
enumeration:
enumeration:
Device Descriptor:
  12 01 10 01 00 00 00 40 C0 16 85 04 77 02 01 02 03 01 
    VendorID = 16C0, ProductID = 0485, Version = 0277
    Class/Subclass/Protocol = 0 / 0 / 0
    Number of Configurations = 1
enumeration:
enumeration:
Manufacturer: Teensyduino
enumeration:
Product: Teensy MIDI
enumeration:
Serial Number: 3614610
enumeration:
Config data length = 115
enumeration:
Configuration Descriptor:
  09 02 73 00 02 01 00 C0 32 
    NumInterfaces = 2
    ConfigurationValue = 1
  09 04 00 00 02 01 03 00 00 
    Interface = 0
    Number of endpoints = 2
    Class/Subclass/Protocol = 1 / 3 / 0
  07 24 01 00 01 25 00 
  06 24 02 01 01 05 
  06 24 02 02 02 05 
  09 24 03 01 03 01 02 01 05 
  09 24 03 02 04 01 01 01 05 
  09 05 04 02 40 00 00 00 00 
    Endpoint = 4 OUT
    Type = Bulk
    Max Size = 64
    Polling Interval = 0
  05 25 01 01 01 
  09 05 83 02 40 00 00 00 00 
    Endpoint = 3 IN
    Type = Bulk
    Max Size = 64
    Polling Interval = 0
  05 25 01 01 03 
  09 04 01 00 02 03 00 00 00 
    Interface = 1
    Number of endpoints = 2
    Class/Subclass/Protocol = 3(HID) / 0 / 0
  09 21 11 01 00 01 22 21 00 
    HID, 1 report descriptor
  07 05 81 03 40 00 01 
    Endpoint = 1 IN
    Type = Interrupt
    Max Size = 64
    Polling Interval = 1
  07 05 02 03 20 00 02 
    Endpoint = 2 OUT
    Type = Interrupt
    Max Size = 32
    Polling Interval = 2
enumeration:
Descriptor 4 = INTERFACE
MIDIDevice claim this=1FFF2020
len = 106
  Interface is MIDI
type: 36, len: 7
    MIDI Header (ignored)
type: 36, len: 6
    MIDI IN Jack (ignored)
type: 36, len: 6
    MIDI IN Jack (ignored)
type: 36, len: 9
    MIDI OUT Jack (ignored)
type: 36, len: 9
    MIDI OUT Jack (ignored)
type: 5, len: 9
    MIDI Endpoint: 4
      tx_size = 64
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
type: 5, len: 9
    MIDI Endpoint: 83
      rx_size = 64
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
type: 4, len: 9
new_Pipe
new_Pipe
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 5 = ENDPOINT
Descriptor 37 =  ???
Descriptor 5 = ENDPOINT
Descriptor 37 =  ???
Descriptor 4 = INTERFACE
Descriptor 33 = HID
Descriptor 5 = ENDPOINT
Descriptor 5 = ENDPOINT
HUB Callback (member)
status = 10
getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
deferred getstatus, port = 4
HUB Callback (member)
status = 10
 
Last edited:
I've spent about 8 hours now trying to get to the bottom of this. Ultimately the problem is that the hub issues a queue_Control_Transfer, but the associated callback is never called.

I can detect when this happens, but I'm not sure how to put the hub back into a good state. Any suggestions?
 
I think I've finally gotten it resolved. What a headache. I'll report back after I've sure the fix I'm using works properly.
 
any news on this?

Yes. It turned out to be a bug with the Mass Storage driver. Should be fixed in Teensydruino 1.58. I say 'should' because I'm still using the workaround JIC, so I don't actually know if the bug that was fixed also fixed this particular issue, but I suspect it did.
 
Back
Top