From 1bac9ce56d3bf6bc4a2347867976e496e7e34560 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sun, 12 May 2024 00:02:59 +0100 Subject: [PATCH] Fix decoding of keymaps where the IRP uses different variables than CODE Signed-off-by: Sean Young --- cir/src/bin/commands/config.rs | 2 +- cir/src/keymap/decode.rs | 50 ++++++++++++++++++++++++++------ cir/tests/decode_tests.rs | 27 +++++++++++++++++ testdata/rc_keymaps/sony-12.toml | 22 +++++++------- 4 files changed, 80 insertions(+), 21 deletions(-) diff --git a/cir/src/bin/commands/config.rs b/cir/src/bin/commands/config.rs index 243176a..ac99332 100644 --- a/cir/src/bin/commands/config.rs +++ b/cir/src/bin/commands/config.rs @@ -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) => { diff --git a/cir/src/keymap/decode.rs b/cir/src/keymap/decode.rs index 986ecb8..03b70b6 100644 --- a/cir/src/keymap/decode.rs +++ b/cir/src/keymap/decode.rs @@ -6,13 +6,16 @@ use log::debug; pub struct KeymapDecoder<'a> { pub remote: &'a Keymap, - pub dfa: Vec, + pub dfa: Vec<(DFA, Option)>, pub decoder: Vec>, } impl Keymap { /// Create DFAs for this remote - pub fn build_dfa<'b>(&'b self, options: &Options<'b>) -> Result, String> { + pub fn build_dfa<'b>( + &'b self, + options: &Options<'b>, + ) -> Result)>, String> { let nfa = if self.raw.is_empty() { let mut irps = Vec::new(); if let Some(irp) = &self.irp { @@ -46,7 +49,7 @@ impl Keymap { let irp = Irp::parse(irp).unwrap(); - irp.build_nfa().unwrap() + (irp.build_nfa().unwrap(), Some(irp)) }) .collect() } else { @@ -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 @@ -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 = 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(¶m.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); diff --git a/cir/tests/decode_tests.rs b/cir/tests/decode_tests.rs index 26b988d..bf591fe 100644 --- a/cir/tests/decode_tests.rs +++ b/cir/tests/decode_tests.rs @@ -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 "# ); @@ -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", diff --git a/testdata/rc_keymaps/sony-12.toml b/testdata/rc_keymaps/sony-12.toml index 7519e32..75c7e2e 100644 --- a/testdata/rc_keymaps/sony-12.toml +++ b/testdata/rc_keymaps/sony-12.toml @@ -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'