Back to Home

HID++ in Logitech: storing 2 bytes in DPI register

The article analyzes the use of the DPI register in Logitech mice as 2-byte session storage via HID++ 2.0. Describes 33 properties of MX Vertical, macOS blocks, and Rust tool for reverse. Gained knowledge about protocols without full documentation.

2 bytes in mouse: HID++ reverse on Rust
Advertisement 728x90

Data Storage in Logitech Mouse Registers via HID++

The Logitech MX Vertical mouse uses flash memory to save DPI settings between devices. This opened up the possibility of turning it into a 2-byte data storage device. A Rust-based tool allowed enumerating 33 device properties via the HID++ 2.0 protocol, built on top of USB HID.

The protocol works with a property table: a stable property ID (e.g., 0x2201) is linked to a mouse model index (e.g., 0x12). Requests are formed as packets: report ID, device index, property index, function ID, and parameters (up to 3 bytes). Responses come in a similar format.

Most properties are undocumented. Promising ones were TemplateBytesNVS (0x1eb0) and PersistentRemappableAction (0x1c00), but they either didn't respond to requests or were blocked by IOHIDManager in macOS. The latter silently discards long reports without errors, requiring a workaround via IOKit.

Google AdInline article slot

Analyzing Registers and Searching for Storage

The device name register accepts writes but ignores them, returning "MX Vertical". The DPI register (u16) turned out to be functional: it accepts any values without validation. Writing 0x6869 persists when switching computers within a single session.

When the mouse is turned off/on, the value resets to default. Writing only affects the active DPI, not the default value.

Testing other registers (0x1e, 0x1f, 0x18xx) didn't yield persistent storage. The default DPI is likely stored in a closed part of the firmware or is only accessible via Logitech's proprietary tools.

Google AdInline article slot

Key features of session storage:

  • Works only while the mouse is powered on.
  • Cross-computer: moving the Unifying receiver preserves data.
  • Capacity: strictly 2 bytes (u16).
  • No validation: any value from 0 to 65535.

Lessons from HID++ Reverse Engineering

The investigation revealed differences between the feature table and feature index. Reverse lookup of IFeatureSet in Logitech is broken. Documentation covers half the properties; the rest is through experimentation.

macOS IOHIDManager silently blocks non-standard reports. Writing to PersistentRemappableAction requires notifications or low-level access.

Google AdInline article slot

Advantages of the Rust approach:

  • Full property dump without dependencies on Logitech SDK.
  • Support for all mice with Unifying receiver.
  • Batch exchange for debugging: request/response in real time.

The goal—persistent storage—was not achieved, but knowledge about protocols and OS behavior was gained.

Key Takeaways

  • HID++ 2.0 uses dynamic property indices tied to the device model.
  • The DPI register is the only accessible 2-byte session storage without validation.
  • macOS blocks long HID reports via IOHIDManager; workaround via IOKit.
  • 33 properties in the MX Vertical, half undocumented.
  • The tool's code is universal for Logitech Unifying mice.

— Editorial Team

Advertisement 728x90

Read Next