OpenLogi Device Keys: Structure, Types, and Implementation
OpenLogi device keys are typed string wrappers that uniquely identify hardware devices, distinguishing between lightweight runtime UI state tracking and stable persistent configuration storage.
In the AprilNEA/OpenLogi codebase, device keys serve as the foundation for per-device state management and configuration persistence. Understanding how these keys are structured is essential for working with the desktop UI, HID route handling, and TOML configuration files. This article examines the two primary types of OpenLogi device keys and their implementation in the Rust source code.
Two Types of OpenLogi Device Keys
The codebase defines two distinct key types that serve different architectural purposes: one for runtime state management and one for durable storage.
DeviceKey: Runtime UI State Identifier
DeviceKey is a lightweight wrapper used as the map key for per-device UI state, including DPI settings, SmartShift behavior, and lighting configurations. Defined in crates/openlogi-desktop/src/state/device_key.rs as pub(crate) struct DeviceKey(String), this type guarantees that only configuration-derived identifiers are inserted into BTreeMap structures.
The implementation includes a custom Borrow<str> trait, enabling zero-allocation lookups using plain string slices. According to the source code, this allows a &str to locate entries without constructing a new wrapper instance.
PhysicalDeviceKey: Persistent Configuration Identifier
PhysicalDeviceKey provides a stable identifier that survives process restarts and is used for persisted per-device configuration. This type lives in crates/openlogi-core/src/device_order.rs and represents a thin wrapper around a String that encodes a physical device identity.
Unlike DeviceKey, this wrapper is only produced when a device possesses a non-empty serial number or a non-zero unit ID, ensuring the key truly represents physical hardware rather than transient connections.
How OpenLogi Device Keys Are Structured
Both key types ultimately resolve to deterministic string representations, but their formats differ significantly based on data source and device route.
DeviceKey String Format
The DeviceKey stores the raw configuration key directly as provided in the TOML configuration file. Typical formats include:
"2b034"– A short hexadecimal identifier"receiver:abcd:slot:1"– A receiver-based addressing scheme
These strings are passed directly into DeviceKey::from() and stored without transformation.
PhysicalDeviceKey String Format
The PhysicalDeviceKey string is constructed through DeviceStableId, which assembles the identifier from HID route information and device identity. The format varies by connection type:
Bolt/Unifying Receivers
receiver:{uid}:slot:{slot}
The UID is lower-cased, and the slot represents the device position on the receiver.
Direct USB Connections
direct:{vid:04x}:{pid:04x}:{identity}
Where identity is either serial:{serial} or unit:{hex}, depending on available device metadata.
Raw HID Devices
raw:{vid:04x}:{pid:04x}:{usage_page:04x}:{usage_id:04x}:{identity}
This expanded format includes usage page and usage ID for devices requiring specific HID descriptors.
Unknown Routes
unknown:slot:{slot}:{identity}
A fallback format when the specific route type cannot be determined.
The PhysicalDeviceKey::parse method in crates/openlogi-core/src/device_order.rs recognizes these prefix forms and rejects legacy model-scoped keys.
Constructing Device Keys in Code
Programmatic construction follows distinct patterns for each key type.
Creating a DeviceKey
Use DeviceKey::from() to wrap a configuration string, then leverage the Borrow<str> implementation for efficient map operations:
use openlogi_desktop::state::device_key::DeviceKey;
let mut dpi_map = std::collections::BTreeMap::new();
dpi_map.insert(DeviceKey::from("2b034"), 1200);
assert_eq!(dpi_map.get("2b034"), Some(&1200));
This pattern appears throughout the desktop UI state management, allowing &str lookups without allocating temporary DeviceKey instances.
Building a PhysicalDeviceKey
Construction requires a DeviceStableId assembled from route and identity information:
use openlogi_core::device_order::{DeviceStableId, PhysicalDeviceKey};
use openlogi_hidpp::DeviceRoute;
let route = DeviceRoute::Direct {
vendor_id: 0x046d,
product_id: 0xb023,
};
let stable_id = DeviceStableId::from_parts(
Some(&route),
0xff, // slot
Some("ABCDEF"), // serial
[0; 4], // unit_id
);
let phys_key: Option<PhysicalDeviceKey> = stable_id.physical_key();
assert_eq!(
phys_key.map(|k| k.into_string()),
Some("direct:046d:b023:serial:abcdef".to_string())
);
The DeviceStableId::physical_key method returns Option<PhysicalDeviceKey> because it only produces a key when the identity qualifies as physical (non-empty serial or non-zero unit ID).
Source Code Locations
The implementation is split across two main crates to maintain separation between UI state and core device logic:
crates/openlogi-desktop/src/state/device_key.rs– Contains theDeviceKeystruct definition and itsBorrow<str>implementationcrates/openlogi-core/src/device_order.rs– HousesPhysicalDeviceKey,DeviceStableId, and the string formatting logic for various HID route types
Additional context for how these keys appear in user-editable configuration is documented in docs/CONFIGURATION.md.
Summary
- OpenLogi device keys provide type-safe, deterministic identifiers for hardware devices throughout the application lifecycle.
- DeviceKey handles runtime UI state using raw configuration strings and implements
Borrow<str>for efficient map lookups inBTreeMapstructures. - PhysicalDeviceKey provides persistent, process-surviving identifiers constructed from
DeviceStableIdonly when physical device characteristics (serial or unit ID) are present. - String formats encode route type (Bolt, Direct, RawHid, Unknown) and device identity in a human-readable, parseable structure.
DeviceStableId::from_partsandDeviceStableId::physical_keydrive the construction of persistent keys, whileDeviceKey::fromwraps configuration strings for runtime use.
Frequently Asked Questions
What is the difference between DeviceKey and PhysicalDeviceKey?
DeviceKey is a lightweight runtime wrapper used exclusively for UI state management in the desktop application, while PhysicalDeviceKey represents a stable, persistent identifier that survives process restarts and is stored in configuration files. The key distinction lies in their lifecycles: DeviceKey exists only during runtime, whereas PhysicalDeviceKey is derived from physical device characteristics like serial numbers.
How does PhysicalDeviceKey handle different connection types?
The string representation adapts to the HID route type. Bolt and Unifying receivers use the format receiver:{uid}:slot:{slot}, direct USB connections use direct:{vid:04x}:{pid:04x}:{identity}, and RawHid devices include usage page and usage ID in the format raw:{vid:04x}:{pid:04x}:{usage_page:04x}:{usage_id:04x}:{identity}. The PhysicalDeviceKey::parse method recognizes these prefixes to reconstruct keys from stored configuration strings.
Why does DeviceKey implement Borrow?
This implementation allows BTreeMap lookups using a plain &str reference without allocating a new DeviceKey wrapper. According to the source code in crates/openlogi-desktop/src/state/device_key.rs, this optimization is critical for performance when accessing per-device UI state maps frequently during UI updates, as it eliminates unnecessary string allocations during hash map operations.
Can a device have both a DeviceKey and a PhysicalDeviceKey simultaneously?
Yes. A single hardware device is typically identified by a DeviceKey within the running desktop UI for state tracking, while simultaneously possessing a PhysicalDeviceKey for configuration persistence. The DeviceKey usually contains the PhysicalDeviceKey string or a configuration alias, but the types remain distinct to prevent accidental mixing of runtime and persistent storage logic.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →