Skip to content

Commit

Permalink
Teach cir to encode all the protocols that ir-ctl can encode
Browse files Browse the repository at this point in the history
Also compare the output to ir-ctl.

Note the ir-ctl bpf protocols are not included yet.

Signed-off-by: Sean Young <[email protected]>
  • Loading branch information
seanyoung committed Apr 20, 2024
1 parent 6ae12c9 commit 3283b6e
Show file tree
Hide file tree
Showing 6 changed files with 422 additions and 43 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ irp = { version = "0.3.2", path = "irp" }
assert_cmd = "2.0"
serde_json = "1.0"
liblircd = { path = "liblircd" }
rand = "0.8"

[workspace]
members = [
Expand Down
6 changes: 3 additions & 3 deletions liblircd/src/ir-encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,9 @@ static const struct {
} protocols[] = {
[RC_PROTO_UNKNOWN] = { "unknown" },
[RC_PROTO_OTHER] = { "other" },
[RC_PROTO_RC5] = { "rc5", 0x1f7f, 24, 36000, rc5_encode },
[RC_PROTO_RC5] = { "rc5", 0x1f7f, 25, 36000, rc5_encode },
[RC_PROTO_RC5X_20] = { "rc5x_20", 0x1f7f3f, 40, 36000, rc5_encode },
[RC_PROTO_RC5_SZ] = { "rc5_sz", 0x2fff, 26, 36000, rc5_encode },
[RC_PROTO_RC5_SZ] = { "rc5_sz", 0x2fff, 27, 36000, rc5_encode },
[RC_PROTO_SONY12] = { "sony12", 0x1f007f, 25, 40000, sony_encode },
[RC_PROTO_SONY15] = { "sony15", 0xff007f, 31, 40000, sony_encode },
[RC_PROTO_SONY20] = { "sony20", 0x1fff7f, 41, 40000, sony_encode },
Expand All @@ -390,7 +390,7 @@ static const struct {
[RC_PROTO_NECX] = { "necx", 0xffffff, 67, 38000, nec_encode },
[RC_PROTO_NEC32] = { "nec32", 0xffffffff, 67, 38000, nec_encode },
[RC_PROTO_SANYO] = { "sanyo", 0x1fffff, 87, 38000, sanyo_encode },
[RC_PROTO_RC6_0] = { "rc6_0", 0xffff, 24, 36000, rc6_encode },
[RC_PROTO_RC6_0] = { "rc6_0", 0xffff, 41, 36000, rc6_encode },
[RC_PROTO_RC6_6A_20] = { "rc6_6a_20", 0xfffff, 52, 36000, rc6_encode },
[RC_PROTO_RC6_6A_24] = { "rc6_6a_24", 0xffffff, 60, 36000, rc6_encode },
[RC_PROTO_RC6_6A_32] = { "rc6_6a_32", 0xffffffff, 76, 36000, rc6_encode },
Expand Down
17 changes: 9 additions & 8 deletions liblircd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ impl<'a> Code<'a> {
}
}

#[derive(Clone, Copy, PartialEq, Debug)]
#[repr(u32)]
pub enum rc_proto {
RC_PROTO_UNKNOWN = 0,
Expand Down Expand Up @@ -391,12 +392,12 @@ pub enum rc_proto {
// These functions are defined in ir-encode.[ch], which comes from v4l-utils' ir-ctl
#[allow(unused)]
extern "C" {
fn protocol_match(name: *const c_char, proto: rc_proto);
fn protocol_carrier(proto: rc_proto) -> u32;
fn protocol_max_size(proto: rc_proto) -> u32;
fn protocol_scancode_valid(proto: rc_proto, scancode: *mut u32) -> bool;
fn protocol_scancode_mask(proto: rc_proto) -> u32;
fn protocol_encoder_available(proto: rc_proto) -> bool;
fn protocol_encode(proto: rc_proto, scancode: u32, buf: *mut u8) -> u32;
fn protocol_name(proto: rc_proto) -> *const c_char;
pub fn protocol_match(name: *const c_char, proto: rc_proto);
pub fn protocol_carrier(proto: rc_proto) -> u32;
pub fn protocol_max_size(proto: rc_proto) -> u32;
pub fn protocol_scancode_valid(proto: rc_proto, scancode: *mut u32) -> bool;
pub fn protocol_scancode_mask(proto: rc_proto) -> u32;
pub fn protocol_encoder_available(proto: rc_proto) -> bool;
pub fn protocol_encode(proto: rc_proto, scancode: u32, buf: *mut u32) -> u32;
pub fn protocol_name(proto: rc_proto) -> *const c_char;
}
41 changes: 9 additions & 32 deletions src/bin/commands/transmit.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#[cfg(target_os = "linux")]
use super::config::{open_lirc, Purpose};
use cir::lircd_conf;
use cir::{linux_protocol::LinuxProtocol, lircd_conf};
use irp::{Irp, Message, Pronto, Vartable};
use log::{error, info, warn};
use std::{ffi::OsStr, fs, path::Path, str::FromStr};
Expand Down Expand Up @@ -412,45 +412,22 @@ fn encode_scancode(protocol: &str, code: &str) -> Result<Message, String> {
return Err(format!("invalid scancode {code}"));
};

let (irp, mask) = match protocol.to_ascii_lowercase().as_str() {
// TODO needs decoder name and protocol number
"rc5" => ("{36k,msb,889}<1,-1|-1,1>(1,~CODE:1:6,T:1,CODE:5:8,CODE:6,^114m) [CODE:0..0x1FFF,T:0..1=0]", 0x1f7f),
"rc5x_20" => ("{36k,msb,889}<1,-1|-1,1>(1,~CODE:1:14,T:1,CODE:5:16,-4,CODE:8:6,CODE:6,^114m) [CODE:0..0x1fffff,T:0..1=0]", 0x1f7f3f),
"rc5_sz" => ("{36k,msb,889}<1,-1|-1,1>(1,~CODE:1:13,T:1,T:1,CODE:12,^114m) [CODE:0..0x2fff,T:0..1=0]", 0x2fff),
"sony12" => ("{40k,600}<1,-1|2,-1>(4,-1,CODE:7,CODE:5:16,^45m)* [CODE:0..0x1fffff]",0x1f007f),
"sony15" => ("{40k,600}<1,-1|2,-1>(4,-1,CODE:7,CODE:8:16,^45m)* [CODE:0..0xffffff]",0xff007f),
"sony20" => ("{40k,600}<1,-1|2,-1>(4,-1,CODE:7,CODE:5:16,CODE:8:8,^45m)* [CODE:0..0x1fffff]", 0x1fff7f),
"jvc" => ("{37.9k,527,33%}<1,-1|1,-3>(16,-8,CODE:16,1,^59.08m,(CODE:16,1,^46.42m)*) [CODE=0..0xffff]", 0xffff),
// TODO: necx and nec32 must not match nec
"nec" => ("{38.4k,564}<1,-1|1,-3>(16,-8,CODE:8:8,CODE:8,~CODE:8:8,~CODE:8,1,^108m,(16,-4,1,^108m)*) [CODE:0..0xffff]", 0xffff),
"sanyo" => ("{38k,562.5}<1,-1|1,-3>(16,-8,CODE:13:8,~CODE:13:8,CODE:8,~CODE:8,1,-42,(16,-8,1,-150)*) [CODE:0..0x1fffff]", 0x1fffff),
"rc6_0" => ("{36k,444,msb}<-1,1|1,-1>((6,-2,1:1,0:3,<-2,2|2,-2>(T:1),CODE:16,^107m)*,T=1-T) [CODE:0..0xffff,T@:0..1=0]", 0xffff),
"rc6_6a_20" => ("{36k,444,msb}<-1,1|1,-1>((6,-2,1:1,6:3,<-2,2|2,-2>(T:1),CODE:20,-100m)*,T=1-T)[CODE:0..0xfffff,T@:0..1=0]", 0xf_ffff),
"rc6_6a_24" => ("{36k,444,msb}<-1,1|1,-1>((6,-2,1:1,6:3,<-2,2|2,-2>(T:1),CODE:24,^105m)*,T=1-T)[CODE:0..0xffffff,T@:0..1=0]", 0xff_ff_ff),
"rc6_6a_32" => ("{36k,444,msb}<-1,1|1,-1>((6,-2,1:1,6:3,<-2,2|2,-2>(T:1),CODE:32,MCE=(CODE>>16)==0x800f||(CODE>>16)==0x8034||(CODE>>16)==0x8046,^105m)*,T=1-T){MCE=0}[CODE:0..0xffffffff,T@:0..1=0]", 0xffff_ffff),
"rc6_mce" => ("{36k,444,msb}<-1,1|1,-1>((6,-2,1:1,6:3,-2,2,CODE:16:16,T:1,CODE:15,MCE=(CODE>>16)==0x800f||(CODE>>16)==0x8034||(CODE>>16)==0x8046,^105m)*,T=1-T){MCE=1}[CODE:0..0xffffffff,T@:0..1=0]", 0xffff_ffff),
"sharp" => ("{38k,264}<1,-3|1,-7>(CODE:5:8,CODE:8,1:2,1,-165,CODE:5:8,~CODE:8,2:2,1,-165)*[CODE:0..0x1fff]", 0x1fff),
"rc-mm-12" => ("{36k,msb}<166.7,-277.8|166.7,-444.4|166.7,-611.1|166.7,-777.8>(416.7,-277.8,CODE:12,166.7,^27.778ms) [CODE:0..0xfff]", 0xfff),
"rc-mm-24" => ("{36k,msb}<166.7,-277.8|166.7,-444.4|166.7,-611.1|166.7,-777.8>(416.7,-277.8,CODE:24,166.7,^27.778ms) [CODE:0..0xffffff]", 0xfff_fff),
// TODO: toggle bit
"rc-mm-32" => ("{36k,msb}<166.7,-277.8|166.7,-444.4|166.7,-611.1|166.7,-777.8>(416.7,-277.8,CODE:32,166.7,^27.778ms) [CODE:0..0xffffffff]", 0xffff_ffff),
// TODO: xbox-dvd trailing space?
"xbox-dvd" => ("{38k,msb}<550,-900|550,-1900>(4000,-3900,~CODE:12,CODE:12,550,Xm) [CODE:0..0xfff]", 0xfff),
// xmp, mcir2
"imon" => ("{416,38k,msb}<-1|1>(1,<P:1,1:1,(CHK=CHK>>1,P=CHK&1)|0:2,(CHK=CHK>>1,P=1)>(CODE:31),^106m){P=1,CHK=0x7efec2} [CODE:0..0x7fffffff]", 0x7fffffff),
_ => {
return Err(format!("protocol {protocol} is not known"));
}
let Some(linux) = LinuxProtocol::find_like(protocol) else {
return Err(format!("protocol {protocol} is not known"));
};

let masked = scancode & mask;
if linux.irp.is_none() {
return Err(format!("protocol {protocol} is cannot be encoded"));
}

let masked = scancode & linux.scancode_mask as u64;

if masked != scancode {
warn!("error: scancode {scancode:#x} masked to {masked:#x}");
scancode = masked;
}

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

let mut vars = Vartable::new();

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod keymap;
pub mod linux_protocol;
#[cfg(target_os = "linux")]
pub mod lirc;
pub mod lircd_conf;
Expand Down
Loading

0 comments on commit 3283b6e

Please sign in to comment.