Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 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 @@ -29,6 +29,7 @@ env_logger = "0.11"
toml = "1.0.3"
aya = "0.13.1"
serde_json = "1.0.149"
tokio-stream = "0.1.18"

[profile.dev]
panic = "abort"
Expand Down
2 changes: 2 additions & 0 deletions crates/cardwire-daemon/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ anyhow.workspace = true
env_logger.workspace = true
toml.workspace = true
serde_json.workspace = true
tokio-stream.workspace = true

[[bin]]
name = "cardwired"
path = "src/daemon.rs"
23 changes: 16 additions & 7 deletions crates/cardwire-daemon/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,22 @@ enum FileKind {
ModeState,
PciState,
}
// TODO: Handle fs error for tomorrow
#[derive(Deserialize, Serialize)]
#[derive(Deserialize, Serialize, Debug)]
#[serde(default)]
pub struct CardwireConfig {
auto_apply_gpu_state: bool,
block_nvidia_vulkan: bool,
battery_auto_switch: bool,
}
impl Default for CardwireConfig {
fn default() -> Self {
CardwireConfig {
auto_apply_gpu_state: true,
block_nvidia_vulkan: false,
battery_auto_switch: false,
}
}
}

impl CardwireConfig {
/// Read TOML config file and return it's settings as a struct
// TODO: Error handling on std::fs
Expand Down Expand Up @@ -51,6 +60,9 @@ impl CardwireConfig {
pub fn auto_apply_gpu_state(&self) -> bool {
self.auto_apply_gpu_state
}
pub fn battery_auto_switch(&self) -> bool {
self.battery_auto_switch
}
}

// This is the easiest way i found to have a good looking json, might change later
Expand Down Expand Up @@ -186,10 +198,7 @@ fn create_default_file(kind: FileKind) -> anyhow::Result<()> {
.context("could not create default folder for cardwire.toml")?;
// Default config for cardwire
// TODO: Move to default trait?
let default_config = toml::to_string_pretty(&CardwireConfig {
auto_apply_gpu_state: true,
block_nvidia_vulkan: false,
})?;
let default_config = toml::to_string_pretty(&CardwireConfig::default())?;
// write
fs::write(format!("{}/cardwire.toml", CONFIG_PATH), default_config)
}
Expand Down
1 change: 1 addition & 0 deletions crates/cardwire-daemon/src/daemon.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! entry point of cardwired
mod config;
mod dbus;
mod listeners;
mod models;

use crate::models::Daemon;
Expand Down
45 changes: 45 additions & 0 deletions crates/cardwire-daemon/src/listeners.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//! Used to listen to other dbus interface, mainly for auto battery switch and display detection

use log::info;
use tokio_stream::StreamExt;
use zbus::{Connection, Result, proxy};

#[proxy(
interface = "org.freedesktop.UPower",
default_service = "org.freedesktop.UPower",
default_path = "/org/freedesktop/UPower"
)]
trait UPower {
#[zbus(property)]
fn on_battery(&self) -> Result<bool>;
}
#[proxy(
interface = "com.github.opengamingcollective.cardwire",
default_service = "com.github.opengamingcollective.cardwire",
default_path = "/com/github/opengamingcollective/cardwire"
)]
trait Cardwire {
#[zbus(property)]
fn set_mode(&self, mode: u32) -> Result<()>;
}

pub async fn watch_battery_status() -> zbus::Result<()> {
let connection = Connection::system().await?;
let upower_proxy = UPowerProxy::new(&connection).await?;

let cardwire = CardwireProxy::new(&connection).await?;
info!("Started listening to on_battery property");
let mut battery_stream = upower_proxy.receive_on_battery_changed().await;

while let Some(msg) = battery_stream.next().await {
if let Ok(state) = msg.get().await {
info!("battery event detected: {:?}", state);
match state {
true => cardwire.set_mode(0).await?,
false => cardwire.set_mode(1).await?,
};
}
}

Ok(())
}
7 changes: 5 additions & 2 deletions crates/cardwire-daemon/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,12 @@ impl Daemon {
Modes::Hybrid => 1,
Modes::Manual => 2,
};

self.set_mode(mode_to_apply as u32).await?;

// get config lock again
let config = self.state.config.read().await;
if config.battery_auto_switch() {
tokio::task::spawn(crate::listeners::watch_battery_status());
}
Ok(())
}
}
2 changes: 1 addition & 1 deletion nix/ci-2gpu.nix
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,6 @@
t.assertIn("Hybrid", machine.succeed("cat /var/lib/cardwire/mode.json"), "mode.json didnt get saved")

with subtest("Try to block default gpu"):
t.assertIn("cannot be blocked", machine.succeed("cardwire gpu 0 --block 2>&1"), "Default gpu got blocked")
t.assertIn("Per GPU block is only available on manual mode", machine.succeed("cardwire gpu 0 --block 2>&1"), "Default gpu got blocked")
'';
}
1 change: 1 addition & 0 deletions nix/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ in
];
runtimeDeps = [
pkgs.hwdata
pkgs.upower
];
doCheck = false;
doInstallCheck = true;
Expand Down
2 changes: 1 addition & 1 deletion packages/arch-linux/cardwire-PKGBUILD
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pkgdesc='GPU manager for Linux using eBPF LSM hooks'
arch=('x86_64')
url='https://github.com/OpenGamingCollective/cardwire'
license=('GPL3')
depends=('hwdata' 'dbus' 'systemd')
depends=('hwdata' 'dbus' 'systemd' 'upower')
makedepends=('libbpf' 'rust' 'clang')
source=("https://github.com/OpenGamingCollective/cardwire/archive/refs/tags/v$pkgver.tar.gz")
sha256sums=('37882d4d0d431c3ff48e24bd47cea03b7847080623254d8bdb4af9846134d700')
Expand Down
3 changes: 3 additions & 0 deletions packages/fedora/cardwire.spec
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ BuildRequires: libbpf-devel
BuildRequires: make
BuildRequires: systemd-rpm-macros

Requires: hwdata
Requires: upower

%description
Cardwire is a GPU manager for Linux that uses eBPF LSM hooks to block or
unblock access to GPU device nodes.
Expand Down