usb host on teensy 3.6 midi devices serial Numbers inconsistent.

lokki

Well-known member
hi,
i have several usb-midi devices connected via a hub to a teensy 3.6 host port. all is working great communication wise, i can send messages to all devices.
to distinguish devices i used the following code in setup.

Code:
for (int i=0; i<7; i++) {
  if (midilist[i]->manufacturer() != NULL && midilist[i]->serialNumber() != NULL) {
     serialNumbers[i] = (int*)midilist[i]->serialNumber();
    Serial.println(serialNumbers[i]);
     }
     }
  }
  }

i thought i could then send messages to specific devices by checking for known serial numbers (i gathered with the code above)

strange thing is, these serial numbers reported by
Code:
(int*)midilist[i]->serialNumber();
change depending on what devices are plugged in.

example:

i plug in my waldorf synth into the hub, and get a serialNr: 536820542
i plug in my axoloti synth as well and get two serialNr's:
536822296
536822302

as you can see, the serial nr. of the waldorf has changed! is this a known bug/feature?

i first thought this is a bug/problem with the waldorf synth. but the same happens with other synths as well. you plug in one, read the serials, plug in a second one, and both serial numbers change.

switching to
Code:
midilist[i]->idProduct()
is not really an option, because i have several axoloties connected to the hub
and they all share idProduct() and idVendor() or is there another function i can call which gives me a unique ID per device connected?

any help/insight would be greatly welcome.
 
ah i see... so
Code:
midilist[i]->serialNumber();
returns a string, and that probably gets corrupted when saved to an int...

is the serial nr string fixed length? or how can i check against known serials in the easiest way?
 
It has been awhile since I looked at it, but pretty sure the device header has a length value for each of the different strings, so can be variable in length.

idProduct is the vendors product ID, likewise we have a vendor number...
So for example if you plug in an FTDI cable, it will probably the vendor ID of 0x0403
And the main cables I have used have the product ID of: 0x6001

But the Serial number will be different for all of them.
 
thanks,

using:

Code:
Serial.println((char*)midilist[i]->serialNumber());

i now get consistent serial-numbers even if i plug in more devices etc. so it was really about storing to an int, which of course messed up the serial number.

how do i now compare the serial obtained?

i tried:

Code:
if (midilist[i]->serialNumber() == (char)"11390072173-1304284600") {
//do something
}

but that does not work. how do i check if a serial number is equal to a known good one?
sorry if this all obvious.
 
perfect, that works! hmm, did not know that function :)

here is the working code for reference:

Code:
for (int i=0; i<7; i++) {
  if (midilist[i]->manufacturer() != NULL && midilist[i]->serialNumber() != NULL) {
     Serial.println((char*)midilist[i]->serialNumber());
     
     if (!strcmp(midilist[i]->serialNumber(), "11390072173-1304284600")) { //Waldorf Blofeld Serial
      Serial.println("here is blofeld");
      blofeld = i;
     }

     if (!strcmp(midilist[i]->serialNumber(),"003600433435511733353932")) {//Axoloti for qunexus/vocoder serial
      Serial.println("here is axovocoder");
      keysaxo = i;
     }
  }
  }
 
ok, got another problem.

i have a teensy 4 midi foot controller that works fine connected to a pc. i want to connect this to the teensy 3.6. host/hub i wrote about above. unfortunately my setup code to obtain the serialNumber (to further process the midi messages from the teensy 4) does not return any serial for the connected teensy 4. do i need to set ->manufacturer and ->serialNumber somehow in the teensy4 code? or does usb type have to be something special? (i am using serial + midi)

this is the setup code:

Code:
    myusb.begin();
     delay(1500);
for (int i=0; i<7; i++) {
  if (midilist[i]->manufacturer() != NULL && midilist[i]->serialNumber() != NULL) {
     Serial.println((char*)midilist[i]->serialNumber());
     
     if (!strcmp(midilist[i]->serialNumber(), "11390072173-1304284600")) { //Waldorf Blofeld Serial
      Serial.println("here is blofeld");
      blofeld = i;
     }

     if (!strcmp(midilist[i]->serialNumber(),"003600433435511733353932")) {//Axoloti for qunexus/vocoder serial
      Serial.println("here is axovocoder");
      keysaxo = i;
     }
  }
  }

it finds all other connected devices without problems.

the teensy 4.0 does boot up and works, but it is not recognised
 
The T_4.0 will always put the Serial# in the descriptor AFAIK - maybe the USBHost code doesn't parse that out as written - unless the midi doesn't pass that like Serial always does?
 
If it works from PC, then the info is findable - either from midi connect - or from Serial connect finding the Serial number for the device and then doing midi using that 'port' device? KurtE was just looking at USBHost Serial - perhaps he can clarify if not Paul.
 
hmm, yes it definitely works from PC, i also tried with:

an arduino uno setup as usb-midi controller. this also does not spit out a serial number but with:

Code:
Serial.println(midilist[i]->idProduct());

i at least get a number for it :)

the teensy 4.0 is just not showing up. maybe (since the hub is powered before the teensy 3.6 gets started) the connected devices have to be polled for their serial number etc. and the teensy 4 does not handle this polling request correctly?
 
Can only suggest anecdotally ... it seems the Teensy will get the same info as the PC - hub or not - if the Teensy asks for or records it.

Might show something looking in CORES code for the MIDI versus SERIAL descriptor to see if the info is packed in there.
 
ok, the cores file of the "slave midi" teensy 4.0 or the teensy 3.6 that is the host? sorry i am new to this :)
 
Sorry I am sort of confused on your setup and the like: Also I don't do much/anything with MIDI nor Audio so may not be much help here.

But if I look at the code like:
Code:
    myusb.begin();
    delay(1500);
    for (int i=0; i<7; i++) {
        if (midilist[i]->manufacturer() != NULL && midilist[i]->serialNumber() != NULL) {
             Serial.println((char*)midilist[i]->serialNumber());
     
         if (!strcmp(midilist[i]->serialNumber(), "11390072173-1304284600")) { //Waldorf Blofeld Serial
            Serial.println("here is blofeld");
            blofeld = i;
         }

         if (!strcmp(midilist[i]->serialNumber(),"003600433435511733353932")) {//Axoloti for qunexus/vocoder serial
            Serial.println("here is axovocoder");
             keysaxo = i;
        }
     }
  }
This assumes all 7 devices started up successfully. You may want to first test to see if you have a connected like:
Code:
    for (int i=0; i<7; i++) {
        if (!midilist[i]) {
            Serial.printf("No Midi device on index %d\n", i);
            continue; // don't do the rest of the stuff for this index
        }
        if (midilist[i]->manufacturer() != NULL && midilist[i]->serialNumber() != NULL) {
BUT, I what I am really wondering, is does the T4 default to build the MIDI interface with TX and RX of 512 bytes instead of the older 64 byte TX/RX?...
Would not have even wondered this if not for my recent fixes for Serial, where an FTDI device does 512 byte transfers and Paul mentioned something about MidiDevice_BigBuffer

If so, in order to use a T4 in the USBHost Midi code you would need to use a: MidiDevice_BigBuffer class, instead of: MIDIDevice
Now maybe it is supposed to handle both and maybe it does?

If it were me, I would try a bigbuffer and see if it connects or not. It appears like the T4 USB code has code in it to detect if the connection came in as a USB_HIGH_SPEED or not and configure it self for either 64 or 512... Would be interesting to see which way this binds...

Probably more a question for Paul, although we can debug the current stuff, by the buffer size and likewise:
getting more debug information, by editing the USBHost header file USBHost_t36.h and uncomment the line: //#define USBHOST_PRINT_DEBUG

And then rebuild your program.
 
this is what i get with debug enabled, which seems to indicate you are on the right track :) (sorry for the strange device names, it was an attempt to get it working)

Code:
sizeof Device = 36
sizeof Pipe = 96
sizeof Transfer = 64
power up USBHS PHY
 reset waited 4
USBHS_ASYNCLISTADDR = 0
USBHS_PERIODICLISTBASE = 1FFF7000
periodictable = 1FFF7000
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 02 40 40 1A 01 02 00 01 00 01 00 01 
    VendorID = 1A40, ProductID = 0201, Version = 0100
    Class/Subclass/Protocol = 9(Hub) / 0 / 2(Multi-TT)
    Number of Configurations = 1
enumeration:
enumeration:
Product: USB 2.0 Hub [MTT]
enumeration:
Config data length = 41
enumeration:
Configuration Descriptor:
  09 02 29 00 01 01 00 E0 32 
    NumInterfaces = 1
    ConfigurationValue = 1
  09 04 00 00 01 09 00 01 00 
    Interface = 0
    Number of endpoints = 1
    Class/Subclass/Protocol = 9(Hub) / 0 / 1(Single-TT)
  07 05 81 03 01 00 0C 
    Endpoint = 1 IN
    Type = Interrupt
    Max Size = 1
    Polling Interval = 12
  09 04 00 01 01 09 00 02 00 
    Interface = 0
    Number of endpoints = 1
    Class/Subclass/Protocol = 9(Hub) / 0 / 2(Multi-TT)
  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=1FFF4C40
found possible interface, altsetting=0
found possible interface, altsetting=1
number of interfaces found = 2
best interface is 0 using altsetting 1
USBHub control callback
09 29 07 88 00 32 64 00 FF 00 00 00 00 00 00 00 
Hub ports = 7
USBHub control callback
unhandled setup, message = 10B01
USBHub control callback
USBHub control callback
USBHub control callback
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 = 80
getstatus, port = 7
USBHub control callback
01 01 01 00 
New Port Status
  status=10101  port=7
  state=0
  Device is present: 
  Has Power
USBHub control callback
Port Status Cleared, port=7
timer event (20000 us): Debounce Timer, this = 1FFF4C40, timer = 1FFF4F58
ports in use bitmask = 80
getstatus, port = 7
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=7
  state=2
  Device is present: 
  Has Power
timer event (19999 us): Debounce Timer, this = 1FFF4C40, timer = 1FFF4F58
ports in use bitmask = 80
getstatus, port = 7
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=7
  state=3
  Device is present: 
  Has Power
timer event (19999 us): Debounce Timer, this = 1FFF4C40, timer = 1FFF4F58
ports in use bitmask = 80
getstatus, port = 7
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=7
  state=4
  Device is present: 
  Has Power
timer event (20000 us): Debounce Timer, this = 1FFF4C40, timer = 1FFF4F58
ports in use bitmask = 80
getstatus, port = 7
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=7
  state=5
  Device is present: 
  Has Power
timer event (20000 us): Debounce Timer, this = 1FFF4C40, timer = 1FFF4F58
ports in use bitmask = 80
getstatus, port = 7
USBHub control callback
01 01 00 00 
New Port Status
  status=101  port=7
  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 = 1FFF4C40, timer = 1FFF4F58
ports in use bitmask = 0
HUB Callback (member)
status = 80
getstatus, port = 7
USBHub control callback
03 05 10 00 
New Port Status
  status=100503  port=7
  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 = 1FFF4C40, timer = 1FFF4F74
port_doing_reset = 7
PORT_RECOVERY
new_Device: 480 Mbit/sec
new_Pipe
enumeration:
enumeration:
enumeration:
Device Descriptor:
  12 01 00 02 00 00 00 40 C0 16 89 04 79 02 01 02 03 01 
    VendorID = 16C0, ProductID = 0489, Version = 0279
    Class/Subclass/Protocol = 0 / 0 / 0
    Number of Configurations = 1
enumeration:
enumeration:
Manufacturer: LokkiLabs
enumeration:
Product: FOOT
enumeration:
Serial Number: EncoderFanel
enumeration:
Config data length = 149
enumeration:
Configuration Descriptor:
  09 02 95 00 03 01 00 C0 32 
    NumInterfaces = 3
    ConfigurationValue = 1
  08 0B 00 02 02 02 01 00 
    Interface Association = 0 through 1
    Class / Subclass / Protocol = 2 / 2 / 0
  09 04 00 00 01 02 02 01 00 
    Interface = 0
    Number of endpoints = 1
    Class/Subclass/Protocol = 2 / 2 / 1
  05 24 00 10 01 
  05 24 01 01 01 
  04 24 02 06 
  05 24 06 00 01 
  07 05 82 03 10 00 05 
    Endpoint = 2 IN
    Type = Interrupt
    Max Size = 16
    Polling Interval = 5
  09 04 01 00 02 0A 00 00 00 
    Interface = 1
    Number of endpoints = 2
    Class/Subclass/Protocol = 10 / 0 / 0
  07 05 03 02 00 02 00 
    Endpoint = 3 OUT
    Type = Bulk
    Max Size = 512
    Polling Interval = 0
  07 05 83 02 00 02 00 
    Endpoint = 3 IN
    Type = Bulk
    Max Size = 512
    Polling Interval = 0
  09 04 02 00 02 01 03 00 00 
    Interface = 2
    Number of endpoints = 2
    Class/Subclass/Protocol = 1 / 3 / 0
  07 24 01 00 01 25 00 
  06 24 02 01 01 00 
  06 24 02 02 02 00 
  09 24 03 01 03 01 02 01 00 
  09 24 03 02 04 01 01 01 00 
  09 05 04 02 00 02 00 00 00 
    Endpoint = 4 OUT
    Type = Bulk
    Max Size = 512
    Polling Interval = 0
  05 25 01 01 01 
  09 05 84 02 00 02 00 00 00 
    Endpoint = 4 IN
    Type = Bulk
    Max Size = 512
    Polling Interval = 0
  05 25 01 01 03 
enumeration:
USBHub memory usage = 960
USBHub claim_device this=1FFF5780
USBHub memory usage = 960
USBHub claim_device this=1FFF5B40
USBHub memory usage = 960
USBHub claim_device this=1FFF5F00
Descriptor 11 = IAD
Descriptor 4 = INTERFACE
MIDIDevice claim this=1FFF21A0
len = 132
MIDIDevice claim this=1FFF5080
len = 132
MIDIDevice claim this=1FFF28A0
len = 132
MIDIDevice claim this=1FFF2F80
len = 132
MIDIDevice claim this=1FFF3660
len = 132
MIDIDevice claim this=1FFF3D40
len = 132
MIDIDevice claim this=1FFF4420
len = 132
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 5 = ENDPOINT
Descriptor 4 = INTERFACE
MIDIDevice claim this=1FFF21A0
len = 97
MIDIDevice claim this=1FFF5080
len = 97
MIDIDevice claim this=1FFF28A0
len = 97
MIDIDevice claim this=1FFF2F80
len = 97
MIDIDevice claim this=1FFF3660
len = 97
MIDIDevice claim this=1FFF3D40
len = 97
MIDIDevice claim this=1FFF4420
len = 97
Descriptor 5 = ENDPOINT
Descriptor 5 = ENDPOINT
Descriptor 4 = INTERFACE
MIDIDevice claim this=1FFF21A0
len = 74
  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 = 512
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
type: 5, len: 9
    MIDI Endpoint: 84
      rx_size = 512
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
MIDIDevice claim this=1FFF5080
len = 74
  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 = 512
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
type: 5, len: 9
    MIDI Endpoint: 84
      rx_size = 512
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
MIDIDevice claim this=1FFF28A0
len = 74
  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 = 512
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
type: 5, len: 9
    MIDI Endpoint: 84
      rx_size = 512
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
MIDIDevice claim this=1FFF2F80
len = 74
  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 = 512
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
type: 5, len: 9
    MIDI Endpoint: 84
      rx_size = 512
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
MIDIDevice claim this=1FFF3660
len = 74
  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 = 512
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
type: 5, len: 9
    MIDI Endpoint: 84
      rx_size = 512
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
MIDIDevice claim this=1FFF3D40
len = 74
  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 = 512
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
type: 5, len: 9
    MIDI Endpoint: 84
      rx_size = 512
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
MIDIDevice claim this=1FFF4420
len = 74
  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 = 512
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
type: 5, len: 9
    MIDI Endpoint: 84
      rx_size = 512
type: 37, len: 5
    MIDI Endpoint Jack Association (ignored)
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 5 = ENDPOINT
Descriptor 37 =  ???
Descriptor 5 = ENDPOINT
Descriptor 37 =  ???

so how do i change my current initialisiation code for big buffer? will it increase latency? or just memory usage?

i have:

Code:
// Create the ports for USB devices plugged into Teensy's 2nd USB port (via hubs)
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);
MIDIDevice midi01(myusb);
MIDIDevice midi02(myusb);
MIDIDevice midi03(myusb);
MIDIDevice midi04(myusb);
MIDIDevice midi05(myusb);
MIDIDevice midi06(myusb);
MIDIDevice midi07(myusb);
MIDIDevice * midilist[07] = {
  &midi01, &midi02, &midi03, &midi04, &midi05, &midi06, &midi07
};
 
Sorry I don't know the inner workings of MIDI stuff. If it can use larger buffers and as such take longer to pack, than maybe could impact latency. But I again I don't know the interface to know if there are logical flushes of data and the like.

The only thing I can say is try it and see...
 
and it works... amazing and thanks for chiming in @KurtE

if somebody can shed some light on latency issues that would be very welcome. i guess the bigger buffer should not introduce more latency since usb is polled every ms anyway, right? memory wise the jump is quite huge, since i had to create 7 MidiDevice_BigBuffer instances (since i don't know to which the pedal will be assigned to) but it's ok for now
 
You are welcome,

Note when I did the USBSerial_BigBuffer (still waiting on PR), I added an extra parameter to the constructor, to limit it to minimum size USB RX/TX the instance should claim... That way if I had a case like this with 7 Serial devices with only one needing the Big buffer, the other Small buffer devices won't be claimed by it and as such reserved....

But I don't see anything like this here. It would not be hard to probably create a sub-class pretty simple that could allow you to do this and/or constrain it to some specific device or PID/VID pair...

Again not suggesting it... But for example something like:

Code:
class MIDIDevice_BigBuffer_PIDVID : public MIDIDevice_BigBuffer{
public:
	MIDIDevice_BigBuffer_PIDVID (USBHost &host, (uint16_t idVendor, uint16_t idProduct) :
		_idVendor_match(idVendor), _idProduct_match(idProduct),
		MIDIDevice_BigBuffer(host) {};
	// MIDIDevice(USBHost *host) : ....
protected:
	virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len) {
		if (device->idVendor != _idVendor_match) return false;
		if (device->idVendor != dev->idProduct) return false;
		return MIDIDevice_BigBuffer::cliam(device, type, descriptors, len);
	}

private:
		uint16_t _idVendor_match;
	uint16_t _idProduct_match;
};
Sort of gross, and after fixing up my probable error, one can create versions that are more specific on who they bind with...
 
looking at this from another angle, is there any possibility at all to force the teensy 4 to use the small usb midi buffer even if a usb 2 port is available?
 
I found this thread after posting this one
@lokki, it looks like you've built a USB MIDI hub for MIDI devices using a Teensy 4.0 and a USB Hub... Is that correct?
 
actually i used a teensy 3.6 as host, and had a teensy 4.0 connected to one of the hubs ports. but a teensy 4 as host should also work. the library is really quite easy to use, my 2 small problems were quickly resolved here on the forum :)
 
Back
Top