Firmware Integration
Guide to integrating generated HID descriptors with microcontroller firmware.
Overview
This guide covers using the generated C header files in your embedded firmware.
Supported Platforms
The generated code is platform-independent C and works with:
Arduino (Leonardo, Micro, Due, etc.)
ESP32
STM32
Any microcontroller with USB HID support
Using the Generated Header
Include the Header
#include "my_package/hid_descriptor.h"
USB HID Descriptor
Use the generated descriptor for USB enumeration:
// In your USB HID initialization
const uint8_t* get_hid_descriptor(uint16_t* length) {
*length = HID_REPORT_DESCRIPTOR_SIZE;
return hid_report_descriptor;
}
Report Structures
Use the type-safe structures:
// Input report (sensor data to host)
HIDInputReport input_report = {
.report_id = HID_INPUT_REPORT_ID,
.position_x = 1.5f,
.position_y = 2.3f,
.velocity = 150
};
// Send to host
usb_hid_send((uint8_t*)&input_report, sizeof(input_report));
Receiving Output Reports
// Receive from host
uint8_t buffer[64];
int len = usb_hid_receive(buffer, sizeof(buffer));
if (len > 0 && buffer[0] == HID_OUTPUT_REPORT_ID) {
HIDOutputReport* output = (HIDOutputReport*)buffer;
// Process commands
set_led_brightness(output->led_brightness);
set_motor_speed(output->motor_speed);
}
Platform-Specific Examples
Arduino
#include "HID.h"
#include "my_package/hid_descriptor.h"
static const uint8_t _hidReportDescriptor[] PROGMEM = {
// Copy from generated hid_report_descriptor
};
void setup() {
static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
HID().AppendDescriptor(&node);
}
void loop() {
HIDInputReport report = { /* ... */ };
HID().SendReport(HID_INPUT_REPORT_ID, &report, sizeof(report));
delay(10);
}
ESP32
#include "my_package/hid_descriptor.h"
#include "esp_hid_device.h"
// Use generated descriptor
const uint8_t* desc = hid_report_descriptor;
uint16_t desc_len = HID_REPORT_DESCRIPTOR_SIZE;
// Initialize ESP32 HID
esp_hid_device_config_t config = {
.vendor_id = 0xCAFE,
.product_id = 0x4000,
.report_maps = &desc,
.report_maps_len = desc_len
};
esp_hid_device_init(&config);
Important Considerations
Structure Packing
Always use __attribute__((packed)) (already in generated code):
typedef struct __attribute__((packed)) {
uint8_t report_id;
float value;
} HIDInputReport;
Byte Order
Use little-endian (standard for USB HID). The generated structures handle this automatically on little-endian platforms (ARM, x86).
Report Size
Keep reports under 64 bytes for maximum compatibility:
Full-speed USB: 64 bytes max
Low-speed USB: 8 bytes max
Timing
Match the update rate in your firmware to the update_rate in the schema.
Debugging
Verify Descriptor
Use Linux usbhid-dump to verify your device’s descriptor:
sudo usbhid-dump -e descriptor -m VID:PID
Compare with generated descriptor.
Test with inspect_device
ros2 run hid_tools inspect_device --vid 0xVVVV --pid 0xPPPP
This shows raw reports your device sends.
Example Projects
See examples/ directory for complete firmware examples.