doc/help/Drivers-HID.md
The HID driver lets Serial Studio talk to USB Human Interface Device (HID) class peripherals: keyboards, mice, gamepads, joysticks, drawing tablets, custom HID firmware, and any vendor-specific device that registers itself as a HID class member.
HID is the simplest path to a device that works on every consumer OS without per-vendor driver installs. Every modern OS includes a generic HID driver, so a HID-class device shows up immediately. This makes HID a good choice for custom controllers and low-cost data-acquisition devices.
The HID class was defined by the USB-IF in 1996 to handle "input devices for humans" generically. The original goal was to standardise keyboards, mice, joysticks, and game controllers so the OS would not need a per-vendor driver for each one. Over time, "human interface" stretched to include anything with a small periodic data stream: barcode scanners, RFID readers, fingerprint sensors, and simple instruments.
A HID device is a USB device that:
The USB packet structure is the standard interrupt-transfer mechanism (see the USB driver page); the HID class layer adds the report descriptor and a small control-transfer protocol.
A report is a unit of data exchanged between host and device. There are three types:
Reports may be numbered (each begins with a 1-byte report ID, used when the device has multiple report formats) or unnumbered (a single format, no ID byte).
Rather than each HID device family inventing its own protocol, the device describes its data structure to the host through a report descriptor. A report descriptor is a sequence of small items declaring:
A trivial gamepad might declare:
Usage Page (Generic Desktop)
Usage (Joystick)
Collection (Application)
Usage (X)
Usage (Y)
Logical Minimum (-127)
Logical Maximum (127)
Report Size (8)
Report Count (2)
Input (Data, Var, Abs)
Usage Page (Button)
Usage Minimum (Button 1)
Usage Maximum (Button 8)
Logical Minimum (0)
Logical Maximum (1)
Report Size (1)
Report Count (8)
Input (Data, Var, Abs)
End Collection
That declares a joystick with two 8-bit signed axes (X and Y, range -127 to +127) and 8 single-bit buttons. A report is 3 bytes: X, Y, and a packed byte of button states.
The OS's generic HID driver reads this descriptor, identifies the device, and presents standardised events to user-space.
A usage page is a namespace defining the meaning of fields. Standard usage pages include:
0x01): X/Y/Z axes, joysticks, mice, keyboards.0x07): keyboard scan codes.0x09): generic numbered buttons.0x08): caps lock, num lock, scroll lock indicators.0x20): accelerometers, gyroscopes, environmental sensors.Vendors can also define custom usage pages in the top half of the 32-bit page space. A custom page lets the device declare arbitrary fields without colliding with anything in the standard space.
hidapi is a small cross-platform C library that provides a uniform API for talking to HID devices on Windows, macOS, and Linux. It abstracts over the OS-specific HID stacks (HIDClass on Windows, IOHIDManager on macOS, hidraw or libusb on Linux). Serial Studio's HID driver is built on hidapi.
The advantage over raw libusb is that HID devices are typically already claimed by an OS driver, and libusb cannot open them without first unbinding that driver. hidapi cooperates with the OS HID stack, so reading a HID device alongside the OS driver works without extra setup.
The HID driver wraps hidapi. The setup flow is:
Product Name (VID:PID) with VID and PID in uppercase hex. Interfaces of a composite device that share VID, PID, and serial number are merged into a single entry.0x0001 and 0x0004) reporting the opened device's usage.From that point, every input report arrives as a chunk of raw bytes in the standard FrameReader pipeline; frame detection and parsing work the same as for any other driver. Writes from the console go out through hid_write, where the first payload byte is the report ID (0x00 for devices without numbered reports).
The HID driver runs a dedicated read thread that issues blocking hid_read_timeout calls (100 ms timeout, 65-byte buffer: one report ID byte plus a 64-byte report). Each call returns at most one input report. When data arrives, the thread captures a SteadyClock::now() timestamp and posts the data to the main thread via Qt::AutoConnection, which resolves to Qt::QueuedConnection for the cross-thread hop. See Threading and Timing Guarantees.
HID data is just bytes. If the device declares a custom report format (for example 8-byte reports with two int16 axes and a uint8 packed button byte), write a frame parser to decode it as you would any other binary protocol. The HID report descriptor itself is advisory at the protocol level; the host does not require you to honour it.
For step-by-step setup, see the Protocol Setup Guides, HID section.
The TCP API and the in-app AI assistant configure this driver through the io.hid.* scope:
| Command | Parameters | Returns |
|---|---|---|
io.hid.listDevices | none | devices array and selectedIndex (index 0 is the "Select Device" placeholder) |
io.hid.setDeviceIndex | deviceIndex (integer) | Selected index and device name |
io.hid.getConfig | none | deviceIndex, usagePage, usage |
Transport details and command safety tiers are in the API Reference.
hidraw access. Add a udev rule:
/etc/udev/rules.d/99-hidraw.rules:
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", MODE="0666"
hid_send_feature_report instead of hid_write, depending on how the device declares its output endpoints. This is a hidapi-level quirk; the workaround usually has to be made on the firmware side.kEnumIntervalMs in app/src/IO/Drivers/HID.cpp and rebuild.