0x1C00 · persistentRemappableAction
Non-volatile control remapping — read or write per-control, per-host action assignments (keys, mouse buttons, consumer codes, internal functions) stored in device memory.
Persistently remaps a device control to a different HID action, writing the
mapping to the device's non-volatile memory. Controls are identified by the same
ControlIds as 0x1B04 (reprogControls); when both features are present, a
live divert from 0x1B04 takes precedence over a persistent remap here.
get_feature_info reports which HID output categories the device supports;
get_count returns the number of remappable controls and host slots.
get_cid_info enumerates the control table; get_persistent_action /
set_persistent_action read and write a per-control, per-host mapping.
reset_persistent_action restores one mapping to its factory default;
reset_to_factory_settings clears all mappings for a selected set of host slots.
ActionId— the action type a control produces:SendKeyboard,SendMouseButton,SendXDisplacement,SendYDisplacement,SendVerticalRoller,SendHorizontalRoller,SendConsumerControl,ExecuteInternalFunction,SendPowerKey.RemappableCapabilities— bitflags advertising whichActionIdtypes the device can produce; returned byget_feature_info.ModifierMask— keyboard modifier flags (left/right Ctrl, Shift, Alt, GUI); applicable toSendKeyboardactions only.HostMask— selects one or more host slots (HOST_1–HOST_3) forreset_to_factory_settings.
Spec: Logitech HID++ 2.0 — persistentRemappableAction. Used by: Typed wrapper in
openlogi-hidpp.
Function reference
The PersistentRemappableActionFeature wrapper (0x1c00) exposes:
Methods
| Function | HID++ fn | Signature | Returns |
|---|---|---|---|
get_feature_info | 0 | () | RemappableCapabilities |
get_count | 1 | () | RemappableInfo |
get_cid_info | 2 | (index: u8, host: HostIndex) | ControlId |
get_persistent_action | 3 | (cid: ControlId, host: HostIndex) | PersistentAction |
set_persistent_action | 4 | (cid: ControlId, host: HostIndex, config: PersistentActionConfig) | () |
reset_persistent_action | 5 | (cid: ControlId, host: HostIndex) | () |
reset_to_factory_settings | 6 | (hosts: HostMask) | () |
All methods are async and return Result<…, Hidpp20Error>.
Types
RemappableCapabilities
Bitflags advertising which HID output categories the device's persistent remapping can produce; returned by get_feature_info.
| Flag | Bit/Value | Description |
|---|---|---|
KEYBOARD_REPORT | 1 << 0 | Can send keyboard/keypad keys. |
MOUSE_BUTTONS | 1 << 1 | Can send mouse buttons. |
X_DISPLACEMENT | 1 << 2 | Can send mouse X displacement. |
Y_DISPLACEMENT | 1 << 3 | Can send mouse Y displacement. |
VERTICAL_ROLLER | 1 << 4 | Can send vertical roller increments. |
HORIZONTAL_ROLLER | 1 << 5 | Can send horizontal roller (AC pan) increments. |
CONSUMER_CONTROL | 1 << 6 | Can send consumer-control codes. |
INTERNAL_FUNCTION | 1 << 7 | Can execute internal functions. |
POWER_KEY | 1 << 8 | Can send power keys. |
RemappableInfo
Control-table sizing returned by get_count.
| Field | Type | Description |
|---|---|---|
count | u8 | Number of control IDs in the table. |
host_count | u8 | Number of hosts the device supports. |
PersistentAction
The action mapped to a control, returned by get_persistent_action.
| Field | Type | Description |
|---|---|---|
cid | ControlId | The control the action belongs to. |
host | HostIndex | The host slot the mapping applies to. |
action_id | ActionId | The action performed when triggered. |
value | u16 | The HID usage code, displacement, or internal-function index sent. |
modifier_mask | ModifierMask | Keyboard modifiers applied (keyboard actions only). |
remapped | bool | Whether the control is remapped away from its default behaviour. |
PersistentActionConfig
The action to assign via set_persistent_action.
| Field | Type | Description |
|---|---|---|
action_id | ActionId | The action to perform when triggered. |
value | u16 | The HID usage code, displacement, or internal-function index to send. |
modifier_mask | ModifierMask | Keyboard modifiers to apply (keyboard actions only). |
ActionId
The action a control performs when triggered.
| Variant | Value | Description |
|---|---|---|
SendKeyboard | 0x01 | Send a keyboard/keypad report (HID usage page 7). |
SendMouseButton | 0x02 | Send a mouse-button report (usage page 9). |
SendXDisplacement | 0x03 | Send mouse X displacement (usage page 1, code 0x30). |
SendYDisplacement | 0x04 | Send mouse Y displacement (usage page 1, code 0x31). |
SendVerticalRoller | 0x05 | Send vertical roller/wheel displacement (usage page 1, code 0x38). |
SendHorizontalRoller | 0x06 | Send horizontal roller / AC pan displacement (usage page 12, code 0x0238). |
SendConsumerControl | 0x07 | Send a consumer-control report (usage page 12). |
ExecuteInternalFunction | 0x08 | Execute an internal function (the value is the function index). |
SendPowerKey | 0x09 | Send a power-key report (usage page 1). |
ModifierMask
Standard keyboard modifier keys for a remapped keyboard action. Modifiers only apply to keyboard reports.
| Flag | Bit/Value | Description |
|---|---|---|
LEFT_CTRL | 1 << 0 | Left Control. |
LEFT_SHIFT | 1 << 1 | Left Shift. |
LEFT_ALT | 1 << 2 | Left Alt. |
LEFT_GUI | 1 << 3 | Left GUI (Win/Command). |
RIGHT_CTRL | 1 << 4 | Right Control. |
RIGHT_SHIFT | 1 << 5 | Right Shift. |
RIGHT_ALT | 1 << 6 | Right Alt. |
RIGHT_GUI | 1 << 7 | Right GUI (Win/Command). |
HostMask
A set of host slots for reset_to_factory_settings.
| Flag | Bit/Value | Description |
|---|---|---|
HOST_1 | 1 << 0 | Host 1. |
HOST_2 | 1 << 1 | Host 2. |
HOST_3 | 1 << 2 | Host 3. |
Wire format
Short getter requests carry a 3-byte zero payload; set_persistent_action uses a 16-byte long-payload request. All responses are read from the 16-byte long payload returned by .extend_payload().
get_feature_info (fn 0)
Request: [0x00, 0x00, 0x00]
Response (byte → field):
| Byte | Field | Notes |
|---|---|---|
| 0–1 | RemappableCapabilities | Big-endian u16 bitfield; see flag table above. |
get_count (fn 1)
Request: [0x00, 0x00, 0x00]
Response (byte → field):
| Byte | Field | Notes |
|---|---|---|
| 0 | count | Number of control IDs in the table. |
| 1 | host_count | Number of host slots the device supports. |
get_cid_info (fn 2)
Request: [index, host, 0x00]
Response (byte → field):
| Byte | Field | Notes |
|---|---|---|
| 0–1 | ControlId | Big-endian u16 control identifier. |
get_persistent_action (fn 3)
Request: [cid_hi, cid_lo, host] — ControlId split into two bytes big-endian, followed by the HostIndex byte.
Response (byte → field):
| Byte | Field | Notes |
|---|---|---|
| 0–1 | cid | ControlId as big-endian u16. |
| 2 | host | HostIndex byte. |
| 3 | action_id | ActionId discriminant (0x01–0x09). |
| 4–5 | value | HID usage code, displacement, or function index as big-endian u16. |
| 6 | modifier_mask | ModifierMask bitfield byte. |
| 7 | remapped | Bit 0: 1 = remapped away from factory default. |
set_persistent_action (fn 4)
Uses call_long: a 16-byte request payload; bytes 7–15 are zero-padded.
| Byte | Field | Notes |
|---|---|---|
| 0–1 | cid | ControlId as big-endian u16. |
| 2 | host | HostIndex byte. |
| 3 | action_id | ActionId discriminant. |
| 4–5 | value | HID usage / displacement / function index as big-endian u16. |
| 6 | modifier_mask | ModifierMask bitfield byte. |
| 7–15 | — | Reserved, zero. |
No meaningful response body.
reset_persistent_action (fn 5)
Request: [cid_hi, cid_lo, host] — same layout as get_persistent_action request.
No meaningful response body.
reset_to_factory_settings (fn 6)
Request: [hosts_bits, 0x00, 0x00] — HostMask bitfield in byte 0; bits 0/1/2 select HOST_1/HOST_2/HOST_3.
No meaningful response body.
Usage (Rust)
use hidpp::{
device::Device,
feature::{
hosts_info::HostIndex,
persistent_remappable_action::{
ActionId, ModifierMask, PersistentActionConfig, PersistentRemappableActionFeature,
},
reprog_controls::ControlId,
},
};
// device: &mut Device, already created via Device::new(channel, device_index)
device.enumerate_features().await?;
if let Some(feat) = device.get_feature::<PersistentRemappableActionFeature>() {
// Query device capabilities and table size.
let caps = feat.get_feature_info().await?;
let info = feat.get_count().await?;
println!("caps={caps:?}, controls={}, hosts={}", info.count, info.host_count);
// Read the current mapping for control 0x00c4 on host 0.
let host = HostIndex::from(0u8);
let cid = ControlId::from(0x00c4u16);
let action = feat.get_persistent_action(cid, host).await?;
println!("current action: {:?}", action.action_id);
// Remap the control to send Ctrl+C (usage 0x06 = HID keycode for 'c').
let config = PersistentActionConfig {
action_id: ActionId::SendKeyboard,
value: 0x0006,
modifier_mask: ModifierMask::LEFT_CTRL,
};
feat.set_persistent_action(cid, host, config).await?;
}