OpenLogi
Features

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.

  • wheelMode1 free-spin (frictionless), 2 ratchet (clicky).
  • autoDisengage0x010xFE, the wheel speed (in 0.25 turn/s steps) past which a ratchet-mode wheel releases into free-spin — the SmartShift threshold. 0xFF keeps the ratchet engaged permanently.
  • tunable torque — ratchet resistance as a percent of the device maximum, or 0 when 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

FunctionHID++ fnSignatureReturns
get_capabilities0()SmartShiftEnhancedInfo
get_ratchet_control_mode1()SmartShiftEnhancedStatus
set_ratchet_control_mode2(change: SmartShiftEnhancedStatusChange)SmartShiftEnhancedStatus

All methods are async and return Result<…, Hidpp20Error>.

Types

SmartShiftEnhancedInfo

Capability and default values for enhanced SmartShift.

FieldTypeDescription
capabilitiesSmartShiftEnhancedCapabilitiesSupported capabilities.
auto_disengage_defaultu8Default automatic disengage threshold.
default_tunable_torqueu8Default tunable torque, as a percentage of maximum force.
max_forceu8Maximum force in gram-force units.

SmartShiftEnhancedStatus

Current enhanced SmartShift status.

FieldTypeDescription
wheel_modeWheelModeCurrent requested wheel mode.
auto_disengageu8Automatic disengage threshold.
current_tunable_torqueu8Current 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.

FieldTypeDescription
wheel_modeOption<WheelMode>Wheel mode to apply, or None to leave unchanged.
auto_disengageOption<NonZeroU8>Automatic disengage threshold, or None to leave unchanged. HID++ encodes 0 as "do not change", so writable values must be non-zero.
tunable_torqueOption<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.

FlagBit/ValueDescription
TUNABLE_TORQUEbit 0The device supports tunable ratchet torque.

WheelMode

Represents the ratchet mode of the scroll wheel (re-exported from 0x2110).

VariantValueDescription
Freespin1Free-spin wheel mode.
Ratchet2Ratchet 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):

ByteFieldNotes
0capabilitiesBitfield — bit 0 = TUNABLE_TORQUE
1auto_disengage_defaultDefault auto-disengage threshold
2default_tunable_torqueDefault torque as % of max force
3max_forceMaximum force in gram-force units

get_ratchet_control_mode (fn 1)

Request: [0x00, 0x00, 0x00] (no parameters)

Response (byte → field):

ByteFieldNotes
0wheel_mode1 = Freespin, 2 = Ratchet; unknown values fall back to Ratchet
1auto_disengageCurrent threshold (0x010xFE; 0xFF = always ratchet)
2current_tunable_torqueCurrent torque as % of max force

set_ratchet_control_mode (fn 2)

Request: [wheel_mode, auto_disengage, tunable_torque]

ByteSourceNotes
0change.wheel_mode as u80 = do not change, 1 = Freespin, 2 = Ratchet
1change.auto_disengage as u80 = do not change (NonZeroU8 enforces this)
2change.tunable_torque as u80 = 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);
}

On this page