0x19b0 · hapticFeedback
Device haptic actuator control — capabilities, enable state and intensity, and playing a typed waveform, as used by the MX Master 4's Actions Ring.
Controls a device's haptic actuator: which waveforms it can play, whether haptics are enabled and at what intensity, and playing one waveform immediately.
OpenLogi uses it for the Actions Ring on the MX Master 4, a subtle pulse when the highlighted slot changes, and a firmer one when an action runs.
Logitech has not published this feature in the public HID++ spec. The function and payload layouts here were cross-checked against Solaar and an MX Master 4; additions must be verified against hardware rather than guessed.
Spec: reverse-engineered — x19b0 hapticFeedback. Used by: Actions Ring hover and activation feedback.
Function reference
The HapticFeedbackFeature wrapper (0x19b0) exposes:
Methods
| Function | HID++ fn | Signature | Returns |
|---|---|---|---|
get_capabilities | 0 | () | HapticCapabilities |
get_configuration | 1 | () | HapticConfiguration |
set_configuration | 2 | (enabled: bool, intensity: HapticIntensity) | () |
play | 4 | (waveform: HapticWaveform) | () |
All are async and return Result<…, Hidpp20Error>.
Types
HapticCapabilities
| Field | Type | Description |
|---|---|---|
unknown_prefix | [u8; 4] | Bytes whose meaning has not yet been verified. |
waveforms | SupportedWaveforms | Supported waveform mask. |
SupportedWaveforms
A bitflags mask; unknown bits are retained so newer firmware doesn't silently lose capability information.
| Flag | Bit | Description |
|---|---|---|
DAMP_STATE_CHANGE | 1 | A damp state-change pulse, used after activating a ring action. |
SUBTLE_COLLISION | 4 | A subtle collision pulse, used when the highlighted ring slot changes. |
HapticWaveform
| Variant | Value | Description |
|---|---|---|
DampStateChange | 1 | Confirmation pulse used when an action runs. |
SubtleCollision | 4 | Light boundary pulse used for hover transitions. |
HapticConfiguration
| Field | Type | Description |
|---|---|---|
enabled | bool | Whether firmware haptic playback is enabled. |
intensity | HapticIntensity | Current intensity percentage. |
level_count | u8 | Number of discrete levels advertised by the firmware. |
level_step | u8 | Percentage step between discrete levels. |
HapticIntensity
A validated 0–100 percentage: HapticIntensity::new(value) returns None
above HapticIntensity::MAX (100), so an out-of-range intensity can never
reach the wire.
Wire format
| Function | Request | Response |
|---|---|---|
0 get_capabilities | [0x00, 0x00, 0x00] | bytes 0–3 unverified prefix; bytes 4–7 big-endian u32 waveform mask |
1 get_configuration | [0x00, 0x00, 0x00] | byte 0 enabled (0/1); byte 1 intensity percent; byte 2 high nibble = level step, low nibble = level count |
2 set_configuration | [enabled, intensity, 0x00] | — |
4 play | [waveform, 0x00, 0x00] | — |
An enabled byte other than 0/1, or an intensity above 100, fails as
Hidpp20Error::UnsupportedResponse rather than being coerced.
Usage (Rust)
use hidpp::{
device::Device,
feature::haptic_feedback::{HapticFeedbackFeature, HapticIntensity, HapticWaveform},
};
// device: &mut Device, already created via Device::new(channel, index)
device.enumerate_features().await?;
if let Some(feat) = device.get_feature::<HapticFeedbackFeature>() {
let caps = feat.get_capabilities().await?;
println!("waveforms: {:?}", caps.waveforms);
if let Some(intensity) = HapticIntensity::new(60) {
feat.set_configuration(true, intensity).await?;
}
feat.play(HapticWaveform::SubtleCollision).await?;
}0x1990 · illumination
Device illumination control — toggle the light on or off and independently read or write brightness (Lumens) and color temperature (Kelvin).
0x1a00 · presenterControl
Presenter remote control interface — enumerate slide-navigation buttons and divert their events to host software instead of default HID reports.