tinyusb icon indicating copy to clipboard operation
tinyusb copied to clipboard

Multi MIDI Device with RP2040

Open DatanoiseTV opened this issue 3 years ago • 3 comments

Operating System

Linux

Board

Raspberry Pico

Firmware

examples/device/midi_test with modifications

What happened ?

When trying to add multiple MIDI ports, the device will enumerate, but aconnect won't show MIDI ports anymore.

How to reproduce ?

  1. Clone the midi-test example
  2. Change #define CFG_TUD_MIDI 4 in tusb_config.h
  3. In usb_descriptors.c add..
To enum:
  ITF_NUM_MIDI_0 = 0,
  ITF_NUM_MIDI_STREAMING_0,
  ITF_NUM_MIDI_1,
  ITF_NUM_MIDI_STREAMING_1,
  ITF_NUM_MIDI_2,
  ITF_NUM_MIDI_STREAMING_2,
  ITF_NUM_MIDI_3,
  ITF_NUM_MIDI_STREAMING_3,

#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + (TUD_MIDI_DESC_LEN * CFG_TUD_MIDI))

#define USBD_MIDI_0_EP_OUT 0x01
#define USBD_MIDI_1_EP_OUT 0x03
#define USBD_MIDI_2_EP_OUT 0x05
#define USBD_MIDI_3_EP_OUT 0x07

#define USBD_MIDI_0_EP_IN 0x81
#define USBD_MIDI_1_EP_IN 0x83
#define USBD_MIDI_2_EP_IN 0x85
#define USBD_MIDI_3_EP_IN 0x87

uint8_t const desc_fs_configuration[] =
    {
        // Config number, interface count, string index, total length, attribute, power in mA
        TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),

        // Interface number, string index, EP Out & EP In address, EP size
        TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI_0, 0, USBD_MIDI_0_EP_OUT, USBD_MIDI_0_EP_IN, 64),
        TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI_1, 1, USBD_MIDI_1_EP_OUT, USBD_MIDI_1_EP_IN, 64),
        TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI_2, 2, USBD_MIDI_2_EP_OUT, USBD_MIDI_2_EP_IN, 64),
        TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI_3, 3, USBD_MIDI_3_EP_OUT, USBD_MIDI_3_EP_IN, 64),

    };

Debug Log

No response

Screenshots

No response

DatanoiseTV avatar Jan 21 '22 12:01 DatanoiseTV

  1. I have never tried multiple MIDI, however string index for interface cannot be 1,2,3 since those are already used for manufacturer, product string. If you dont have any use for those, try to change it to all 0
  2. Please provide your example code which is compilable for reproducing
  3. Also provide usb log with LOG=2 and/or 3

hathach avatar Feb 01 '22 18:02 hathach

  1. I have never tried multiple MIDI, however string index for interface cannot be 1,2,3 since those are already used for manufacturer, product string. If you dont have any use for those, try to change it to all 0

    1. Please provide your example code which is compilable for reproducing

    2. Also provide usb log with LOG=2 and/or 3

I have tried with string index 0 without success.

Here are the files attached: https://gist.github.com/DatanoiseTV/2499fee93d23234048e8d7b6cea88a38

USBD init
MIDI init
BUS RESET
USBD Bus Reset : Full Speed

USBD Setup Received 80 06 00 01 00 00 40 00
  Get Descriptor Device
  Queue EP 80 with 18 bytes ...
  Prepare BufCtrl: [0] = 0x62482  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24594  [1] = 0x0000
  Short packet on buffer 0 with 18 bytes
Completed transfer of 18 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 18 bytes
  Queue EP 00 with 0 bytes ...
  Prepare BufCtrl: [0] = 0x29696  [1] = 0x0000
buf_status = 0x00000002
  Sync BufCtrl: [0] = 0x57344  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 out
BUS RESET
USBD Xfer Complete on EP 00 with 0 bytes
USBD Bus Reset : Full Speed

USBD Setup Received 00 05 09 00 00 00 00 00
  Set Address
  Prepare BufCtrl: [0] = 0x62464  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24576  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 in
USBD Xfer CompletBUS RESET
e on EP 80 with 0 bytes
USBD Bus Reset : Full Speed
BUS RESET
USBD Bus Reset : Full Speed

USBD Setup Received 80 06 00 01 00 00 40 00
  Get Descriptor Device
  Queue EP 80 with 18 bytes ...
  Prepare BufCtrl: [0] = 0x62482  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24594  [1] = 0x0000
  Short packet on buffer 0 with 18 bytes
Completed transfer of 18 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 18 bytes
  Queue EP 00 with 0 bytes ...
  Prepare BufCtrl: [0] = 0x29696  [1] = 0x0000
buf_status = 0x00000002
  Sync BufCtrl: [0] = 0x57344  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 out
BUS RESET
USBD Xfer Complete on EP 00 with 0 bytes
USBD Bus Reset : Full Speed

USBD Setup Received 00 05 09 00 00 00 00 00
  Set Address
  Prepare BufCtrl: [0] = 0x62464  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24576  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 0 bytes
USBD Suspend : Remote Wakeup = 0
BUS RESET
USBD Bus Reset : Full Speed
BUS RESET
USBD Bus Reset : Full Speed

USBD Setup Received 00 05 09 00 00 00 00 00
  Set Address
  Prepare BufCtrl: [0] = 0x62464  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24576  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 0 bytes

USBD Setup Received 80 06 00 01 00 00 08 00
  Get Descriptor Device
  Queue EP 80 with 8 bytes ...
  Prepare BufCtrl: [0] = 0x62472  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24584  [1] = 0x0000
  Short packet on buffer 0 with 8 bytes
Completed transfer of 8 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 8 bytes
  Queue EP 00 with 0 bytes ...
  Prepare BufCtrl: [0] = 0x29696  [1] = 0x0000
buf_status = 0x00000002
  Sync BufCtrl: [0] = 0x57344  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 out
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 00 01 00 00 12 00
  Get Descriptor Device
  Queue EP 80 with 18 bytes ...
  Prepare BufCtrl: [0] = 0x62482  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24594  [1] = 0x0000
  Short packet on buffer 0 with 18 bytes
Completed transfer of 18 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 18 bytes
  Queue EP 00 with 0 bytes ...
  Prepare BufCtrl: [0] = 0x29696  [1] = 0x0000
buf_status = 0x00000002
  Sync BufCtrl: [0] = 0x57344  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 out
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 00 06 00 00 0A 00
  Get Descriptor Device Qualifier
  Stall EP0

USBD Setup Received 80 06 00 06 00 00 0A 00
  Get Descriptor Device Qualifier
  Stall EP0

USBD Setup Received 80 06 00 06 00 00 0A 00
  Get Descriptor Device Qualifier
  Stall EP0

USBD Setup Received 80 06 00 02 00 00 09 00
  Get Descriptor Configuration[0]
  Queue EP 80 with 9 bytes ...
  Prepare BufCtrl: [0] = 0x62473  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24585  [1] = 0x0000
  Short packet on buffer 0 with 9 bytes
Completed transfer of 9 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 9 bytes
  Queue EP 00 with 0 bytes ...
  Prepare BufCtrl: [0] = 0x29696  [1] = 0x0000
buf_status = 0x00000002
  Sync BufCtrl: [0] = 0x57344  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 out
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 00 02 00 00 79 01
  Get Descriptor Configuration[0]
  Queue EP 80 with 64 bytes ...
  Prepare BufCtrl: [0] = 0x62528  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24640  [1] = 0x0000
Completed transfer of 64 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 64 bytes
  Queue EP 80 with 64 bytes ...
  Prepare BufCtrl: [0] = 0x54336  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x16448  [1] = 0x0000
Completed transfer of 64 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 64 bytes
  Queue EP 80 with 64 bytes ...
  Prepare BufCtrl: [0] = 0x62528  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24640  [1] = 0x0000
Completed transfer of 64 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 64 bytes
  Queue EP 80 with 64 bytes ...
  Prepare BufCtrl: [0] = 0x54336  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x16448  [1] = 0x0000
Completed transfer of 64 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 64 bytes
  Queue EP 80 with 64 bytes ...
  Prepare BufCtrl: [0] = 0x62528  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24640  [1] = 0x0000
Completed transfer of 64 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 64 bytes
  Queue EP 80 with 57 bytes ...
  Prepare BufCtrl: [0] = 0x54329  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x16441  [1] = 0x0000
  Short packet on buffer 0 with 57 bytes
Completed transfer of 57 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 57 bytes
  Queue EP 00 with 0 bytes ...
  Prepare BufCtrl: [0] = 0x29696  [1] = 0x0000
buf_status = 0x00000002
  Sync BufCtrl: [0] = 0x57344  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 out
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 00 03 00 00 FF 00
  Get Descriptor String[0]
  Queue EP 80 with 4 bytes ...
  Prepare BufCtrl: [0] = 0x62468  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24580  [1] = 0x0000
  Short packet on buffer 0 with 4 bytes
Completed transfer of 4 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 4 bytes
  Queue EP 00 with 0 bytes ...
  Prepare BufCtrl: [0] = 0x29696  [1] = 0x0000
buf_status = 0x00000002
  Sync BufCtrl: [0] = 0x57344  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 out
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 02 03 09 04 FF 00
  Get Descriptor String[2]
  Queue EP 80 with 28 bytes ...
  Prepare BufCtrl: [0] = 0x62492  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24604  [1] = 0x0000
  Short packet on buffer 0 with 28 bytes
Completed transfer of 28 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 28 bytes
  Queue EP 00 with 0 bytes ...
  Prepare BufCtrl: [0] = 0x29696  [1] = 0x0000
buf_status = 0x00000002
  Sync BufCtrl: [0] = 0x57344  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 out
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 01 03 09 04 FF 00
  Get Descriptor String[1]
  Queue EP 80 with 16 bytes ...
  Prepare BufCtrl: [0] = 0x62480  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24592  [1] = 0x0000
  Short packet on buffer 0 with 16 bytes
Completed transfer of 16 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 16 bytes
  Queue EP 00 with 0 bytes ...
  Prepare BufCtrl: [0] = 0x29696  [1] = 0x0000
buf_status = 0x00000002
  Sync BufCtrl: [0] = 0x57344  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 out
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 03 03 09 04 FF 00
  Get Descriptor String[3]
  Queue EP 80 with 16 bytes ...
  Prepare BufCtrl: [0] = 0x62480  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24592  [1] = 0x0000
  Short packet on buffer 0 with 16 bytes
Completed transfer of 16 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 16 bytes
  Queue EP 00 with 0 bytes ...
  Prepare BufCtrl: [0] = 0x29696  [1] = 0x0000
buf_status = 0x00000002
  Sync BufCtrl: [0] = 0x57344  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 out
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 00 09 01 00 00 00 00 00
  Set Configuration
  Open EP 01 with Size = 64
  Alloced 128 bytes at offset 0x180 (0x50100180)
  Open EP 81 with Size = 64
  Alloced 128 bytes at offset 0x200 (0x50100200)
  Queue EP 01 with 64 bytes ...
  Prepare BufCtrl: [0] = 0x21568  [1] = 0x0000
  MIDI opened
  Bind EP 01 to driver id 0
  Bind EP 81 to driver id 0
  Open EP 03 with Size = 64
  Alloced 128 bytes at offset 0x280 (0x50100280)
  Open EP 83 with Size = 64
  Alloced 128 bytes at offset 0x300 (0x50100300)
  Queue EP 03 with 64 bytes ...
  Prepare BufCtrl: [0] = 0x21568  [1] = 0x0000
  MIDI opened
  Bind EP 03 to driver id 0
  Bind EP 83 to driver id 0
  Open EP 05 with Size = 64
  Alloced 128 bytes at offset 0x380 (0x50100380)
  Open EP 85 with Size = 64
  Alloced 128 bytes at offset 0x400 (0x50100400)
  Queue EP 05 with 64 bytes ...
  Prepare BufCtrl: [0] = 0x21568  [1] = 0x0000
  MIDI opened
  Bind EP 05 to driver id 0
  Bind EP 85 to driver id 0
  Open EP 07 with Size = 64
  Alloced 128 bytes at offset 0x480 (0x50100480)
  Open EP 87 with Size = 64
  Alloced 128 bytes at offset 0x500 (0x50100500)
  Queue EP 07 with 64 bytes ...
  Prepare BufCtrl: [0] = 0x21568  [1] = 0x0000
  MIDI opened
  Bind EP 07 to driver id 0
  Bind EP 87 to driver id 0
  Queue EP 80 with 0 bytes ...
  Prepare BufCtrl: [0] = 0x62464  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24576  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 0 bytes

USBD Setup Received 80 06 02 03 09 04 FF 00
  Get Descriptor String[2]
  Queue EP 80 with 28 bytes ...
  Prepare BufCtrl: [0] = 0x62492  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24604  [1] = 0x0000
  Short packet on buffer 0 with 28 bytes
Completed transfer of 28 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 28 bytes
  Queue EP 00 with 0 bytes ...
  Prepare BufCtrl: [0] = 0x29696  [1] = 0x0000
buf_status = 0x00000002
  Sync BufCtrl: [0] = 0x57344  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 out
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 01 03 09 04 FF 00
  Get Descriptor String[1]
  Queue EP 80 with 16 bytes ...
  Prepare BufCtrl: [0] = 0x62480  [1] = 0x0000
buf_status = 0x00000001
  Sync BufCtrl: [0] = 0x24592  [1] = 0x0000
  Short packet on buffer 0 with 16 bytes
Completed transfer of 16 bytes on ep 0 in
USBD Xfer Complete on EP 80 with 16 bytes
  Queue EP 00 with 0 bytes ...
  Prepare BufCtrl: [0] = 0x29696  [1] = 0x0000
buf_status = 0x00000002
  Sync BufCtrl: [0] = 0x57344  [1] = 0x0000
  Short packet on buffer 0 with 0 bytes
Completed transfer of 0 bytes on ep 0 out
USBD Xfer Complete on EP 00 with 0 bytes
[ 1791.108019] usb 5-2.4.3: new full-speed USB device number 34 using xhci_hcd
[ 1791.211884] usb 5-2.4.3: New USB device found, idVendor=cafe, idProduct=4020, bcdDevice= 1.00
[ 1791.211889] usb 5-2.4.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 1791.211891] usb 5-2.4.3: Product: 4x4 MIDI Test
[ 1791.211893] usb 5-2.4.3: Manufacturer: TinyUSB
[ 1791.211894] usb 5-2.4.3: SerialNumber: 1234567
[ 1791.218457] snd-usb-audio: probe of 5-2.4.3:1.2 failed with error -16
[ 1791.218560] snd-usb-audio: probe of 5-2.4.3:1.4 failed with error -16
[ 1791.218655] snd-usb-audio: probe of 5-2.4.3:1.6 failed with error -16

DatanoiseTV avatar Feb 02 '22 10:02 DatanoiseTV

@DatanoiseTV I do not think the issue is with TinyUSB. I modified the example descriptors.c using the following code snip. Now amidi -l shows all 4 virtual cables. Please note the change to the CONFIG_TOTAL_LEN macro. I hope this helps.

$ amidi -l
Dir Device    Name
IO  hw:1,0,0  TinyUSB Device MIDI 1
IO  hw:1,0,1  TinyUSB Device MIDI 2
IO  hw:1,0,2  TinyUSB Device MIDI 3
IO  hw:1,0,3  TinyUSB Device MIDI 4

Code Snip:

#define CONFIG_TOTAL_LEN(num_cables_)  (TUD_CONFIG_DESC_LEN + (TUD_MIDI_DESC_HEAD_LEN + TUD_MIDI_DESC_JACK_LEN * num_cables_ + TUD_MIDI_DESC_EP_LEN(num_cables_) * 2))

#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
  // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
  // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ...
  #define EPNUM_MIDI   0x02
#else
  #define EPNUM_MIDI   0x01
#endif

#define MIDI_NUM_CABLES 4
uint8_t const desc_fs_configuration[] =
{
  // Config number, interface count, string index, total length, attribute, power in mA
  TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN(MIDI_NUM_CABLES), 0x00, 100),

  // Interface number, string index, EP Out & EP In address, EP size
  //TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 64)
  TUD_MIDI_DESC_HEAD(ITF_NUM_MIDI, 0, MIDI_NUM_CABLES),
  TUD_MIDI_DESC_JACK(1),
#if MIDI_NUM_CABLES>1
  TUD_MIDI_DESC_JACK(2),
#if MIDI_NUM_CABLES>2
  TUD_MIDI_DESC_JACK(3),
#if MIDI_NUM_CABLES>3
  TUD_MIDI_DESC_JACK(3),
#endif
#endif
#endif
  TUD_MIDI_DESC_EP(EPNUM_MIDI, 64, MIDI_NUM_CABLES),
  TUD_MIDI_JACKID_IN_EMB(1),
#if MIDI_NUM_CABLES>1
  TUD_MIDI_JACKID_IN_EMB(2),
#if MIDI_NUM_CABLES>2
  TUD_MIDI_JACKID_IN_EMB(3),
#if MIDI_NUM_CABLES>3
  TUD_MIDI_JACKID_IN_EMB(4),
#endif
#endif
#endif
  TUD_MIDI_DESC_EP(0x80 | EPNUM_MIDI, 64, MIDI_NUM_CABLES),
  TUD_MIDI_JACKID_OUT_EMB(1),
#if MIDI_NUM_CABLES>1
  TUD_MIDI_JACKID_OUT_EMB(2),
#if MIDI_NUM_CABLES>2
  TUD_MIDI_JACKID_OUT_EMB(3),
#if MIDI_NUM_CABLES>3
  TUD_MIDI_JACKID_OUT_EMB(4),
#endif
#endif
#endif
};

rppicomidi avatar Feb 21 '22 04:02 rppicomidi

Thanks for that @rppicomidi, very useful info.

There is a typo though which causes issues on a mac:

#if MIDI_NUM_CABLES>1
  TUD_MIDI_DESC_JACK(2),
#if MIDI_NUM_CABLES>2
  TUD_MIDI_DESC_JACK(3),
#if MIDI_NUM_CABLES>3
  TUD_MIDI_DESC_JACK(3),

should be

#if MIDI_NUM_CABLES>1
  TUD_MIDI_DESC_JACK(2),
#if MIDI_NUM_CABLES>2
  TUD_MIDI_DESC_JACK(3),
#if MIDI_NUM_CABLES>3
  TUD_MIDI_DESC_JACK(4),

AndrewCapon avatar Nov 11 '22 16:11 AndrewCapon

Oops! Thanks @AndrewCapon. Sorry @DatanoiseTV if my typo messed you up.

rppicomidi avatar Nov 11 '22 23:11 rppicomidi

I have created an example USB MIDI device with 2 MIDI In and 6 MIDI Out here. You may find the files midi_device_multistream.h helpful for building a USB descriptor with an arbitrary number of virtual cables. It uses the Boost Preprocessor library to help.

rppicomidi avatar May 08 '23 17:05 rppicomidi

thank you @rppicomidi for the update, and the example, I think this could be closed now.

hathach avatar May 09 '23 01:05 hathach