custom USB Device name - modifying the core *instead* of the boards.txt file

Hey everyone,

This is a question specifically for people who know the Arduino core well, especially the USB core files. I'm trying to figure out a way to modify the usb_product name, which is normally derived from the boards.txt file. Rather than editing the boards.txt file, I want to change the name by altering the Arduino core c++ files.

If you use one of the libraries for USBMIDI or HID on a project, say if you want to make a diy midi controller or a diy generic hid keyboard, after you flash the arduino and you plug the board into your computer via usb it will show up as a generic midi or hid device, the name of this device will by default be the name from the build.usb_product line from the boards.txt file of the currently selected board, ex. "Arduino Micro"

Changing the boards file is easy enough, but if I'm sharing a diy arduino project with less technical people, I would rather find an easy way for them to customize the device name. If I can figure out where it is in the source code, I can find a way for my firmware to change that string via a custom config.h file.

The USB core files span over many linked files and they are not commented very much, so I'm not sure I'm gonna be able to figure it out without having more experience with these libraries. Anyone know where to find it? :slight_smile:

I don't know much about this, but I'll try to get you started. I'm using the Leonardo as an example.

As you are aware, the build.usb_product property is defined in boards.txt:"Arduino Leonardo"

That property is used in platform.txt to define a property named build.usb_flags that contains a -D compiler flag used to create a global macro named USB_PRODUCT that is set to the value of {build.usb_product}:

build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}'

Now it gets convoluted. We have to go back to boards.txt to see where build.usb_flags is used to define yet another property named build.extra_flags:{build.usb_flags}

Then back to platform.txt where build.extra_flags is used in the compilation recipes:

recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"

So now you just have to search the source code to see where that USB_PRODUCT macro is used:

// If no product is provided, use USB IO Board
#define USB_PRODUCT     "USB IO Board"


So now you have a variable name STRING_PRODUCT to follow.


So now you have a variable name STRING_PRODUCT to follow.

Thank you, this is extremely helpful. Since the STRING_PRODUCT array is in caps and that array lengths need to be known at compile time I'm assuming this is also a macro whose real name/length is being generated by a json script as well?

No, it's just what you see there.

Although I prefer to only use CAPS_CASE for macros, some people use it for constants as well.

The length is determined at compile time by the compiler. There's no JSON at all involved in the process.

Ah okay, this is a c-style string except instead of a char array it’s an unsigned 8bit integer array. Thanks again.

I’m gonna try and modify the const string through some pointer hackery or undefining the USB_PRODUCT macro and redefining it, and see if that could be a solution being able to change the device name from my main .ino project file. Will let you know the results!

So yes modifying this string in the USBcore.cpp successfully changes the USB device name, hurray.

const u8 STRING_PRODUCT[] PROGMEM = "My Midi Controller";

I am stumped however on how to find a way to externally modify the const (internal linkage) string via pointers or macros. Ideally I would like to be able to modify this string from either the main .ino file or a file in the local project directory.

My thoughts are since this string array is stored in program memory then as long as I can find the memory address of this string then it can be modified from any file in the project. Once it's modified, hopefully the arduino can just be reset and it will now use this string name when interfacing with the computer via usb... Is this a correct line of reasoning? If so then is there a way to a) get the address of this string from an external file that isn't the USBcore.cpp? and b) is there a way to modify it since it's stored in the program memory and not the sram?

Ah I may have found the solution here thanks to facchin on github:

“the suggested way to modify the name is creating a derived core and override the name from there. You can take inspiration from arduino/hardware/webusb/avr at gh-pages · webusb/arduino · GitHub (which is very thing and easy to maintain)”

Not the exact answer I was looking for, but I think installing a derived library versus having users modify their boards.txt might be slightly better. I think it’s the best I’m gonna find.

I think this is the best solution if you are happy with fixed device names. The reason I didn't mention it is because from your original statement:

I would rather find an easy way for them to customize the device name.

which I took to mean that you wanted the users to be able to set arbitrary device names.

There is more information on the subject of "derived cores" here:

If you want to give the users the choice of multiple fixed device names, you can define them as custom board actions, which will result in a submenu being added to the Arduino IDE's Tools menu with the list of available names:

And to make it easy for the users to install and update, be sure to add support for Boards Manager installation:

Thanks again pert, super helpful, looks like this is the route I'm gonna take.

You're welcome. I'm glad if I was able to be of assistance. It's pretty interesting to explore the way the Arduino boards platform (AKA "core") system works. Enjoy!