Skip to content

Commit

Permalink
Logind fallback support for unprivileged users (#83)
Browse files Browse the repository at this point in the history
  • Loading branch information
geekylthyosaur committed Aug 6, 2023
1 parent 77e5e0d commit 55d98fe
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 7 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- run: sudo apt-get update
- run: sudo apt-get -y install v4l-utils libv4l-dev libudev-dev libvulkan-dev
- run: sudo apt-get -y install v4l-utils libv4l-dev libudev-dev libvulkan-dev libdbus-1-dev
- run: make test

lint:
Expand All @@ -21,5 +21,5 @@ jobs:
steps:
- uses: actions/checkout@v3
- run: sudo apt-get update
- run: sudo apt-get -y install v4l-utils libv4l-dev libudev-dev libvulkan-dev
- run: sudo apt-get -y install v4l-utils libv4l-dev libudev-dev libvulkan-dev libdbus-1-dev
- run: make lint
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ env_logger = "0.9"
inotify = "0.10"
lazy_static = "1.4"
xdg = "2.4.1"
dbus = "0.9.7"

[dev-dependencies]
mockall = "0.11.4"
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,17 @@ Use one of the available packages and methods below:

[![CI](https://github.com/maximbaz/wluma/actions/workflows/ci.yml/badge.svg)](https://github.com/maximbaz/wluma/actions/workflows/ci.yml)

If you want to build the app yourself, make sure you use latest stable Rust, otherwise you might get compilation errors! Using `rustup` is perhaps the easiest. Ubuntu needs the following dependencies: `sudo apt-get -y install v4l-utils libv4l-dev libudev-dev libvulkan-dev`.
If you want to build the app yourself, make sure you use latest stable Rust, otherwise you might get compilation errors! Using `rustup` is perhaps the easiest. Ubuntu needs the following dependencies: `sudo apt-get -y install v4l-utils libv4l-dev libudev-dev libvulkan-dev libdbus-1-dev`.

Then simply run `make build`.

## Permissions

In order to access backlight devices, `wluma` must either run as `root`, or preferrably instead you should add your user to `video` group in combination with installing the supplied `90-wluma-backlight.rules` udev rule (don't forget to reboot thereafter).
In order to access backlight devices, `wluma` must either:

- have direct driver access: install the supplied `90-wluma-backlight.rules` udev rule, add your user to the `video` group and reboot (fastest)
- run on a system that uses `elogind` or `systemd-logind` (they provide a safe interface for unprivileged users to control device's brightness through `dbus`, no configuration necessary)
- run as `root` (not recommended)

## Configuration

Expand Down
51 changes: 49 additions & 2 deletions src/brightness/backlight.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,62 @@
use crate::device_file::{read, write};
use dbus::channel::Sender;
use dbus::{self, blocking::Connection, Message};
use inotify::{Inotify, WatchMask};
use std::error::Error;
use std::fs;
use std::fs::{File, OpenOptions};
use std::io::ErrorKind;
use std::path::Path;

struct Dbus {
connection: Connection,
message: Message,
}

pub struct Backlight {
file: File,
min_brightness: u64,
max_brightness: u64,
inotify: Inotify,
current: Option<u64>,
dbus: Option<Dbus>,
has_write_permission: bool,
}

impl Backlight {
pub fn new(path: &str, min_brightness: u64) -> Result<Self, Box<dyn Error>> {
let brightness_path = Path::new(path).join("brightness");
let file = OpenOptions::new()
let mut file = OpenOptions::new()
.read(true)
.write(true)
.open(&brightness_path)?;
let current_brightness = read(&mut file)?;
let has_write_permission = write(&mut file, current_brightness).is_ok();

let dbus = if has_write_permission {
None
} else {
let id = Path::new(path)
.file_name()
.and_then(|x| x.to_str())
.ok_or("Unable to identify backlight ID")?;

let message = Message::new_method_call(
"org.freedesktop.login1",
"/org/freedesktop/login1/session/auto",
"org.freedesktop.login1.Session",
"SetBrightness",
)
.ok()
.map(|m| m.append2("backlight", id));

Connection::new_system().ok().and_then(|connection| {
message.map(|message| Dbus {
connection,
message,
})
})
};

let max_brightness = fs::read_to_string(Path::new(path).join("max_brightness"))?
.trim()
Expand All @@ -40,6 +76,8 @@ impl Backlight {
max_brightness,
inotify,
current: None,
dbus,
has_write_permission,
})
}
}
Expand Down Expand Up @@ -70,7 +108,16 @@ impl super::Brightness for Backlight {
fn set(&mut self, value: u64) -> Result<u64, Box<dyn Error>> {
let value = value.clamp(self.min_brightness, self.max_brightness);

write(&mut self.file, value as f64)?;
if self.has_write_permission {
write(&mut self.file, value as f64)?;
} else if let Some(dbus) = &self.dbus {
dbus.connection
.send(dbus.message.duplicate()?.append1(value as u32))
.map_err(|_| "Unable to send brightness change message via dbus")?;
} else {
Err(std::io::Error::from(ErrorKind::PermissionDenied))?
}

self.current = Some(value);

// Consume file events to not trigger get() update
Expand Down
2 changes: 1 addition & 1 deletion src/brightness/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ impl Controller {
if target.reached(current) {
self.target = None;
} else {
let new_value = (current as i64 + target.step).max(0) as u64;
let new_value = current.saturating_add_signed(target.step);
match self.brightness.set(new_value) {
Ok(new_value) => self.current = Some(new_value),
Err(err) => log::error!(
Expand Down

0 comments on commit 55d98fe

Please sign in to comment.