# When to Use `openlogi diag features` vs `openlogi diag controls` for Debugging Device Enumeration

> Debug device enumeration with OpenLogi. Learn when to use `openlogi diag features` vs `openlogi diag controls` to troubleshoot HID++ device reporting and control mapping issues.

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

---

**Use `openlogi diag features` to verify that a Logitech HID++ device reports the required feature IDs during enumeration, and use `openlogi diag controls` to inspect individual control mappings when remapping or control detection fails.**

OpenLogi provides two low-level diagnostic sub-commands that probe Logitech HID++ devices at the protocol level. Understanding when to use each command helps you isolate whether a problem stems from **feature discovery** (the device isn't recognized as supporting a capability) or **control enumeration** (the device supports the feature but specific buttons or controls aren't being mapped correctly). This guide walks through both commands based on the actual implementation in [AprilNEA/OpenLogi](https://github.com/AprilNEA/OpenLogi).

## `openlogi diag features`: Inspect HID++ Feature Tables

The **`openlogi diag features`** command calls `dump_features` to read every HID++ feature entry the device advertises—including feature ID, version, and size. The output displays as a list of feature IDs that determine which OpenLogi sub-commands are applicable to that device.

### When to Use `diag features`

- You suspect a device is being **mis-identified or ignored** during enumeration.
- A higher-level command (e.g., DPI adjustment, SmartShift configuration) fails with a "feature not supported" error.
- You need to confirm whether the device actually reports the feature ID required by a specific command.

For example, DPI commands in OpenLogi require feature **0x0c0e**. If `dpi set` fails, running `diag features` reveals whether that ID appears in the device's feature table.

### Code Example

```bash

# List all HID++ features of the first online device

openlogi diag features

# Target a specific device by name

openlogi diag features --device "MX Master 3S"

```

The `features::run` handler in [`crates/openlogi-cli/src/cmd/features.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-cli/src/cmd/features.rs) implements this command by invoking `openlogi_hid::dump_features`.

## `openlogi diag controls`: Inspect Reprogrammable Controls

The **`openlogi diag controls`** command uses the **0x1b04 Reprogrammable Controls** feature to dump each control's ID, capability flags, and reporting mode. Unlike `diag features`, this is a **diagnostics-only probe** specifically designed to discover new or undocumented controls on unfamiliar devices.

### When to Use `diag controls`

- You need to verify that **control enumeration** (programmable buttons, crown dial, host-switch, etc.) matches what the OpenLogi GUI expects.
- You're adding support for a newly released device and want to see which controls the firmware exposes.
- A particular control doesn't respond to remapping commands despite the feature being present.

### Code Example

```bash

# Dump reprogrammable controls for a specific device

openlogi diag controls --device "MX Master 3S"

```

The implementation in [`crates/openlogi-cli/src/cmd/controls.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-cli/src/cmd/controls.rs) calls `dump_reprog_controls`, defined in [`crates/openlogi-device/src/write/diagnostics.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/diagnostics.rs). This low-level function queries control IDs and their flags directly from the device's 0x1b04 feature.

## How the Commands Fit Into Enumeration Flow

Understanding the device discovery pipeline clarifies when each diagnostic applies:

1. **Device discovery** — `openlogi_hid::enumerate()` builds an inventory of all paired devices across receivers, Bluetooth, and USB connections.

2. **Feature probing** — For each online device, OpenLogi probes the HID++ feature table. This step determines which sub-commands are enabled. No feature ID means no access to that capability.

3. **Control probing** — If the device advertises feature 0x1b04, `dump_reprog_controls` queries control IDs and flags. The GUI uses this data to populate the **Controls** page and enable or disable remapping UI elements.

Both commands share the same device-selection logic defined in `select_device` at [`crates/openlogi-cli/src/cmd/diag.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-cli/src/cmd/diag.rs) ([lines 22-27](https://github.com/AprilNEA/OpenLogi/blob/master/crates/openlogi-cli/src/cmd/diag.rs#L22-L27)). The `required_features` argument lets the CLI automatically filter devices that lack a needed feature.

## Diagnostic Workflow

Follow this decision tree when debugging enumeration or remapping issues:

| Symptom | First Command | Second Command (if needed) |
|---------|-------------|---------------------------|
| Device not recognized; command unavailable | `openlogi diag features` | Check firmware or connection |
| Feature present but control misbehaves | `openlogi diag features` (confirm feature 0x1b04) | `openlogi diag controls` |
| New device, unknown button layout | `openlogi diag features` | `openlogi diag controls` |
| Remapping fails silently | `openlogi diag controls` | Verify GUI control mapping |

## Key Source Files

| File | Purpose |
|------|---------|
| [`crates/openlogi-cli/src/cmd/diag.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-cli/src/cmd/diag.rs) | Defines `DiagCmd` enum and `select_device` helper for resolving device routes |
| [`crates/openlogi-cli/src/cmd/features.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-cli/src/cmd/features.rs) | Implements `features::run` handler calling `dump_features` |
| [`crates/openlogi-cli/src/cmd/controls.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-cli/src/cmd/controls.rs) | Implements `controls::run` handler calling `dump_reprog_controls` |
| [`crates/openlogi-device/src/write/diagnostics.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/diagnostics.rs) | Low-level `dump_reprog_controls` function for 0x1b04 feature reads |
| [`crates/openlogi-core/src/diagnostics.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/diagnostics.rs) | Data structures (`ReceiverDiag`, `DeviceDiag`, `DiagnosticsReport`) for output formatting |

## Summary

- **`openlogi diag features`** verifies the HID++ feature table during enumeration—use this when devices are misidentified or commands fail due to missing capabilities.
- **`openlogi diag controls`** inspects reprogrammable control mappings via feature 0x1b04—use this when the feature set is correct but individual buttons or controls don't behave as expected.
- Both commands rely on `select_device` in [`crates/openlogi-cli/src/cmd/diag.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-cli/src/cmd/diag.rs) for consistent device targeting.
- Start with `diag features` to confirm feature discovery, then proceed to `diag controls` if control-level debugging is needed.

## Frequently Asked Questions

### What HID++ feature ID does `diag controls` require?

`openlogi diag controls` requires feature **0x1b04** (Reprogrammable Controls). If `diag features` doesn't show this ID, the controls command will not function for that device.

### Can I run these commands on offline or sleeping devices?

No. Both commands require the device to be **online** (enumerated and responsive). The `select_device` helper filters for online devices only, and HID++ protocol commands time out if the device is in power-saving mode.

### Why does a device support DPI in Logitech Options+ but `diag features` shows no 0x0c0e?

Some Logitech devices use **feature variants** or **different protocol versions** that report alternative feature IDs. Check the raw feature list for similar IDs (e.g., 0x2201 for adjustable DPI) and consult [`crates/openlogi-hid/src/features.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hid/src/features.rs) for how OpenLogi maps feature variants.