Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 11 of 11

Thread: Teensy 4.1 and sysex MIDI messages in host mode

  1. #1
    Junior Member
    Join Date
    Jul 2020
    Posts
    15

    Teensy 4.1 and sysex MIDI messages in host mode

    Hi All,
    Here's some context first. I'm trying to connect my guitar amp to a teensy 4.1 via usb in order to control the amp via some custom code running on the teensy. The end goal is to be able to turn effects on and off via some foot switches. The messages I need to send to the amp are sysex midi over usb, and I already found plenty of resources on that topic. But most (all) people doing such thing seems to be using an SPI to USB adapter instead of a built-in usb like I want to do with my teensy 4.1.

    I think I need to select "Serial + MIDI" in the Tool, USB type menu in the Arduino IDE. Am I correct in assuming that this means the programming USB will stay as my Serial link for debug and the other USB (the one I soldered to the usb host cable) will be my host for the amp and I will be able to talk to it via MIDI commands ?

    I think my best bet will be to use usbMIDI.sendSysEx() right ?

    Is there something I need to run to initialise the usb, or the midi ? Before I send any command, how can I check that something is connected to the usb host ? And how can I query it to know what it is ?


    Thanks

  2. #2
    Junior Member
    Join Date
    Jul 2020
    Posts
    15
    I have been doing some more reading on the forum and other places, and I think I made some progress but I also have new questions now. But let me start by answering one of my own question.
    Quote Originally Posted by Xantra View Post
    I think I need to select "Serial + MIDI" in the Tool, USB type menu in the Arduino IDE. Am I correct in assuming that this means the programming USB will stay as my Serial link for debug and the other USB (the one I soldered to the usb host cable) will be my host for the amp and I will be able to talk to it via MIDI commands ?
    This only affects the main USB, not the USB Host (2nd interface).

    I have now coded the following basic thing, and enabled USBHost debug.
    Code:
    #include "USBHost_t36.h"
    
    USBHost myusb;
    USBHub hub1(myusb);
    USBHub hub2(myusb);
    MIDIDevice midi1(myusb);
    
    void setup() {
      Serial.begin(115200);
      delay(1500);
      myusb.begin();
      Serial.println("Ready");
    }
    
    void loop() {
      myusb.Task();
      midi1.read();
    }
    When I plug the amp to the teensy I get the following from the Serial port :
    Code:
    USB2 PLL running
     reset waited 6
    USBHS_ASYNCLISTADDR = 0
    USBHS_PERIODICLISTBASE = 20003000
    periodictable = 20003000
    Ready
    port change: 14001403
        connect
      begin reset
    port change: 14001005
      port enabled
      end recovery
    new_Device: 1.5 Mbit/sec
    new_Pipe
    ERROR Followup
        remove from followup list
        stray halted 200034C0
      qtd: 20003480, token=80080180, next=200034C0
      qtd: 200034C0, token=80008080, next=20003500
      dummy halt: 20003500
    enumeration:
        remain on followup list
        remain on followup list
        remain on followup list
    So something seem to be going wrong during enumeration. I have just soldered a bunch of wires to the teensy without shielding for the usb, is this the problem ? Or is the USBHost lib not able to recognise the device I'm plugging in ?

  3. #3
    Junior Member
    Join Date
    Jul 2020
    Posts
    15
    Quote Originally Posted by Xantra View Post
    I have just soldered a bunch of wires to the teensy without shielding for the usb, is this the problem ?
    I have now used a shielded cable and grounded it on both sides, and I'm still getting the same error, so it seems to be an enumeration issue.

    I tried to plug a usb key onto it instead because that's the only other usb device I have on hand, but nothing happens.
    Any idea what could be the issue here or what I could try ?

  4. #4
    Junior Member
    Join Date
    Jul 2020
    Posts
    15
    Here are some details from Linux of what happens when I plug the amp

    Code:
    [  167.356085] usb 1-1.3: new high-speed USB device number 4 using dwc_otg
    [  167.488353] usb 1-1.3: New USB device found, idVendor=0582, idProduct=01d8, bcdDevice= 0.00
    [  167.488439] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
    [  167.488465] usb 1-1.3: Product: KATANA
    [  167.488487] usb 1-1.3: Manufacturer: BOSS
    [  168.015425] usbcore: registered new interface driver snd-usb-audio
    Code:
    pi@raspberrypi:~ $ sudo amidi -l
    Dir Device    Name
    IO  hw:2,0,0  KATANA MIDI 1
    IO  hw:2,0,1  KATANA MIDI 2
    IO  hw:2,0,2  KATANA MIDI 3
    Code:
    pi@raspberrypi:~ $ lsusb -v -d 0582:01d8
    Bus 001 Device 005: ID 0582:01d8 Roland Corp.
    Couldn't open device, some information will be missing
    Device Descriptor:
      bLength                18
      bDescriptorType         1
      bcdUSB               2.00
      bDeviceClass          255 Vendor Specific Class
      bDeviceSubClass         0
      bDeviceProtocol       255
      bMaxPacketSize0        64
      idVendor           0x0582 Roland Corp.
      idProduct          0x01d8
      bcdDevice            0.00
      iManufacturer           1
      iProduct                2
      iSerial                 0
      bNumConfigurations      1
      Configuration Descriptor:
        bLength                 9
        bDescriptorType         2
        wTotalLength       0x00bc
        bNumInterfaces          4
        bConfigurationValue     1
        iConfiguration          0
        bmAttributes         0xc0
          Self Powered
        MaxPower                0mA
        Interface Descriptor:
          bLength                 9
          bDescriptorType         4
          bInterfaceNumber        0
          bAlternateSetting       0
          bNumEndpoints           0
          bInterfaceClass       255 Vendor Specific Class
          bInterfaceSubClass    255 Vendor Specific Subclass
          bInterfaceProtocol      0
          iInterface              0
        Interface Descriptor:
          bLength                 9
          bDescriptorType         4
          bInterfaceNumber        1
          bAlternateSetting       0
          bNumEndpoints           0
          bInterfaceClass       255 Vendor Specific Class
          bInterfaceSubClass      2
          bInterfaceProtocol      2
          iInterface              0
          ** UNRECOGNIZED:  06 24 f1 01 00 00
        Interface Descriptor:
          bLength                 9
          bDescriptorType         4
          bInterfaceNumber        1
          bAlternateSetting       1
          bNumEndpoints           1
          bInterfaceClass       255 Vendor Specific Class
          bInterfaceSubClass      2
          bInterfaceProtocol      2
          iInterface              0
          ** UNRECOGNIZED:  07 24 01 01 00 01 00
          ** UNRECOGNIZED:  0b 24 02 01 04 04 18 01 44 ac 00
          ** UNRECOGNIZED:  06 24 f1 04 16 00
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x0d  EP 13 OUT
            bmAttributes            5
              Transfer Type            Isochronous
              Synch Type               Asynchronous
              Usage Type               Data
            wMaxPacketSize     0x0070  1x 112 bytes
            bInterval               1
        Interface Descriptor:
          bLength                 9
          bDescriptorType         4
          bInterfaceNumber        2
          bAlternateSetting       0
          bNumEndpoints           0
          bInterfaceClass       255 Vendor Specific Class
          bInterfaceSubClass      2
          bInterfaceProtocol      1
          iInterface              0
        Interface Descriptor:
          bLength                 9
          bDescriptorType         4
          bInterfaceNumber        2
          bAlternateSetting       1
          bNumEndpoints           1
          bInterfaceClass       255 Vendor Specific Class
          bInterfaceSubClass      2
          bInterfaceProtocol      1
          iInterface              0
          ** UNRECOGNIZED:  07 24 01 07 00 01 00
          ** UNRECOGNIZED:  0b 24 02 01 04 04 18 01 44 ac 00
          ** UNRECOGNIZED:  06 24 f1 04 16 00
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x8e  EP 14 IN
            bmAttributes           37
              Transfer Type            Isochronous
              Synch Type               Asynchronous
              Usage Type               Implicit feedback Data
            wMaxPacketSize     0x0070  1x 112 bytes
            bInterval               1
        Interface Descriptor:
          bLength                 9
          bDescriptorType         4
          bInterfaceNumber        3
          bAlternateSetting       0
          bNumEndpoints           2
          bInterfaceClass       255 Vendor Specific Class
          bInterfaceSubClass      3
          bInterfaceProtocol      0
          iInterface              0
          ** UNRECOGNIZED:  06 24 f1 02 03 03
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x03  EP 3 OUT
            bmAttributes            2
              Transfer Type            Bulk
              Synch Type               None
              Usage Type               Data
            wMaxPacketSize     0x0200  1x 512 bytes
            bInterval               1
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x84  EP 4 IN
            bmAttributes            2
              Transfer Type            Bulk
              Synch Type               None
              Usage Type               Data
            wMaxPacketSize     0x0200  1x 512 bytes
            bInterval               0
        Interface Descriptor:
          bLength                 9
          bDescriptorType         4
          bInterfaceNumber        3
          bAlternateSetting       1
          bNumEndpoints           2
          bInterfaceClass       255 Vendor Specific Class
          bInterfaceSubClass      3
          bInterfaceProtocol      0
          iInterface              0
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x03  EP 3 OUT
            bmAttributes            3
              Transfer Type            Interrupt
              Synch Type               None
              Usage Type               Data
            wMaxPacketSize     0x0200  1x 512 bytes
            bInterval               4
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x85  EP 5 IN
            bmAttributes            3
              Transfer Type            Interrupt
              Synch Type               None
              Usage Type               Data
            wMaxPacketSize     0x0200  1x 512 bytes
            bInterval               4

  5. #5
    Senior Member vjmuzik's Avatar
    Join Date
    Apr 2017
    Posts
    691
    Best I can tell is that the USB Midi is not class compliant since this device does need a driver as per the Boss website and the the lsusb results only show Vender Specific Classes. If you wanted to go the hard route you’d have to reverse engineer a driver for the Teensy for this or you could just use the DIN Midi on the Katana.

  6. #6
    Junior Member
    Join Date
    Jul 2020
    Posts
    15
    It seems to be registered as a MIDI device out of the box in Linux though, so their must be some sort of a driver built into Linux that does that right ? Would this be part of the Linux Kernel or would ALSA bridge the gap in this case ? As both projects are opensource, I should be able to find the source of the driver right ? Any idea where I could start on this quest ?

    Also, it seems that some people have been able to work around that problem by using a USB host shield based on the MAX3421E and the following lib : https://github.com/felis/USB_Host_Shield_2.0
    I doubt that the MAX3421E has special support for the Katana, so would that mean that this library contain special code for the Katana ?

    Unfortunately I have the model that only has a USB port, and doesn't have the DIN MIDI plug. I wouldn't mind to go the hard way, as I don't know anything about USB that would be a good learning exercise. But unfortunately as I don't know anything about USB I'm not too sure where to start from .

    By the way, I also found the following post that seems to be in the exact same condition as me (none class compliant midi device), but in his case the enumeration does work successfully, so I think there's something else wrong causing the followup error I'm seeing preventing the enumeration to complete correctly :
    https://forum.pjrc.com/threads/55142...Ex-on-USB-host
    Last edited by Xantra; 09-17-2020 at 12:09 PM.

  7. #7
    Junior Member
    Join Date
    Jul 2020
    Posts
    15
    So I have now sorted my enumeration issue, and I'm a bit confused because it seems that the library picked-up the device as a midi device and seems to have associated it correctly.

    Code:
    USB2 PLL running
     reset waited 6
    USBHS_ASYNCLISTADDR = 0
    USBHS_PERIODICLISTBASE = 20003000
    periodictable = 20003000
    Ready
    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 FF 00 FF 40 82 05 D8 01 00 00 01 02 00 01 
        VendorID = 0582, ProductID = 01D8, Version = 0000
        Class/Subclass/Protocol = 255 / 0 / 255
        Number of Configurations = 1
    enumeration:
    enumeration:
    Manufacturer: BOSS
    enumeration:
    Product: KATANA
    enumeration:
    Config data length = 188
    enumeration:
    Configuration Descriptor:
      09 02 BC 00 04 01 00 C0 00 
        NumInterfaces = 4
        ConfigurationValue = 1
      09 04 00 00 00 FF FF 00 00 
        Interface = 0
        Number of endpoints = 0
        Class/Subclass/Protocol = 255 / 255 / 0
      09 04 01 00 00 FF 02 02 00 
        Interface = 1
        Number of endpoints = 0
        Class/Subclass/Protocol = 255 / 2 / 2
      06 24 F1 01 00 00 
      09 04 01 01 01 FF 02 02 00 
        Interface = 1
        Number of endpoints = 1
        Class/Subclass/Protocol = 255 / 2 / 2
      07 24 01 01 00 01 00 
      0B 24 02 01 04 04 18 01 44 AC 00 
      06 24 F1 04 16 00 
      07 05 0D 05 70 00 01 
        Endpoint = 13 OUT
        Type = Isochronous
        Max Size = 112
        Polling Interval = 1
      07 25 01 00 00 00 00 
      09 04 02 00 00 FF 02 01 00 
        Interface = 2
        Number of endpoints = 0
        Class/Subclass/Protocol = 255 / 2 / 1
      09 04 02 01 01 FF 02 01 00 
        Interface = 2
        Number of endpoints = 1
        Class/Subclass/Protocol = 255 / 2 / 1
      07 24 01 07 00 01 00 
      0B 24 02 01 04 04 18 01 44 AC 00 
      06 24 F1 04 16 00 
      07 05 8E 25 70 00 01 
        Endpoint = 14 IN
        Type = Isochronous
        Max Size = 112
        Polling Interval = 1
      07 25 01 00 00 00 00 
      09 04 03 00 02 FF 03 00 00 
        Interface = 3
        Number of endpoints = 2
        Class/Subclass/Protocol = 255 / 3 / 0
      06 24 F1 02 03 03 
      07 05 03 02 00 02 01 
        Endpoint = 3 OUT
        Type = Bulk
        Max Size = 512
        Polling Interval = 1
      07 05 84 02 00 02 00 
        Endpoint = 4 IN
        Type = Bulk
        Max Size = 512
        Polling Interval = 0
      09 04 03 01 02 FF 03 00 00 
        Interface = 3
        Number of endpoints = 2
        Class/Subclass/Protocol = 255 / 3 / 0
      07 05 03 03 00 02 04 
        Endpoint = 3 OUT
        Type = Interrupt
        Max Size = 512
        Polling Interval = 4
      07 05 85 03 00 02 04 
        Endpoint = 5 IN
        Type = Interrupt
        Max Size = 512
        Polling Interval = 4
    enumeration:
    USBHub memory usage = 960
    USBHub claim_device this=200023A0
    USBHub memory usage = 960
    USBHub claim_device this=20002760
    Descriptor 4 = INTERFACE
    MIDIDevice claim this=20001CC0
    len = 179
      Interface is unknown (might be Yahama)
    type: 4, len: 9
    This interface is not MIDI
    Descriptor 4 = INTERFACE
    MIDIDevice claim this=20001CC0
    len = 170
      Interface is unknown (might be Yahama)
    type: 36, len: 6
        Unknown MIDI CS_INTERFACE descriptor!
    Descriptor 36 =  ???
    Descriptor 4 = INTERFACE
    MIDIDevice claim this=20001CC0
    len = 155
      Interface is unknown (might be Yahama)
    type: 36, len: 7
        MIDI Header (ignored)
    type: 36, len: 11
        MIDI IN Jack (ignored)
    type: 36, len: 6
        Unknown MIDI CS_INTERFACE descriptor!
    Descriptor 36 =  ???
    Descriptor 36 =  ???
    Descriptor 36 =  ???
    Descriptor 5 = ENDPOINT
    Descriptor 37 =  ???
    Descriptor 4 = INTERFACE
    MIDIDevice claim this=20001CC0
    len = 108
      Interface is unknown (might be Yahama)
    type: 4, len: 9
    This interface is not MIDI
    Descriptor 4 = INTERFACE
    MIDIDevice claim this=20001CC0
    len = 99
      Interface is unknown (might be Yahama)
    type: 36, len: 7
        MIDI Header (ignored)
    type: 36, len: 11
        MIDI IN Jack (ignored)
    type: 36, len: 6
        Unknown MIDI CS_INTERFACE descriptor!
    Descriptor 36 =  ???
    Descriptor 36 =  ???
    Descriptor 36 =  ???
    Descriptor 5 = ENDPOINT
    Descriptor 37 =  ???
    Descriptor 4 = INTERFACE
    MIDIDevice claim this=20001CC0
    len = 52
      Interface is unknown (might be Yahama)
    type: 36, len: 6
        Roland vendor-specific (ignored)
    type: 5, len: 7
        MIDI Endpoint: 3
          tx_size = 512
    type: 5, len: 7
        MIDI Endpoint: 84
          rx_size = 512
    type: 4, len: 9
    Descriptor 36 =  ???
    Descriptor 5 = ENDPOINT
    Descriptor 5 = ENDPOINT
    Descriptor 4 = INTERFACE
    MIDIDevice claim this=20001CC0
    len = 23
      Interface is unknown (might be Yahama)
    type: 5, len: 7
        MIDI Endpoint: 3
          tx_size = 512
    type: 5, len: 7
        MIDI Endpoint: 85
          rx_size = 512
    This interface is not MIDI
    Descriptor 5 = ENDPOINT
    Descriptor 5 = ENDPOINT
    I think the following means that the device was registered as a midi device right ?
    Code:
    ...
    Descriptor 4 = INTERFACE
    MIDIDevice claim this=20001CC0
    len = 52
      Interface is unknown (might be Yahama)
    type: 36, len: 6
        Roland vendor-specific (ignored)
    type: 5, len: 7
        MIDI Endpoint: 3
          tx_size = 512
    type: 5, len: 7
        MIDI Endpoint: 84
          rx_size = 512
    type: 4, len: 9
    Descriptor 36 =  ???
    ...

  8. #8
    Senior Member vjmuzik's Avatar
    Join Date
    Apr 2017
    Posts
    691
    Itís close but I can see the issue with these lines here:
    Code:
     Descriptor 4 = INTERFACE
    MIDIDevice claim this=20001CC0
    len = 99
      Interface is unknown (might be Yahama)
    type: 36, len: 7
        MIDI Header (ignored)
    type: 36, len: 11
        MIDI IN Jack (ignored)
    type: 36, len: 6
        Unknown MIDI CS_INTERFACE descriptor!
    Where it says unknown descriptor thatís where it fails.


    From your lsusb information it corresponds to this interface and the unknown part is the 3rd unrecognized line.
    Code:
     Interface Descriptor:
          bLength                 9
          bDescriptorType         4
          bInterfaceNumber        2
          bAlternateSetting       1
          bNumEndpoints           1
          bInterfaceClass       255 Vendor Specific Class
          bInterfaceSubClass      2
          bInterfaceProtocol      1
          iInterface              0
          ** UNRECOGNIZED:  07 24 01 07 00 01 00
          ** UNRECOGNIZED:  0b 24 02 01 04 04 18 01 44 ac 00
          ** UNRECOGNIZED:  06 24 f1 04 16 00
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x8e  EP 14 IN
            bmAttributes           37
              Transfer Type            Isochronous
              Synch Type               Asynchronous
              Usage Type               Implicit feedback Data
            wMaxPacketSize     0x0070  1x 112 bytes
            bInterval               1
    From looking through the host code here you can see where it comes close to matching.
    Code:
     else if (subtype == 0xF1 && p[3] == 2) {
    				// see Linux sound/usb/quirks.c create_roland_midi_quirk()
    				println("    Roland vendor-specific (ignored)");
    				ismidi = true;
    			}
    You can add another copy of this else if statement to match your Katana and it should pass.
    Code:
     else if (subtype == 0xF1 && p[3] == 4) {
    				// see Linux sound/usb/quirks.c create_roland_midi_quirk()
    				println("    Roland/Boss vendor-specific (ignored)");
    				ismidi = true;
    			}

  9. #9
    Junior Member
    Join Date
    Jul 2020
    Posts
    15
    Right, so as expected I'm now discovering 3 MIDI devices, which matches what Linux reports.

    Code:
    MIDIDevice claim this=20001CC0
    len = 155
      Interface is unknown (might be Yahama)
    type: 36, len: 7
        MIDI Header (ignored)
    type: 36, len: 11
        MIDI IN Jack (ignored)
    type: 36, len: 6
        Roland vendor-specific (ignored)
    type: 5, len: 7
    
    MIDIDevice claim this=20001CC0
    len = 99
      Interface is unknown (might be Yahama)
    type: 36, len: 7
        MIDI Header (ignored)
    type: 36, len: 11
        MIDI IN Jack (ignored)
    type: 36, len: 6
        Roland vendor-specific (ignored)
    type: 5, len: 7
    
    MIDIDevice claim this=20001CC0
    len = 52
      Interface is unknown (might be Yahama)
    type: 36, len: 6
        Roland vendor-specific (ignored)
    type: 5, len: 7
        MIDI Endpoint: 3
          tx_size = 512
    type: 5, len: 7
        MIDI Endpoint: 84
          rx_size = 512
    type: 4, len: 9
    How would the MIDIDevice driver deals with the 3 devices now ? Do I need to declare 3 MIDIDevice in my code ? Because when I do that I then see everything reported 3 times, like if all 3 MIDI devices where getting associated with all the 3 MIDIDevice.
    I'm not sure how I can address each individual MIDI device.
    Also, is there a way to check what is associated to the MIDIDevice ? Something like midi1.is_connected() or midi1.get_descriptor() ?

  10. #10
    Junior Member
    Join Date
    Jul 2020
    Posts
    15
    Right, quick update guys, I got it to work in the end without making any update to the library. Here's what I coded to change the Reverb mode every second for example :

    Code:
    #include "USBHost_t36.h"
    
    const byte editor[15] = {0xF0, 0x41, 0x00, 0x00, 0x00, 0x00, 0x33, 0x12, 0x7F, 0x00, 0x00, 0x01, 0x01, 0x7F, 0xF7};
    const byte reverb[15] = {0xF0, 0x41, 0x00, 0x00, 0x00, 0x00, 0x33, 0x12, 0x7F, 0x01, 0x01, 0x05, 0x00, 0x7A, 0xF7};
    
    USBHost myusb;
    USBHub hub1(myusb);
    USBHub hub2(myusb);
    MIDIDevice_BigBuffer midi1(myusb);
    
    
    void setup() {
      Serial.begin(115200);
      delay(1500);
      myusb.begin();
      Serial.println("Ready");
    }
    
    void loop() {
      myusb.Task();
    
      midi1.sendSysEx(15, editor, true);
      midi1.send_now();
      delay(100);
      midi1.sendSysEx(15, reverb, true);
      midi1.send_now();
      delay(100);
    
      delay(1000);
    
    }
    I think the trick was to execute the send_now after each command and wait for a bit.

  11. #11
    Senior Member vjmuzik's Avatar
    Join Date
    Apr 2017
    Posts
    691
    You can do an if statement to tell if something is connected like this:
    Code:
    if(midi1){
    //Do something here
    }
    The other things you can do are these to help identify devices, but I don't believe there is anything to get the individual midi port names if a device has more than one:
    Code:
    midi1.idVendor(); //2 byte vendor id
    midi1.idProduct(); //2 byte product id
    midi1.manufacturer(); //Null-terminated manufacturer string
    midi1.product(); //Null-terminated product string
    midi1.serialNumber(); //Null-terminated serial number string

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •