HID++ Reference
Logitech's vendor protocol for mice, keyboards, and receivers, as OpenLogi speaks it — message format, errors, feature discovery, and how to read the feature pages.
HID++ is Logitech's vendor protocol for configuring mice, keyboards, lights, and
receivers. It runs over USB HID and Bluetooth HID. OpenLogi speaks it directly
through openlogi-hidpp, its hard fork of the
hidpp Rust crate. The library name stays
hidpp, so code examples on these pages write use hidpp::....
Two generations
- HID++ 1.0 uses a fixed set of numbered registers. Unifying and Bolt receivers still use it for pairing and device enumeration.
- HID++ 2.0 uses a discoverable set of features. A 16-bit ID names each
feature, written
0xZZZZ, for example0x2201. Modern devices use this generation for every setting.
Message format
Every HID++ message is a short or a long HID report. OpenLogi uses only these two report types for HID++.
| Report | Report ID | Length | Parameter bytes |
|---|---|---|---|
| Short | 0x10 | 7 bytes | 3 |
| Long | 0x11 | 20 bytes | 16 |
The first four bytes have the same meaning in both reports:
| Byte | HID++ 2.0 | HID++ 1.0 |
|---|---|---|
| 0 | Report ID (0x10 or 0x11) | Report ID |
| 1 | Device index | Device index |
| 2 | Feature index | Sub-ID (0x80–0x83 for register access) |
| 3 | Function ID (high nibble) and software ID (low nibble) | Register address |
| 4… | Parameters | Register data |
The device index selects the target. 0xFF addresses a receiver itself, or
the features of a directly connected device (Bluetooth or USB cable). A device
paired to a receiver is addressed by its slot number, starting at 1. See
Receivers.
The feature index is a per-device runtime number, not the feature ID. A host
resolves it once through 0x0000 root. The
function ID selects one function of that feature. The feature pages write it
as fn 0, fn 1, and so on.
Software ID
The software ID lets a host match a reply to its request. Requests carry
1–15. A device sends 0 in its own notifications, so a report with software
ID 0 is an event, not a reply. OpenLogi assigns the ID per channel: a fixed ID,
a rotating ID, or an ID leased for the life of the channel. The lease keeps two
concurrent opens of the same HID node from sharing an ID.
A reply echoes bytes 1–3 of its request. OpenLogi matches a reply to the oldest pending request with the same three bytes. It never has two requests with the same three bytes in flight at once, because a wireless receiver can deliver their replies out of order.
Register access (HID++ 1.0)
| Sub-ID | Request |
|---|---|
0x80 | Set a short register (3 data bytes) |
0x81 | Get a short register |
0x82 | Set a long register (16 data bytes) |
0x83 | Get a long register |
0x8F | Error reply |
Errors
A HID++ 2.0 error reply has feature index 0xFF. Byte 3 repeats the feature
index of the failed request, byte 4 repeats its function and software ID byte,
and byte 5 holds the error code. OpenLogi returns the code as
Hidpp20Error::Feature(ErrorType). An unknown code becomes
Hidpp20Error::UnsupportedResponse.
| Code | ErrorType | Meaning |
|---|---|---|
0 | NoError | No error |
1 | Unknown | Unknown error |
2 | InvalidArgument | Invalid argument |
3 | OutOfRange | Argument out of range |
4 | HwError | Hardware error |
5 | LogitechInternal | Firmware-internal error |
6 | InvalidFeatureIndex | No feature at this index |
7 | InvalidFunctionId | The feature has no such function |
8 | Busy | The device is busy |
9 | Unsupported | The operation is not supported |
A HID++ 1.0 error reply has sub-ID 0x8F. Bytes 3 and 4 repeat the request's
sub-ID and register address, and byte 5 holds the error code. OpenLogi returns it
as Hidpp10Error::RegisterAccess(ErrorType).
| Code | ErrorType (1.0) | Code | ErrorType (1.0) |
|---|---|---|---|
0x00 | Success | 0x07 | Busy |
0x01 | InvalidSubId | 0x08 | UnknownDevice |
0x02 | InvalidAddress | 0x09 | ResourceError |
0x03 | InvalidValue | 0x0A | RequestUnavailable |
0x04 | ConnectFail | 0x0B | InvalidParamValue |
0x05 | TooManyDevices | 0x0C | WrongPinCode |
0x06 | AlreadyExists |
Feature discovery
A 2.0 device exposes its capabilities through two root features:
0x0000root resolves a feature ID to its runtime feature index.0x0001featureSet enumerates every feature the device implements.
OpenLogi enumerates the feature set when it probes a device. It then queries the features it supports: device information, battery, DPI, SmartShift, and others. The feature index lists every catalogued feature and its status in OpenLogi.
Identity
Two things name a device on the wire. A receiver has a USB vendor and product
ID; see Receivers. A device reports a model ID through
0x0003 deviceInformation. The
model ID index lists every known model ID.
Reading the feature pages
Each implemented feature has one page with the same sections:
- Spec line: the sources for the layout and the OpenLogi pages that use the feature.
- Function reference: the methods, types, and events of the
openlogi-hidppwrapper at OpenLogi v0.8.15. - Wire format: the request and reply bytes of every function and event.
Multi-byte fields name their byte order (
BEorLE). - How OpenLogi uses it: the device-layer behavior, such as read-modify-write and read-back checks.
- Open questions: points where the sources disagree or no hardware capture exists yet.
No public Logitech specification covers some features or fields. For those, the pages use static analysis of Logitech's own software, done for interoperability. A Notes cell then carries a source tag:
| Tag | Source |
|---|---|
Options+ 2.8 | Static analysis of Logi Options+ 2.8. It shows what that software sends and reads, not what the firmware does. |
G HUB | Static analysis of Logitech G HUB. Same limit as above. |
Solaar | The Solaar open-source implementation. |
A fact without a tag comes from a Logitech HID++ document or from OpenLogi's own tested code.
Attribution & copyright
This HID++ reference is an original summary written for the OpenLogi
project. It describes Logitech's HID++ 1.0 and 2.0 protocol from publicly
available documentation, the hidpp
implementation, Solaar, and static analysis of Logitech software for
interoperability. It reproduces no Logitech document or code. “Logitech”,
“Unifying”, “Logi Bolt”, “Options+”, and “G HUB” are trademarks of Logitech.
OpenLogi is an independent project and is not affiliated with, authorized, or
endorsed by Logitech. The material is provided “as is”, without warranty of
any kind.