diff --git a/Cargo.lock b/Cargo.lock index 56869a4..4746e3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,9 +68,9 @@ dependencies = [ [[package]] name = "i2c-linux-sys" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b70fd3d30157850c87f4c7c09c0857d9c2e8c996bcbe23ec1299126e0479ec" +checksum = "55cd060ed0016621d3da4ed3a23b0158084de90d1f3a8e59f3d391aacd3bbcf8" dependencies = [ "bitflags", "byteorder", @@ -79,9 +79,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.121" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" +checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" [[package]] name = "libudev-sys" @@ -104,9 +104,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "minimal-lexical" @@ -126,9 +126,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "resize-slice" diff --git a/flake.lock b/flake.lock index db22ab7..c6c2c5c 100644 --- a/flake.lock +++ b/flake.lock @@ -6,11 +6,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1647857022, - "narHash": "sha256-Aw70NWLOIwKhT60MHDGjgWis3DP3faCzr6ap9CSayek=", + "lastModified": 1649691969, + "narHash": "sha256-nY1aUWIyh3TcGVo3sn+3vyCh+tOiEZL4JtMX3aOZSeY=", "owner": "numtide", "repo": "devshell", - "rev": "0a5ff74dacb9ea22614f64e61aeb3ca0bf0e7311", + "rev": "e22633b05fec2fe196888c593d4d9b3f4f648a25", "type": "github" }, "original": { @@ -36,11 +36,26 @@ }, "flake-utils_2": { "locked": { - "lastModified": 1648297722, - "narHash": "sha256-W+qlPsiZd8F3XkzXOzAoR+mpFqzm3ekQkJNa+PIh1BQ=", + "lastModified": 1649676176, + "narHash": "sha256-OWKJratjt2RW151VUlJPRALb7OU2S5s+f0vLj4o1bHM=", "owner": "numtide", "repo": "flake-utils", - "rev": "0f8662f1319ad6abf89b3380dd2722369fc51ade", + "rev": "a4b154ebbdc88c8498a5c7b01589addc9e9cb678", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "locked": { + "lastModified": 1637014545, + "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", "type": "github" }, "original": { @@ -54,11 +69,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1648544490, - "narHash": "sha256-EoBDcccV70tfz2LAs5lK0BjC7en5mzUVlgLsd5E6DW4=", + "lastModified": 1649096192, + "narHash": "sha256-7O8e+eZEYeU+ET98u/zW5epuoN/xYx9G+CIh4DjZVzY=", "owner": "nix-community", "repo": "naersk", - "rev": "e30ef9a5ce9b3de8bb438f15829c50f9525ca730", + "rev": "d626f73332a8f587b613b0afe7293dd0777be07d", "type": "github" }, "original": { @@ -109,12 +124,48 @@ "type": "indirect" } }, + "nixpkgs_4": { + "locked": { + "lastModified": 1637453606, + "narHash": "sha256-Gy6cwUswft9xqsjWxFYEnx/63/qzaFUwatcbV5GF/GQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "8afc4e543663ca0a6a4f496262cd05233737e732", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { "devshell": "devshell", "flake-utils": "flake-utils_2", "naersk": "naersk", - "nixpkgs": "nixpkgs_3" + "nixpkgs": "nixpkgs_3", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "flake-utils": "flake-utils_3", + "nixpkgs": "nixpkgs_4" + }, + "locked": { + "lastModified": 1649644592, + "narHash": "sha256-q4vQ54pmCC+b5+bdsH2/90jIeiydTAJhF2IvP13r3yA=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "4770c6c6cb518d2c5b660c5099816c3512d8bdad", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" } } }, diff --git a/flake.nix b/flake.nix index 5d8fc1f..6905237 100644 --- a/flake.nix +++ b/flake.nix @@ -4,12 +4,17 @@ inputs.devshell.url = "github:numtide/devshell"; inputs.flake-utils.url = "github:numtide/flake-utils"; inputs.naersk.url = "github:nix-community/naersk"; + inputs.rust-overlay.url = "github:oxalica/rust-overlay"; - outputs = { self, flake-utils, devshell, nixpkgs, naersk }: + outputs = { self, flake-utils, devshell, nixpkgs, naersk, rust-overlay }: flake-utils.lib.eachDefaultSystem (system: let - pkgs = nixpkgs.legacyPackages."${system}"; + pkgs = import nixpkgs { + inherit system; + overlays = [ (import rust-overlay) ]; + }; naersk-lib = naersk.lib."${system}"; in { + /* defaultPackage = naersk-lib.buildPackage { pname = "ddcmqtt"; root = ./.; @@ -28,8 +33,8 @@ nativeBuildInputs = with pkgs; [ libudev pkgconfig ]; }; */ - devshell = pkgs.mkShell{ - nativeBuildInputs = with pkgs; [ rustc cargo libudev pkgconfig ]; + devShell = pkgs.mkShell{ + nativeBuildInputs = with pkgs; [ rust-bin.stable.latest.default libudev pkgconfig ]; }; }); } diff --git a/src/bin/ddcmqtt.rs b/src/bin/ddcmqtt.rs index fc9a6d2..252fe98 100644 --- a/src/bin/ddcmqtt.rs +++ b/src/bin/ddcmqtt.rs @@ -1,7 +1,5 @@ use ::ddcmqtt::{main as main_, StdError}; - fn main() -> StdError<()> { main_() } - diff --git a/src/bin/setmon.rs b/src/bin/setmon.rs index dc93f63..7d63edd 100644 --- a/src/bin/setmon.rs +++ b/src/bin/setmon.rs @@ -1,7 +1,7 @@ -use ddc_i2c::{I2cDeviceEnumerator, I2cDeviceDdc}; use ddc::Ddc; +use ddc_i2c::{I2cDeviceDdc, I2cDeviceEnumerator}; -use ::ddcmqtt::{StdError}; +use ::ddcmqtt::StdError; fn main() -> StdError<()> { let args_: Vec<_> = std::env::args().skip(1).collect(); @@ -10,14 +10,14 @@ fn main() -> StdError<()> { ["brightness", arg] => ddc_all(0x10, arg.parse::()?), ["input", arg] => ddc_all(0x60, arg.parse::()?), _ => Err("Bad usage".into()), - }?; Ok(()) } fn ddc_all(feat: u8, val: u16) -> StdError<()> { - for mut display in I2cDeviceEnumerator::new()? { - display.set_vcp_feature(feat, val)?; - } + let mut m1 = ddc_i2c::from_i2c_device("/dev/i2c-20")?; + let mut m2 = ddc_i2c::from_i2c_device("/dev/i2c-21")?; + m1.set_vcp_feature(feat, val)?; + m2.set_vcp_feature(feat, val)?; Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index b7da121..eab79cf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,12 @@ -#![allow(unreachable_code)] use ddc::Ddc; -use ddc_i2c::{I2cDeviceEnumerator, I2cDeviceDdc}; -use rosc; -use std::net::UdpSocket; -use std::thread; -use std::sync::mpsc::{channel, Receiver, Sender}; -use std::time::{Duration, Instant}; +use ddc_i2c::{I2cDeviceDdc, I2cDeviceEnumerator}; use std::collections::HashMap; - use std::error::Error; +use std::net::UdpSocket; +use std::sync::mpsc::{channel, Receiver, Sender}; +use std::thread; +use std::time::{Duration, Instant}; +use rosc; pub type StdError = Result>; @@ -18,7 +16,7 @@ enum Command { enum MonitorCommand { Brightness(u8), - Input(u8) + Input(u8), } impl MonitorCommand { @@ -37,10 +35,9 @@ impl MonitorCommand { } } - // Run an i2c command handler for a specific i2c device, rate limiting each type of command fn run_i2c(mut dev: I2cDeviceDdc, command_channel: Receiver) { - let mut last_sent_command: HashMap<&str, Option> = HashMap::new(); + let mut last_sent_command: HashMap<&str, Option> = HashMap::new(); loop { let cmd = command_channel.recv().unwrap(); if let Some(last) = last_sent_command.entry(cmd.cmd_str()).or_insert(None) { @@ -52,7 +49,7 @@ fn run_i2c(mut dev: I2cDeviceDdc, command_channel: Receiver) { match cmd { MonitorCommand::Brightness(b) => dev.set_vcp_feature(0x10, b.into()).unwrap(), // Hack - add 15 to align with DELL monitors - MonitorCommand::Input(i) => dev.set_vcp_feature(0x60, (i+15).into()).unwrap(), + MonitorCommand::Input(i) => dev.set_vcp_feature(0x60, (i + 15).into()).unwrap(), } last_sent_command.insert(cmd.cmd_str(), Some(Instant::now())); } @@ -61,24 +58,29 @@ fn run_i2c(mut dev: I2cDeviceDdc, command_channel: Receiver) { pub fn main() -> StdError<()> { let displays = I2cDeviceEnumerator::new().unwrap().collect::>(); println!("Enumerated {} displays", displays.len()); - let txes: Vec<_> = displays.into_iter().map(|d| { - let (tx, rx) = channel(); - thread::spawn(move|| run_i2c(d, rx)); - tx - }).collect(); + let txes: Vec<_> = displays + .into_iter() + .map(|d| { + let (tx, rx) = channel(); + thread::spawn(move || run_i2c(d, rx)); + tx + }) + .collect(); let sock = UdpSocket::bind("0.0.0.0:1234").unwrap(); let mut buf = [0u8; rosc::decoder::MTU]; loop { - let (size, addr) = sock.recv_from(&mut buf).unwrap(); + let (size, addr) = sock.recv_from(&mut buf).unwrap(); println!("Got {} bytes from {}", size, addr); let (_, pack) = rosc::decoder::decode_udp(&buf[..size]).unwrap(); match pack { rosc::OscPacket::Message(msg) => { match osc_message_to_command(msg) { - Ok(cmd) => if let Err(e) = handle_cmd(cmd, &txes) { - println!("Error handling command: {:?}", e); - }, + Ok(cmd) => { + if let Err(e) = handle_cmd(cmd, &txes) { + println!("Error handling command: {:?}", e); + } + } Err(e) => println!("Unrecognised OSC command: {:?}", e), }; } @@ -103,13 +105,18 @@ fn osc_message_to_command(msg: rosc::OscMessage) -> StdError { ["monitor", idx, control] => { println!("Monitor {}, control {}, args {:?}", idx, control, msg.args); let command = match *control { - "brightness" => Some(MonitorCommand::Brightness((msg.args[0].clone().float().unwrap() * 100.0) as u8)), - "input" => Some(MonitorCommand::Input((msg.args[0].clone().int().unwrap()) as u8)), + "brightness" => Some(MonitorCommand::Brightness( + (msg.args[0].clone().float().unwrap() * 100.0) as u8, + )), + "input" => Some(MonitorCommand::Input( + (msg.args[0].clone().int().unwrap()) as u8, + )), _ => None, - }.ok_or(format!("Unrecognised monitor control: {}", *control))?; + } + .ok_or(format!("Unrecognised monitor control: {}", *control))?; let idx = idx.parse::().or(Err("Bad monitor index"))?; Ok(Command::Monitor((idx, command))) - }, + } _ => Err("Unsupported osc address, ignoring".into()), } }