set_rewriteInstall or overwrite one rule

fn set_rewrite(&self, rule: &RewriteRule) -> Result<()>

Fire-and-forget

ParameterTypeDescription
ruleRewriteRuleIts address, action, and any masked match or payload.

Rules are keyed by (class, id, direction, match, mask). Setting an existing key overwrites the rule, resets its hits and moves it to the end of the table. The crate checks the box's limits before sending.

REFUSALS
LimitPast it
2048 payload bytes across every held rule (REWRITE_PAYLOAD_POOL), checked first. An overwrite frees the bytes of the rule it replaces.Error::RewritePoolFull
32 rules (REWRITE_MAX_ENTRIES), for a new keyError::RewriteTableFull
EXAMPLE
use medius::{Device, Direction, RewriteRule, RewriteClass, RewriteAction};

let device = Device::find()?;
device.allow_imperfect_clones(true)?;

// Drop every report the clone emits on interrupt-IN endpoint 1.
device.set_rewrite(&RewriteRule::new(RewriteClass::Emit, 1, Direction::IN, RewriteAction::Drop))?;

// Overwrite byte 2 of each report the clone emits on endpoint 1, when byte 0 is the report id 0x01.
device.set_rewrite(
    &RewriteRule::new(RewriteClass::Emit, 1, Direction::IN, RewriteAction::Patch)
        .matching([0x01], [0xFF])
        .at_offset(2)
        .with_payload([0x00]),
)?;

remove_rewriteDrop one rule

fn remove_rewrite(&self, rule: &RewriteRule) -> Result<()>

Fire-and-forget

Drops the rule with this rule's (class, id, direction, match, mask) key, ignoring its action and payload. A no-op if no such rule is held.

EXAMPLE
let rule = RewriteRule::new(RewriteClass::Emit, 1, Direction::IN, RewriteAction::Drop);
device.set_rewrite(&rule)?;
device.remove_rewrite(&rule)?; // the same key, dropped

clear_rewriteDrop every rule

fn clear_rewrite(&self) -> Result<()>

Fire-and-forget

Drops the whole table. Whatever the opt-in, it also drops the crate's held rules, so a reconnect never re-asserts a cleared rule.

EXAMPLE
device.clear_rewrite()?;

query_rewriteTable summary

fn query_rewrite(&self) -> Result<RewriteTable>

Blocks

Returns a RewriteTable: a full flag, a generation counter, and a row per rule without its match, mask, or payload bytes. The full flag means the box refused the last new rule or overwrite for lack of room. The next table change or a clear resets it.

EXAMPLE
let table = device.query_rewrite()?;
println!("{} rules, gen {}", table.entries.len(), table.generation);
for e in &table.entries {
    println!("  {:?} id {:#04x} -> {:?}, {} hits", e.class, e.id, e.action, e.hits);
}

query_rewrite_entryOne rule in full

fn query_rewrite_entry(&self, index: u8) -> Result<RewriteRule>

Blocks

ParameterTypeDescription
indexu8The row in the query_rewrite summary.

Returns one RewriteRule in full, in the shape set_rewrite takes.

EXAMPLE
let table = device.query_rewrite()?;
for i in 0..table.entries.len() as u8 {
    let rule = device.query_rewrite_entry(i)?; // replayable as a set
    let _ = rule;
}

On AsyncDeviceset_rewrite and the queries await; remove and clear fire

AsyncDevice makes set_rewrite a future that awaits the opt-in check before sending. query_rewrite and query_rewrite_entry are futures too. remove_rewrite and clear_rewrite carry no opt-in check and stay synchronous.

EXAMPLE
use futures::executor::block_on;
use medius::{AsyncDevice, Direction, RewriteRule, RewriteClass, RewriteAction};

let device = AsyncDevice::open("/dev/ttyACM0")?;
device.allow_imperfect_clones(true)?;
let rule = RewriteRule::new(RewriteClass::Emit, 1, Direction::IN, RewriteAction::Drop);
block_on(device.set_rewrite(&rule))?;            // awaits the opt-in gate
device.remove_rewrite(&rule)?;                   // sync: no gate
let table = block_on(device.query_rewrite())?;   // query awaits