Configurable usbMIDI Port Names

vjmuzik

Well-known member
For those interested I've added a way to configure the usbMIDI Port Names, these are changed in the same manner as the Manufacturer Name, Device Name, and Serial Number. So to change the names from the default "Port 1" - "Port 16" you add the following struct to the name.c in your project, one for each port number.


Code:
#define MIDI_PORT1_NAME {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'1'}
#define MIDI_PORT1_NAME_LEN 8

struct usb_string_descriptor_struct usb_string_midi_port1 = {
        2 + MIDI_PORT1_NAME_LEN * 2,
        3,
        MIDI_PORT1_NAME
};

Teensy Port Names.png
 

Attachments

  • usb_desc.c
    82 KB · Views: 238
  • usb_names.h
    3 KB · Views: 222
Great. Thank you! Funny, I was searching to forum to find the answer prior to posting the question, but missed that thread. I am going to try it out.
 
I’m trying specify custom port names with Teensyduino 1.53, Teensy 4, and macOS Catalina.

Serial + MIDIx16

Product name, Manufacturer, and Serial are not a problem. I increment the serial number to load a fresh build.

Not sure where I’m going wrong and could use some help.

Here’s my name.c :

Code:
// To give your project a unique name, this code must be
// placed into a .c file (its own tab).  It can not be in
// a .cpp file or your main sketch (the .ino file).

#include "usb_names.h"

// Edit these lines to create your own name.  The length must
// match the number of characters in your custom name.

#define MIDI_NAME   {'M','y','H','u','b'}
#define MIDI_NAME_LEN  5

#define MIDI_MANUFACTURER_NAME   {'D','a','h'}
#define MIDI_MANUFACTURER_NAME_LEN 3

#define MIDI_SERIAL_NUMBER   {'1','6'}
#define MIDI_SERIAL_NUMBER_LEN 2

#define MIDI_PORT1_NAME   {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'1'}
#define MIDI_PORT1_NAME_LEN 8

#define MIDI_PORT2_NAME   {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'2'}
#define MIDI_PORT2_NAME_LEN 8

#define MIDI_PORT3_NAME   {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'3'}
#define MIDI_PORT3_NAME_LEN 8

#define MIDI_PORT4_NAME   {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'4'}
#define MIDI_PORT4_NAME_LEN 8

#define MIDI_PORT5_NAME   {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'5'}
#define MIDI_PORT5_NAME_LEN 8

#define MIDI_PORT6_NAME   {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'6'}
#define MIDI_PORT6_NAME_LEN 8

#define MIDI_PORT7_NAME   {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'7'}
#define MIDI_PORT7_NAME_LEN 8

#define MIDI_PORT8_NAME   {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'8'}
#define MIDI_PORT8_NAME_LEN 8

#define MIDI_PORT9_NAME   {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'9'}
#define MIDI_PORT9_NAME_LEN 8

#define MIDI_PORT10_NAME  {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'1', '0'}
#define MIDI_PORT10_NAME_LEN 9

#define MIDI_PORT11_NAME  {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'1', '1'}
#define MIDI_PORT11_NAME_LEN 9

#define MIDI_PORT12_NAME  {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'1', '2'}
#define MIDI_PORT12_NAME_LEN 9

#define MIDI_PORT13_NAME  {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'1', '3'}
#define MIDI_PORT13_NAME_LEN 9

#define MIDI_PORT14_NAME  {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'1', '4'}
#define MIDI_PORT14_NAME_LEN 9

#define MIDI_PORT15_NAME  {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'1', '5'}
#define MIDI_PORT15_NAME_LEN 9

#define MIDI_PORT16_NAME  {'T', 'e', 'e', 'n' ,'s' ,'y' ,' ' ,'1', '6'}
#define MIDI_PORT16_NAME_LEN 9



// ****************************************

// Do not change this part.  This exact format is required by USB.

// ****************************************

struct usb_string_descriptor_struct usb_string_product_name = {
        2 + MIDI_NAME_LEN * 2,
        3,
        MIDI_NAME
};


struct usb_string_descriptor_struct usb_string_manufacturer_name = {
        2 + MIDI_MANUFACTURER_NAME_LEN * 2,
        3,
        MIDI_MANUFACTURER_NAME
};


struct usb_string_descriptor_struct usb_string_serial_number = {
        2 + MIDI_SERIAL_NUMBER_LEN * 2,
        3,
        MIDI_SERIAL_NUMBER
};

// ****************************************
struct usb_string_descriptor_struct usb_string_midi_port1 = {
        2 + MIDI_PORT1_NAME_LEN * 2,
        3,
        MIDI_PORT1_NAME
};


struct usb_string_descriptor_struct usb_string_midi_port2 = {
        2 + MIDI_PORT2_NAME_LEN * 2,
        3,
        MIDI_PORT2_NAME
};


struct usb_string_descriptor_struct usb_string_midi_port3 = {
        2 + MIDI_PORT3_NAME_LEN * 2,
        3,
        MIDI_PORT3_NAME
};



struct usb_string_descriptor_struct usb_string_midi_port4 = {
        2 + MIDI_PORT4_NAME_LEN * 2,
        3,
        MIDI_PORT4_NAME
};



struct usb_string_descriptor_struct usb_string_midi_port5 = {
        2 + MIDI_PORT5_NAME_LEN * 2,
        3,
        MIDI_PORT5_NAME
};



struct usb_string_descriptor_struct usb_string_midi_port6 = {
        2 + MIDI_PORT6_NAME_LEN * 2,
        3,
        MIDI_PORT6_NAME
};


struct usb_string_descriptor_struct usb_string_midi_port7 = {
        2 + MIDI_PORT7_NAME_LEN * 2,
        3,
        MIDI_PORT7_NAME
};


struct usb_string_descriptor_struct usb_string_midi_port8 = {
        2 + MIDI_PORT8_NAME_LEN * 2,
        3,
        MIDI_PORT8_NAME
};


struct usb_string_descriptor_struct usb_string_midi_port9 = {
        2 + MIDI_PORT9_NAME_LEN * 2,
        3,
        MIDI_PORT9_NAME
};


struct usb_string_descriptor_struct usb_string_midi_port10 = {
        2 + MIDI_PORT10_NAME_LEN * 2,
        3,
        MIDI_PORT10_NAME
};


struct usb_string_descriptor_struct usb_string_midi_port11 = {
        2 + MIDI_PORT11_NAME_LEN * 2,
        3,
        MIDI_PORT11_NAME
};

struct usb_string_descriptor_struct usb_string_midi_port12 = {
        2 + MIDI_PORT12_NAME_LEN * 2,
        3,
        MIDI_PORT12_NAME
};


struct usb_string_descriptor_struct usb_string_midi_port13 = {
        2 + MIDI_PORT13_NAME_LEN * 2,
        3,
        MIDI_PORT13_NAME
};


struct usb_string_descriptor_struct usb_string_midi_port14 = {
        2 + MIDI_PORT14_NAME_LEN * 2,
        3,
        MIDI_PORT14_NAME
};

struct usb_string_descriptor_struct usb_string_midi_port15 = {
        2 + MIDI_PORT15_NAME_LEN * 2,
        3,
        MIDI_PORT15_NAME
};


struct usb_string_descriptor_struct usb_string_midi_port16 = {
        2 + MIDI_PORT16_NAME_LEN * 2,
        3,
        MIDI_PORT16_NAME
};


and here are my edits to usb_names.h in the Teensyduino package. I’m only editing the files for teensy 4.0.

Code:
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

struct usb_string_descriptor_struct {
	uint8_t bLength;
	uint8_t bDescriptorType;
	uint16_t wString[];
};

extern struct usb_string_descriptor_struct usb_string_manufacturer_name;
extern struct usb_string_descriptor_struct usb_string_product_name;
extern struct usb_string_descriptor_struct usb_string_serial_number;
extern struct usb_string_descriptor_struct usb_string_midi_port1;
extern struct usb_string_descriptor_struct usb_string_midi_port2;
extern struct usb_string_descriptor_struct usb_string_midi_port3;
extern struct usb_string_descriptor_struct usb_string_midi_port4;
extern struct usb_string_descriptor_struct usb_string_midi_port5;
extern struct usb_string_descriptor_struct usb_string_midi_port6;
extern struct usb_string_descriptor_struct usb_string_midi_port7;
extern struct usb_string_descriptor_struct usb_string_midi_port8;
extern struct usb_string_descriptor_struct usb_string_midi_port9;
extern struct usb_string_descriptor_struct usb_string_midi_port10;
extern struct usb_string_descriptor_struct usb_string_midi_port11;
extern struct usb_string_descriptor_struct usb_string_midi_port12;
extern struct usb_string_descriptor_struct usb_string_midi_port13;
extern struct usb_string_descriptor_struct usb_string_midi_port14;
extern struct usb_string_descriptor_struct usb_string_midi_port15;
extern struct usb_string_descriptor_struct usb_string_midi_port16;


#ifdef __cplusplus
}
#endif

#endif

and usb_desc.c. Search on JJM to quick find the three blocks of code that I added.

View attachment usb_desc.c
 
The other part that needs changed in usb_desc.c is this which appears twice for the T4.x:
Code:
#if MIDI_NUM_CABLES >= 2
	#define MIDI_INTERFACE_JACK_PAIR(a, b, c, d, e) \
		6, 0x24, 0x02, 0x01, (a), (e), \
		6, 0x24, 0x02, 0x02, (b), (e), \
		9, 0x24, 0x03, 0x01, (c), 1, (b), 1, (e), \
		9, 0x24, 0x03, 0x02, (d), 1, (a), 1, (e),
	MIDI_INTERFACE_JACK_PAIR(5, 6, 7, 8, 0x06)
  #endif
  #if MIDI_NUM_CABLES >= 3
	MIDI_INTERFACE_JACK_PAIR(9, 10, 11, 12, 0x07)
  #endif
  #if MIDI_NUM_CABLES >= 4
	MIDI_INTERFACE_JACK_PAIR(13, 14, 15, 16, 0x08)
  #endif
  #if MIDI_NUM_CABLES >= 5
	MIDI_INTERFACE_JACK_PAIR(17, 18, 19, 20, 0x09)
  #endif
  #if MIDI_NUM_CABLES >= 6
	MIDI_INTERFACE_JACK_PAIR(21, 22, 23, 24, 0x0A)
  #endif
  #if MIDI_NUM_CABLES >= 7
	MIDI_INTERFACE_JACK_PAIR(25, 26, 27, 28, 0x0B)
  #endif
  #if MIDI_NUM_CABLES >= 8
	MIDI_INTERFACE_JACK_PAIR(29, 30, 31, 32, 0x0C)
  #endif
  #if MIDI_NUM_CABLES >= 9
	MIDI_INTERFACE_JACK_PAIR(33, 34, 35, 36, 0x0D)
  #endif
  #if MIDI_NUM_CABLES >= 10
	MIDI_INTERFACE_JACK_PAIR(37, 38, 39, 40, 0x0E)
  #endif
  #if MIDI_NUM_CABLES >= 11
	MIDI_INTERFACE_JACK_PAIR(41, 42, 43, 44, 0x0F)
  #endif
  #if MIDI_NUM_CABLES >= 12
	MIDI_INTERFACE_JACK_PAIR(45, 46, 47, 48, 0x10)
  #endif
  #if MIDI_NUM_CABLES >= 13
	MIDI_INTERFACE_JACK_PAIR(49, 50, 51, 52, 0x11)
  #endif
  #if MIDI_NUM_CABLES >= 14
	MIDI_INTERFACE_JACK_PAIR(53, 54, 55, 56, 0x12)
  #endif
  #if MIDI_NUM_CABLES >= 15
	MIDI_INTERFACE_JACK_PAIR(57, 58, 59, 60, 0x13)
  #endif
  #if MIDI_NUM_CABLES >= 16
	MIDI_INTERFACE_JACK_PAIR(61, 62, 63, 64, 0x14)
  #endif

This is what maps each port to the changes in the array at JJM Start 3.
 
Are these changes compatible with Teensy 4.1? I'm new to the Teensy world and would rather not make assumptions that could lead to weird bugs down the road.
 
I backed up 'usb_desc.c.' and 'usb_names.h' and copied the contents of the attached files above to each respective file. This resulted in multiple errors. A way to fix would be awesome.
 
After comparing @jmercer's usb_desc.c to my own I was comfortable making the changes and it seems to work on the 1.58.1 branch. However there was one deference that stood out between his usb_desc.c and my own:

His usb_desc.c lines 1301 - 1312
C:
#ifdef MTP_INTERFACE
    // configuration for 480 Mbit/sec speed
        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
        9,                                      // bLength
        4,                                      // bDescriptorType
        MTP_INTERFACE,                          // bInterfaceNumber
        0,                                      // bAlternateSetting
        3,                                      // bNumEndpoints
        0x06,                                   // bInterfaceClass (0x06 = still image)
        0x01,                                   // bInterfaceSubClass
        0x01,                                   // bInterfaceProtocol
        0,                                      // iInterface

My usb_desc.c lines 1340 - 1351
C:
#ifdef MTP_INTERFACE
    // configuration for 480 Mbit/sec speed
        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
        9,                                      // bLength
        4,                                      // bDescriptorType
        MTP_INTERFACE,                          // bInterfaceNumber
        0,                                      // bAlternateSetting
        3,                                      // bNumEndpoints
        0x06,                                   // bInterfaceClass (0x06 = still image)
        0x01,                                   // bInterfaceSubClass
        0x01,                                   // bInterfaceProtocol
        4,                                      // iInterface

The values of the last lines (iInterface?) is deferent, mine 4 and his 0. It seems unrelated but I'm not familiar. Should this change be made to my usb_desc.c?
 
iInterface isn't critically important. It just tries to associate a name (which should be defined as string #4) with the interface. But it turns out Windows Device Manager (where it's needed most) just ignores it.
 
Hi !

Is there a way to "bypass" Port Name in single port mode (MIDI or Serial + MIDI) ?
Previously (my first interfaces were programmed between 2018 and 2020), I had only the MIDI Name displayed, but now I always have a "Port 1" (or whatever I define using the previous posts) displayed after my interface name.

My interfaces are controlled by some Max code which looks for particular names, and the "Port 1" (or whatever) breaks everything...

Regards,

Jérémie
 
Is there a way to "bypass" Port Name in single port mode (MIDI or Serial + MIDI) ?

I am not aware of any way, at least from code running on Teensy. I did try this by editing descriptors. For Serial it is possible to affect the name shown on MacOS and Linux, but not Windows (because it ignores the descriptor name and gets the name from an INF inside Windows). For MIDI, as far as I know the descriptors can only affect the name of the whole interface. If there is a way for the descriptors to give names to the individual cables/ports within the MIDI interface, I was not able to find it.

On Windows, this sort of thing can (probably) be done by crafting a special INF file which you install into Windows. But that is a pretty unpleasant path. On top of the pain of figuring out Microsoft's horrible INF format, all modern versions of Windows require a CAT file with digital signature to install any INF. Recently the process of obtaining a code signing cert has become more difficult, requiring either the one-time cost and complexity of a hardware token or the use of a cloud service with ongoing monthly cost. At least the good news is you only need an OV type cert. EV is only needed if your install includes actual executable kernel-mode code. For just an INF you only need OV type signing. Even once you get a properly signed INF+CAT, the process of installing a "driver" for Windows usually means giving users a set of error-prone steps to follow or you end up providing an installer program (which you'll be able to sign with same code signing cert).
 
Hi Paul,

Maybe I didn't explain my problem very clearly because I'm not sure to understand your answer...

Let me try again :
Firstly, lets assume I only work on Mac to narrow the answer...
Several years ago, when I uploaded code to my Teensy 3.2 in Midi mode, it used to be visible as "Teensy USB" (or any other name I configured in name.c file). Now, when I upload the same code to the same Teensy, it shows as "Teensy USB Port 1". I suppose it is due to some refactoring for MIDIx4 and MIDIx16 modes that need a name for each port...

Here is my question :
In MIDI or Serial+MIDI modes, is there a way to display only the name "Teensy USB" (or any other name I configured in name.c file), like it was in previous version of Teensyduino, instead of "Teensy USB Port 1" ?

Regards,
 
Answer to myself : if I set an empty port name in the "name.c" file, it works.
I already tried this before but I can see the change only if I restart the program I use to receive MIDI.

Here is the code if someone needs it :
C:
#define MIDI_PORT1_NAME {}
#define MIDI_PORT1_NAME_LEN 0

struct usb_string_descriptor_struct usb_string_midi_port1 = {
        2 + MIDI_PORT1_NAME_LEN * 2,
        3,
        MIDI_PORT1_NAME
};
 
Back
Top