# How the SmartShift Wheel Mode Toggle Works with HID++ Feature 0x1b04 in OpenLogi

> Learn how OpenLogi's SmartShift wheel mode toggle uses HID++ Feature 0x1b04 to cycle DPI presets. Understand Control ID 0xC4 and custom button mapping for enhanced control.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: deep-dive
- Published: 2026-09-06

---

**OpenLogi implements the SmartShift wheel-mode toggle by mapping Control ID 0xC4 through the HID++ Reprogrammable Controls feature (0x1b04), converting raw wheel events into DPI preset cycles when the dedicated button is held.**

OpenLogi is an open-source driver for Logitech HID++ devices that exposes low-level hardware controls through a structured abstraction layer. The SmartShift button—typically used to toggle between normal scrolling and DPI-shifting modes—is managed via the Reprogrammable Controls protocol. This article traces the exact code path from HID++ feature detection to the UI update, using the actual source implementation in the AprilNEA/OpenLogi repository.

## Identifying the SmartShift Control ID

The SmartShift button is exposed by the hardware as **Control ID 0xC4**. This constant is defined in the HID++ crate's control registry.

In [`crates/openlogi-hidpp/src/feature/reprog_controls/control_ids.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hidpp/src/feature/reprog_controls/control_ids.rs), the constant is declared as `SMART_SHIFT`. This identifier represents the physical button located beneath the mouse wheel on supported Logitech devices. When the device reports its available controls via HID++, this ID signals the presence of the wheel-mode toggle mechanism.

## Resolving the Default Task ID

Every control in the HID++ protocol has a default **Task ID** that describes its built-in action. For SmartShift, this task is **0x9D** (`SMART_SHIFT`).

This mapping is defined in [`crates/openlogi-hidpp/src/feature/reprog_controls/task_ids.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hidpp/src/feature/reprog_controls/task_ids.rs). The Task ID represents the firmware's native behavior—switching the wheel from scroll mode to DPI-shift mode—which OpenLogi can either preserve or override through its binding system.

## Querying Control Information via HID++ 0x1b04

OpenLogi communicates with the device through the **Reprogrammable Controls** feature (HID++ Feature ID **0x1b04**). The `ReprogControlsV4` accessor in [`crates/openlogi-device/src/reprog_controls.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/reprog_controls.rs) handles this communication.

The code calls `get_ctrl_id_info` to retrieve the control's capabilities:

```rust
let reprog = ReprogControlsV4::new(chan.clone(), dev_idx, feat_idx);
let ctrl_info = reprog.get_ctrl_id_info(/* index of SMART_SHIFT */).await?;

```

This function returns a `CidInfo` structure that the accessor converts into a local `CtrlIdInfo` type. This metadata includes flags indicating whether the control supports raw wheel reporting—a critical capability for the SmartShift functionality.

## Mapping Hardware Controls to OpenLogi Bindings

OpenLogi abstracts hardware-specific Control IDs into generic `ButtonId` types. The SmartShift control (0xC4) maps to **`ButtonId::DpiToggle`**—a historical name preserved in the codebase.

This mapping occurs in [`crates/openlogi-core/src/binding/button.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/button.rs). The abstraction allows the core logic to remain agnostic of hardware-specific IDs while maintaining a consistent API for gesture handling and UI updates.

## Enabling Raw Wheel Mode Detection

The wheel-mode toggle relies on the **`supports_raw_wheel`** flag exposed in `CtrlIdInfo`. When the SmartShift button is held, the agent checks this capability to determine if the control can emit raw wheel data instead of processed scroll events.

In [`crates/openlogi-device/src/reprog_controls.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/reprog_controls.rs), the `supports_raw_wheel` method returns a boolean indicating this capability. While the button remains pressed, the `rawWheelEvent` stream from the HID++ device is intercepted by the agent core. The wheel deltas are then routed to the DPI-cycle logic rather than the standard scrolling pipeline.

## Executing the DPI Cycle Action

When SmartShift is active, wheel movements trigger **Action::CycleDpiPresets**. This default binding is established in [`crates/openlogi-core/src/binding/defaults.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/defaults.rs), where `ButtonId::DpiToggle` is assigned the cycle action.

The gesture watcher in [`crates/openlogi-agent-core/src/watchers/gesture.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-agent-core/src/watchers/gesture.rs) processes these events. It monitors for `ButtonPulse(ButtonId::DpiToggle)` events and translates wheel increments into DPI preset changes. Simultaneously, the GUI layer (`openlogi-desktop`) listens via IPC channels to update on-screen indicators, providing real-time feedback that the wheel-mode toggle is active.

## Code Example: Detecting and Handling SmartShift

The following Rust code demonstrates the complete detection and handling flow:

```rust
// 1. Query the device for the Smart Shift control
let reprog = ReprogControlsV4::new(chan.clone(), dev_idx, feat_idx);
let ctrl_info = reprog.get_ctrl_id_info( /* index of SMART_SHIFT */ ).await?;

// 2. Verify it can report raw wheel data
assert!(ctrl_info.supports_raw_wheel());

// 3. Translate to OpenLogi's binding
let button = openlogi_core::binding::ButtonId::DpiToggle;

// 4. In the gesture handler, an active Smart Shift makes wheel deltas
//    become DPI changes instead of scroll events
if button == ButtonId::DpiToggle && button_is_pressed {
    // Apply DPI preset change
    apply_next_dpi_preset();
}

```

## Summary

The SmartShift wheel-mode toggle operates through the following sequence:

- **Control ID 0xC4** (`SMART_SHIFT`) is exposed via HID++ Feature 0x1b04 and defined in [`control_ids.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/control_ids.rs)
- **Task ID 0x9D** identifies the default wheel-mode behavior in [`task_ids.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/task_ids.rs)
- **`ReprogControlsV4`** queries device capabilities and detects `supports_raw_wheel`
- **`ButtonId::DpiToggle`** abstracts the hardware control in the binding layer
- **`Action::CycleDpiPresets`** executes when raw wheel events occur during button hold
- **IPC propagation** updates the UI overlay via `ButtonPulse` events in the gesture watcher

## Frequently Asked Questions

### What HID++ feature ID controls the SmartShift button in OpenLogi?

OpenLogi accesses the SmartShift button through **HID++ Feature 0x1b04** (Reprogrammable Controls), not the dedicated SmartShift feature. The button is identified as Control ID 0xC4 within this interface, queried via the `ReprogControlsV4` accessor in [`crates/openlogi-device/src/reprog_controls.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/reprog_controls.rs).

### How does OpenLogi distinguish between normal scrolling and DPI shifting?

The system checks the **`supports_raw_wheel`** flag in `CtrlIdInfo` (defined in [`crates/openlogi-device/src/reprog_controls.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/reprog_controls.rs)). When this flag is true and the SmartShift button is held, raw wheel events are routed to `Action::CycleDpiPresets` instead of the standard scroll handler.

### Where is the SmartShift button mapped to OpenLogi's internal model?

The hardware Control ID 0xC4 is mapped to **`ButtonId::DpiToggle`** in [`crates/openlogi-core/src/binding/button.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/button.rs). This abstraction decouples the hardware-specific HID++ protocol from the core binding logic and UI representation.

### What is the default action assigned to the SmartShift button?

By default, OpenLogi assigns **`Action::CycleDpiPresets`** to `ButtonId::DpiToggle` in [`crates/openlogi-core/src/binding/defaults.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/defaults.rs). This action increments through configured DPI presets when the wheel is rotated while the SmartShift button is depressed.