Skip to content

Commit 6952595

Browse files
authored
Merge pull request #11720 from espressif/feature/device_name_usb_midi
feat(usb): allow the MIDI constructor to define a device name
2 parents a42f4a7 + 4bca706 commit 6952595

File tree

5 files changed

+119
-2
lines changed

5 files changed

+119
-2
lines changed

β€Žcores/esp32/Arduino.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,22 @@ size_t getArduinoLoopTaskStackSize(void);
222222
return sz; \
223223
}
224224

225+
#define ESP32_USB_MIDI_DEFAULT_NAME "TinyUSB MIDI"
226+
/**
227+
* @brief Set the current device name
228+
* 1. Name set via constructor (if any)
229+
* 2. Name set via SET_USB_MIDI_DEVICE_NAME() macro (if defined)
230+
* 3. Default name "TinyUSB MIDI"
231+
* If device name is set as "", it will be ignored
232+
*/
233+
#define SET_USB_MIDI_DEVICE_NAME(name) \
234+
const char *getUSBMIDIDefaultDeviceName() { \
235+
if (!name || strlen(name) == 0) { \
236+
return ESP32_USB_MIDI_DEFAULT_NAME; \
237+
} \
238+
return name; \
239+
}
240+
225241
bool shouldPrintChipDebugReport(void);
226242
#define ENABLE_CHIP_DEBUG_REPORT \
227243
bool shouldPrintChipDebugReport(void) { \

β€Žlibraries/USB/examples/MIDI/MidiController/MidiController.ino

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ void loop() {}
2020

2121
#include "USB.h"
2222
#include "USBMIDI.h"
23-
USBMIDI MIDI;
23+
// Creates the MIDI device with specific descriptor
24+
USBMIDI MIDI("ESP MIDI Device");
2425

2526
#define MIDI_NOTE_C4 60
2627

β€Žlibraries/USB/examples/MIDI/MidiInterface/MidiInterface.ino

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@ void setup() {}
2424
void loop() {}
2525
#else
2626

27+
// define a new USB MIDI device name using a macro
28+
SET_USB_MIDI_DEVICE_NAME("ESP MIDI Device")
29+
2730
#include "USB.h"
2831
#include "USBMIDI.h"
32+
// Creates the MIDI device with specific name defined with the SET_USB_MIDI_DEVICE_NAME() macro
2933
USBMIDI MIDI;
3034

3135
#define MIDI_RX 39

β€Žlibraries/USB/src/USBMIDI.cpp

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66
#include "Arduino.h"
77
#include "esp32-hal-tinyusb.h"
88

9+
// Initialize static members
10+
char *USBMIDI::midiUserDeviceName = nullptr;
11+
// Weak definition of getUSBMIDIDefaultDeviceName to provide a default name
12+
__attribute__((weak)) const char *getUSBMIDIDefaultDeviceName() {
13+
return ESP32_USB_MIDI_DEFAULT_NAME;
14+
}
15+
916
// Default Cable Number (for simplified APIs that do not expose this)
1017
#define DEFAULT_CN 0
1118

@@ -18,7 +25,7 @@ extern "C" uint16_t tusb_midi_load_descriptor(uint8_t *dst, uint8_t *itf) {
1825
}
1926
tinyusb_midi_descriptor_loaded = true;
2027

21-
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB MIDI");
28+
uint8_t str_index = tinyusb_add_string_descriptor(USBMIDI::getCurrentDeviceName());
2229
uint8_t ep_in = tinyusb_get_free_in_endpoint();
2330
TU_VERIFY(ep_in != 0);
2431
uint8_t ep_out = tinyusb_get_free_out_endpoint();
@@ -41,9 +48,68 @@ USBMIDI::USBMIDI() {
4148
}
4249
}
4350

51+
// private function for setting a not null/empty MIDI device name limited to 32 characters
52+
void USBMIDI::setDeviceName(const char *name) {
53+
const uint8_t maxNameLength = 32; // tinyUSB Descriptor limit
54+
if (name != nullptr && strlen(name) > 0) {
55+
if (strlen(name) > maxNameLength) {
56+
log_w("USBMIDI: Device name too long, truncating to %d characters.", maxNameLength);
57+
}
58+
if (!midiUserDeviceName) {
59+
midiUserDeviceName = new char[maxNameLength + 1]; // +1 for null-terminator
60+
}
61+
if (midiUserDeviceName) {
62+
strncpy(midiUserDeviceName, name, maxNameLength);
63+
// Ensure null-termination when overflowing
64+
midiUserDeviceName[maxNameLength] = '\0';
65+
} else {
66+
log_e("USBMIDI: Failed to allocate memory for device name, using default name.");
67+
}
68+
} else {
69+
log_w("USBMIDI: No device name provided, using default name [%s].", getUSBMIDIDefaultDeviceName());
70+
}
71+
}
72+
73+
/**
74+
* @brief Constructor for setting the current device name
75+
* 1. Name set via constructor (if any)
76+
* 2. Name set via SET_USB_MIDI_DEVICE_NAME() macro (if defined)
77+
* 3. Default name "TinyUSB MIDI"
78+
* If device name is set as "", it will be ignored
79+
*/
80+
USBMIDI::USBMIDI(const char *name) {
81+
if (!tinyusb_midi_interface_enabled) {
82+
setDeviceName(name);
83+
tinyusb_midi_interface_enabled = true;
84+
tinyusb_enable_interface(USB_INTERFACE_MIDI, TUD_MIDI_DESC_LEN, tusb_midi_load_descriptor);
85+
} else {
86+
log_e("USBMIDI: Multiple instances of USBMIDI not supported!");
87+
}
88+
}
89+
90+
USBMIDI::~USBMIDI() {
91+
if (midiUserDeviceName) {
92+
delete[] midiUserDeviceName;
93+
midiUserDeviceName = nullptr;
94+
}
95+
}
96+
4497
void USBMIDI::begin() {}
4598
void USBMIDI::end() {}
4699

100+
const char *USBMIDI::getCurrentDeviceName(void) {
101+
if (midiUserDeviceName) {
102+
return midiUserDeviceName;
103+
}
104+
// If no user name set, use the compile-time default name limited to 32 characters
105+
setDeviceName(getUSBMIDIDefaultDeviceName());
106+
if (midiUserDeviceName && strlen(midiUserDeviceName)) {
107+
return midiUserDeviceName;
108+
} else {
109+
return "TinyUSB MIDI";
110+
}
111+
}
112+
47113
// uint compatible version of constrain
48114
#define uconstrain(amt, low, high) ((amt) <= (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
49115

β€Žlibraries/USB/src/USBMIDI.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,41 @@ typedef struct {
1818
} midiEventPacket_t;
1919

2020
class USBMIDI {
21+
private:
22+
static char *midiUserDeviceName; // user device name
23+
static void setDeviceName(const char *name); // set user device name limited to 32 characters
24+
2125
public:
26+
/**
27+
* @brief Default constructor
28+
* Will use the compile-time name if set via SET_USB_MIDI_DEVICE_NAME(),
29+
* otherwise uses "TinyUSB MIDI"
30+
*/
2231
USBMIDI(void);
32+
33+
/**
34+
* @brief Set the current device name
35+
* 1. Name set via constructor (if any)
36+
* 2. Name set via SET_USB_MIDI_DEVICE_NAME() macro (if defined)
37+
* 3. Default name "TinyUSB MIDI"
38+
* It has no effect if name is set as NULL or ""
39+
*/
40+
USBMIDI(const char *name);
41+
42+
~USBMIDI();
43+
2344
void begin(void);
2445
void end(void);
2546

47+
/**
48+
* @brief Get the current device name
49+
* @return The device name in order of precedence:
50+
* 1. Name set via constructor (if any)
51+
* 2. Name set via SET_USB_MIDI_DEVICE_NAME() macro (if defined)
52+
* 3. Default name "TinyUSB MIDI"
53+
*/
54+
static const char *getCurrentDeviceName(void);
55+
2656
/* User-level API */
2757

2858
// Note On

0 commit comments

Comments
 (0)