0x2111 · smartShiftEnhanced
Enhanced SmartShift — read or write the wheel mode, auto-disengage speed threshold, and tunable ratchet torque on current MX-line mice.
The SmartShift Enhanced wheel feature — the variant on the MX Master 3 / 3S /
4 and most current MX-line mice, and the one OpenLogi's SmartShift panel and the
ToggleSmartShift action actually drive. getStatus (function 1) reads the wheel
mode, the auto-disengage threshold, and the tunable-torque value; setStatus
(function 2) writes them back. The device persists all three in its own
non-volatile memory.
- wheelMode —
1free-spin (frictionless),2ratchet (clicky). - autoDisengage —
0x01–0xFE, the wheel speed (in 0.25 turn/s steps) past which a ratchet-mode wheel releases into free-spin — the SmartShift threshold.0xFFkeeps the ratchet engaged permanently. - tunable torque — ratchet resistance as a percent of the device maximum, or
0when unsupported; read and re-sent unchanged so adjusting the mode or threshold doesn't disturb it.
The original 0x2110 smartShift uses a different function table — the vendored
hidpp library implements that one — but OpenLogi drives the Enhanced 0x2111
variant.
Spec: Logitech HID++ 2.0 — x2111 smartShift Enhanced. Used by: SmartShift panel,
ToggleSmartShift.
Function reference
The SmartShiftEnhancedFeature wrapper (0x2111) exposes:
Methods
| Function | HID++ fn | Signature | Returns |
|---|---|---|---|
get_capabilities | 0 | () | SmartShiftEnhancedInfo |
get_ratchet_control_mode | 1 | () | SmartShiftEnhancedStatus |
set_ratchet_control_mode | 2 | (change: SmartShiftEnhancedStatusChange) | SmartShiftEnhancedStatus |
All methods are async and return Result<…, Hidpp20Error>.
Types
SmartShiftEnhancedInfo
Capability and default values for enhanced SmartShift.
| Field | Type | Description |
|---|---|---|
capabilities | SmartShiftEnhancedCapabilities | Supported capabilities. |
auto_disengage_default | u8 | Default automatic disengage threshold. |
default_tunable_torque | u8 | Default tunable torque, as a percentage of maximum force. |
max_force | u8 | Maximum force in gram-force units. |
SmartShiftEnhancedStatus
Current enhanced SmartShift status.
| Field | Type | Description |
|---|---|---|
wheel_mode | WheelMode | Current requested wheel mode. |
auto_disengage | u8 | Automatic disengage threshold. |
current_tunable_torque | u8 | Current tunable torque, as a percentage of maximum force. |
SmartShiftEnhancedStatusChange
Enhanced SmartShift status update. None fields are encoded as 0 ("do not change") on the wire.
| Field | Type | Description |
|---|---|---|
wheel_mode | Option<WheelMode> | Wheel mode to apply, or None to leave unchanged. |
auto_disengage | Option<NonZeroU8> | Automatic disengage threshold, or None to leave unchanged. HID++ encodes 0 as "do not change", so writable values must be non-zero. |
tunable_torque | Option<NonZeroU8> | Tunable torque, or None to leave unchanged. HID++ encodes 0 as "do not change", so writable values must be non-zero. |
SmartShiftEnhancedCapabilities
Capabilities reported by SmartShiftWheelEnhanced.
| Flag | Bit/Value | Description |
|---|---|---|
TUNABLE_TORQUE | bit 0 | The device supports tunable ratchet torque. |
WheelMode
Represents the ratchet mode of the scroll wheel (re-exported from 0x2110).
| Variant | Value | Description |
|---|---|---|
Freespin | 1 | Free-spin wheel mode. |
Ratchet | 2 | Ratchet wheel mode. |
Wire format
All three functions use a 3-byte request payload and return a 16-byte long-message response. Fields absent from a set call are encoded as 0 (the documented "do not change" sentinel).
get_capabilities (fn 0)
Request: [0x00, 0x00, 0x00] (no parameters)
Response (byte → field):
| Byte | Field | Notes |
|---|---|---|
| 0 | capabilities | Bitfield — bit 0 = TUNABLE_TORQUE |
| 1 | auto_disengage_default | Default auto-disengage threshold |
| 2 | default_tunable_torque | Default torque as % of max force |
| 3 | max_force | Maximum force in gram-force units |
get_ratchet_control_mode (fn 1)
Request: [0x00, 0x00, 0x00] (no parameters)
Response (byte → field):
| Byte | Field | Notes |
|---|---|---|
| 0 | wheel_mode | 1 = Freespin, 2 = Ratchet; unknown values fall back to Ratchet |
| 1 | auto_disengage | Current threshold (0x01–0xFE; 0xFF = always ratchet) |
| 2 | current_tunable_torque | Current torque as % of max force |
set_ratchet_control_mode (fn 2)
Request: [wheel_mode, auto_disengage, tunable_torque]
| Byte | Source | Notes |
|---|---|---|
| 0 | change.wheel_mode as u8 | 0 = do not change, 1 = Freespin, 2 = Ratchet |
| 1 | change.auto_disengage as u8 | 0 = do not change (NonZeroU8 enforces this) |
| 2 | change.tunable_torque as u8 | 0 = do not change (NonZeroU8 enforces this) |
Response layout is identical to get_ratchet_control_mode — the device echoes back the resulting state.
Usage (Rust)
use hidpp::{
device::Device,
feature::smartshift_enhanced::{SmartShiftEnhancedFeature, SmartShiftEnhancedStatusChange},
feature::smartshift::WheelMode,
};
use std::num::NonZeroU8;
// device: &mut Device, already created via Device::new(channel, index)
device.enumerate_features().await?;
if let Some(feat) = device.get_feature::<SmartShiftEnhancedFeature>() {
let info = feat.get_capabilities().await?;
println!("max force: {}gf, default threshold: {}", info.max_force, info.auto_disengage_default);
let status = feat.get_ratchet_control_mode().await?;
println!("wheel mode: {:?}, threshold: {}", status.wheel_mode, status.auto_disengage);
// Switch to ratchet and raise the auto-disengage threshold to 50
let updated = feat.set_ratchet_control_mode(SmartShiftEnhancedStatusChange {
wheel_mode: Some(WheelMode::Ratchet),
auto_disengage: NonZeroU8::new(50),
tunable_torque: None, // leave unchanged
}).await?;
println!("new threshold: {}", updated.auto_disengage);
}0x2110 · smartShift
Read or write the scroll wheel mode (free-spin or ratchet) and the speed threshold at which the wheel automatically disengages into free-spin.
0x2120 · highResolutionScrolling
Older feature for querying and enabling fine-grained high-resolution wheel reporting — a predecessor to 0x2121 hiResWheel without ratchet-mode switching.