Skip to content

Commit

Permalink
Fix decoding of keymaps where the IRP uses different variables than CODE
Browse files Browse the repository at this point in the history
Signed-off-by: Sean Young <[email protected]>
  • Loading branch information
seanyoung committed May 11, 2024
1 parent be49647 commit 1bac9ce
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 21 deletions.
2 changes: 1 addition & 1 deletion cir/src/bin/commands/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ fn load_keymap(
}
};

for dfa in dfas {
for (dfa, _) in dfas {
let bpf = match dfa.compile_bpf(&options) {
Ok((bpf, _)) => bpf,
Err(e) => {
Expand Down
50 changes: 41 additions & 9 deletions cir/src/keymap/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ use log::debug;

pub struct KeymapDecoder<'a> {
pub remote: &'a Keymap,
pub dfa: Vec<DFA>,
pub dfa: Vec<(DFA, Option<Irp>)>,
pub decoder: Vec<Decoder<'a>>,
}

impl Keymap {
/// Create DFAs for this remote
pub fn build_dfa<'b>(&'b self, options: &Options<'b>) -> Result<Vec<DFA>, String> {
pub fn build_dfa<'b>(
&'b self,
options: &Options<'b>,
) -> Result<Vec<(DFA, Option<Irp>)>, String> {
let nfa = if self.raw.is_empty() {
let mut irps = Vec::new();
if let Some(irp) = &self.irp {
Expand Down Expand Up @@ -46,7 +49,7 @@ impl Keymap {

let irp = Irp::parse(irp).unwrap();

irp.build_nfa().unwrap()
(irp.build_nfa().unwrap(), Some(irp))
})
.collect()
} else {
Expand All @@ -57,11 +60,14 @@ impl Keymap {
nfa.add_raw(&message.raw, irp::Event::Down, u32::MAX as i64 + i as i64);
}

vec![nfa]
vec![(nfa, None)]
};

// TODO: merge NFAs so we end up with one DFA
Ok(nfa.iter().map(|nfa| nfa.build_dfa(options)).collect())
Ok(nfa
.into_iter()
.map(|(nfa, irp)| (nfa.build_dfa(options), irp))
.collect())
}

/// Create a decoder for this remote
Expand All @@ -84,10 +90,36 @@ impl<'a> KeymapDecoder<'a> {
F: FnMut(&'a str, u64),
{
for i in 0..self.dfa.len() {
self.decoder[i].dfa_input(ir, &self.dfa[i], |_, vars| {
// FIXME: vars do not have to be called CODE
if let Some(decoded) = vars.get("CODE") {
let decoded = *decoded as u64;
self.decoder[i].dfa_input(ir, &self.dfa[i].0, |_, vars| {
let scancode: Option<u64> = if let Some(irp) = &self.dfa[i].1 {
let mut scancode = 0;
let mut found = true;

for param in &irp.parameters {
if param.name == "T" {
continue;
}

if let Some(v) = vars.get(&param.name) {
log::debug!("variable {}={v}", param.name);

scancode <<= param.max.ilog2() + 1;
scancode |= *v as u64;
} else {
found = false;
}
}

found.then(|| {
log::debug!("scancode 0x{scancode:x}");

scancode
})
} else {
vars.get("CODE").map(|v| *v as u64)
};

if let Some(decoded) = scancode {
if self.remote.raw.is_empty() {
if let Some(key_code) = self.remote.scancodes.get(&decoded) {
callback(key_code, decoded);
Expand Down
27 changes: 27 additions & 0 deletions cir/tests/decode_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ debug: generated DFA for Sony-RM-U305C
debug: generated NFA for Sony-RM-U305C
debug: generated DFA for Sony-RM-U305C
info: decoding: +2400 -600 +600 -600 +600 -600 +600 -600 +600 -600 +600 -600 +1200 -600 +1200 -600 +600 -600 +600 -600 +600 -600 +600 -600 +1200 -26400
debug: variable CODE=1048672
debug: scancode 0x100060
"#
);

Expand All @@ -115,6 +117,31 @@ info: decoding: +2400 -600 +600 -600 +600 -600 +600 -600 +600 -600 +600 -600 +12

let mut cmd = Command::cargo_bin("cir").unwrap();

let assert = cmd
.args([
"decode", "keymap", "../testdata/rc_keymaps/sony-12.toml", "-r",
"+2400 -600 +1200 -600 +600 -600 +1200 -600 +600 -600 +1200 -600 +600 -600 +600 -600 +600 -600 +600 -600 +600 -600 +600 -600 +600 -26400"
])
.assert();

let output = assert.get_output();

let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);

assert_eq!(
stderr,
r#"info: decoding: +2400 -600 +1200 -600 +600 -600 +1200 -600 +600 -600 +1200 -600 +600 -600 +600 -600 +600 -600 +600 -600 +600 -600 +600 -600 +600 -26400
"#
);

assert_eq!(
stdout,
r#"decoded: keymap:Sony-RM-U305C code:KEY_SONY-AV-AV-I/O
"#
);
let mut cmd = Command::cargo_bin("cir").unwrap();

let assert = cmd
.args([
"decode", "keymap", "../testdata/rc_keymaps/dish_network.toml", "-q", "-r",
Expand Down
22 changes: 11 additions & 11 deletions testdata/rc_keymaps/sony-12.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[[protocols]]
name = 'Sony-RM-U305C'
protocol = 'sony'
variant = 'sony-12'
protocol = 'irp'
irp = '{40k,600}<1,-1|2,-1>(4,-1,F:7,D:5,^45m) [D:0..31,F:0..127]'
[protocols.scancodes]
0x100060 = 'KEY_SONY-AV-SLEEP'
0x10015 = 'KEY_SONY-AV-AV-I/O'
0x100022 = 'KEY_SONY-AV-VIDEO'
0x10007d = 'KEY_SONY-AV-DVD/LD'
0x10006a = 'KEY_SONY-AV-TV/SAT'
0x10001d = 'KEY_SONY-AV-AUX'
0x100025 = 'KEY_SONY-AV-CD/SACD'
0x100021 = 'KEY_SONY-AV-TUNER'
0x100015 = 'KEY_SONY-AV-1'
0x60 = 'KEY_SONY-AV-SLEEP'
0x15 = 'KEY_SONY-AV-AV-I/O'
0x22 = 'KEY_SONY-AV-VIDEO'
0x7d = 'KEY_SONY-AV-DVD/LD'
0x6a = 'KEY_SONY-AV-TV/SAT'
0x1d = 'KEY_SONY-AV-AUX'
0x25 = 'KEY_SONY-AV-CD/SACD'
0x21 = 'KEY_SONY-AV-TUNER'
0x17 = 'KEY_SONY-AV-1'

0 comments on commit 1bac9ce

Please sign in to comment.