USB Host Component

Overview

espp::UsbHost is the host-side counterpart to espp::UsbDevice. It drives the ESP32-S2 / -S3 / -P4 USB-OTG peripheral as a USB host, enumerates attached devices, and exposes the HID class devices it finds — mice, keyboards, gamepads, and vendor-specific HID devices (for example another ESP running espp::UsbDevice as a HID device, such as an espp::WdiUsbPeripheral).

It is a thin, idiomatic wrapper over the ESP-IDF USB Host library (usb) and the usb_host_hid class driver: it owns the whole host lifecycle — installing the host library and HID driver, running their event tasks, opening interfaces, and teardown — and marshals the driver’s C callbacks into per-device std::function objects. Like the rest of espp it does not throw and reports failures via std::error_code.

Report directions are named from the connected device’s point of view, as in the USB HID spec: an Input report is device→host (delivered to a HidDevice input callback), an Output report is host→device (sent with HidDevice::send_output_report()). This mirrors espp::UsbDevice exactly, so the two ends of a link (for example the device and host roles of the wdi component) line up.

Features

  • Installs / uninstalls the USB Host library and the HID class driver and runs their event-handling tasks.

  • Device connect / disconnect callbacks, with an optional filter predicate so only the devices you care about are opened (by VID/PID, interface, etc.).

  • Per-device Input report callback (device→host) delivering the raw report bytes (report id in byte 0 for report-ID’d descriptors).

  • Send Output reports (host→device) and issue the HID class control requests (Get/Set Report, Get/Set Idle, Set Protocol).

  • Read a connected device’s HID report descriptor.

  • No exceptions; initialize() reports failures via std::error_code.

Basic Usage

espp::UsbHost host({
    .on_device_connected =
        [](const std::shared_ptr<espp::UsbHost::HidDevice> &dev) {
          auto info = dev->info();
          printf("connected: %s %s %04x:%04x\n", info.manufacturer.c_str(),
                 info.product.c_str(), info.vid, info.pid);
          dev->set_input_callback([](std::span<const uint8_t> report) {
            // handle a device->host Input report (report[0] is the report id)
          });
        },
    .on_device_disconnected = [](const auto &) { /* ... */ },
    // optional: only open the devices you want
    // .should_open = [](const auto &info, const auto &) { return info.vid == 0x1209; },
});

std::error_code ec;
if (!host.initialize(ec)) { /* handle ec */ }

// later, send an Output report (host->device) -- devices() may be empty, so
// guard it (or keep the shared_ptr handed to on_device_connected and use that):
std::array<uint8_t, 4> payload{/* ... */};
if (auto devs = host.devices(); !devs.empty())
  devs.front()->send_output_report(/*report_id*/ 0x02, payload, ec);

Requirements and caveats

  • USB-OTG host mode is only available on the ESP32-S2, -S3 and -P4.

  • Only one espp::UsbHost may exist at a time (the USB Host library and HID class driver are global singletons). It cannot coexist with espp::UsbDevice (they both claim the USB-OTG peripheral).

  • The board must be able to source VBUS to the attached device — a board with a USB-A host port / VBUS switch, or a self-powered hub. UsbHost does not manage board power.

  • On the ESP32-S3 the USB-Serial-JTAG shares the USB-OTG PHY, so when the host role is active the console must run on UART0 (see the example’s sdkconfig.defaults).

  • Requires ESP-IDF ≥ 5.4 (root-port power control in IDF’s built-in USB Host library). On ESP-IDF ≥ 6.0 the USB Host library is the registry usb component instead (≥ 1.3.0, whose peripheral_map is what Config::port needs: ESPP_USB_HOST_HAS_PORT_SELECT), and usb_host_hid declares that dependency only through the component manager, so build the examples with the manager on (the default) rather than the manager-off flow used by the device-side USB examples. On 5.x Config::port must stay at its default.

Threading model

The HID class driver delivers its events on its own background task, and that same task is what completes the driver’s synchronous control transfers (Set/Get Report, Set Protocol, …). A control transfer issued from that task can therefore never complete. espp::UsbHost handles this the way the ESP-IDF HID host example does, but internally: the driver task only enqueues events (copying each Input report out of the driver’s buffer, which must happen inside the callback), and a dedicated dispatch task owned by UsbHost opens/starts/closes devices and invokes every user callback.

  • It is safe to call send_output_report() and the other HidDevice methods from inside on_device_connected / the input callback (e.g. to answer a request/response HID protocol).

  • Events for a device are delivered in order (connected → inputs → disconnected), and the connect callback runs before the device is started, so an input callback installed there sees the very first report.

  • HidDevice methods may also be called from any application task; each device serializes its driver calls internally.

  • Keep callbacks reasonably short: one that blocks delays every later event. The event queue is bounded (Config::max_queued_events); when the consumer falls behind, Input reports are dropped (logged) rather than blocking the USB stack.

  • info() / params() / report_descriptor() are snapshots taken at connect time and remain valid after the device disconnects.

Roadmap

Only the HID class driver is wired up today (it covers mice, keyboards, gamepads and vendor HID devices, and is what the wdi host role needs). The component is structured so other class drivers (CDC-ACM, MSC) can be layered in later without changing the host-lifecycle model — the same way espp::UsbDevice composes CDC / Vendor / HID functions on the device side.

API Reference

Header File

Macros

ESP_IDF_VERSION_VAL(major, minor, patch)
ESP_IDF_VERSION
ESPP_USB_HOST_HAS_PORT_SELECT

Whether UsbHost::Config::port can select the USB-OTG peripheral: needs a target with more than one and usb_host_config_t::peripheral_map, which the esp-usb `usb` component gained in 1.3.0 (the version this component pulls in on ESP-IDF >= 6.0). IDF’s built-in USB Host library (ESP-IDF 5.x) has no peripheral selection: there, port must stay at its default.

Classes

class UsbHost : public espp::BaseComponent

Native-USB **host** built on the ESP-IDF USB Host library (`usb`) and the `usb_host_hid` class driver, for the ESP32-S2 / -S3 / -P4 USB-OTG peripheral acting as a host.

`esppUsbHost` is the counterpart to `espp::UsbDevice`: instead of enumerating *as* a USB device, it drives the bus as a **host**, enumerates attached devices, and exposes the **HID** class devices it finds (mice, keyboards, gamepads, and vendor-specific HID devices such as an `espp::WdiUsbPeripheral`). It owns the whole host-side lifecycle:

  • installs the USB Host library and runs its event-handling task,

  • installs the HID class driver (with its own background task),

  • on device attach, opens each HID interface and (optionally) starts receiving its **Input** reports, delivering them to a per-device callback,

  • lets the application send **Output** reports (and issue the HID class Get/Set Report / Idle / Protocol control requests) back to a device,

  • and cleans everything up on teardown.

Report directions are named from the connected **device’s** point of view (as in the USB HID spec): an *Input* report is device→host (delivered to `HidDevice`’s input callback), an *Output* report is host→device (sent with `HidDevice::send_output_report()`). This is deliberately symmetric with `espp::UsbDevice`’s HID function, so the two sides of a link (e.g. the two roles of the `wdi` component) mirror each other.

**Threading model.** The HID class driver delivers its events on its own background task, and that same task is the one that completes the driver’s synchronous control transfers (Set/Get Report, Set Protocol, …). A control transfer issued *from* that task can therefore never complete. `UsbHost` handles this the way the ESP-IDF HID host example does: the driver task only *enqueues* events (copying each Input report out of the driver’s buffer, which must happen inside the callback), and a dedicated **dispatch task** owned by `UsbHost` opens/starts/closes devices and invokes every user callback. So it is safe to call `HidDevice::send_output_report()` (and the other device methods) from within the callbacks, and callbacks never stall the USB stack. Events for a device are delivered in order (connected → inputs → disconnected). Device methods may also be called from any application task; each device serializes its driver calls internally.

The class is idiomatic espp: it does not throw, reports failures via `std::error_code`, and marshals the USB-host driver’s C callbacks into per-device `std::function`s.

UsbHost (generic HID host) Example

extern "C" void app_main(void) {
  espp::Logger logger({.tag = "USB Host", .level = espp::Logger::Verbosity::INFO});
  logger.info("Starting USB HID host example");

  espp::UsbHost host({
      .on_device_connected =
          [&](const std::shared_ptr<espp::UsbHost::HidDevice> &device) {
            auto info = device->info();
            auto params = device->params();
            logger.info("connected: '{}' '{}' VID={:#06x} PID={:#06x} iface={} proto={}",
                        info.manufacturer, info.product, info.vid, info.pid,
                        params.interface_number, params.protocol);
            auto desc = device->report_descriptor();
            logger.info("  report descriptor: {} bytes", desc.size());

            // Log every Input report this device sends (device -> host).
            device->set_input_callback([&logger](std::span<const uint8_t> data) {
              logger.info("input report ({} bytes): {::#04x}", data.size(), data);
            });
          },
      .on_device_disconnected =
          [&](const std::shared_ptr<espp::UsbHost::HidDevice> &device) {
            logger.info("disconnected: PID={:#06x}", device->info().pid);
          },
      // .should_open = [](const auto &info, const auto &) { return info.vid == 0x1209; },
      .log_level = espp::Logger::Verbosity::INFO,
  });

  std::error_code ec;
  if (!host.initialize(ec)) {
    logger.error("Failed to initialize USB host: {}", ec.message());
    return;
  }
  logger.info("USB host ready; plug in a USB HID device.");

  while (true) {
    logger.debug("connected HID devices: {}", host.devices().size());
    std::this_thread::sleep_for(2s);
  }
}

Note

Only one `esppUsbHost` may exist at a time: the USB Host library and the HID class driver are global singletons. USB-OTG **host** mode is only available on the ESP32-S2, ESP32-S3 and ESP32-P4, and the board must be able to source VBUS to the attached device (a self-powered hub or a board with a VBUS switch); the host does not manage board power.

Note

Callbacks run on the dispatch task. Keep them reasonably short: a callback that blocks delays every later event (and `deinitialize()`).

Public Types

using device_callback_fn = std::function<void(const std::shared_ptr<HidDevice> &device)>

Callback invoked when a HID device is connected / disconnected.

using open_filter_fn = std::function<bool(const HidDevice::Info &info, const HidDevice::Params &params)>

Predicate deciding whether to open a newly attached HID interface. Return false to ignore it (no callbacks, not listed in devices()).

Public Functions

explicit UsbHost(const Config &config)

Construct a USB host. Call initialize() to actually install the stack.

~UsbHost()

Uninstall the stack (if still installed).

bool initialize(std::error_code &ec)

Install the USB Host library + HID class driver and start the tasks.

Parameters:

ec – Set on failure.

Returns:

true on success.

bool deinitialize(std::error_code &ec)

Uninstall the HID class driver + USB Host library and stop the tasks. Attached devices are closed (their disconnect callbacks fire, on the calling task) and the root port is powered down so the driver can release them. Must not be called from within a `UsbHost` callback.

Parameters:

ec – Set on failure. If any step of the teardown fails (a device the driver cannot release, or the library refusing to uninstall) the host stays initialized (is_initialized() remains true) and false is returned, rather than tearing down under a live driver. In that state event delivery has already stopped, every device has been retired, and the root port is left powered off (powering it back up would only make the driver re-track the device that a retry needs gone), so the host is not usable: the only valid next steps are to call deinitialize() again (which waits for the driver again) or to destroy the object, which aborts if teardown still fails (see the destructor). The HID event pump is deliberately left running in that state &#8212; the driver’s uninstall only completes while something pumps its events, so stopping it would make every retry fail &#8212; and because the destructor aborts instead of freeing, the driver never holds a pointer to a destroyed host. Bounded: waiting for the driver to release the devices and retrying its uninstall share one budget of about two seconds (tens of milliseconds in the normal case, since the driver signals the release as it happens).

Returns:

true on success.

inline bool is_initialized() const

Whether the host stack is installed.

std::vector<std::shared_ptr<HidDevice>> devices() const

Snapshot of the currently connected (opened) HID devices.

size_t num_usb_devices() const

Number of USB devices currently enumerated on the root port(s), HID or not (from the USB Host Library). A device that shows up here but not in devices() enumerated but was not opened as HID (no HID interface, or rejected by the should_open filter).

Returns:

The device count, or 0 when not initialized.

bool print_usb_devices()

Print the device and configuration descriptors of every enumerated USB device to stdout (the host library’s usb_print_* helpers), for diagnosing a device that enumerates but is not opened as HID: it shows each interface’s class and endpoints. Registers a short-lived host-library client for the duration of the call. The header line gives both the library’s device count (which includes devices still being enumerated) and the number of fully enumerated devices listed, so a device stuck in enumeration shows as the difference.

Returns:

true if the devices could be listed.

inline const std::string &get_name() const

Get the name of the component

Note

This is the tag of the logger

Returns:

A const reference to the name of the component

inline void set_log_tag(const std::string_view &tag)

Set the tag for the logger

Parameters:

tag – The tag to use for the logger

inline espp::Logger::Verbosity get_log_level() const

Get the log level for the logger

Returns:

The verbosity level of the logger

inline void set_log_level(espp::Logger::Verbosity level)

Set the log level for the logger

Parameters:

level – The verbosity level to use for the logger

inline void set_log_verbosity(espp::Logger::Verbosity level)

Set the log verbosity for the logger

See also

set_log_level

Note

This is a convenience method that calls set_log_level

Parameters:

level – The verbosity level to use for the logger

inline espp::Logger::Verbosity get_log_verbosity() const

Get the log verbosity for the logger

See also

get_log_level

Note

This is a convenience method that calls get_log_level

Returns:

The verbosity level of the logger

inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)

Set the rate limit for the logger

Note

Only calls to the logger that have _rate_limit suffix will be rate limited

Parameters:

rate_limit – The rate limit to use for the logger

struct Config

Configuration for the USB host.

Public Members

device_callback_fn on_device_connected = {nullptr}

a HID device attached and opened

device_callback_fn on_device_disconnected = {nullptr}

a HID device detached

open_filter_fn should_open = {nullptr}

optional filter (default: open every HID interface)

bool auto_start = {true}

start receiving Input reports as soon as a device opens

int port = {-1}

USB-OTG peripheral (root port) to host on, on targets with more than one: -1 = the USB Host Library’s default (peripheral 0), n = peripheral n. On the ESP32-P4, controller 0 is the high-speed OTG 2.0 on the UTMI PHY and controller 1 the full-speed OTG 1.1 on its own FSLS PHY (GPIO 26/27 by default); which connector, if any, each reaches is the board’s business (the M5Stack Tab5 routes controller 0 to its USB-A jack and neither to its USB-C port, which carries the USB-Serial-JTAG PHY). Only available with ESPP_USB_HOST_HAS_PORT_SELECT (esp-usb `usb` >= 1.3.0, i.e. ESP-IDF >= 6.0, on a multi-controller target); elsewhere initialize() rejects any value but -1.

std::chrono::milliseconds root_port_power_on_delay = {0}

Wait this long between installing the host library (which brings up the USB PHY) and powering the root port. A device attached at power-up is enumerated as soon as the port powers on; this gives a board whose supply is still settling after a cold boot a margin before that first enumeration. 0 = power the port at once.

std::function<void(bool on)> vbus_control = {nullptr}

Board-level VBUS control for the host jack, for boards where an IO expander or load switch (not the USB controller) switches the jack’s 5 V, so the library’s own root-port power control does not reach the device. Called with true once the host is listening (after the root port powers on) and false at deinitialize(). Turn the jack off yourself before initialize() if a device attached at boot should see VBUS only once the host is ready.

size_t task_priority = {5}

priority of the internal tasks

int task_core_id = {-1}

core for the internal tasks (-1 = no affinity)

size_t lib_task_stack_size = {4096}

stack for the USB-host-library event task

size_t hid_task_stack_size = {4096}

stack for the HID driver’s event task (it only enqueues)

size_t dispatch_task_stack_size = {6 * 1024}

Stack for the dispatch task that runs the user callbacks (size it for what your callbacks do &#8212; logging with fmt, protocol work, …).

size_t max_input_report_size = {64}

Per-device Input-report copy size. A report larger than this is truncated (the driver copies at most this many bytes); raise it if your device sends larger reports. 64 covers full-speed HID.

size_t max_queued_events = {32}

Bound on queued-but-undispatched events. When the queue is full: a new Input report is dropped; a lifecycle event first evicts the oldest queued Input report, and if there is none a *new-device* event is dropped (that device simply stays unopened while the consumer is overloaded) while a *disconnect* is always kept (it is needed to release the device, and can only follow a device that was opened). The queue length is therefore never more than max_queued_events + the number of currently open devices, and the USB stack is never blocked. Drops are counted and logged at a rate-limited cadence.

bool full_speed_only = {false}

Run the root port in full/low-speed-only mode. “Full speed” here names the USB speed *class* that includes low speed (the DWC bit is FSLSSupp), so a low-speed device still enumerates. Only meaningful on targets whose host controller is high-speed capable, i.e. the ESP32-P4. ESP-IDF’s hub support has no transaction translator, so full-speed devices (every HID keyboard / mouse / gamepad) behind a *high-speed* hub cannot be reached (“TT is not supported”). With this set the hub enumerates at full speed and its devices are reached directly; HID never needs more bandwidth than that. No effect on targets with a full-speed-only controller (ESP32-S2 / -S3).

std::chrono::milliseconds full_speed_reassert_interval = {100}

How often the library event task wakes to re-assert full_speed_only. The bit is cleared by a root port recovery (after an unplug / transfer error) and no event reports that, so it has to be re-applied on a timer. Shorter = the port spends less time in high-speed-capable mode after a recovery; longer = fewer wakeups. Each wake is a single task switch plus one register write. Only used when full_speed_only is set on a high-speed capable controller; ignored otherwise (the task then blocks indefinitely and wakes only on real events). Rounded *up* to at least one RTOS tick (the default tick is 10ms), so a shorter interval &#8212; 0 or a negative one included &#8212; wakes once per tick rather than turning the event wait into a busy loop; initialize() warns when the configured value is not positive.

uint32_t task_stack_alloc_caps = {0}

ESP only: heap capabilities for the internal tasks’ stacks (see espp::Task::BaseConfig::stack_alloc_caps); 0 = internal RAM. MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT puts the three stacks (~14 KB) in PSRAM, worth it where internal RAM is scarce (ESP32-P4).

class HidDevice

A HID interface on a device connected to the host.

Created by `UsbHost` when a HID device is attached; handed to the application (as a `std::shared_ptr`) through the connect / disconnect callbacks and `UsbHostdevices()`. Owns nothing itself &#8212; the underlying driver handle is owned by `UsbHost` &#8212; and becomes inert once the device is disconnected (methods then fail with `std::errc::no_such_device`; the identity accessors keep returning the values captured at connect time).

Public Types

using input_callback_fn = std::function<void(std::span<const uint8_t> data)>

Callback invoked with a raw HID Input report from the device.

Param data:

The report bytes. For a device whose report descriptor uses report IDs, byte 0 is the report ID (matching how `espp::UsbDevice`’s HID receive callback delivers OUT reports).

Public Functions

inline const Info &info() const

The identity of the connected device (captured at connect time, so it stays valid after a disconnect).

inline const Params &params() const

The parameters of this HID interface (captured at connect time).

inline const std::vector<uint8_t> &report_descriptor() const

The device’s HID report descriptor (captured at connect time; a copy owned by this object, not a view into driver memory).

void set_input_callback(input_callback_fn cb)

Install the callback invoked with each Input report. Install it from the connect callback: `UsbHost` invokes that *before* it starts the device, so no report is missed.

bool start(std::error_code &ec)

Start receiving Input reports (called automatically on open when `Config::auto_start` is set).

bool stop(std::error_code &ec)

Stop receiving Input reports.

bool send_output_report(uint8_t report_id, std::span<const uint8_t> data, std::error_code &ec)

Send a HID **Output** report to the device (host→device).

Parameters:
  • report_id – The report ID (0 if the descriptor is not report-ID’d).

  • data – The report payload (without the report-ID byte).

  • ec – Set on failure.

Returns:

true on success.

bool get_report(hid_report_type_t report_type, uint8_t report_id, std::span<uint8_t> buffer, size_t &out_length, std::error_code &ec)

Request a report from the device (HID class Get_Report).

Parameters:
  • report_type – The HID report type (HID_REPORT_TYPE_INPUT / _OUTPUT / _FEATURE).

  • report_id – The report ID.

  • buffer – Buffer that receives the report.

  • out_length – Number of bytes written into buffer.

  • ec – Set on failure.

bool set_idle(uint8_t duration, uint8_t report_id, std::error_code &ec)

Set the device’s idle rate (HID class Set_Idle).

bool set_protocol(hid_report_protocol_t protocol, std::error_code &ec)

Set the device’s HID protocol (boot vs report; HID class Set_Protocol).

inline bool is_connected() const

Whether the device’s interface is still usable, i.e. whether a driver call made through this object can still reach it. It goes false as soon as the interface is closed on disconnect, which happens on the driver task and therefore *before* any input reports already queued for this device are delivered.

inline hid_host_device_handle_t handle() const

The underlying driver handle (for advanced use; only valid while is_connected()).

struct Info

Device descriptor identity (VID/PID + string descriptors).

Public Members

uint16_t vid = {0}

idVendor

uint16_t pid = {0}

idProduct

std::string manufacturer = {}

iManufacturer string (UTF-8, converted from the device’s UTF-16)

std::string product = {}

iProduct string (UTF-8, converted from the device’s UTF-16)

std::string serial_number = {}

iSerialNumber string (UTF-8, converted from the device’s UTF-16)

struct Params

HID interface parameters.

Public Members

uint8_t address = {0}

USB device address.

uint8_t interface_number = {0}

bInterfaceNumber of this HID interface

uint8_t sub_class = {0}

bInterfaceSubClass (1 = boot interface)

uint8_t protocol = {0}

bInterfaceProtocol (1 = keyboard, 2 = mouse, 0 = none)

class HidDevice

A HID interface on a device connected to the host.

Created by `UsbHost` when a HID device is attached; handed to the application (as a `std::shared_ptr`) through the connect / disconnect callbacks and `UsbHostdevices()`. Owns nothing itself &#8212; the underlying driver handle is owned by `UsbHost` &#8212; and becomes inert once the device is disconnected (methods then fail with `std::errc::no_such_device`; the identity accessors keep returning the values captured at connect time).

Public Types

using input_callback_fn = std::function<void(std::span<const uint8_t> data)>

Callback invoked with a raw HID Input report from the device.

Param data:

The report bytes. For a device whose report descriptor uses report IDs, byte 0 is the report ID (matching how `espp::UsbDevice`’s HID receive callback delivers OUT reports).

Public Functions

inline const Info &info() const

The identity of the connected device (captured at connect time, so it stays valid after a disconnect).

inline const Params &params() const

The parameters of this HID interface (captured at connect time).

inline const std::vector<uint8_t> &report_descriptor() const

The device’s HID report descriptor (captured at connect time; a copy owned by this object, not a view into driver memory).

void set_input_callback(input_callback_fn cb)

Install the callback invoked with each Input report. Install it from the connect callback: `UsbHost` invokes that *before* it starts the device, so no report is missed.

bool start(std::error_code &ec)

Start receiving Input reports (called automatically on open when `Config::auto_start` is set).

bool stop(std::error_code &ec)

Stop receiving Input reports.

bool send_output_report(uint8_t report_id, std::span<const uint8_t> data, std::error_code &ec)

Send a HID **Output** report to the device (host→device).

Parameters:
  • report_id – The report ID (0 if the descriptor is not report-ID’d).

  • data – The report payload (without the report-ID byte).

  • ec – Set on failure.

Returns:

true on success.

bool get_report(hid_report_type_t report_type, uint8_t report_id, std::span<uint8_t> buffer, size_t &out_length, std::error_code &ec)

Request a report from the device (HID class Get_Report).

Parameters:
  • report_type – The HID report type (HID_REPORT_TYPE_INPUT / _OUTPUT / _FEATURE).

  • report_id – The report ID.

  • buffer – Buffer that receives the report.

  • out_length – Number of bytes written into buffer.

  • ec – Set on failure.

bool set_idle(uint8_t duration, uint8_t report_id, std::error_code &ec)

Set the device’s idle rate (HID class Set_Idle).

bool set_protocol(hid_report_protocol_t protocol, std::error_code &ec)

Set the device’s HID protocol (boot vs report; HID class Set_Protocol).

inline bool is_connected() const

Whether the device’s interface is still usable, i.e. whether a driver call made through this object can still reach it. It goes false as soon as the interface is closed on disconnect, which happens on the driver task and therefore *before* any input reports already queued for this device are delivered.

inline hid_host_device_handle_t handle() const

The underlying driver handle (for advanced use; only valid while is_connected()).

struct Info

Device descriptor identity (VID/PID + string descriptors).

Public Members

uint16_t vid = {0}

idVendor

uint16_t pid = {0}

idProduct

std::string manufacturer = {}

iManufacturer string (UTF-8, converted from the device’s UTF-16)

std::string product = {}

iProduct string (UTF-8, converted from the device’s UTF-16)

std::string serial_number = {}

iSerialNumber string (UTF-8, converted from the device’s UTF-16)

struct Params

HID interface parameters.

Public Members

uint8_t address = {0}

USB device address.

uint8_t interface_number = {0}

bInterfaceNumber of this HID interface

uint8_t sub_class = {0}

bInterfaceSubClass (1 = boot interface)

uint8_t protocol = {0}

bInterfaceProtocol (1 = keyboard, 2 = mouse, 0 = none)