How to change Teensy 3.0 PRODUCT_NAME ?

gatheround

Well-known member
Hey all,
Is there an easy way to change the name that the teensy shows up as when plugged in? Instead of saying "USB Serial" or "Teensy Flight Sim Controls" I'd like it to say something else for my project.

I did find the file /hardware/teensy/cores/teensy3/usb_desc.h where this is defined:

Code:
  #define PRODUCT_NAME		{'U','S','B',' ','S','e','r','i','a','l'}
  #define PRODUCT_NAME_LEN	10

Changing this does work, but I don't want to edit this file. Is there anything I can insert into my code that will change this instead?
 
A special header file, usb_names.h, was recently added to make this possible. So far, it hasn't ever been used or tested. But it might work if you try using it? So far, there's no documentation about how to do so, other than the header file itself.....
 
A special header file, usb_names.h, was recently added to make this possible. So far, it hasn't ever been used or tested. But it might work if you try using it? So far, there's no documentation about how to do so, other than the header file itself.....

Thanks Paul, so does usb_names.h get edited directly or are there variables that I can change in the main program itself?
 
Thanks Paul, so does usb_names.h get edited directly or are there variables that I can change in the main program itself?

The basic idea is you #include the file in your program. You should not need to be edit the header or anything in the core library (its entire purpose is so you do not need to edit other code).

Then you add your own copy of those structs, probably by copy-n-paste of the ones from usb_desc.c. Remove the "default" from their names, so they match the non-aliased definitions from usb_names.h.

If you get it to actually work, please post the code here so others might have an easier time using this?
 
I tried, and failed with errors I don't understand.

Code:
/* 
 Make a MIDI USB device with custom names
 This example code is in the public domain.
 */
#include <usb_names.h>
#define middleC 60  // midi note 60 is C4

#define MANUFACTURER_NAME	{'F','o','o','B','a','r'}
#define MANUFACTURER_NAME_LEN	6
#define PRODUCT_NAME		{'M','e','g','a','M','I','D','I'}
#define PRODUCT_NAME_LEN	8

struct usb_string_descriptor_struct usb_string_manufacturer_name = {
  2 + MANUFACTURER_NAME_LEN * 2,
  3,
  MANUFACTURER_NAME
};
struct usb_string_descriptor_struct usb_string_product_name = {
  2 + PRODUCT_NAME_LEN * 2,
  3,
  PRODUCT_NAME
};
struct usb_string_descriptor_struct usb_string_serial_number = {
  12,
  3,
  {
    0,0,7,0,0,0,7,0,0,7  }
};

void setup(){
}

void loop() {
  int i = 0;
  delay(5000);
  for (i=0; i<= 128; i+=4)
  {
    usbMIDI.sendNoteOn(middleC, i, 1);
    delay (500);
    usbMIDI.sendNoteOff(middleC, 64 , 1);
    delay (200);
  }
}

Code:
  This report would have more information with
  "Show verbose output during compilation"
  enabled in File > Preferences.
Arduino: 1.0.5 (Windows 7), Board: "Teensy 3.0"
In file included from MIDI_Rename.ino:5:0:
F:\Arduino\arduino-105-td114\hardware\teensy\cores\teensy3/usb_names.h:12:2: error: 'uint8_t' does not name a type
F:\Arduino\arduino-105-td114\hardware\teensy\cores\teensy3/usb_names.h:13:2: error: 'uint8_t' does not name a type
F:\Arduino\arduino-105-td114\hardware\teensy\cores\teensy3/usb_names.h:14:2: error: 'uint16_t' does not name a type
MIDI_Rename:13: error: redefinition of 'usb_string_descriptor_struct usb_string_manufacturer_name'
In file included from MIDI_Rename.ino:5:0:
F:\Arduino\arduino-105-td114\hardware\teensy\cores\teensy3/usb_names.h:17:44: error: 'usb_string_descriptor_struct usb_string_manufacturer_name' previously declared here
MIDI_Rename:18: error: redefinition of 'usb_string_descriptor_struct usb_string_product_name'
In file included from MIDI_Rename.ino:5:0:
F:\Arduino\arduino-105-td114\hardware\teensy\cores\teensy3/usb_names.h:19:44: error: 'usb_string_descriptor_struct usb_string_product_name' previously declared here
MIDI_Rename:23: error: redefinition of 'usb_string_descriptor_struct usb_string_serial_number'
In file included from MIDI_Rename.ino:5:0:
F:\Arduino\arduino-105-td114\hardware\teensy\cores\teensy3/usb_names.h:21:44: error: 'usb_string_descriptor_struct usb_string_serial_number' previously declared here
F:\Arduino\arduino-105-td114\hardware\teensy\cores\teensy3/usb_names.h:17:44: error: 'usb_string_manufacturer_name' aliased to undefined symbol 'usb_string_manufacturer_name_default'
F:\Arduino\arduino-105-td114\hardware\teensy\cores\teensy3/usb_names.h:19:44: error: 'usb_string_product_name' aliased to undefined symbol 'usb_string_product_name_default'
F:\Arduino\arduino-105-td114\hardware\teensy\cores\teensy3/usb_names.h:21:44: error: 'usb_string_serial_number' aliased to undefined symbol 'usb_string_serial_number_default'
 
Hmmm.... looks like the alias stuff should not have been in the header. There are a couple other issues too.

First, these in hardware/teensy/cores/teensy3
 

Attachments

  • usb_desc.c
    42 KB · Views: 595
  • usb_names.h
    590 bytes · Views: 485
To use these, you must create a new tab in Arduino. Use the button on the right hand side of the tabs toolbar, then select "New Tab". It will ask for you for "Name for new file". It must end in ".c". For example, "myname.c". If you use .ino, .pde or .cpp, this will not work.

In the new tab, try this:

Code:
#include "usb_names.h"

#define PRODUCT_NAME		{'M','e','t','a','M','I','D','I'}
#define PRODUCT_NAME_LEN	8

struct usb_string_descriptor_struct usb_string_product_name = {
  2 + PRODUCT_NAME_LEN * 2,
  3,
  PRODUCT_NAME
};
 
Windows and Mac may cache the name and other info. I tested on Linux and it seems to work.

I'm not sure how to get Windows to "forget" the old name. Maybe edit something in the registry?
 
OK, this now compiles, uploads to Teensy 3.0.

Code:
#define middleC 60  // midi note 60 is C4

void setup(){
}

void loop() {
  int i = 0;
  delay(5000);
  for (i=0; i<= 128; i+=4)
  {
    usbMIDI.sendNoteOn(middleC, i, 1);
    delay (500);
    usbMIDI.sendNoteOff(middleC, 64 , 1);
    delay (200);
  }
}
and in a new tab
Code:
#include <usb_names.h>

#define MANUFACTURER_NAME	{'F','o','o','B','a','r'}
#define MANUFACTURER_NAME_LEN	6
#define PRODUCT_NAME		{'M','e','g','a','M','I','D','I'}
#define PRODUCT_NAME_LEN	8

struct usb_string_descriptor_struct usb_string_manufacturer_name = {
  2 + MANUFACTURER_NAME_LEN * 2,
  3,
  MANUFACTURER_NAME
};
struct usb_string_descriptor_struct usb_string_product_name = {
  2 + PRODUCT_NAME_LEN * 2,
  3,
  PRODUCT_NAME
};
struct usb_string_descriptor_struct usb_string_serial_number = {
  12,
  3,
  {
    0,0,7,0,0,0,7,0,0,7  }
};

After it reboots, Windows tries and fails to install the new device.

midi-rename-err01.png

Nothing is shown in Device Manager (no 'unknown device' or anything like that). Compiling some other sketch (like blink) makes Windows re-install the new device and recognise it, as whatever the USB type was set to.

It seems that Windows would need a .inf file to tell it that this manufacturer and product name is whatever standard type it is, and to use it's own driver. Similar to the one used for Teensy itself. Odd that it uses the name and not the VID/PID. Maybe it uses that as well.

Now that the Teensy driver is bundled into Teensyduino, its less convenient for me to examine. Do you have the teensy .inf file handy for me to look at?
 
Here is the INF file the Teensyduino installer and stand-alone serial installer use.

I had to rename it to .txt to post here, but it's exactly the same file when you change back to .inf.
 

Attachments

  • cdc_acm_class.txt
    1.1 KB · Views: 1,603
I only find usb_names.h in the hardware\teensy\cores\teensy3 dir.
Does it not work Teensy with 2.0/2.0++ ?
 
Related item:

In my verbose compiler output, I see USB_VID and USB_PID defined to null (in red text):
C:\Arduino\1.0.5\hardware\tools\avr\bin\avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=at90usb1286 -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=105 -felide-constructors -std=c++0x -DUSB_SERIAL -DLAYOUT_US_ENGLISH -IC:\Arduino\1.0.5\hardware\teensy\cores\teensy C:\Arduino\1.0.5\hardware\teensy\cores\teensy\usb_api.cpp -o C:\Users\DCHAMB~1.LAB\AppData\Local\Temp\build8184370118083348986.tmp\usb_api.cpp.o

Anyone know how/where these are set?
If I could set these I could use them to key some #ifdefs
 
Answering my own question :)

In boards.txt you set
<board>.build.vid=0x1234
<board>.build.pid=0x5678

and that passes them as "-D" defines to the c compiler.
 
and that passes them as "-D" defines to the c compiler.

Yes, but Teensy doesn't use these, even if you define them. Maybe it should?

They are meant for one of Arduino's boards. Their code in the Arduino IDE always puts them in to the compiler command line, even if they're not defined. A cleaner approach would have only added them to the command line when lines in boards.txt actually define them.
 
What I was thinking is that it'd be super cool if there were a weak function that gets called at the top of usb_init(), named eg. usb_preinit(), which would allow a program to optionally override the values from usb_private.h (VID, PID, MANUFACTURER, PRODUCT, SERIAL_NUMBER) at run time.
I realize that all the USB descriptors, etc are PROGMEM, so they can't easily be changed on the fly, but those are details to be worked out.

Something else I'm playing with is to add each "project" to boards.txt.
For example, I have something based on a Teensy++ 2.0, so in boards.txt I cloned the teensypp2 section, set the .name to my project, stripped down all the options to just those that I use (only menu.usb.serial, menu.speed.16, menu.keys.en-us, etc), and set the vid and pid as mentioned above.
Then in usb_private.h I #include "my_usb_ids.h" (my custom file) at the top of file, and in the body of usb_private.h I key off the USB_VID define thusly:
#if !USB_VID // Default for all Teensy boards has USB_VID as NULL
# define STR_MANUFACTURER L"Teensyduino"
# define STR_PRODUCT L"USB Serial"
#elif (USB_VID == MY_VENDOR_ID)
# define STR_MANUFACTURER MY_STR_MANUFACTURER
# define STR_PRODUCT MY_STR_PRODUCT
#endif
(same for all other #defines in usb_private.h)

This all works quite well, EXCEPT that I've altered some stock files in hardware\teensy, which I don't like, and I have to extend boards.txt for each project.

Preferably, I'd be able to use 100% stock source files and set my project-specific USB stuff at compile time with a custom file in my project dir, as you've done with usb_names.h (though, curiously, this doesn't allow for setting my own VID & PID).
 
I have my own VID, bought & paid from USB-IF, and I want to use that with a Teensy 3.0.

This is purely a technical question, not an ethical/legal one.
 
I'm trying to figure out the "right" way to go with a potential product we are basing on the Teensy3. We will want data offload over USB by users who certainly won't have the TeensyDuino environment installed including the .inf files Paul's installer adds on Windows to allow the virtual serial interface to work. As I look into this I did find the Arachnidlabs.com post @Headroom mentioned above quite interesting. I did find on http://usb-ids.gowdy.us/read/UD/16c0 that the USB VID and PID Paul's using for the Teensy3 was probably something from EZ Prototypes who must resell PIDs from defunct vendors. And that makes sense to me since $5000/year for your own VID from USB-IF seems ridiculously expensive for small companies.

I don't think it's a good idea to change the VID/PID pair for the product. So I am thinking I should change something else that is used in finding the correct driver to load so that I can provide my own .inf file to set a good "device name". As far as I can tell, changing usb_string_manufacturer_name, usb_string_product_name, or usb_string_serial_number in my Teensy3 application won't have any effect on windows because it seems like Windows sets the DriverDesc and ProviderName that shows up in the DeviceManager entry for the Teensy3 serial port using the MFGNAME and DEVNAME strings from the .inf installation file (which Paul included in an earlier post above). And I'm not really sure how Windows even figured out to use the .inf file Paul provided. Because the DeviceManager entry says that the matchingDeviceId was usb\class_02&subclass_02&prot_01 but I can't see that the device_descriptor in usb_desc.c which is set from values in usb_desc.h sets anything but the "class" value for a USB_SERIAL interface. So I am confused.

Has anyone used a custom .inf file with a Teensy3 based board?
 
Hey all,

The proper way to change the PID/VID and product name for the teensy 3.1 is to access and modify usb_desc.h located in "arduino root folder\hardware\teensy\cores\teensy3\". Once modified the auto refresh will not program the teensy and you will need to manually press the reset button in order for the teensy to show up as itself while connected to your computer.

Cheers!

Rob
 
Last edited:
You can customize all this stuff by simply editing usb_desc.h. There's comments in the code and the names and organization of the file should be pretty obvious.
 
And I'm not really sure how Windows even figured out to use the .inf file Paul provided. Because the DeviceManager entry says that the matchingDeviceId was usb\class_02&subclass_02&prot_01 but I can't see that the device_descriptor in usb_desc.c which is set from values in usb_desc.h sets anything but the "class" value for a USB_SERIAL interface. So I am confused.

In usb_desc.c:
Code:
#ifdef CDC_DATA_INTERFACE
        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
        9,                                      // bLength
        4,                                      // bDescriptorType
        CDC_STATUS_INTERFACE,                   // bInterfaceNumber
        0,                                      // bAlternateSetting
        1,                                      // bNumEndpoints
[B]        0x02,                                   // bInterfaceClass
        0x02,                                   // bInterfaceSubClass
        0x01,                                   // bInterfaceProtocol[/B]
 
Is there a trick to changing the product name?
#define PRODUCT_NAME {'U','S','B',' ','S','e','r','i','a','l'}
#define PRODUCT_NAME_LEN 10

As a quick test I simply changed the usb serial to some thing else (and the byte count) re programmed my teensy 3.1 but then the pc did not recognise the device any more. Do i need to make a similar change in the usb .ini file?

I am using windows 7

Regards
Russell
 
Back
Top