PDA

View Full Version : How to change Teensy 3.0 PRODUCT_NAME ?



gatheround
06-10-2013, 08:37 PM
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:




#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?

PaulStoffregen
06-10-2013, 08:50 PM
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.....

gatheround
06-10-2013, 08:52 PM
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?

PaulStoffregen
06-10-2013, 09:05 PM
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?

Nantonos
06-11-2013, 12:11 PM
I tried, and failed with errors I don't understand.


/*
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);
}
}




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'

PaulStoffregen
06-11-2013, 01:00 PM
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

PaulStoffregen
06-11-2013, 01:03 PM
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:



#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
};

PaulStoffregen
06-11-2013, 01:05 PM
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?

Nantonos
06-12-2013, 02:05 PM
OK, this now compiles, uploads to Teensy 3.0.


#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

#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.

566

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?

PaulStoffregen
06-12-2013, 02:15 PM
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.

dlchambers
07-05-2013, 12:34 AM
I only find usb_names.h in the hardware\teensy\cores\teensy3 dir.
Does it not work Teensy with 2.0/2.0++ ?

PaulStoffregen
07-05-2013, 02:35 PM
usb_names.h only exists on Teesny3.

On Teensy2, you must edit the code in hardware/teensy/cores/...

dlchambers
07-08-2013, 04:03 PM
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\build8184 370118083348986.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

dlchambers
07-08-2013, 05:43 PM
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.

PaulStoffregen
07-08-2013, 07:37 PM
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.

dlchambers
07-10-2013, 12:06 PM
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).

dlchambers
10-22-2013, 03:34 PM
So, how does one spec a custom VID and PID for the Teensy 3.0 ?

Headroom
10-22-2013, 04:26 PM
PID I don't know. VID may be unlikely.

See this (http://www.arachnidlabs.com/blog/2013/10/18/usb-if-no-vid-for-open-source/)recent post on Arachnidlabs.com

dlchambers
10-22-2013, 05:56 PM
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.

froeber
11-02-2013, 05:17 PM
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?

robwhite2777
08-13-2014, 07:58 PM
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

PaulStoffregen
08-13-2014, 08:03 PM
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.

PaulStoffregen
08-13-2014, 08:06 PM
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:


#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
0x02, // bInterfaceClass
0x02, // bInterfaceSubClass
0x01, // bInterfaceProtocol

robwhite2777
08-13-2014, 08:07 PM
Thanks again Paul!

I changed the file name as I posted that one up there very quickly.

russdx
09-18-2015, 10:06 AM
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

russdx
09-18-2015, 02:57 PM
Ah hunting down the .inf and changing the information here made it work :)

bafonso
10-21-2015, 03:23 PM
How would I change the serial name/description to "a40h-456" ?

bafonso
10-22-2015, 02:39 PM
How would I change the serial name/description to "a40h-456" ?

Ok nevermind, this was so simple I can't believe I didn't see how to do it. :-) Changing the serial may be enough to build a teensynome (teensy driven monome-like adafruit untz), that looks just like a monome so one can use all the monome software.

brianmichalk
12-29-2016, 03:37 AM
I tried this code, and it is not working for Teensy 3.2.
It appears that to get this to work, the struct in usb_names.h needs to have an explicit size defined.

For example, if I change usb_names.h to


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

then the code in the parent works. This is Teensy 3.2, and something may have changed since 3.0. Is there a different way to do this now?
If I compile with the original code, I get this error:


Arduino: 1.6.7 (Linux), TD: 1.27, Board: "Teensy 3.2 / 3.1, Serial, 72 MHz optimized, US English"

product:12: error: too many initializers for 'uint16_t [0] {aka short unsigned int [0]}'
};
^
product:17: error: too many initializers for 'uint16_t [0] {aka short unsigned int [0]}'
};
^
exit status 1
too many initializers for 'uint16_t [0] {aka short unsigned int [0]}'



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:



#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
};

PaulStoffregen
01-03-2017, 12:15 AM
The USB serial number is handled differently that the product name. The memory is written at startup by the usb_init_serialnumber() function in usb_desc.c. This is done because the serial number is stored in a special "write once" memory within Teensy (which PJRC programs with a unique 32 bit number). This code reads the serial number from that memory and converts it to string for the USB descriptor array.

If you want a custom USB serial number, you'll need to edit that code. At first glance it looks complex, but the first part just reads the special memory, so you can delete that. The 2nd part converts a 32 bit number to a string. Simple stuff.