Compare commits

..

44 Commits

Author SHA1 Message Date
Luke Jones cd0b9fe350 Merge branch 'fluke/asus_bios_settings' into 'next'
Fluke/asus bios settings

See merge request asus-linux/asus-nb-ctrl!15
2021-01-26 08:08:13 +00:00
Luke 82900f4645 CLI args for bios. Cleanup and improve
- dbus method for 'supported modes'
- add dedicated gfx safety
- bring ctrl-gfx back in to main control for better integration
- safely upgrade config files
2021-01-26 21:07:19 +13:00
Luke 703bba9ffd Correct changelog 2021-01-10 22:34:45 +13:00
Luke Jones 73706154a4 Merge branch 'fluke/fixes' into 'next'
Fixes

See merge request asus-linux/asus-nb-ctrl!14
2021-01-10 09:31:46 +00:00
Luke c9b2a0c777 Fixes
- Adjust gfx controller to assume that the graphics driver is loaded if the
  mode is set for nvidia/hybrid
- Small code adjustments for error handling
2021-01-10 22:27:56 +13:00
Luke 54cc51fe5d Minor update to deps 2021-01-09 13:48:13 +13:00
Luke 81645d0777 Update deps and fmt 2021-01-09 13:42:46 +13:00
Luke Jones d61c180ee5 Update discord link 2020-12-20 21:21:53 +00:00
Luke Jones a668800fd9 Merge branch 'asere/anime_better_options' into 'next'
Better anime options & gumdrop error Display

See merge request asus-linux/asus-nb-ctrl!12
2020-12-20 21:18:51 +00:00
Asere 3bdc11c994 Better anime options & gumdrop error Display 2020-11-25 18:37:36 +01:00
Luke Jones b496139063 Merge branch 'StaticRocket-next-patch-05672' into 'next'
Update paths and variables to follow GNU Make standards

See merge request asus-linux/asus-nb-ctrl!13
2020-11-08 00:17:44 +00:00
Randolph Sapp 607483629a Don't rebuild during install
Rebuild during all
2020-11-08 00:17:44 +00:00
Luke D Jones 5c8d138cef Update readme 2020-10-25 20:37:53 +13:00
Luke D Jones e3db1f7c4c Add notification dbus signal for aura next/prev 2020-10-25 19:34:40 +13:00
Luke D Jones de3b803f14 Add DBUS methods to toggle next/previous aura mode 2020-10-25 15:49:14 +13:00
Luke D Jones 0558f919c4 Add DBUS method to toggle to next profile 2020-10-25 15:02:35 +13:00
Luke Jones 68ea73c847 Merge branch 'asere/anime_on_off' into 'next'
AniMe: adding --on and --off options to turn on/off (and accept/reject write requests)

See merge request asus-linux/asus-nb-ctrl!11
2020-10-25 01:14:12 +00:00
Luke Jones 96ddb7132d Merge branch 'asere/show_keyboard_brightness' into 'next'
Improving user experience by showing current keyboard led brightness

See merge request asus-linux/asus-nb-ctrl!10
2020-10-25 01:12:21 +00:00
Asere d36ac44603 updating option "-k" to show current brightness: asusctl -k 2020-10-23 02:00:08 +02:00
Asere 5d06c87943 AniMe: adding --on and --off options to turn on/off (and accept/reject write requests) 2020-10-22 14:09:05 +02:00
Luke D Jones 588e3c0102 Panic if config file is bad 2020-10-22 08:28:12 +13:00
Luke D Jones 6ce32c1cab Fix one super silly bug
closes #30
2020-10-22 08:16:00 +13:00
Luke Jones a23c51e5db Adding Anime commands to asusctl 2020-10-11 22:46:06 +00:00
Asere 3845071ba3 adding Anime feature: led brightness command to asusctl, and updating dbus client 2020-10-12 00:11:26 +02:00
Luke Jones a48b3634bf Merge branch 'next' into 'next'
Add some basic zsh completions for asusctl

See merge request asus-linux/asus-nb-ctrl!8
2020-10-05 00:38:34 +00:00
Luke Jones 806882b2e9 Merge branch 'next' into 'next'
fixed fan presets for profiles

See merge request asus-linux/asus-nb-ctrl!7
2020-10-05 00:37:43 +00:00
Luke D Jones 9ac3c46fe6 Actually enable/disable gfx switch control 2020-10-05 09:32:46 +13:00
Luke D Jones 6817a1c027 Bump dbus autogen 2020-10-05 09:31:07 +13:00
Dylan Jones cf2be1b12b Add some basic zsh completions for asusctl 2020-09-30 13:28:05 -04:00
Luke D Jones 9ffeb19c8c Bump version 2020-09-29 21:30:23 +13:00
Cuong a7f6e8bd24 fixed fan presets for profiles 2020-09-28 10:04:57 +00:00
Luke Jones f61f62c219 Merge branch 'feature/dbus-profile-name' into 'next'
 Add ActiveProfileName() dbus method returning name of current profile

See merge request asus-linux/asus-nb-ctrl!5
2020-09-26 08:50:03 +00:00
Andreas Streichardt bb70fd7b71 Add ActiveProfileName() dbus method returning name of current profile 2020-09-26 09:05:50 +02:00
Luke D Jones b80c860b7a Fix args to systemctl for reboot 2020-09-25 21:05:47 +12:00
Luke D Jones 3c7544f034 Explicitly state arch is not supported 2020-09-25 14:14:21 +12:00
Luke D Jones 6746c2b654 Update changelog 2020-09-24 09:04:49 +12:00
Luke D Jones 8d59f89438 Add verbose error for LED node missing 2020-09-24 08:18:10 +12:00
Luke D Jones 5753160e91 Don't throw away do_task error, log it 2020-09-24 08:10:05 +12:00
Luke D Jones 622cd9d943 Fix timeout for GFX switching 2020-09-24 08:00:37 +12:00
Luke D Jones 2daa7f0811 Git internal version from crate version 2020-09-23 22:12:47 +12:00
Luke D Jones 05c53df0ed Better description of config panic 2020-09-23 21:24:25 +12:00
Luke D Jones a7419cbc4c Remove many unwraps or change to maps 2020-09-23 20:47:33 +12:00
Luke D Jones 67ad38a7e6 Ditch the gsync line in screen settings file. Oops
- Add force option to `systemctl reboot`. Be careful.
2020-09-23 16:51:46 +12:00
Luke Jones e572ae2c62 Update Makefile 2020-09-23 02:32:25 +00:00
46 changed files with 2199 additions and 561 deletions
+41 -1
View File
@@ -6,7 +6,47 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
# [2.0.0] - 2020-09-21 # [2.2.0] - 2021-01-26
### Added
- Dbus command to fetch all supported functions of the laptop. That is, all the
functions that asusd supports for the currently running laptop.
- Bios setting toggles for:
+ Dedicated gfx toggle (support depends on the laptop)
+ Bios boot POST sound toggle
### Changed
- added config option for dedicated gfx mode on laptops with it to enable
switching directly to dedicated using `asusctl graphics -m nvidia`
# [2.1.2] - 2021-01-10
### Changed
- Adjust gfx controller to assume that the graphics driver is loaded if the
mode is set for nvidia/hybrid
# [2.1.1] - 2021-01-09
### Changed
- Updates to dependencies
# [2.1.0] - 2020-10-25
### Added
- Option to turn off AniMe display (@asere)
### Changed
- Change option -k to show current LED bright (@asere)
- Correctly disable GFX control via config
- Panic and exit if config can't be parsed
- Add DBUS method to toggle to next fan/thermal profile
- Add DBUS method to toggle to next/prev Aura mode
# [2.0.5] - 2020-09-29
### Changed
- Bugfixes
# [2.0.4] - 2020-09-24
### Changed
- Better and more verbose error handling and logging in many places.
- Fix timeout for client waiting on reply for graphics switching
# [2.0.2] - 2020-09-21
### Changed ### Changed
- graphics options via CLI are now a command block: - graphics options via CLI are now a command block:
+ `asusctl graphics` + `asusctl graphics`
Generated
+394 -152
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,5 +1,5 @@
[workspace] [workspace]
members = ["asus-notify", "asus-nb-ctrl", "asus-nb", "ctrl-gfx"] members = ["asus-notify", "asus-nb-ctrl", "asus-nb"]
[profile.release] [profile.release]
lto = true lto = true
+48 -42
View File
@@ -1,36 +1,37 @@
prefix ?= /usr VERSION := $(shell grep -Pm1 'version = "(\d.\d.\d)"' asus-nb-ctrl/Cargo.toml | cut -d'"' -f2)
sysconfdir ?= /etc
INSTALL = install
INSTALL_PROGRAM = ${INSTALL} -D -m 0755
INSTALL_DATA = ${INSTALL} -D -m 0644
prefix = /usr
exec_prefix = $(prefix) exec_prefix = $(prefix)
bindir = $(exec_prefix)/bin bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
includedir = $(prefix)/include
datarootdir = $(prefix)/share datarootdir = $(prefix)/share
datadir = $(datarootdir) libdir = $(exec_prefix)/lib
zshcpl = $(datarootdir)/zsh/site-functions
SRC = Cargo.toml Cargo.lock Makefile $(shell find -type f -wholename '**/src/*.rs') BIN_C := asusctl
BIN_D := asusd
BIN_N := asus-notify
LEDCFG := asusd-ledmodes.toml
X11CFG := 90-nvidia-screen-G05.conf
PMRULES := 90-asusd-nvidia-pm.rules
.PHONY: all clean distclean install uninstall update SRC := Cargo.toml Cargo.lock Makefile $(shell find -type f -wholename '**/src/*.rs')
BIN_C=asusctl
BIN_D=asusd
BIN_N=asus-notify
LEDCFG=asusd-ledmodes.toml
X11CFG=90-nvidia-screen-G05.conf
PMRULES=90-asusd-nvidia-pm.rules
VERSION:=$(shell grep -Pm1 'version = "(\d.\d.\d)"' asus-nb-ctrl/Cargo.toml | cut -d'"' -f2)
DEBUG ?= 0 DEBUG ?= 0
ifeq ($(DEBUG),0) ifeq ($(DEBUG),0)
ARGS += "--release" ARGS += --release
TARGET = release TARGET = release
endif endif
VENDORED ?= 0 VENDORED ?= 0
ifeq ($(VENDORED),1) ifeq ($(VENDORED),1)
ARGS += "--frozen" ARGS += --frozen
endif endif
all: target/release/$(BIN_D) all: build
clean: clean:
cargo clean cargo clean
@@ -38,34 +39,37 @@ clean:
distclean: distclean:
rm -rf .cargo vendor vendor.tar.xz rm -rf .cargo vendor vendor.tar.xz
install: all install:
install -D -m 0755 "target/release/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)" $(INSTALL_PROGRAM) "./target/release/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)"
install -D -m 0755 "target/release/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)" $(INSTALL_PROGRAM) "./target/release/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
install -D -m 0755 "target/release/$(BIN_N)" "$(DESTDIR)$(bindir)/$(BIN_N)" $(INSTALL_PROGRAM) "./target/release/$(BIN_N)" "$(DESTDIR)$(bindir)/$(BIN_N)"
install -D -m 0644 "data/$(PMRULES)" "$(DESTDIR)/lib/udev/rules.d/$(PMRULES)" $(INSTALL_DATA) "./data/$(PMRULES)" "$(DESTDIR)$(libdir)/udev/rules.d/$(PMRULES)"
install -D -m 0644 "data/$(BIN_D).rules" "$(DESTDIR)/lib/udev/rules.d/99-$(BIN_D).rules" $(INSTALL_DATA) "./data/$(BIN_D).rules" "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules"
install -D -m 0644 "data/$(PMRULES).rules" "$(DESTDIR)/lib/udev/rules.d/$(PMRULES).rules" $(INSTALL_DATA) "./data/$(LEDCFG)" "$(DESTDIR)/etc/asusd/$(LEDCFG)"
install -D -m 0644 "data/$(LEDCFG)" "$(DESTDIR)$(sysconfdir)/asusd/$(LEDCFG)" $(INSTALL_DATA) "./data/$(BIN_D).conf" "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf"
install -D -m 0644 "data/$(BIN_D).conf" "$(DESTDIR)$(sysconfdir)/dbus-1/system.d/$(BIN_D).conf" $(INSTALL_DATA) "./data/$(X11CFG)" "$(DESTDIR)$(datarootdir)/X11/xorg.conf.d/$(X11CFG)"
install -D -m 0644 "data/$(X11CFG)" "$(DESTDIR)$(sysconfdir)/X11/xorg.conf.d/$(X11CFG)" $(INSTALL_DATA) "./data/$(BIN_D).service" "$(DESTDIR)$(libdir)/systemd/system/$(BIN_D).service"
install -D -m 0644 "data/$(BIN_D).service" "$(DESTDIR)/lib/systemd/system/$(BIN_D).service" $(INSTALL_DATA) "./data/$(BIN_N).service" "$(DESTDIR)$(libdir)/systemd/user/$(BIN_N).service"
install -D -m 0644 "data/$(BIN_N).service" "$(DESTDIR)/lib/systemd/user/$(BIN_N).service" $(INSTALL_DATA) "./data/icons/asus_notif_yellow.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_yellow.png"
install -D -m 0644 "data/icons/asus_notif_yellow.png" "$(DESTDIR)/usr/share/icons/hicolor/512x512/apps/asus_notif_yellow.png" $(INSTALL_DATA) "./data/icons/asus_notif_green.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_green.png"
install -D -m 0644 "data/icons/asus_notif_green.png" "$(DESTDIR)/usr/share/icons/hicolor/512x512/apps/asus_notif_green.png" $(INSTALL_DATA) "./data/icons/asus_notif_red.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_red.png"
install -D -m 0644 "data/icons/asus_notif_red.png" "$(DESTDIR)/usr/share/icons/hicolor/512x512/apps/asus_notif_red.png" $(INSTALL_DATA) "./data/_asusctl" "$(DESTDIR)$(zshcpl)/_asusctl"
uninstall: uninstall:
rm -f "$(DESTDIR)$(bindir)/$(BIN_C)" rm -f "$(DESTDIR)$(bindir)/$(BIN_C)"
rm -f "$(DESTDIR)$(bindir)/$(BIN_D)" rm -f "$(DESTDIR)$(bindir)/$(BIN_D)"
rm -f "$(DESTDIR)$(bindir)/$(BIN_N)" rm -f "$(DESTDIR)$(bindir)/$(BIN_N)"
rm -f "$(DESTDIR)/lib/udev/rules.d/$(PMRULES)" rm -f "$(DESTDIR)$(libdir)/udev/rules.d/$(PMRULES)"
rm -f "$(DESTDIR)/lib/udev/rules.d/99-$(BIN_D).rules" rm -f "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules"
rm -f "$(DESTDIR)/lib/udev/rules.d/$(PMRULES).rules" rm -f "$(DESTDIR)/etc/asusd/$(LEDCFG)"
rm -f "$(DESTDIR)$(sysconfdir)/dbus-1/system.d/$(BIN_D).conf" rm -f "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf"
rm -f "$(DESTDIR)$(sysconfdir)/X11/xorg.conf.d/$(X11CFG)" rm -f "$(DESTDIR)$(datarootdir)/X11/xorg.conf.d/$(X11CFG)"
rm -f "$(DESTDIR)/lib/systemd/system/$(BIN_D).service" rm -f "$(DESTDIR)$(libdir)/systemd/system/$(BIN_D).service"
rm -r "$(DESTDIR)/lib/systemd/user/$(BIN_N).service" rm -r "$(DESTDIR)$(libdir)/systemd/user/$(BIN_N).service"
rm -r "$(DESTDIR)/usr/share/icons/hicolor/512x512/apps/asus_notif_*" rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_yellow.png"
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_green.png"
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_red.png"
rm -f "$(DESTDIR)$(zshcpl)/_asusctl"
update: update:
cargo update cargo update
@@ -79,9 +83,11 @@ vendor:
tar pcfJ vendor_asus-nb-ctrl_$(VERSION).tar.xz vendor tar pcfJ vendor_asus-nb-ctrl_$(VERSION).tar.xz vendor
rm -rf vendor rm -rf vendor
target/release/$(BIN_D): $(SRC) build:
ifeq ($(VENDORED),1) ifeq ($(VENDORED),1)
@echo "version = $(VERSION)" @echo "version = $(VERSION)"
tar pxf vendor_asus-nb-ctrl_$(VERSION).tar.xz tar pxf vendor_asus-nb-ctrl_$(VERSION).tar.xz
endif endif
cargo build $(ARGS) cargo build $(ARGS)
.PHONY: all clean distclean install uninstall update build
+23 -11
View File
@@ -5,6 +5,8 @@ but can also be used with non-asus laptops with reduced features.
**NOTICE:** **NOTICE:**
This app is developed and tested on fedora only. Support is not provided for Arch or Arch based distros.
This program requires the kernel patch [here](https://www.spinics.net/lists/linux-input/msg68977.html) to be applied. This program requires the kernel patch [here](https://www.spinics.net/lists/linux-input/msg68977.html) to be applied.
Alternatively you may use the dkms module for 'hid-asus-rog` from one of the Alternatively you may use the dkms module for 'hid-asus-rog` from one of the
repositories [here](https://download.opensuse.org/repositories/home:/luke_nukem:/asus/). repositories [here](https://download.opensuse.org/repositories/home:/luke_nukem:/asus/).
@@ -23,7 +25,7 @@ in to the kernel.
## Discord ## Discord
[Discord server link](https://discord.gg/PVyFzWj) [Discord server link](https://discord.gg/ngbdKabAnP)
## SUPPORTED LAPTOPS ## SUPPORTED LAPTOPS
@@ -74,9 +76,6 @@ stray configs blocking nvidia modules from loading in:
If you have installed the Nvidia driver manually you will require the If you have installed the Nvidia driver manually you will require the
`data/90-asusd-nvidia-pm.rules` udev rule to be installed in `/etc/udev/rules.d/`. `data/90-asusd-nvidia-pm.rules` udev rule to be installed in `/etc/udev/rules.d/`.
The above seems to also apply to Arch in general as it leaves a lot of things up
to the user.
### fedora and openSUSE ### fedora and openSUSE
You *may* need a file `/etc/dracut.conf.d/90-nvidia-dracut-G05.conf` installed You *may* need a file `/etc/dracut.conf.d/90-nvidia-dracut-G05.conf` installed
@@ -118,16 +117,27 @@ If you model isn't getting the correct led modes, you can edit the file
use `cat /sys/class/dmi/id/product_name` to get details about your laptop. use `cat /sys/class/dmi/id/product_name` to get details about your laptop.
# Keybinds
To switch to next/previous Aura modes you will need to bind both the aura keys (if available) to one of:
**Next**
```
asusctl led-mode -n
```
**Previous**
```
asusctl led-mode -p
```
To switch Fan/Thermal profiles you need to bind the Fn+F5 key to `asusctl profile -n`.
# BUILDING # BUILDING
Requirements are: Requirements are rust >= 1.40 installed from rustup.io if the distro provided version is too old, and `make`.
- `rustc` + `cargo` + `make` **Ubuntu*:** `apt install libdbus-1-dev libclang-dev libudev-dev`
- `libusb-1.0-0-dev`
- `libdbus-1-dev` **fedora:** `dnf install clang-devel dbus-devel systemd-devel`
- `llvm`
- `libclang-dev`
- `libudev-dev`
## Installing ## Installing
@@ -135,6 +145,8 @@ Packaging and auto-builds are available [here](https://build.opensuse.org/packag
Download repositories are available [here](https://download.opensuse.org/repositories/home:/luke_nukem:/asus/) Download repositories are available [here](https://download.opensuse.org/repositories/home:/luke_nukem:/asus/)
Alternatively check the releases page for f33 RPM.
--- ---
Run `make` then `sudo make install` then reboot. Run `make` then `sudo make install` then reboot.
+6
View File
@@ -76,6 +76,12 @@ Accepts an integer from the following:
- `1`: Boost mode - `1`: Boost mode
- `2`: Silent mode - `2`: Silent mode
## dbus-send examples:
```
dbus-send --system --type=method_call --dest=org.asuslinux.Daemon /org/asuslinux/Profile org.asuslinux.Daemon.NextProfile
```
## dbus-send examples OUTDATED ## dbus-send examples OUTDATED
``` ```
+3 -6
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "asus-nb-ctrl" name = "asus-nb-ctrl"
version = "2.0.2" version = "2.2.0"
license = "MPL-2.0" license = "MPL-2.0"
readme = "README.md" readme = "README.md"
authors = ["Luke <luke@ljones.dev>"] authors = ["Luke <luke@ljones.dev>"]
@@ -22,7 +22,6 @@ name = "asusd"
path = "src/daemon.rs" path = "src/daemon.rs"
[dependencies] [dependencies]
ctrl-gfx = { path = "../ctrl-gfx" }
asus-nb = { path = "../asus-nb" } asus-nb = { path = "../asus-nb" }
rusb = "^0.6.0" rusb = "^0.6.0"
udev = "^0.4.0" udev = "^0.4.0"
@@ -32,10 +31,8 @@ gumdrop = "^0.8.0"
log = "^0.4.8" log = "^0.4.8"
env_logger = "^0.7.1" env_logger = "^0.7.1"
# async zbus = "^1.8.0"
zbus = "1.1.1" zvariant = "^2.4.0"
zvariant = "2.2.0"
#tokio = { version = "^0.2.4", features = ["rt-threaded", "sync"] }
# serialisation # serialisation
serde = "^1.0" serde = "^1.0"
+61 -17
View File
@@ -1,16 +1,51 @@
use asus_nb::aura_modes::AuraModes; use asus_nb::aura_modes::AuraModes;
use log::{error, warn}; use log::{error, info, warn};
use rog_fan_curve::Curve; use rog_fan_curve::Curve;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::io::{Read, Write}; use std::io::{Read, Write};
use crate::VERSION;
pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf"; pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf";
/// for parsing old v2.1.2 config
#[derive(Deserialize)]
struct ConfigV212 {
gfx_managed: bool,
active_profile: String,
toggle_profiles: Vec<String>,
// TODO: remove power_profile
power_profile: u8,
bat_charge_limit: u8,
kbd_led_brightness: u8,
kbd_backlight_mode: u8,
kbd_backlight_modes: Vec<AuraModes>,
power_profiles: BTreeMap<String, Profile>,
}
impl ConfigV212 {
fn into_current(self) -> Config {
Config {
gfx_managed: self.gfx_managed,
gfx_nv_mode_is_dedicated: true,
active_profile: self.active_profile,
toggle_profiles: self.toggle_profiles,
power_profile: self.power_profile,
bat_charge_limit: self.bat_charge_limit,
kbd_led_brightness: self.kbd_led_brightness,
kbd_backlight_mode: self.kbd_backlight_mode,
kbd_backlight_modes: self.kbd_backlight_modes,
power_profiles: self.power_profiles,
}
}
}
#[derive(Default, Deserialize, Serialize)] #[derive(Default, Deserialize, Serialize)]
pub struct Config { pub struct Config {
pub gfx_managed: bool, pub gfx_managed: bool,
pub gfx_nv_mode_is_dedicated: bool,
pub active_profile: String, pub active_profile: String,
pub toggle_profiles: Vec<String>, pub toggle_profiles: Vec<String>,
// TODO: remove power_profile // TODO: remove power_profile
@@ -23,36 +58,42 @@ pub struct Config {
} }
impl Config { impl Config {
/// `load` will attempt to read the config, but if it is not found it /// `load` will attempt to read the config, and panic if the dir is missing
/// will create a new default config and write that out. pub fn load(supported_led_modes: &[u8]) -> Self {
pub fn load(mut self, supported_led_modes: &[u8]) -> Self {
let mut file = OpenOptions::new() let mut file = OpenOptions::new()
.read(true) .read(true)
.write(true) .write(true)
.create(true) .create(true)
.open(&CONFIG_PATH) .open(&CONFIG_PATH)
.unwrap(); // okay to cause panic here .expect(&format!(
"The file {} or directory /etc/asusd/ is missing",
CONFIG_PATH
)); // okay to cause panic here
let mut buf = String::new(); let mut buf = String::new();
if let Ok(l) = file.read_to_string(&mut buf) { if let Ok(read_len) = file.read_to_string(&mut buf) {
if l == 0 { if read_len == 0 {
self = Config::create_default(&mut file, &supported_led_modes); return Config::create_default(&mut file, &supported_led_modes);
} else { } else {
self = serde_json::from_str(&buf).unwrap_or_else(|_| { if let Ok(data) = serde_json::from_str(&buf) {
warn!( return data;
"Could not deserialise {}. Overwriting with default", } else if let Ok(data) = serde_json::from_str::<ConfigV212>(&buf) {
CONFIG_PATH let config = data.into_current();
); config.write();
Config::create_default(&mut file, &supported_led_modes) info!("Updated config version to: {}", VERSION);
}); return config;
}
warn!("Could not deserialise {}", CONFIG_PATH);
panic!("Please remove {} then restart asusd", CONFIG_PATH);
} }
} }
self Config::create_default(&mut file, &supported_led_modes)
} }
fn create_default(file: &mut File, supported_led_modes: &[u8]) -> Self { fn create_default(file: &mut File, supported_led_modes: &[u8]) -> Self {
// create a default config here // create a default config here
let mut config = Config::default(); let mut config = Config::default();
config.gfx_managed = true; config.gfx_managed = true;
config.gfx_nv_mode_is_dedicated = true;
config.bat_charge_limit = 100; config.bat_charge_limit = 100;
config.kbd_backlight_mode = 0; config.kbd_backlight_mode = 0;
@@ -62,11 +103,14 @@ impl Config {
config.kbd_backlight_modes.push(AuraModes::from(*n)) config.kbd_backlight_modes.push(AuraModes::from(*n))
} }
let profile = Profile::default(); let mut profile = Profile::default();
profile.fan_preset = 0;
profile.turbo = true;
config.power_profiles.insert("normal".into(), profile); config.power_profiles.insert("normal".into(), profile);
let mut profile = Profile::default(); let mut profile = Profile::default();
profile.fan_preset = 1; profile.fan_preset = 1;
profile.turbo = true;
config.power_profiles.insert("boost".into(), profile); config.power_profiles.insert("boost".into(), profile);
let mut profile = Profile::default(); let mut profile = Profile::default();
+70 -9
View File
@@ -6,8 +6,12 @@ const DEV_PAGE: u8 = 0x5e;
// These bytes are in [1] position of the array // These bytes are in [1] position of the array
const WRITE: u8 = 0xc0; const WRITE: u8 = 0xc0;
const INIT: u8 = 0xc2; const INIT: u8 = 0xc2;
const APPLY: u8 = 0xc3; const SET: u8 = 0xc3;
const SET: u8 = 0xc4; const APPLY: u8 = 0xc4;
// Used to turn the panel on and off
// The next byte can be 0x03 for "on" and 0x00 for "off"
const ON_OFF: u8 = 0x04;
use asus_nb::error::AuraError; use asus_nb::error::AuraError;
use log::{error, info, warn}; use log::{error, info, warn};
@@ -17,11 +21,26 @@ use std::error::Error;
use std::time::Duration; use std::time::Duration;
use zbus::dbus_interface; use zbus::dbus_interface;
use crate::GetSupported;
use serde_derive::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct AnimeSupportedFunctions(bool);
impl GetSupported for CtrlAnimeDisplay {
type A = AnimeSupportedFunctions;
fn get_supported() -> Self::A {
AnimeSupportedFunctions(CtrlAnimeDisplay::get_device(0x0b05, 0x193b).is_ok())
}
}
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug)] #[derive(Debug)]
pub enum AnimatrixCommand { pub enum AnimatrixCommand {
Apply, Apply,
Set, SetBoot(bool),
Write(Vec<u8>),
WriteImage(Vec<Vec<u8>>), WriteImage(Vec<Vec<u8>>),
//ReloadLast, //ReloadLast,
} }
@@ -34,13 +53,21 @@ pub struct CtrlAnimeDisplay {
//AnimatrixWrite //AnimatrixWrite
pub trait Dbus { pub trait Dbus {
fn set_anime(&mut self, input: Vec<Vec<u8>>); fn set_anime(&mut self, input: Vec<Vec<u8>>);
fn set_on_off(&mut self, status: bool);
fn set_boot_on_off(&mut self, status: bool);
} }
impl crate::ZbusAdd for CtrlAnimeDisplay { impl crate::ZbusAdd for CtrlAnimeDisplay {
fn add_to_server(self, server: &mut zbus::ObjectServer) { fn add_to_server(self, server: &mut zbus::ObjectServer) {
server server
.at(&"/org/asuslinux/Anime".try_into().unwrap(), self) .at(&"/org/asuslinux/Anime".try_into().unwrap(), self)
.unwrap(); .map_err(|err| {
warn!("CtrlAnimeDisplay: add_to_server {}", err);
err
})
.ok();
} }
} }
@@ -48,7 +75,39 @@ impl crate::ZbusAdd for CtrlAnimeDisplay {
impl Dbus for CtrlAnimeDisplay { impl Dbus for CtrlAnimeDisplay {
fn set_anime(&mut self, input: Vec<Vec<u8>>) { fn set_anime(&mut self, input: Vec<Vec<u8>>) {
self.do_command(AnimatrixCommand::WriteImage(input)) self.do_command(AnimatrixCommand::WriteImage(input))
.unwrap_or_else(|err| warn!("{}", err)); .map_or_else(|err| warn!("{}", err), |()| info!("Writing image to Anime"));
}
fn set_on_off(&mut self, status: bool) {
let mut flush: Vec<u8> = vec![0; PACKET_SIZE];
flush[0] = DEV_PAGE;
flush[1] = WRITE;
flush[2] = ON_OFF;
let status_str;
if status {
flush[3] = 0x03;
status_str = "on";
} else {
flush[3] = 0x00;
status_str = "off";
}
self.do_command(AnimatrixCommand::Write(flush)).map_or_else(
|err| warn!("{}", err),
|()| info!("Turning {} the AniMe", status_str),
);
}
fn set_boot_on_off(&mut self, status: bool) {
let status_str = if status { "on" } else { "off" };
self.do_command(AnimatrixCommand::SetBoot(status))
.and_then(|()| self.do_command(AnimatrixCommand::Apply))
.map_or_else(
|err| warn!("{}", err),
|()| info!("Turning {} the AniMe at boot/shutdown", status_str),
);
} }
} }
@@ -95,9 +154,11 @@ impl CtrlAnimeDisplay {
} }
match command { match command {
AnimatrixCommand::WriteImage(effect) => self.write_image(effect)?,
AnimatrixCommand::Set => self.do_set()?,
AnimatrixCommand::Apply => self.do_apply()?, AnimatrixCommand::Apply => self.do_apply()?,
//AnimatrixCommand::Set => self.do_set_boot()?,
AnimatrixCommand::SetBoot(status) => self.do_set_boot(status)?,
AnimatrixCommand::Write(bytes) => self.write_bytes(&bytes)?,
AnimatrixCommand::WriteImage(effect) => self.write_image(effect)?,
//AnimatrixCommand::ReloadLast => self.reload_last_builtin(&config).await?, //AnimatrixCommand::ReloadLast => self.reload_last_builtin(&config).await?,
} }
Ok(()) Ok(())
@@ -180,12 +241,12 @@ impl CtrlAnimeDisplay {
} }
#[inline] #[inline]
fn do_set(&mut self) -> Result<(), AuraError> { fn do_set_boot(&mut self, status: bool) -> Result<(), AuraError> {
let mut flush = [0; PACKET_SIZE]; let mut flush = [0; PACKET_SIZE];
flush[0] = DEV_PAGE; flush[0] = DEV_PAGE;
flush[1] = SET; flush[1] = SET;
flush[2] = 0x01; flush[2] = 0x01;
flush[3] = 0x80; flush[3] = if status { 0x00 } else { 0x80 };
self.write_bytes(&flush)?; self.write_bytes(&flush)?;
Ok(()) Ok(())
+45 -23
View File
@@ -1,6 +1,7 @@
use crate::{config::Config, error::RogError}; use crate::{config::Config, error::RogError, GetSupported};
//use crate::dbus::DbusEvents; //use crate::dbus::DbusEvents;
use log::{info, warn}; use log::{info, warn};
use serde_derive::{Deserialize, Serialize};
use std::convert::TryInto; use std::convert::TryInto;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::Write; use std::io::Write;
@@ -11,27 +12,45 @@ use zbus::dbus_interface;
static BAT_CHARGE_PATH: &str = "/sys/class/power_supply/BAT0/charge_control_end_threshold"; static BAT_CHARGE_PATH: &str = "/sys/class/power_supply/BAT0/charge_control_end_threshold";
#[derive(Serialize, Deserialize)]
pub struct ChargeSupportedFunctions {
pub charge_level_set: bool,
}
impl GetSupported for CtrlCharge {
type A = ChargeSupportedFunctions;
fn get_supported() -> Self::A {
ChargeSupportedFunctions {
charge_level_set: CtrlCharge::get_battery_path().is_ok(),
}
}
}
pub struct CtrlCharge { pub struct CtrlCharge {
path: &'static str,
config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
} }
trait Dbus {
fn set_limit(&mut self, charge: u8);
fn limit(&self) -> i8;
fn notify_charge(&self, limit: u8) -> zbus::Result<()>;
}
#[dbus_interface(name = "org.asuslinux.Daemon")] #[dbus_interface(name = "org.asuslinux.Daemon")]
impl Dbus for CtrlCharge { impl CtrlCharge {
fn set_limit(&mut self, limit: u8) { pub fn set_limit(&mut self, limit: u8) {
if let Ok(mut config) = self.config.try_lock() { if let Ok(mut config) = self.config.try_lock() {
self.set(limit, &mut config).unwrap(); self.set(limit, &mut config)
self.notify_charge(limit).unwrap(); .map_err(|err| {
warn!("CtrlCharge: set_limit {}", err);
err
})
.ok();
self.notify_charge(limit)
.map_err(|err| {
warn!("CtrlCharge: set_limit {}", err);
err
})
.ok();
} }
} }
fn limit(&self) -> i8 { pub fn limit(&self) -> i8 {
if let Ok(config) = self.config.try_lock() { if let Ok(config) = self.config.try_lock() {
return config.bat_charge_limit as i8; return config.bat_charge_limit as i8;
} }
@@ -39,14 +58,18 @@ impl Dbus for CtrlCharge {
} }
#[dbus_interface(signal)] #[dbus_interface(signal)]
fn notify_charge(&self, limit: u8) -> zbus::Result<()>; pub fn notify_charge(&self, limit: u8) -> zbus::Result<()> {}
} }
impl crate::ZbusAdd for CtrlCharge { impl crate::ZbusAdd for CtrlCharge {
fn add_to_server(self, server: &mut zbus::ObjectServer) { fn add_to_server(self, server: &mut zbus::ObjectServer) {
server server
.at(&"/org/asuslinux/Charge".try_into().unwrap(), self) .at(&"/org/asuslinux/Charge".try_into().unwrap(), self)
.unwrap(); .map_err(|err| {
warn!("CtrlCharge: add_to_server {}", err);
err
})
.ok();
} }
} }
@@ -54,7 +77,6 @@ impl crate::Reloadable for CtrlCharge {
fn reload(&mut self) -> Result<(), RogError> { fn reload(&mut self) -> Result<(), RogError> {
if let Ok(mut config) = self.config.try_lock() { if let Ok(mut config) = self.config.try_lock() {
config.read(); config.read();
info!("Reloaded battery charge limit");
self.set(config.bat_charge_limit, &mut config)?; self.set(config.bat_charge_limit, &mut config)?;
} }
Ok(()) Ok(())
@@ -63,9 +85,8 @@ impl crate::Reloadable for CtrlCharge {
impl CtrlCharge { impl CtrlCharge {
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> { pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
let path = CtrlCharge::get_battery_path()?; CtrlCharge::get_battery_path()?;
info!("Device has battery charge threshold control"); Ok(CtrlCharge { config })
Ok(CtrlCharge { path, config })
} }
fn get_battery_path() -> Result<&'static str, RogError> { fn get_battery_path() -> Result<&'static str, RogError> {
@@ -73,7 +94,8 @@ impl CtrlCharge {
Ok(BAT_CHARGE_PATH) Ok(BAT_CHARGE_PATH)
} else { } else {
Err(RogError::MissingFunction( Err(RogError::MissingFunction(
"Charge control not available".into(), "Charge control not available, you may require a v5.8.10 series kernel or newer"
.into(),
)) ))
} }
} }
@@ -88,10 +110,10 @@ impl CtrlCharge {
let mut file = OpenOptions::new() let mut file = OpenOptions::new()
.write(true) .write(true)
.open(self.path) .open(BAT_CHARGE_PATH)
.map_err(|err| RogError::Path(self.path.into(), err))?; .map_err(|err| RogError::Path(BAT_CHARGE_PATH.into(), err))?;
file.write_all(limit.to_string().as_bytes()) file.write_all(limit.to_string().as_bytes())
.map_err(|err| RogError::Write(self.path.into(), err))?; .map_err(|err| RogError::Write(BAT_CHARGE_PATH.into(), err))?;
info!("Battery charge limit: {}", limit); info!("Battery charge limit: {}", limit);
config.read(); config.read();
+64 -7
View File
@@ -1,6 +1,10 @@
use crate::config::{Config, Profile}; use crate::{
config::{Config, Profile},
GetSupported,
};
use asus_nb::profile::ProfileEvent; use asus_nb::profile::ProfileEvent;
use log::{info, warn}; use log::{info, warn};
use serde_derive::{Deserialize, Serialize};
use std::convert::TryInto; use std::convert::TryInto;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::{Read, Write}; use std::io::{Read, Write};
@@ -19,6 +23,25 @@ pub struct CtrlFanAndCPU {
config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
} }
#[derive(Serialize, Deserialize)]
pub struct FanCpuSupportedFunctions {
pub stock_fan_modes: bool,
pub min_max_freq: bool,
pub fan_curve_set: bool,
}
impl GetSupported for CtrlFanAndCPU {
type A = FanCpuSupportedFunctions;
fn get_supported() -> Self::A {
FanCpuSupportedFunctions {
stock_fan_modes: CtrlFanAndCPU::get_fan_path().is_ok(),
min_max_freq: intel_pstate::PState::new().is_ok(),
fan_curve_set: rog_fan_curve::Board::from_board_name().is_some(),
}
}
}
pub struct DbusFanAndCpu { pub struct DbusFanAndCpu {
inner: Arc<Mutex<CtrlFanAndCPU>>, inner: Arc<Mutex<CtrlFanAndCPU>>,
} }
@@ -31,6 +54,7 @@ impl DbusFanAndCpu {
#[dbus_interface(name = "org.asuslinux.Daemon")] #[dbus_interface(name = "org.asuslinux.Daemon")]
impl DbusFanAndCpu { impl DbusFanAndCpu {
/// Set profile details
fn set_profile(&self, profile: String) { fn set_profile(&self, profile: String) {
if let Ok(event) = serde_json::from_str(&profile) { if let Ok(event) = serde_json::from_str(&profile) {
if let Ok(mut ctrl) = self.inner.try_lock() { if let Ok(mut ctrl) = self.inner.try_lock() {
@@ -45,6 +69,34 @@ impl DbusFanAndCpu {
} }
} }
/// Fetch the active profile name
fn next_profile(&mut self) {
if let Ok(mut ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
ctrl.do_next_profile(&mut cfg)
.unwrap_or_else(|err| warn!("{}", err));
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
if let Ok(json) = serde_json::to_string(profile) {
self.notify_profile(&json)
.unwrap_or_else(|err| warn!("{}", err));
}
}
}
}
}
/// Fetch the active profile name
fn active_profile_name(&mut self) -> String {
if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.try_lock() {
cfg.read();
return cfg.active_profile.clone();
}
}
"Failed".to_string()
}
/// Fetch the active profile details
fn profile(&mut self) -> String { fn profile(&mut self) -> String {
if let Ok(ctrl) = self.inner.try_lock() { if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.try_lock() { if let Ok(mut cfg) = ctrl.config.try_lock() {
@@ -72,14 +124,18 @@ impl DbusFanAndCpu {
} }
#[dbus_interface(signal)] #[dbus_interface(signal)]
fn notify_profile(&self, profile: &str) -> zbus::Result<()>; fn notify_profile(&self, profile: &str) -> zbus::Result<()> {}
} }
impl crate::ZbusAdd for DbusFanAndCpu { impl crate::ZbusAdd for DbusFanAndCpu {
fn add_to_server(self, server: &mut zbus::ObjectServer) { fn add_to_server(self, server: &mut zbus::ObjectServer) {
server server
.at(&"/org/asuslinux/Profile".try_into().unwrap(), self) .at(&"/org/asuslinux/Profile".try_into().unwrap(), self)
.unwrap(); .map_err(|err| {
warn!("DbusFanAndCpu: {}", err);
err
})
.ok();
} }
} }
@@ -159,12 +215,13 @@ impl CtrlFanAndCPU {
Ok(FAN_TYPE_2_PATH) Ok(FAN_TYPE_2_PATH)
} else { } else {
Err(RogError::MissingFunction( Err(RogError::MissingFunction(
"Fan mode not available, you may require a v5.8 series kernel or newer".into(), "Fan mode not available, you may require a v5.8.10 series kernel or newer".into(),
)) ))
} }
} }
pub(super) fn do_update(&mut self, config: &mut Config) -> Result<(), RogError> { /// Toggle to next profile in list
pub(super) fn do_next_profile(&mut self, config: &mut Config) -> Result<(), RogError> {
config.read(); config.read();
let mut i = config let mut i = config
@@ -218,7 +275,7 @@ impl CtrlFanAndCPU {
config: &mut Config, config: &mut Config,
) -> Result<(), RogError> { ) -> Result<(), RogError> {
match event { match event {
ProfileEvent::Toggle => self.do_update(config)?, ProfileEvent::Toggle => self.do_next_profile(config)?,
ProfileEvent::ChangeMode(mode) => { ProfileEvent::ChangeMode(mode) => {
self.set_fan_mode(*mode, config)?; self.set_fan_mode(*mode, config)?;
} }
@@ -311,7 +368,7 @@ impl CtrlFanAndCPU {
let boost = if mode_config.turbo { "1" } else { "0" }; // opposite of Intel let boost = if mode_config.turbo { "1" } else { "0" }; // opposite of Intel
file.write_all(boost.as_bytes()) file.write_all(boost.as_bytes())
.map_err(|err| RogError::Write(AMD_BOOST_PATH.into(), err))?; .map_err(|err| RogError::Write(AMD_BOOST_PATH.into(), err))?;
info!("AMD CPU Turbo: {}", boost); info!("AMD CPU Turbo: {}", boost);
} }
Ok(()) Ok(())
@@ -1,16 +1,19 @@
use ctrl_gfx::error::GfxError;
use ctrl_gfx::*;
use ctrl_rog_bios::CtrlRogBios;
use log::{error, info, warn}; use log::{error, info, warn};
use std::error::Error;
use std::io::Write; use std::io::Write;
use std::iter::FromIterator; use std::iter::FromIterator;
use std::path::Path; use std::path::Path;
use std::process::Command; use std::process::Command;
use std::str::FromStr; use std::str::FromStr;
use std::{error::Error, sync::Arc, sync::Mutex};
use sysfs_class::{PciDevice, SysClass}; use sysfs_class::{PciDevice, SysClass};
use system::{GraphicsDevice, Module, PciBus};
use vendors::{GfxCtrlAction, GfxVendors};
use zbus::dbus_interface; use zbus::dbus_interface;
use crate::vendors::*;
use crate::*; use crate::*;
use crate::{error::GfxError, system::*};
pub struct CtrlGraphics { pub struct CtrlGraphics {
bus: PciBus, bus: PciBus,
@@ -20,6 +23,7 @@ pub struct CtrlGraphics {
#[allow(dead_code)] #[allow(dead_code)]
other: Vec<GraphicsDevice>, other: Vec<GraphicsDevice>,
initfs_cmd: Option<Command>, initfs_cmd: Option<Command>,
config: Arc<Mutex<Config>>,
} }
trait Dbus { trait Dbus {
@@ -30,22 +34,16 @@ trait Dbus {
fn notify_action(&self, action: &str) -> zbus::Result<()>; fn notify_action(&self, action: &str) -> zbus::Result<()>;
} }
#[cfg(feature = "use-zbus")]
use std::convert::TryInto; use std::convert::TryInto;
#[cfg(feature = "use-zbus")]
#[dbus_interface(name = "org.asuslinux.Daemon")] #[dbus_interface(name = "org.asuslinux.Daemon")]
impl Dbus for CtrlGraphics { impl Dbus for CtrlGraphics {
fn vendor(&self) -> String { fn vendor(&self) -> String {
Self::get_vendor() Self::get_vendor().unwrap_or_else(|err| format!("Get vendor failed: {}", err))
.map_err(|err| format!("Get vendor failed: {}", err))
.unwrap()
} }
fn power(&self) -> String { fn power(&self) -> String {
Self::get_runtime_status() Self::get_runtime_status().unwrap_or_else(|err| format!("Get power status failed: {}", err))
.map_err(|err| format!("Get power status failed: {}", err))
.unwrap()
} }
fn set_vendor(&mut self, vendor: String) { fn set_vendor(&mut self, vendor: String) {
@@ -62,14 +60,14 @@ impl Dbus for CtrlGraphics {
} }
#[dbus_interface(signal)] #[dbus_interface(signal)]
fn notify_gfx(&self, vendor: &str) -> zbus::Result<()>; fn notify_gfx(&self, vendor: &str) -> zbus::Result<()> {}
#[dbus_interface(signal)] #[dbus_interface(signal)]
fn notify_action(&self, action: &str) -> zbus::Result<()>; fn notify_action(&self, action: &str) -> zbus::Result<()> {}
} }
impl CtrlGraphics { impl CtrlGraphics {
pub fn new() -> std::io::Result<CtrlGraphics> { pub fn new(config: Arc<Mutex<Config>>) -> std::io::Result<CtrlGraphics> {
let bus = PciBus::new()?; let bus = PciBus::new()?;
info!("Rescanning PCI bus"); info!("Rescanning PCI bus");
@@ -142,14 +140,21 @@ impl CtrlGraphics {
nvidia, nvidia,
other, other,
initfs_cmd, initfs_cmd,
config,
}) })
} }
#[cfg(feature = "use-zbus")]
pub fn add_to_server(self, server: &mut zbus::ObjectServer) { pub fn add_to_server(self, server: &mut zbus::ObjectServer) {
server server
.at(&"/org/asuslinux/Gfx".try_into().unwrap(), self) .at(
.unwrap(); &"/org/asuslinux/Gfx".try_into().expect("Some fail here"),
self,
)
.map_err(|err| {
warn!("CtrlGraphics: add_to_server {}", err);
err
})
.ok();
} }
pub fn reload(&mut self) -> Result<(), Box<dyn Error>> { pub fn reload(&mut self) -> Result<(), Box<dyn Error>> {
@@ -158,10 +163,6 @@ impl CtrlGraphics {
Ok(()) Ok(())
} }
// fn can_switch(&self) -> bool {
// !self.nvidia.is_empty() && (!self.intel.is_empty() || !self.amd.is_empty())
// }
fn get_prime_discrete() -> Result<String, GfxError> { fn get_prime_discrete() -> Result<String, GfxError> {
let s = std::fs::read_to_string(PRIME_DISCRETE_PATH) let s = std::fs::read_to_string(PRIME_DISCRETE_PATH)
.map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))? .map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))?
@@ -178,27 +179,36 @@ impl CtrlGraphics {
/// Associated method to get which vendor mode is set /// Associated method to get which vendor mode is set
pub fn get_vendor() -> Result<String, GfxError> { pub fn get_vendor() -> Result<String, GfxError> {
let mode = match Self::get_prime_discrete() {
Ok(m) => m,
Err(_) => "nvidia".to_string(),
};
let modules = Module::all().map_err(|err| GfxError::Read("get_vendor".into(), err))?; let modules = Module::all().map_err(|err| GfxError::Read("get_vendor".into(), err))?;
let vendor = if modules
let driver_loaded = if modules
.iter() .iter()
.any(|module| module.name == "nouveau" || module.name == "nvidia") .any(|module| module.name == "nouveau" || module.name == "nvidia")
{ {
info!("nvidia or nouveau module found"); true
let mode = match Self::get_prime_discrete() { } else {
Ok(m) => m, false
Err(_) => "nvidia".to_string(), };
};
let vendor = if mode == "off" {
if driver_loaded {
info!("dGPU driver loaded for compute mode");
"compute".to_string()
} else {
info!("No dGPU driver loaded");
"integrated".to_string()
}
} else {
info!("Assuming dGPU driver loaded");
if mode == "on-demand" { if mode == "on-demand" {
"hybrid".to_string() "hybrid".to_string()
} else if mode == "off" {
"compute".to_string()
} else { } else {
"nvidia".to_string() "nvidia".to_string()
} }
} else {
info!("No dGPU driver (nouveau or nvidia) loaded");
"integrated".to_string()
}; };
Ok(vendor) Ok(vendor)
@@ -211,10 +221,7 @@ impl CtrlGraphics {
Ok(x) Ok(x)
} }
/// Write out config files if required, enable/disable relevant services, and update the ramdisk pub fn set_gfx_config(vendor: GfxVendors) -> Result<(), GfxError> {
pub fn set(&mut self, vendor: GfxVendors) -> Result<String, GfxError> {
//self.switchable_or_fail()?;
let mode = if vendor == GfxVendors::Hybrid { let mode = if vendor == GfxVendors::Hybrid {
"on-demand\n" "on-demand\n"
} else if vendor == GfxVendors::Nvidia { } else if vendor == GfxVendors::Nvidia {
@@ -227,10 +234,6 @@ impl CtrlGraphics {
info!("Setting {} to {}", PRIME_DISCRETE_PATH, mode); info!("Setting {} to {}", PRIME_DISCRETE_PATH, mode);
Self::set_prime_discrete(mode)?; Self::set_prime_discrete(mode)?;
// Switching from hybrid to/from nvidia shouldn't require a ramdisk update
// or a reboot.
let no_reboot = Self::is_switching_prime_modes(&vendor)?;
{ {
info!("Writing {}", MODPROBE_PATH); info!("Writing {}", MODPROBE_PATH);
@@ -298,6 +301,32 @@ impl CtrlGraphics {
status status
); );
} }
Ok(())
}
/// Write out config files if required, enable/disable relevant services, and update the ramdisk
pub fn set(&mut self, vendor: GfxVendors) -> Result<String, GfxError> {
if CtrlRogBios::has_dedicated_gfx_toggle() {
if let Ok(config) = self.config.clone().try_lock() {
// Switch to dedicated if config says to do so
if config.gfx_nv_mode_is_dedicated && vendor == GfxVendors::Nvidia {
CtrlRogBios::set_gfx_mode(true)
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
} else if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
// otherwise if switching to non-Nvidia mode turn off dedicated mode
if ded == 1 && vendor != GfxVendors::Nvidia {
CtrlRogBios::set_gfx_mode(false)
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
}
}
}
}
// Switching from hybrid to/from nvidia shouldn't require a ramdisk update
// or a reboot.
let no_reboot = Self::is_switching_prime_modes(&vendor)?;
Self::set_gfx_config(vendor)?;
let mut required_action = GfxCtrlAction::None; let mut required_action = GfxCtrlAction::None;
if !no_reboot { if !no_reboot {
@@ -320,22 +349,13 @@ impl CtrlGraphics {
Ok(required_action.into()) Ok(required_action.into())
} }
// pub fn get_power(&self) -> Option<bool> {
// if self.can_switch() {
// return Some(self.nvidia.iter().any(GraphicsDevice::exists));
// }
// None
// }
pub fn get_runtime_status() -> Result<String, GfxError> { pub fn get_runtime_status() -> Result<String, GfxError> {
const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status"; const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status";
let buf = std::fs::read_to_string(PATH) let buf = std::fs::read_to_string(PATH).map_err(|err| GfxError::Read(PATH.into(), err))?;
.map_err(|err| GfxError::Read(PATH.into(), err))?;
Ok(buf) Ok(buf)
} }
fn set_power(&self, power: bool) -> Result<(), GfxError> { fn set_power(&self, power: bool) -> Result<(), GfxError> {
// self.switchable_or_fail()?;
if power { if power {
info!("Enabling graphics power"); info!("Enabling graphics power");
self.bus self.bus
@@ -2,14 +2,14 @@ pub mod vendors;
pub mod error; pub mod error;
pub mod ctrl_gfx; pub mod gfx;
pub mod system; pub mod system;
const PRIME_DISCRETE_PATH: &str = "/etc/prime-discrete"; const PRIME_DISCRETE_PATH: &str = "/etc/prime-discrete";
const MODPROBE_PATH: &str = "/etc/modprobe.d/asusd.conf"; const MODPROBE_PATH: &str = "/etc/modprobe.d/asusd.conf";
const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs"; const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs";
//const DRACUT_PATH: &str = "/usr/bin/dracut"; // const DRACUT_PATH: &str = "/usr/bin/dracut";
static MODPROBE_NVIDIA: &[u8] = MODPROBE_HYBRID; static MODPROBE_NVIDIA: &[u8] = MODPROBE_HYBRID;
@@ -55,4 +55,3 @@ static PRIMARY_GPU_NVIDIA: &[u8] = br#"
static PRIMARY_GPU_END: &[u8] = br#" static PRIMARY_GPU_END: &[u8] = br#"
EndSection"#; EndSection"#;
@@ -121,7 +121,7 @@ impl GraphicsDevice {
warn!("{}: Already removed", func.id()); warn!("{}: Already removed", func.id());
} }
} }
info!("Remmoved all gfx devices"); info!("Removed all gfx devices");
Ok(()) Ok(())
} }
} }
@@ -6,9 +6,10 @@ pub enum GfxVendors {
Hybrid, Hybrid,
} }
use crate::error::GfxError;
use std::str::FromStr; use std::str::FromStr;
use super::error::GfxError;
impl FromStr for GfxVendors { impl FromStr for GfxVendors {
type Err = GfxError; type Err = GfxError;
+177 -23
View File
@@ -2,16 +2,65 @@
static LED_APPLY: [u8; 17] = [0x5d, 0xb4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; static LED_APPLY: [u8; 17] = [0x5d, 0xb4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
static LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; static LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
use crate::{config::Config, error::RogError, laptops::HELP_ADDRESS}; static KBD_BRIGHT_PATH: &str = "/sys/class/leds/asus::kbd_backlight/brightness";
use asus_nb::{aura_brightness_bytes, aura_modes::AuraModes, fancy::KeyColourArray, LED_MSG_LEN};
use crate::{
config::Config,
error::RogError,
laptops::{match_laptop, HELP_ADDRESS},
};
use asus_nb::{
aura_brightness_bytes,
aura_modes::{AuraModes, PER_KEY},
fancy::KeyColourArray,
LED_MSG_LEN,
};
use log::{info, warn}; use log::{info, warn};
use std::convert::TryInto;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
use std::{convert::TryInto, path::Path};
use zbus::dbus_interface; use zbus::dbus_interface;
use crate::GetSupported;
use serde_derive::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct LedSupportedFunctions {
pub brightness_set: bool,
pub stock_led_modes: Option<Vec<u8>>,
pub per_key_led_mode: bool,
}
impl GetSupported for CtrlKbdBacklight {
type A = LedSupportedFunctions;
fn get_supported() -> Self::A {
// let mode = <&str>::from(&<AuraModes>::from(*mode));
let mut stock_led_modes = None;
let mut per_key_led_mode = false;
if let Some(laptop) = match_laptop() {
let modes = laptop.supported_modes().to_vec();
if modes.contains(&PER_KEY) {
per_key_led_mode = true;
let modes = modes
.iter()
.filter(|x| **x != PER_KEY)
.map(|x| *x)
.collect();
stock_led_modes = Some(modes);
}
}
LedSupportedFunctions {
brightness_set: CtrlKbdBacklight::get_kbd_bright_path().is_ok(),
stock_led_modes,
per_key_led_mode,
}
}
}
pub struct CtrlKbdBacklight { pub struct CtrlKbdBacklight {
led_node: Option<String>, led_node: Option<String>,
#[allow(dead_code)] #[allow(dead_code)]
@@ -42,7 +91,7 @@ impl crate::ZbusAdd for DbusKbdBacklight {
fn add_to_server(self, server: &mut zbus::ObjectServer) { fn add_to_server(self, server: &mut zbus::ObjectServer) {
server server
.at(&"/org/asuslinux/Led".try_into().unwrap(), self) .at(&"/org/asuslinux/Led".try_into().unwrap(), self)
.unwrap(); .ok();
} }
} }
@@ -58,10 +107,11 @@ impl DbusKbdBacklight {
.unwrap_or_else(|err| warn!("{}", err)); .unwrap_or_else(|err| warn!("{}", err));
} }
_ => { _ => {
let json = serde_json::to_string(&data).unwrap(); if let Ok(json) = serde_json::to_string(&data) {
ctrl.do_command(data, &mut cfg) ctrl.do_command(data, &mut cfg)
.unwrap_or_else(|err| warn!("{}", err)); .unwrap_or_else(|err| warn!("{}", err));
self.notify_led(&json).unwrap(); self.notify_led(&json).ok();
}
} }
} }
} }
@@ -71,6 +121,39 @@ impl DbusKbdBacklight {
} }
} }
fn next_led_mode(&self) {
if let Ok(mut ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
ctrl.toggle_mode(false, &mut cfg)
.unwrap_or_else(|err| warn!("{}", err));
if let Some(mode) = cfg.get_led_mode_data(cfg.kbd_backlight_mode) {
if let Ok(json) = serde_json::to_string(&mode) {
self.notify_led(&json)
.unwrap_or_else(|err| warn!("{}", err));
}
}
}
}
}
fn prev_led_mode(&self) {
if let Ok(mut ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
ctrl.toggle_mode(true, &mut cfg)
.unwrap_or_else(|err| warn!("{}", err));
if let Some(mode) = cfg.get_led_mode_data(cfg.kbd_backlight_mode) {
if let Ok(json) = serde_json::to_string(&mode) {
self.notify_led(&json)
.unwrap_or_else(|err| warn!("{}", err));
}
}
}
}
}
/// Return the current mode data
fn led_mode(&self) -> String { fn led_mode(&self) -> String {
if let Ok(ctrl) = self.inner.try_lock() { if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(cfg) = ctrl.config.clone().try_lock() { if let Ok(cfg) = ctrl.config.clone().try_lock() {
@@ -85,6 +168,7 @@ impl DbusKbdBacklight {
"SetKeyBacklight could not deserialise".to_string() "SetKeyBacklight could not deserialise".to_string()
} }
/// Return a list of available modes
fn led_modes(&self) -> String { fn led_modes(&self) -> String {
if let Ok(ctrl) = self.inner.try_lock() { if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(cfg) = ctrl.config.clone().try_lock() { if let Ok(cfg) = ctrl.config.clone().try_lock() {
@@ -97,6 +181,17 @@ impl DbusKbdBacklight {
"SetKeyBacklight could not deserialise".to_string() "SetKeyBacklight could not deserialise".to_string()
} }
/// Return the current LED brightness
fn led_brightness(&self) -> i8 {
if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(cfg) = ctrl.config.clone().try_lock() {
return cfg.kbd_led_brightness as i8;
}
}
warn!("SetKeyBacklight could not deserialise");
-1
}
#[dbus_interface(signal)] #[dbus_interface(signal)]
fn notify_led(&self, data: &str) -> zbus::Result<()>; fn notify_led(&self, data: &str) -> zbus::Result<()>;
} }
@@ -151,7 +246,12 @@ impl crate::CtrlTask for CtrlKbdBacklight {
let mut file = OpenOptions::new() let mut file = OpenOptions::new()
.read(true) .read(true)
.open(&self.bright_node) .open(&self.bright_node)
.map_err(|err| RogError::Path((&self.bright_node).into(), err))?; .map_err(|err| match err.kind() {
std::io::ErrorKind::NotFound => {
RogError::MissingLedBrightNode((&self.bright_node).into(), err)
}
_ => RogError::Path((&self.bright_node).into(), err),
})?;
let mut buf = [0u8; 1]; let mut buf = [0u8; 1];
file.read_exact(&mut buf) file.read_exact(&mut buf)
.map_err(|err| RogError::Read("buffer".into(), err))?; .map_err(|err| RogError::Read("buffer".into(), err))?;
@@ -176,16 +276,29 @@ impl CtrlKbdBacklight {
condev_iface: Option<&String>, condev_iface: Option<&String>,
supported_modes: Vec<u8>, supported_modes: Vec<u8>,
config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
) -> Self { ) -> Result<Self, RogError> {
// TODO: return error if *all* nodes are None // TODO: return error if *all* nodes are None
CtrlKbdBacklight { let ctrl = CtrlKbdBacklight {
// Using `ok` here so we can continue without keyboard features but
// still get brightness control at least... maybe...
led_node: Self::get_node_failover(id_product, None, Self::scan_led_node).ok(), led_node: Self::get_node_failover(id_product, None, Self::scan_led_node).ok(),
kbd_node: Self::get_node_failover(id_product, condev_iface, Self::scan_kbd_node).ok(), kbd_node: Self::get_node_failover(id_product, condev_iface, Self::scan_kbd_node).ok(),
// TODO: Check for existance // TODO: Check for existance
bright_node: "/sys/class/leds/asus::kbd_backlight/brightness".to_string(), bright_node: Self::get_kbd_bright_path()?.to_owned(),
supported_modes, supported_modes,
flip_effect_write: false, flip_effect_write: false,
config, config,
};
Ok(ctrl)
}
fn get_kbd_bright_path() -> Result<&'static str, RogError> {
if Path::new(KBD_BRIGHT_PATH).exists() {
Ok(KBD_BRIGHT_PATH)
} else {
Err(RogError::MissingFunction(
"Keyboard features missing, you may require a v5.11 series kernel or newer".into(),
))
} }
} }
@@ -194,6 +307,8 @@ impl CtrlKbdBacklight {
iface: Option<&String>, iface: Option<&String>,
fun: fn(&str, Option<&String>) -> Result<String, RogError>, fun: fn(&str, Option<&String>) -> Result<String, RogError>,
) -> Result<String, RogError> { ) -> Result<String, RogError> {
// We do three tries here just to be certain that we avoid systemd unit
// load order issues
for n in 0..=2 { for n in 0..=2 {
// 0,1,2 inclusive // 0,1,2 inclusive
match fun(id_product, iface) { match fun(id_product, iface) {
@@ -233,8 +348,11 @@ impl CtrlKbdBacklight {
RogError::Udev("parent_with_subsystem_devtype failed".into(), err) RogError::Udev("parent_with_subsystem_devtype failed".into(), err)
})? })?
{ {
if parent.attribute_value("idProduct").unwrap() == id_product { if parent
// && device.parent().unwrap().sysnum().unwrap() == 3 .attribute_value("idProduct")
.ok_or(RogError::NotFound("LED idProduct".into()))?
== id_product
{
if let Some(dev_node) = device.devnode() { if let Some(dev_node) = device.devnode() {
info!("Using device at: {:?} for LED control", dev_node); info!("Using device at: {:?} for LED control", dev_node);
return Ok(dev_node.to_string_lossy().to_string()); return Ok(dev_node.to_string_lossy().to_string());
@@ -264,13 +382,17 @@ impl CtrlKbdBacklight {
RogError::Udev("match_property failed".into(), err) RogError::Udev("match_property failed".into(), err)
})?; })?;
for device in enumerator.scan_devices().map_err(|err| { for device in enumerator
warn!("{}", err); .scan_devices()
err .map_err(|err| {
}).map_err(|err| { warn!("{}", err);
warn!("{}", err); err
RogError::Udev("scan_devices failed".into(), err) })
})? { .map_err(|err| {
warn!("{}", err);
RogError::Udev("scan_devices failed".into(), err)
})?
{
if let Some(dev_node) = device.devnode() { if let Some(dev_node) = device.devnode() {
if let Some(inum) = device.property_value("ID_USB_INTERFACE_NUM") { if let Some(inum) = device.property_value("ID_USB_INTERFACE_NUM") {
if let Some(iface) = iface { if let Some(iface) = iface {
@@ -298,8 +420,9 @@ impl CtrlKbdBacklight {
fn write_bytes(&self, message: &[u8]) -> Result<(), RogError> { fn write_bytes(&self, message: &[u8]) -> Result<(), RogError> {
if let Some(led_node) = &self.led_node { if let Some(led_node) = &self.led_node {
if let Ok(mut file) = OpenOptions::new().write(true).open(led_node) { if let Ok(mut file) = OpenOptions::new().write(true).open(led_node) {
file.write_all(message).unwrap(); return file
return Ok(()); .write_all(message)
.map_err(|err| RogError::Write("write_bytes".into(), err));
} }
} }
Err(RogError::NotSupported) Err(RogError::NotSupported)
@@ -355,6 +478,37 @@ impl CtrlKbdBacklight {
Ok(()) Ok(())
} }
#[inline]
fn toggle_mode(&mut self, reverse: bool, config: &mut Config) -> Result<(), RogError> {
let current = config.kbd_backlight_mode;
if let Some(idx) = self.supported_modes.iter().position(|v| *v == current) {
let mut idx = idx;
// goes past end of array
if reverse {
if idx == 0 {
idx = self.supported_modes.len() - 1;
} else {
idx -= 1;
}
} else {
idx += 1;
if idx == self.supported_modes.len() {
idx = 0;
}
}
let next = self.supported_modes[idx];
config.read();
if let Some(data) = config.get_led_mode_data(next) {
self.write_mode(&data)?;
config.kbd_backlight_mode = next;
}
config.write();
}
Ok(())
}
#[inline] #[inline]
fn write_mode(&mut self, mode: &AuraModes) -> Result<(), RogError> { fn write_mode(&mut self, mode: &AuraModes) -> Result<(), RogError> {
match mode { match mode {
+261
View File
@@ -0,0 +1,261 @@
use crate::{
config::Config,
ctrl_gfx::{gfx::CtrlGraphics, vendors::GfxVendors},
error::RogError,
GetSupported,
};
//use crate::dbus::DbusEvents;
use log::{info, warn};
use serde_derive::{Deserialize, Serialize};
use std::convert::TryInto;
use std::fs::OpenOptions;
use std::io::{Read, Write};
use std::path::Path;
use std::sync::Arc;
use std::sync::Mutex;
use zbus::dbus_interface;
static ASUS_SWITCH_GRAPHIC_MODE: &str =
"/sys/firmware/efi/efivars/AsusSwitchGraphicMode-607005d5-3f75-4b2e-98f0-85ba66797a3e";
static ASUS_POST_LOGO_SOUND: &str =
"/sys/firmware/efi/efivars/AsusPostLogoSound-607005d5-3f75-4b2e-98f0-85ba66797a3e";
pub struct CtrlRogBios {
config: Arc<Mutex<Config>>,
}
#[derive(Serialize, Deserialize)]
pub struct RogBiosSupportedFunctions {
pub post_sound_toggle: bool,
pub dedicated_gfx_toggle: bool,
}
impl GetSupported for CtrlRogBios {
type A = RogBiosSupportedFunctions;
fn get_supported() -> Self::A {
RogBiosSupportedFunctions {
post_sound_toggle: CtrlRogBios::check_path_exists(ASUS_POST_LOGO_SOUND).is_ok(),
dedicated_gfx_toggle: CtrlRogBios::check_path_exists(ASUS_SWITCH_GRAPHIC_MODE).is_ok(),
}
}
}
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl CtrlRogBios {
pub fn set_dedicated_graphic_mode(&mut self, dedicated: bool) {
Self::set_gfx_mode(dedicated)
.map_err(|err| {
warn!("CtrlRogBios: set_asus_switch_graphic_mode {}", err);
err
})
.ok();
self.notify_dedicated_graphic_mode(dedicated)
.map_err(|err| {
warn!("CtrlRogBios: notify_asus_switch_graphic_mode {}", err);
err
})
.ok();
}
pub fn dedicated_graphic_mode(&self) -> i8 {
Self::get_gfx_mode()
.map_err(|err| {
warn!("CtrlRogBios: get_gfx_mode {}", err);
err
})
.unwrap_or(-1)
}
#[dbus_interface(signal)]
pub fn notify_dedicated_graphic_mode(&self, dedicated: bool) -> zbus::Result<()> {}
// // // // // // // // // //
pub fn set_post_boot_sound(&mut self, on: bool) {
Self::set_boot_sound(on)
.map_err(|err| {
warn!("CtrlRogBios: set_post_boot_sound {}", err);
err
})
.ok();
self.notify_post_boot_sound(on)
.map_err(|err| {
warn!("CtrlRogBios: notify_post_boot_sound {}", err);
err
})
.ok();
}
pub fn post_boot_sound(&self) -> i8 {
Self::get_boot_sound()
.map_err(|err| {
warn!("CtrlRogBios: get_boot_sound {}", err);
err
})
.unwrap_or(-1)
}
#[dbus_interface(signal)]
pub fn notify_post_boot_sound(&self, dedicated: bool) -> zbus::Result<()> {}
}
impl crate::ZbusAdd for CtrlRogBios {
fn add_to_server(self, server: &mut zbus::ObjectServer) {
server
.at(&"/org/asuslinux/RogBios".try_into().unwrap(), self)
.map_err(|err| {
warn!("CtrlRogBios: add_to_server {}", err);
err
})
.ok();
}
}
impl crate::Reloadable for CtrlRogBios {
fn reload(&mut self) -> Result<(), RogError> {
Ok(())
}
}
impl CtrlRogBios {
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
match CtrlRogBios::check_path_exists(ASUS_SWITCH_GRAPHIC_MODE) {
Ok(_) => {
CtrlRogBios::set_path_mutable(ASUS_SWITCH_GRAPHIC_MODE)?;
}
Err(err) => {
info!("ROG Switchable Graphics (bios) not detected: {}", err);
}
}
match CtrlRogBios::check_path_exists(ASUS_POST_LOGO_SOUND) {
Ok(_) => {
CtrlRogBios::set_path_mutable(ASUS_POST_LOGO_SOUND)?;
}
Err(err) => {
info!("ROG boot sound toggle (bios) not detected: {}", err);
}
}
Ok(CtrlRogBios { config })
}
fn set_path_mutable(path: &str) -> Result<(), RogError> {
use std::process::Command;
let output = Command::new("/usr/bin/chattr")
.arg("-i")
.arg(path)
.output()
.map_err(|err| RogError::Path(path.into(), err))?;
info!("Set {} writeable: status: {}", path, output.status);
Ok(())
}
fn check_path_exists(path: &str) -> Result<(), RogError> {
if Path::new(path).exists() {
Ok(())
} else {
Err(RogError::MissingFunction(path.into()))
}
}
pub fn has_dedicated_gfx_toggle() -> bool {
if CtrlRogBios::check_path_exists(ASUS_SWITCH_GRAPHIC_MODE).is_ok() {
return true;
}
false
}
pub fn get_gfx_mode() -> Result<i8, RogError> {
let path = ASUS_SWITCH_GRAPHIC_MODE;
let mut file = OpenOptions::new()
.read(true)
.open(path)
.map_err(|err| RogError::Path(path.into(), err))?;
let mut data = Vec::new();
file.read_to_end(&mut data)
.map_err(|err| RogError::Read(path.into(), err))?;
let idx = data.len() - 1;
Ok(data[idx] as i8)
}
pub(super) fn set_gfx_mode(dedicated: bool) -> Result<(), RogError> {
let path = ASUS_SWITCH_GRAPHIC_MODE;
let mut file = OpenOptions::new()
.read(true)
.write(true)
.open(path)
.map_err(|err| RogError::Path(path.into(), err))?;
let mut data = Vec::new();
file.read_to_end(&mut data).unwrap();
let idx = data.len() - 1;
if dedicated {
data[idx] = 1;
info!("Set system-level graphics mode: Dedicated Nvidia");
} else {
data[idx] = 0;
info!("Set system-level graphics mode: Optimus");
}
file.write_all(&data)
.map_err(|err| RogError::Path(path.into(), err))?;
if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
if let Ok(vendor) = CtrlGraphics::get_vendor() {
if ded == 1 && vendor != "nvidia" {
warn!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode");
CtrlGraphics::set_gfx_config(GfxVendors::Nvidia)
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
}
}
}
Ok(())
}
pub fn get_boot_sound() -> Result<i8, RogError> {
let path = ASUS_POST_LOGO_SOUND;
let mut file = OpenOptions::new()
.read(true)
.open(path)
.map_err(|err| RogError::Path(path.into(), err))?;
let mut data = Vec::new();
file.read_to_end(&mut data)
.map_err(|err| RogError::Read(path.into(), err))?;
let idx = data.len() - 1;
Ok(data[idx] as i8)
}
pub(super) fn set_boot_sound(on: bool) -> Result<(), RogError> {
let path = ASUS_POST_LOGO_SOUND;
let mut file = OpenOptions::new()
.read(true)
.write(true)
.open(path)
.map_err(|err| RogError::Path(path.into(), err))?;
let mut data = Vec::new();
file.read_to_end(&mut data)
.map_err(|err| RogError::Read(path.into(), err))?;
let idx = data.len() - 1;
if on {
data[idx] = 1;
info!("Set boot POST sound on");
} else {
data[idx] = 0;
info!("Set boot POST sound off");
}
file.write_all(&data)
.map_err(|err| RogError::Path(path.into(), err))?;
Ok(())
}
}
+84 -32
View File
@@ -1,10 +1,14 @@
use ctrl_gfx::ctrl_gfx::CtrlGraphics;
use daemon::config::Config;
use daemon::ctrl_anime::CtrlAnimeDisplay;
use daemon::ctrl_charge::CtrlCharge; use daemon::ctrl_charge::CtrlCharge;
use daemon::ctrl_fan_cpu::{CtrlFanAndCPU, DbusFanAndCpu}; use daemon::ctrl_fan_cpu::{CtrlFanAndCPU, DbusFanAndCpu};
use daemon::ctrl_leds::{CtrlKbdBacklight, DbusKbdBacklight}; use daemon::ctrl_leds::{CtrlKbdBacklight, DbusKbdBacklight};
use daemon::laptops::match_laptop; use daemon::laptops::match_laptop;
use daemon::{
config::Config, laptops::print_board_info, supported::SupportedFunctions, GetSupported,
};
use daemon::{
ctrl_anime::CtrlAnimeDisplay,
ctrl_gfx::{gfx::CtrlGraphics, vendors::GfxVendors},
};
use asus_nb::DBUS_NAME; use asus_nb::DBUS_NAME;
use daemon::{CtrlTask, Reloadable, ZbusAdd}; use daemon::{CtrlTask, Reloadable, ZbusAdd};
@@ -15,6 +19,9 @@ use std::io::Write;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
use daemon::ctrl_rog_bios::CtrlRogBios;
use std::convert::Into;
use std::convert::TryInto;
use zbus::fdo; use zbus::fdo;
use zbus::Connection; use zbus::Connection;
@@ -38,14 +45,16 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
// - to maintain constant times of 1ms, per-key colours should use // - to maintain constant times of 1ms, per-key colours should use
// the effect endpoint so that the complete colour block is written // the effect endpoint so that the complete colour block is written
// as fast as 1ms per row of the matrix inside it. (10ms total time) // as fast as 1ms per row of the matrix inside it. (10ms total time)
//
// DBUS processing takes 6ms if not tokiod
fn start_daemon() -> Result<(), Box<dyn Error>> { fn start_daemon() -> Result<(), Box<dyn Error>> {
let supported = SupportedFunctions::get_supported();
print_board_info();
println!("{}", serde_json::to_string_pretty(&supported).unwrap());
let laptop = match_laptop(); let laptop = match_laptop();
let config = if let Some(laptop) = laptop.as_ref() { let config = if let Some(laptop) = laptop.as_ref() {
Config::default().load(laptop.supported_modes()) Config::load(laptop.supported_modes())
} else { } else {
Config::default().load(&[]) Config::load(&[])
}; };
let connection = Connection::new_system()?; let connection = Connection::new_system()?;
@@ -53,8 +62,24 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
.request_name(DBUS_NAME, fdo::RequestNameFlags::ReplaceExisting.into())?; .request_name(DBUS_NAME, fdo::RequestNameFlags::ReplaceExisting.into())?;
let mut object_server = zbus::ObjectServer::new(&connection); let mut object_server = zbus::ObjectServer::new(&connection);
supported.add_to_server(&mut object_server);
let enable_gfx_switching = config.gfx_managed;
let config = Arc::new(Mutex::new(config)); let config = Arc::new(Mutex::new(config));
match CtrlRogBios::new(config.clone()) {
Ok(mut ctrl) => {
// Do a reload of any settings
ctrl.reload()
.unwrap_or_else(|err| warn!("Battery charge limit: {}", err));
// Then register to dbus server
ctrl.add_to_server(&mut object_server);
}
Err(err) => {
error!("rog_bios_control: {}", err);
}
}
match CtrlCharge::new(config.clone()) { match CtrlCharge::new(config.clone()) {
Ok(mut ctrl) => { Ok(mut ctrl) => {
// Do a reload of any settings // Do a reload of any settings
@@ -77,43 +102,61 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
} }
} }
match CtrlGraphics::new() { if enable_gfx_switching {
Ok(mut ctrl) => { match CtrlGraphics::new(config.clone()) {
ctrl.reload() Ok(mut ctrl) => {
.unwrap_or_else(|err| warn!("Gfx controller: {}", err)); // Need to check if a laptop has the dedicated gfx switch
ctrl.add_to_server(&mut object_server); if CtrlRogBios::has_dedicated_gfx_toggle() {
} if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
Err(err) => { if let Ok(vendor) = CtrlGraphics::get_vendor() {
error!("Gfx control: {}", err); if ded == 1 && vendor != "nvidia" {
error!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode");
error!("You must reboot to enable Nvidia driver");
ctrl.set(GfxVendors::Nvidia)?;
} else if ded == 0 {
info!("Dedicated GFX toggle is off");
}
}
}
} else {
ctrl.reload()
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
}
ctrl.add_to_server(&mut object_server);
}
Err(err) => {
error!("Gfx control: {}", err);
}
} }
} }
// Collect tasks for task thread // Collect tasks for task thread
let mut tasks: Vec<Arc<Mutex<dyn CtrlTask + Send>>> = Vec::new(); let mut tasks: Vec<Arc<Mutex<dyn CtrlTask + Send>>> = Vec::new();
match CtrlFanAndCPU::new(config.clone()) { if let Ok(mut ctrl) = CtrlFanAndCPU::new(config.clone()).map_err(|err| {
Ok(mut ctrl) => { error!("Profile control: {}", err);
ctrl.reload() }) {
.unwrap_or_else(|err| warn!("Profile control: {}", err)); ctrl.reload()
let tmp = Arc::new(Mutex::new(ctrl)); .unwrap_or_else(|err| warn!("Profile control: {}", err));
DbusFanAndCpu::new(tmp.clone()).add_to_server(&mut object_server); let tmp = Arc::new(Mutex::new(ctrl));
tasks.push(tmp); DbusFanAndCpu::new(tmp.clone()).add_to_server(&mut object_server);
} tasks.push(tmp);
Err(err) => {
error!("Profile control: {}", err);
}
}; };
if let Some(laptop) = laptop { if let Some(laptop) = laptop {
let ctrl = CtrlKbdBacklight::new( if let Ok(ctrl) = CtrlKbdBacklight::new(
laptop.usb_product(), laptop.usb_product(),
laptop.condev_iface(), laptop.condev_iface(),
laptop.supported_modes().to_owned(), laptop.supported_modes().to_owned(),
config, config,
); )
let tmp = Arc::new(Mutex::new(ctrl)); .map_err(|err| {
DbusKbdBacklight::new(tmp.clone()).add_to_server(&mut object_server); error!("Keyboard control: {}", err);
tasks.push(tmp); }) {
let tmp = Arc::new(Mutex::new(ctrl));
DbusKbdBacklight::new(tmp.clone()).add_to_server(&mut object_server);
tasks.push(tmp);
}
} }
// TODO: implement messaging between threads to check fails // TODO: implement messaging between threads to check fails
@@ -126,11 +169,20 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
for ctrl in tasks.iter() { for ctrl in tasks.iter() {
if let Ok(mut lock) = ctrl.try_lock() { if let Ok(mut lock) = ctrl.try_lock() {
lock.do_task().unwrap(); lock.do_task()
.map_err(|err| {
warn!("do_task error: {}", err);
})
.ok();
} }
} }
}); });
object_server.with(&"/org/asuslinux/Charge".try_into()?, |obj: &CtrlCharge| {
let x = obj.limit();
obj.notify_charge(x as u8)
})?;
loop { loop {
if let Err(err) = object_server.try_handle_next() { if let Err(err) = object_server.try_handle_next() {
eprintln!("{}", err); eprintln!("{}", err);
+6 -2
View File
@@ -1,7 +1,7 @@
use std::fmt;
use std::convert::From;
use intel_pstate::PStateError; use intel_pstate::PStateError;
use rog_fan_curve::CurveError; use rog_fan_curve::CurveError;
use std::convert::From;
use std::fmt;
#[derive(Debug)] #[derive(Debug)]
pub enum RogError { pub enum RogError {
@@ -19,6 +19,8 @@ pub enum RogError {
FanCurve(CurveError), FanCurve(CurveError),
DoTask(String), DoTask(String),
MissingFunction(String), MissingFunction(String),
MissingLedBrightNode(String, std::io::Error),
ReloadFail(String),
} }
impl fmt::Display for RogError { impl fmt::Display for RogError {
@@ -39,6 +41,8 @@ impl fmt::Display for RogError {
RogError::FanCurve(err) => write!(f, "Custom fan-curve error: {}", err), RogError::FanCurve(err) => write!(f, "Custom fan-curve error: {}", err),
RogError::DoTask(deets) => write!(f, "Task error: {}", deets), RogError::DoTask(deets) => write!(f, "Task error: {}", deets),
RogError::MissingFunction(deets) => write!(f, "Missing functionality: {}", deets), RogError::MissingFunction(deets) => write!(f, "Missing functionality: {}", deets),
RogError::MissingLedBrightNode(path, error) => write!(f, "Led node at {} is missing, please check you have the required patch or dkms module installed: {}", path, error),
RogError::ReloadFail(deets) => write!(f, "Task error: {}", deets),
} }
} }
} }
+14 -8
View File
@@ -27,13 +27,12 @@ impl LaptopBase {
} }
pub fn match_laptop() -> Option<LaptopBase> { pub fn match_laptop() -> Option<LaptopBase> {
for device in rusb::devices().unwrap().iter() { for device in rusb::devices().expect("Failed here").iter() {
let device_desc = device.device_descriptor().unwrap(); let device_desc = device.device_descriptor().expect("Failed there");
if device_desc.vendor_id() == 0x0b05 { if device_desc.vendor_id() == 0x0b05 {
match device_desc.product_id() { match device_desc.product_id() {
0x1866 => { 0x1866 => {
let laptop = select_1866_device("1866".to_owned()); let laptop = select_1866_device("1866".to_owned());
print_modes(&laptop.supported_modes);
return Some(laptop); return Some(laptop);
} }
0x1869 => return Some(select_1866_device("1869".to_owned())), 0x1869 => return Some(select_1866_device("1869".to_owned())),
@@ -61,10 +60,6 @@ fn select_1866_device(prod: String) -> LaptopBase {
let dmi = sysfs_class::DmiId::default(); let dmi = sysfs_class::DmiId::default();
let board_name = dmi.board_name().expect("Could not get board_name"); let board_name = dmi.board_name().expect("Could not get board_name");
let prod_family = dmi.product_family().expect("Could not get product_family"); let prod_family = dmi.product_family().expect("Could not get product_family");
let prod_name = dmi.product_name().expect("Could not get product_name");
info!("Product name: {}", prod_name.trim());
info!("Board name: {}", board_name.trim());
let mut laptop = LaptopBase { let mut laptop = LaptopBase {
usb_product: prod, usb_product: prod,
@@ -81,7 +76,18 @@ fn select_1866_device(prod: String) -> LaptopBase {
laptop laptop
} }
fn print_modes(supported_modes: &[u8]) { pub fn print_board_info() {
let dmi = sysfs_class::DmiId::default();
let board_name = dmi.board_name().expect("Could not get board_name");
let prod_name = dmi.product_name().expect("Could not get product_name");
let prod_family = dmi.product_family().expect("Could not get product_family");
info!("Product name: {}", prod_name.trim());
info!("Product family: {}", prod_family.trim());
info!("Board name: {}", board_name.trim());
}
pub fn print_modes(supported_modes: &[u8]) {
if !supported_modes.is_empty() { if !supported_modes.is_empty() {
info!("Supported Keyboard LED modes are:"); info!("Supported Keyboard LED modes are:");
for mode in supported_modes { for mode in supported_modes {
+15 -3
View File
@@ -8,18 +8,24 @@ pub mod ctrl_charge;
/// ///
pub mod ctrl_fan_cpu; pub mod ctrl_fan_cpu;
/// ///
pub mod ctrl_leds; pub mod ctrl_gfx;
/// ///
pub mod ctrl_leds;
/// Control ASUS bios function such as boot sound, Optimus/Dedicated gfx mode
pub mod ctrl_rog_bios;
/// Laptop matching to determine capabilities /// Laptop matching to determine capabilities
pub mod laptops; pub mod laptops;
/// Fetch all supported functions for the laptop
pub mod supported;
mod error; mod error;
use config::Config;
use crate::error::RogError; use crate::error::RogError;
use config::Config;
use zbus::ObjectServer; use zbus::ObjectServer;
pub static VERSION: &str = "2.0.2"; pub static VERSION: &str = env!("CARGO_PKG_VERSION");
pub trait Reloadable { pub trait Reloadable {
fn reload(&mut self) -> Result<(), RogError>; fn reload(&mut self) -> Result<(), RogError>;
@@ -38,3 +44,9 @@ pub trait CtrlTaskComplex {
fn do_task(&mut self, config: &mut Config, event: Self::A); fn do_task(&mut self, config: &mut Config, event: Self::A);
} }
pub trait GetSupported {
type A;
fn get_supported() -> Self::A;
}
+211 -31
View File
@@ -1,28 +1,29 @@
use asus_nb::{ use asus_nb::{
cli_options::{LedBrightness, SetAuraBuiltin}, anime_dbus::AniMeDbusWriter,
cli_options::{AniMeActions, AniMeStatusValue, LedBrightness, SetAuraBuiltin},
core_dbus::AuraDbusClient, core_dbus::AuraDbusClient,
profile::{ProfileCommand, ProfileEvent}, profile::{ProfileCommand, ProfileEvent},
}; };
use ctrl_gfx::vendors::GfxVendors; use daemon::{ctrl_fan_cpu::FanLevel, ctrl_gfx::vendors::GfxVendors};
use daemon::ctrl_fan_cpu::FanLevel; use gumdrop::{Opt, Options};
use gumdrop::Options;
use log::LevelFilter; use log::LevelFilter;
use std::io::Write; use std::{env::args, io::Write, process::Command};
use std::process::Command;
use yansi_term::Colour::Green; use yansi_term::Colour::Green;
use yansi_term::Colour::Red; use yansi_term::Colour::Red;
#[derive(Options)] #[derive(Default, Options)]
struct CLIStart { struct CLIStart {
#[options(help = "print help message")] #[options(help_flag, help = "print help message")]
help: bool, help: bool,
#[options(help = "show program version number")] #[options(help = "show program version number")]
version: bool, version: bool,
#[options(meta = "VAL", help = "<off, low, med, high>")] #[options(help = "show supported functions of this laptop")]
show_supported: bool,
#[options(meta = "", help = "<off, low, med, high>")]
kbd_bright: Option<LedBrightness>, kbd_bright: Option<LedBrightness>,
#[options(meta = "PWR", help = "<silent, normal, boost>")] #[options(meta = "", help = "<silent, normal, boost>")]
pwr_profile: Option<FanLevel>, pwr_profile: Option<FanLevel>,
#[options(meta = "CHRG", help = "<20-100>")] #[options(meta = "", help = "<20-100>")]
chg_limit: Option<u8>, chg_limit: Option<u8>,
#[options(command)] #[options(command)]
command: Option<CliCommand>, command: Option<CliCommand>,
@@ -36,13 +37,21 @@ enum CliCommand {
Profile(ProfileCommand), Profile(ProfileCommand),
#[options(help = "Set the graphics mode")] #[options(help = "Set the graphics mode")]
Graphics(GraphicsCommand), Graphics(GraphicsCommand),
#[options(name = "anime", help = "Manage AniMe Matrix")]
AniMe(AniMeCommand),
#[options(help = "Change bios settings")]
Bios(BiosCommand),
} }
#[derive(Options)] #[derive(Options)]
struct LedModeCommand { struct LedModeCommand {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
#[options(command, required)] #[options(help = "switch to next aura mode")]
next_mode: bool,
#[options(help = "switch to previous aura mode")]
prev_mode: bool,
#[options(command)]
command: Option<SetAuraBuiltin>, command: Option<SetAuraBuiltin>,
} }
@@ -50,7 +59,10 @@ struct LedModeCommand {
struct GraphicsCommand { struct GraphicsCommand {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
#[options(help = "Set graphics mode: <nvidia, hybrid, compute, integrated>")] #[options(
meta = "",
help = "Set graphics mode: <nvidia, hybrid, compute, integrated>"
)]
mode: Option<GfxVendors>, mode: Option<GfxVendors>,
#[options(help = "Get the current mode")] #[options(help = "Get the current mode")]
get: bool, get: bool,
@@ -60,6 +72,35 @@ struct GraphicsCommand {
force: bool, force: bool,
} }
#[derive(Options)]
struct AniMeCommand {
#[options(help = "print help message")]
help: bool,
#[options(
meta = "",
help = "turn on/off the panel (accept/reject write requests)"
)]
turn: Option<AniMeStatusValue>,
#[options(meta = "", help = "turn on/off the panel at boot (with Asus effect)")]
boot: Option<AniMeStatusValue>,
#[options(command)]
command: Option<AniMeActions>,
}
#[derive(Options, Debug)]
struct BiosCommand {
#[options(help = "print help message")]
help: bool,
#[options(meta = "", no_long, help = "toggle bios POST sound")]
post_sound_set: Option<bool>,
#[options(no_long, help = "read bios POST sound")]
post_sound_get: bool,
#[options(meta = "", no_long, help = "toggle GPU to/from dedicated mode")]
dedicated_gfx_set: Option<bool>,
#[options(no_long, help = "get GPU mode")]
dedicated_gfx_get: bool,
}
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut logger = env_logger::Builder::new(); let mut logger = env_logger::Builder::new();
logger logger
@@ -68,49 +109,188 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.filter(None, LevelFilter::Info) .filter(None, LevelFilter::Info)
.init(); .init();
let parsed = CLIStart::parse_args_default_or_exit(); let mut args: Vec<String> = args().collect();
args.remove(0);
let parsed: CLIStart;
let missing_argument_k = gumdrop::Error::missing_argument(Opt::Short('k'));
match CLIStart::parse_args_default(&args) {
Ok(p) => {
parsed = p;
}
Err(err) if err.to_string() == missing_argument_k.to_string() => {
parsed = CLIStart {
kbd_bright: Some(LedBrightness::new(None)),
..Default::default()
};
}
Err(err) => {
eprintln!("source {}", err);
std::process::exit(2);
}
}
if parsed.help_requested() {
// As help option don't work with `parse_args_default`
// we will call `parse_args_default_or_exit` instead
CLIStart::parse_args_default_or_exit();
}
if parsed.version { if parsed.version {
println!("Version: {}", daemon::VERSION); println!("Version: {}", daemon::VERSION);
} }
let writer = AuraDbusClient::new()?; let dbus_client = AuraDbusClient::new()?;
let anime_dbus_client = AniMeDbusWriter::new()?;
match parsed.command { match parsed.command {
Some(CliCommand::LedMode(mode)) => { Some(CliCommand::LedMode(mode)) => {
if let Some(command) = mode.command { if (mode.command.is_none() && !mode.prev_mode && !mode.next_mode) || mode.help {
writer.write_builtin_mode(&command.into())? println!("Missing arg or command\n\n{}", mode.self_usage());
if let Some(lst) = mode.self_command_list() {
println!("\n{}", lst);
}
}
if mode.next_mode && mode.prev_mode {
println!("Please specify either next or previous")
}
if mode.next_mode {
dbus_client.next_keyboard_led_mode()?;
} else if mode.prev_mode {
dbus_client.prev_keyboard_led_mode()?;
} else if let Some(command) = mode.command {
dbus_client.write_builtin_mode(&command.into())?
} }
} }
Some(CliCommand::Profile(command)) => { Some(CliCommand::Profile(cmd)) => {
writer.write_profile_command(&ProfileEvent::Cli(command))? if (!cmd.next
&& !cmd.create
&& cmd.curve.is_none()
&& cmd.max_percentage.is_none()
&& cmd.min_percentage.is_none()
&& cmd.preset.is_none()
&& cmd.profile.is_none()
&& cmd.turbo.is_none())
|| cmd.help
{
println!("Missing arg or command\n\n{}", cmd.self_usage());
if let Some(lst) = cmd.self_command_list() {
println!("\n{}", lst);
}
}
if cmd.next {
dbus_client.next_fan_profile()?;
} else {
dbus_client.write_profile_command(&ProfileEvent::Cli(cmd))?
}
}
Some(CliCommand::Graphics(cmd)) => do_gfx(cmd, &dbus_client)?,
Some(CliCommand::AniMe(cmd)) => {
if (cmd.command.is_none() && cmd.boot.is_none() && cmd.turn.is_none()) || cmd.help {
println!("Missing arg or command\n\n{}", cmd.self_usage());
if let Some(lst) = cmd.self_command_list() {
println!("\n{}", lst);
}
}
if let Some(anime_turn) = cmd.turn {
anime_dbus_client.turn_on_off(anime_turn.into())?
}
if let Some(anime_boot) = cmd.boot {
anime_dbus_client.turn_boot_on_off(anime_boot.into())?
}
if let Some(action) = cmd.command {
match action {
AniMeActions::Leds(anime_leds) => {
let led_brightness = anime_leds.led_brightness();
anime_dbus_client.set_leds_brightness(led_brightness)?;
}
}
}
}
Some(CliCommand::Bios(cmd)) => {
if (cmd.dedicated_gfx_set.is_none()
&& !cmd.dedicated_gfx_get
&& cmd.post_sound_set.is_none()
&& !cmd.post_sound_get)
|| cmd.help
{
println!("Missing arg or command\n\n{}", cmd.self_usage());
if let Some(lst) = cmd.self_command_list() {
println!("\n{}", lst);
}
}
if let Some(opt) = cmd.post_sound_set {
dbus_client.set_bios_post_sound(opt)?;
}
if cmd.post_sound_get {
let res = if dbus_client.get_bios_post_sound()? == 1 {
true
} else {
false
};
println!("Bios POST sound on: {}", res);
}
if let Some(opt) = cmd.dedicated_gfx_set {
dbus_client.set_bios_dedicated_gfx(opt)?;
}
if cmd.dedicated_gfx_get {
let res = if dbus_client.get_bios_dedicated_gfx()? == 1 {
true
} else {
false
};
println!("Bios dedicated GPU on: {}", res);
}
}
None => {
if (!parsed.show_supported
&& parsed.kbd_bright.is_none()
&& parsed.pwr_profile.is_none()
&& parsed.chg_limit.is_none())
|| parsed.help
{
println!("{}", CLIStart::usage());
println!();
println!("{}", CLIStart::command_list().unwrap());
}
} }
Some(CliCommand::Graphics(command)) => do_gfx(command, &writer)?,
None => (),
} }
if let Some(brightness) = parsed.kbd_bright { if let Some(brightness) = parsed.kbd_bright {
writer.write_brightness(brightness.level())?; match brightness.level() {
None => {
let level = dbus_client.get_led_brightness()?;
println!("Current keyboard led brightness: {}", level.to_string());
}
Some(level) => dbus_client.write_brightness(level)?,
}
} }
if parsed.show_supported {
let dat = dbus_client.get_supported_functions()?;
println!("Supported laptop functions:\n{}", dat.to_string());
}
if let Some(fan_level) = parsed.pwr_profile { if let Some(fan_level) = parsed.pwr_profile {
writer.write_fan_mode(fan_level.into())?; dbus_client.write_fan_mode(fan_level.into())?;
} }
if let Some(chg_limit) = parsed.chg_limit { if let Some(chg_limit) = parsed.chg_limit {
writer.write_charge_limit(chg_limit)?; dbus_client.write_charge_limit(chg_limit)?;
} }
Ok(()) Ok(())
} }
fn do_gfx( fn do_gfx(
command: GraphicsCommand, command: GraphicsCommand,
writer: &AuraDbusClient, dbus_client: &AuraDbusClient,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
if let Some(mode) = command.mode { if let Some(mode) = command.mode {
println!("Updating settings, please wait..."); println!("Updating settings, please wait...");
println!("If this takes longer than 30s, ctrl+c then check journalctl"); println!("If this takes longer than 30s, ctrl+c then check `journalctl -b -u asusd`");
writer.write_gfx_mode(mode)?; dbus_client.write_gfx_mode(<&str>::from(&mode).into())?;
let res = writer.wait_gfx_changed()?; let res = dbus_client.wait_gfx_changed()?;
match res.as_str() { match res.as_str() {
"reboot" => { "reboot" => {
println!( println!(
@@ -119,7 +299,7 @@ fn do_gfx(
); );
do_gfx_action( do_gfx_action(
command.force, command.force,
Command::new("systemctl").arg("reboot"), Command::new("systemctl").arg("reboot").arg("-i"),
"Reboot Linux PC", "Reboot Linux PC",
"Please reboot when ready", "Please reboot when ready",
)?; )?;
@@ -144,11 +324,11 @@ fn do_gfx(
std::process::exit(-1) std::process::exit(-1)
} }
if command.get { if command.get {
let res = writer.get_gfx_mode()?; let res = dbus_client.get_gfx_mode()?;
println!("Current graphics mode: {}", res); println!("Current graphics mode: {}", res);
} }
if command.pow { if command.pow {
let res = writer.get_gfx_pwr()?; let res = dbus_client.get_gfx_pwr()?;
if res.contains("active") { if res.contains("active") {
println!("Current power status: {}", Red.paint(&format!("{}", res))); println!("Current power status: {}", Red.paint(&format!("{}", res)));
} else { } else {
+56
View File
@@ -0,0 +1,56 @@
use std::convert::TryInto;
use log::warn;
use serde_derive::{Deserialize, Serialize};
use zbus::dbus_interface;
use crate::{
ctrl_anime::{AnimeSupportedFunctions, CtrlAnimeDisplay},
ctrl_charge::{ChargeSupportedFunctions, CtrlCharge},
ctrl_fan_cpu::{CtrlFanAndCPU, FanCpuSupportedFunctions},
ctrl_leds::{CtrlKbdBacklight, LedSupportedFunctions},
ctrl_rog_bios::{CtrlRogBios, RogBiosSupportedFunctions},
GetSupported,
};
#[derive(Serialize, Deserialize)]
pub struct SupportedFunctions {
anime_ctrl: AnimeSupportedFunctions,
charge_ctrl: ChargeSupportedFunctions,
fan_cpu_ctrl: FanCpuSupportedFunctions,
keyboard_led: LedSupportedFunctions,
rog_bios_ctrl: RogBiosSupportedFunctions,
}
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl SupportedFunctions {
fn supported_functions(&self) -> String {
serde_json::to_string_pretty(self).unwrap()
}
}
impl crate::ZbusAdd for SupportedFunctions {
fn add_to_server(self, server: &mut zbus::ObjectServer) {
server
.at(&"/org/asuslinux/Supported".try_into().unwrap(), self)
.map_err(|err| {
warn!("SupportedFunctions: add_to_server {}", err);
err
})
.ok();
}
}
impl GetSupported for SupportedFunctions {
type A = SupportedFunctions;
fn get_supported() -> Self::A {
SupportedFunctions {
keyboard_led: CtrlKbdBacklight::get_supported(),
anime_ctrl: CtrlAnimeDisplay::get_supported(),
charge_ctrl: CtrlCharge::get_supported(),
fan_cpu_ctrl: CtrlFanAndCPU::get_supported(),
rog_bios_ctrl: CtrlRogBios::get_supported(),
}
}
}
+3 -4
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "asus-nb" name = "asus-nb"
version = "2.0.2" version = "2.2.0"
license = "MPL-2.0" license = "MPL-2.0"
readme = "README.md" readme = "README.md"
authors = ["Luke <luke@ljones.dev>"] authors = ["Luke <luke@ljones.dev>"]
@@ -17,9 +17,8 @@ serde_derive = "^1.0"
serde_json = "^1.0" serde_json = "^1.0"
yansi-term = "^0.1" yansi-term = "^0.1"
rog_fan_curve = { version = "0.1", features = ["serde"] } rog_fan_curve = { version = "0.1", features = ["serde"] }
zbus = "1.1.1" zbus = "^1.8.0"
zvariant = "2.2.0" zvariant = "^2.4.0"
ctrl-gfx = { path = "../ctrl-gfx" }
[dev-dependencies] [dev-dependencies]
tinybmp = "^0.2.3" tinybmp = "^0.2.3"
+3 -2
View File
@@ -14,9 +14,10 @@ fn main() {
let mut matrix = AniMeMatrix::new(); let mut matrix = AniMeMatrix::new();
// Aligned left // Aligned left
for px in pixels { for (i, px) in pixels.iter().enumerate() {
if (px.x as usize / 2) < WIDTH && (px.y as usize) < HEIGHT && px.x % 2 == 0 { if (px.x as usize / 2) < WIDTH && (px.y as usize) < HEIGHT && px.x % 2 == 0 {
matrix.get_mut()[px.y as usize][px.x as usize / 2] = px.color as u8; let mut c = px.color as u32;
matrix.get_mut()[px.y as usize][px.x as usize / 2] = c as u8;
} }
} }
+64 -36
View File
@@ -1,29 +1,26 @@
use crate::anime_matrix::AniMePacketType; const DBUS_ANIME_PATH: &str = "/org/asuslinux/Anime";
use crate::{DBUS_IFACE, DBUS_NAME};
use dbus::channel::Sender;
use dbus::{blocking::Connection, Message};
use std::error::Error;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use std::{thread, time::Duration};
pub const ANIME_PANE1_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02]; pub const ANIME_PANE1_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02];
pub const ANIME_PANE2_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02]; pub const ANIME_PANE2_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02];
use crate::anime_matrix::{AniMeMatrix, AniMePacketType};
use crate::DBUS_NAME;
use dbus::blocking::{Connection, Proxy};
use std::error::Error;
use std::{thread, time::Duration};
use crate::dbus_anime::OrgAsuslinuxDaemon as OrgAsuslinuxDaemonAniMe;
/// Interface for the AniMe dot-matrix display /// Interface for the AniMe dot-matrix display
/// ///
/// The resolution is 34x56 (1904) but only 1,215 LEDs in the top-left are used. /// The resolution is 34x56 (1904) but only 1,215 LEDs in the top-left are used.
/// The display is available only on select GA401 models. /// The display is available only on select GA401 models.
/// ///
/// Actual image ration when displayed is stretched width. /// Actual image ratio when displayed is stretched width.
/// ///
/// Data structure should be nested array of [[u8; 33]; 56] /// Data structure should be nested array of [[u8; 33]; 56]
pub struct AniMeDbusWriter { pub struct AniMeDbusWriter {
connection: Box<Connection>, connection: Box<Connection>,
block_time: u64, block_time: u64,
stop: Arc<AtomicBool>,
} }
impl AniMeDbusWriter { impl AniMeDbusWriter {
@@ -33,47 +30,78 @@ impl AniMeDbusWriter {
Ok(AniMeDbusWriter { Ok(AniMeDbusWriter {
connection: Box::new(connection), connection: Box::new(connection),
block_time: 25, block_time: 25,
stop: Arc::new(AtomicBool::new(false)),
}) })
} }
// Create D-Bus proxy
fn new_proxy(&self) -> Proxy<&Connection> {
self.connection
.with_proxy(DBUS_NAME, DBUS_ANIME_PATH, Duration::from_millis(200))
}
fn thread_sleep(&self) {
thread::sleep(Duration::from_millis(self.block_time));
}
pub fn write_image_to_buf(_buf: &mut AniMePacketType, _image_data: &[u8]) { pub fn write_image_to_buf(_buf: &mut AniMePacketType, _image_data: &[u8]) {
unimplemented!("Image format is in progress of being worked out") unimplemented!("Image format is in progress of being worked out")
} }
/// Write an Animatrix image /// Write an Animatrix image
/// ///
/// The expected input here is *two* Vectors, 640 bytes in length. The two vectors /// The expected input here is *two* Vectors, 640 bytes in length.
/// are each one half of the full image write. /// The two vectors are each one half of the full image write.
/// ///
/// After each write a flush is written, it is assumed that this tells the device to /// After each write a flush is written, it is assumed that this tells the
/// go ahead and display the written bytes /// device to go ahead and display the written bytes
/// ///
/// # Note: /// # Note: The vectors are expected to contain the full sequence of bytes
/// The vectors are expected to contain the full sequence of bytes as follows /// as follows
/// ///
/// - Write packet 1: 0x5e 0xc0 0x02 0x01 0x00 0x73 0x02 .. <led brightness> /// - Write packet 1: 0x5e 0xc0 0x02 0x01 0x00 0x73 0x02 .. <led brightness>
/// - Write packet 2: 0x5e 0xc0 0x02 0x74 0x02 0x73 0x02 .. <led brightness> /// - Write packet 2: 0x5e 0xc0 0x02 0x74 0x02 0x73 0x02 .. <led brightness>
/// ///
/// Where led brightness is 0..255, low to high /// Where led brightness is 0..255, low to high
#[inline] #[inline]
pub fn write_image(&mut self, image: &mut AniMePacketType) -> Result<(), Box<dyn Error>> { pub fn write_image(&self, image: &mut AniMePacketType) -> Result<(), Box<dyn Error>> {
if image[0][0] != ANIME_PANE1_PREFIX[0] && image[0][6] != ANIME_PANE1_PREFIX[6] { let proxy = self.new_proxy();
image[0][..7].copy_from_slice(&ANIME_PANE1_PREFIX);
} image[0][..7].copy_from_slice(&ANIME_PANE1_PREFIX);
if image[1][0] != ANIME_PANE2_PREFIX[0] && image[1][6] != ANIME_PANE2_PREFIX[6] { image[1][..7].copy_from_slice(&ANIME_PANE2_PREFIX);
image[1][..7].copy_from_slice(&ANIME_PANE2_PREFIX);
} proxy.set_anime(vec![image[0].to_vec(), image[1].to_vec()])?;
self.thread_sleep();
Ok(())
}
#[inline]
pub fn set_leds_brightness(&self, led_brightness: u8) -> Result<(), Box<dyn Error>> {
let mut anime_matrix = AniMeMatrix::new();
anime_matrix.fill_with(led_brightness);
self.write_image(&mut AniMePacketType::from(anime_matrix))?;
Ok(())
}
#[inline]
pub fn turn_on_off(&self, status: bool) -> Result<(), Box<dyn Error>> {
let proxy = self.new_proxy();
proxy.set_on_off(status)?;
self.thread_sleep();
Ok(())
}
#[inline]
pub fn turn_boot_on_off(&self, status: bool) -> Result<(), Box<dyn Error>> {
let proxy = self.new_proxy();
proxy.set_boot_on_off(status)?;
self.thread_sleep();
let mut msg =
Message::new_method_call(DBUS_NAME, "/org/asuslinux/Anime", DBUS_IFACE, "SetAnime")?
.append2(image[0].to_vec(), image[1].to_vec());
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
thread::sleep(Duration::from_millis(self.block_time));
if self.stop.load(Ordering::Relaxed) {
panic!("Got signal to stop!");
}
Ok(()) Ok(())
} }
} }
+6 -6
View File
@@ -46,9 +46,9 @@ impl AniMeMatrix {
// Write the top block of LEDs (first 7 rows) // Write the top block of LEDs (first 7 rows)
if count < 6 { if count < 6 {
if count % 2 != 0 { if count % 2 != 0 {
print!(" "); print!(" ");
} else { } else {
print!(" "); print!("");
} }
let tmp = if count == 0 || count == 1 || count == 3 || count == 5 { let tmp = if count == 0 || count == 1 || count == 3 || count == 5 {
row[1..].iter() row[1..].iter()
@@ -56,7 +56,7 @@ impl AniMeMatrix {
row.iter() row.iter()
}; };
for x in tmp { for x in tmp {
print!(" {}", RGB(*x, *x, *x).paint(&format!("{:#04X}", x))); print!(" {}", RGB(*x, *x, *x).paint("XY"));
} }
println!(); println!();
@@ -76,13 +76,13 @@ impl AniMeMatrix {
let index = row.len() - prog_row_len; let index = row.len() - prog_row_len;
if count % 2 == 0 { if count % 2 == 0 {
print!(" "); print!(" ");
} }
for (i, x) in row.iter().enumerate() { for (i, x) in row.iter().enumerate() {
if i >= index { if i >= index {
print!(" {}", RGB(*x, *x, *x).paint(&format!("{:#04X}", x))); print!(" {}", RGB(*x, *x, *x).paint("XY"));
} else { } else {
print!(" "); print!(" ");
} }
} }
println!(); println!();
+79 -7
View File
@@ -5,10 +5,14 @@ use std::str::FromStr;
#[derive(Options)] #[derive(Options)]
pub struct LedBrightness { pub struct LedBrightness {
level: u8, level: Option<u8>,
} }
impl LedBrightness { impl LedBrightness {
pub fn level(&self) -> u8 { pub fn new(level: Option<u8>) -> Self {
LedBrightness { level }
}
pub fn level(&self) -> Option<u8> {
self.level self.level
} }
} }
@@ -18,17 +22,31 @@ impl FromStr for LedBrightness {
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.to_lowercase(); let s = s.to_lowercase();
match s.as_str() { match s.as_str() {
"off" => Ok(LedBrightness { level: 0x00 }), "off" => Ok(LedBrightness { level: Some(0x00) }),
"low" => Ok(LedBrightness { level: 0x01 }), "low" => Ok(LedBrightness { level: Some(0x01) }),
"med" => Ok(LedBrightness { level: 0x02 }), "med" => Ok(LedBrightness { level: Some(0x02) }),
"high" => Ok(LedBrightness { level: 0x03 }), "high" => Ok(LedBrightness { level: Some(0x03) }),
_ => { _ => {
println!("Missing required argument, must be one of:\noff,low,med,high\n"); print!(
"{}\n{}\n",
"Invalid argument, must be one of:", "off, low, med, high"
);
Err(AuraError::ParseBrightness) Err(AuraError::ParseBrightness)
} }
} }
} }
} }
impl ToString for LedBrightness {
fn to_string(&self) -> String {
let s = match self.level {
Some(0x00) => "low",
Some(0x01) => "med",
Some(0x02) => "high",
_ => "unknown",
};
s.to_string()
}
}
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct Colour(pub u8, pub u8, pub u8); pub struct Colour(pub u8, pub u8, pub u8);
@@ -213,3 +231,57 @@ impl Default for SetAuraBuiltin {
}) })
} }
} }
#[derive(Copy, Clone, Debug)]
pub enum AniMeStatusValue {
On,
Off,
}
impl FromStr for AniMeStatusValue {
type Err = AuraError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.to_lowercase();
match s.as_str() {
"on" => Ok(AniMeStatusValue::On),
"off" => Ok(AniMeStatusValue::Off),
_ => {
print!("{}\n{}\n", "Invalid argument, must be one of:", "on, off");
Err(AuraError::ParseAnime)
}
}
}
}
impl From<AniMeStatusValue> for bool {
fn from(value: AniMeStatusValue) -> Self {
match value {
AniMeStatusValue::On => true,
AniMeStatusValue::Off => false,
}
}
}
#[derive(Options)]
pub struct AniMeLeds {
#[options(help = "print help message")]
help: bool,
#[options(
no_long,
required,
short = "b",
meta = "BYTE",
help = "set all leds brightness value"
)]
led_brightness: u8,
}
impl AniMeLeds {
pub fn led_brightness(&self) -> u8 {
self.led_brightness
}
}
#[derive(Options)]
pub enum AniMeActions {
#[options(help = "change all leds brightness")]
Leds(AniMeLeds),
}
+127 -21
View File
@@ -1,7 +1,7 @@
use super::*; use super::*;
use crate::cli_options::LedBrightness;
use crate::fancy::KeyColourArray; use crate::fancy::KeyColourArray;
use crate::profile::ProfileEvent; use crate::profile::ProfileEvent;
use ctrl_gfx::vendors::GfxVendors;
use dbus::{blocking::Connection, Message}; use dbus::{blocking::Connection, Message};
use std::error::Error; use std::error::Error;
use std::sync::{ use std::sync::{
@@ -10,7 +10,9 @@ use std::sync::{
}; };
use std::{thread, time::Duration}; use std::{thread, time::Duration};
use crate::dbus_charge::{OrgAsuslinuxDaemonNotifyCharge, OrgAsuslinuxDaemon as OrgAsuslinuxDaemonCharge}; use crate::dbus_charge::{
OrgAsuslinuxDaemon as OrgAsuslinuxDaemonCharge, OrgAsuslinuxDaemonNotifyCharge,
};
use crate::dbus_gfx::{ use crate::dbus_gfx::{
OrgAsuslinuxDaemon as OrgAsuslinuxDaemonGfx, OrgAsuslinuxDaemonNotifyAction, OrgAsuslinuxDaemon as OrgAsuslinuxDaemonGfx, OrgAsuslinuxDaemonNotifyAction,
OrgAsuslinuxDaemonNotifyGfx, OrgAsuslinuxDaemonNotifyGfx,
@@ -21,6 +23,8 @@ use crate::dbus_ledmode::{
use crate::dbus_profile::{ use crate::dbus_profile::{
OrgAsuslinuxDaemon as OrgAsuslinuxDaemonProfile, OrgAsuslinuxDaemonNotifyProfile, OrgAsuslinuxDaemon as OrgAsuslinuxDaemonProfile, OrgAsuslinuxDaemonNotifyProfile,
}; };
use crate::dbus_rogbios::OrgAsuslinuxDaemon as OrgAsuslinuxDaemonRogBios;
use crate::dbus_supported::OrgAsuslinuxDaemon as OrgAsuslinuxDaemonSupported;
// Signals separated out // Signals separated out
pub struct CtrlSignals { pub struct CtrlSignals {
@@ -37,7 +41,7 @@ impl CtrlSignals {
let proxy = connection.with_proxy( let proxy = connection.with_proxy(
"org.asuslinux.Daemon", "org.asuslinux.Daemon",
"/org/asuslinux/Gfx", "/org/asuslinux/Gfx",
Duration::from_millis(5000), Duration::from_secs(2),
); );
let gfx_vendor_signal = Arc::new(Mutex::new(None)); let gfx_vendor_signal = Arc::new(Mutex::new(None));
@@ -68,7 +72,7 @@ impl CtrlSignals {
let proxy = connection.with_proxy( let proxy = connection.with_proxy(
"org.asuslinux.Daemon", "org.asuslinux.Daemon",
"/org/asuslinux/Profile", "/org/asuslinux/Profile",
Duration::from_millis(5000), Duration::from_secs(2),
); );
let profile_signal = Arc::new(Mutex::new(None)); let profile_signal = Arc::new(Mutex::new(None));
@@ -87,7 +91,7 @@ impl CtrlSignals {
let proxy = connection.with_proxy( let proxy = connection.with_proxy(
"org.asuslinux.Daemon", "org.asuslinux.Daemon",
"/org/asuslinux/Led", "/org/asuslinux/Led",
Duration::from_millis(5000), Duration::from_secs(2),
); );
let ledmode_signal = Arc::new(Mutex::new(None)); let ledmode_signal = Arc::new(Mutex::new(None));
@@ -108,7 +112,7 @@ impl CtrlSignals {
let proxy = connection.with_proxy( let proxy = connection.with_proxy(
"org.asuslinux.Daemon", "org.asuslinux.Daemon",
"/org/asuslinux/Charge", "/org/asuslinux/Charge",
Duration::from_millis(5000), Duration::from_secs(2),
); );
let charge_signal = Arc::new(Mutex::new(None)); let charge_signal = Arc::new(Mutex::new(None));
@@ -168,7 +172,7 @@ impl AuraDbusClient {
pub fn wait_gfx_changed(&self) -> Result<String, Box<dyn Error>> { pub fn wait_gfx_changed(&self) -> Result<String, Box<dyn Error>> {
loop { loop {
self.connection.process(Duration::from_micros(500))?; self.connection.process(Duration::from_millis(1))?;
if let Ok(lock) = self.signals.gfx_action_signal.lock() { if let Ok(lock) = self.signals.gfx_action_signal.lock() {
if let Some(stuff) = lock.as_ref() { if let Some(stuff) = lock.as_ref() {
return Ok(stuff.to_string()); return Ok(stuff.to_string());
@@ -185,7 +189,7 @@ impl AuraDbusClient {
let proxy = self.connection.with_proxy( let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon", "org.asuslinux.Daemon",
"/org/asuslinux/Led", "/org/asuslinux/Led",
Duration::from_millis(5000), Duration::from_secs(2),
); );
proxy.set_led_mode(&serde_json::to_string(&mode)?)?; proxy.set_led_mode(&serde_json::to_string(&mode)?)?;
Ok(()) Ok(())
@@ -224,20 +228,42 @@ impl AuraDbusClient {
let proxy = self.connection.with_proxy( let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon", "org.asuslinux.Daemon",
"/org/asuslinux/Led", "/org/asuslinux/Led",
Duration::from_millis(5000), Duration::from_secs(2),
); );
proxy.set_led_mode(&serde_json::to_string(mode)?)?; proxy.set_led_mode(&serde_json::to_string(mode)?)?;
Ok(()) Ok(())
} }
#[inline]
pub fn next_keyboard_led_mode(&self) -> Result<(), Box<dyn std::error::Error>> {
let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon",
"/org/asuslinux/Led",
Duration::from_secs(2),
);
proxy.next_led_mode()?;
Ok(())
}
#[inline]
pub fn prev_keyboard_led_mode(&self) -> Result<(), Box<dyn std::error::Error>> {
let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon",
"/org/asuslinux/Led",
Duration::from_secs(2),
);
proxy.prev_led_mode()?;
Ok(())
}
#[inline] #[inline]
pub fn get_gfx_pwr(&self) -> Result<String, Box<dyn std::error::Error>> { pub fn get_gfx_pwr(&self) -> Result<String, Box<dyn std::error::Error>> {
let proxy = self.connection.with_proxy( let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon", "org.asuslinux.Daemon",
"/org/asuslinux/Gfx", "/org/asuslinux/Gfx",
Duration::from_millis(5000), Duration::from_secs(2),
); );
let x = proxy.power().unwrap(); let x = proxy.power()?;
Ok(x) Ok(x)
} }
@@ -246,20 +272,31 @@ impl AuraDbusClient {
let proxy = self.connection.with_proxy( let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon", "org.asuslinux.Daemon",
"/org/asuslinux/Gfx", "/org/asuslinux/Gfx",
Duration::from_millis(5000), Duration::from_secs(2),
); );
let x = proxy.vendor().unwrap(); let x = proxy.vendor()?;
Ok(x) Ok(x)
} }
#[inline] #[inline]
pub fn write_gfx_mode(&self, vendor: GfxVendors) -> Result<(), Box<dyn std::error::Error>> { pub fn write_gfx_mode(&self, vendor: String) -> Result<(), Box<dyn std::error::Error>> {
let proxy = self.connection.with_proxy( let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon", "org.asuslinux.Daemon",
"/org/asuslinux/Gfx", "/org/asuslinux/Gfx",
Duration::from_millis(5000), Duration::from_secs(30),
); );
proxy.set_vendor(<&str>::from(&vendor))?; proxy.set_vendor(&vendor)?;
Ok(())
}
#[inline]
pub fn next_fan_profile(&self) -> Result<(), Box<dyn std::error::Error>> {
let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon",
"/org/asuslinux/Profile",
Duration::from_secs(2),
);
proxy.next_profile()?;
Ok(()) Ok(())
} }
@@ -268,7 +305,7 @@ impl AuraDbusClient {
let proxy = self.connection.with_proxy( let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon", "org.asuslinux.Daemon",
"/org/asuslinux/Profile", "/org/asuslinux/Profile",
Duration::from_millis(5000), Duration::from_secs(2),
); );
proxy.set_profile(&serde_json::to_string(&ProfileEvent::ChangeMode(level))?)?; proxy.set_profile(&serde_json::to_string(&ProfileEvent::ChangeMode(level))?)?;
Ok(()) Ok(())
@@ -282,7 +319,7 @@ impl AuraDbusClient {
let proxy = self.connection.with_proxy( let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon", "org.asuslinux.Daemon",
"/org/asuslinux/Profile", "/org/asuslinux/Profile",
Duration::from_millis(5000), Duration::from_secs(2),
); );
proxy.set_profile(&serde_json::to_string(cmd)?)?; proxy.set_profile(&serde_json::to_string(cmd)?)?;
Ok(()) Ok(())
@@ -293,7 +330,7 @@ impl AuraDbusClient {
let proxy = self.connection.with_proxy( let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon", "org.asuslinux.Daemon",
"/org/asuslinux/Charge", "/org/asuslinux/Charge",
Duration::from_millis(5000), Duration::from_secs(2),
); );
proxy.set_limit(level)?; proxy.set_limit(level)?;
Ok(()) Ok(())
@@ -305,8 +342,77 @@ impl AuraDbusClient {
} }
#[inline] #[inline]
pub fn write_brightness(&self, level: u8) -> Result<String, Box<dyn std::error::Error>> { pub fn get_led_brightness(&self) -> Result<LedBrightness, Box<dyn Error>> {
let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon",
"/org/asuslinux/Led",
Duration::from_secs(2),
);
match proxy.led_brightness()? {
-1 => Ok(LedBrightness::new(None)),
level => Ok(LedBrightness::new(Some(level as u8))),
}
}
#[inline]
pub fn write_brightness(&self, level: u8) -> Result<(), Box<dyn std::error::Error>> {
self.write_keyboard_leds(&AuraModes::LedBrightness(level))?; self.write_keyboard_leds(&AuraModes::LedBrightness(level))?;
Ok(String::new()) Ok(())
}
//
#[inline]
pub fn get_bios_dedicated_gfx(&self) -> Result<i16, Box<dyn std::error::Error>> {
let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon",
"/org/asuslinux/RogBios",
Duration::from_secs(2),
);
let x = proxy.dedicated_graphic_mode()?;
Ok(x)
}
#[inline]
pub fn set_bios_dedicated_gfx(&self, on: bool) -> Result<(), Box<dyn std::error::Error>> {
let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon",
"/org/asuslinux/RogBios",
Duration::from_secs(2),
);
proxy.set_dedicated_graphic_mode(<bool>::from(on))?;
Ok(())
}
#[inline]
pub fn get_bios_post_sound(&self) -> Result<i16, Box<dyn std::error::Error>> {
let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon",
"/org/asuslinux/RogBios",
Duration::from_secs(2),
);
let x = proxy.post_boot_sound()?;
Ok(x)
}
#[inline]
pub fn set_bios_post_sound(&self, on: bool) -> Result<(), Box<dyn std::error::Error>> {
let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon",
"/org/asuslinux/RogBios",
Duration::from_secs(2),
);
proxy.set_post_boot_sound(<bool>::from(on))?;
Ok(())
}
#[inline]
pub fn get_supported_functions(&self) -> Result<String, Box<dyn std::error::Error>> {
let proxy = self.connection.with_proxy(
"org.asuslinux.Daemon",
"/org/asuslinux/Supported",
Duration::from_secs(2),
);
let x = proxy.supported_functions()?;
Ok(x)
} }
} }
+27
View File
@@ -0,0 +1,27 @@
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -p /org/asuslinux/Anime -m None -f org.asuslinux.Daemon -c blocking`, see https://github.com/diwic/dbus-rs
use dbus;
#[allow(unused_imports)]
use dbus::arg;
use dbus::blocking;
pub trait OrgAsuslinuxDaemon {
fn set_anime(&self, input: Vec<Vec<u8>>) -> Result<(), dbus::Error>;
fn set_on_off(&self, status: bool) -> Result<(), dbus::Error>;
fn set_boot_on_off(&self, status: bool) -> Result<(), dbus::Error>;
}
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
for blocking::Proxy<'a, C>
{
fn set_anime(&self, input: Vec<Vec<u8>>) -> Result<(), dbus::Error> {
self.method_call("org.asuslinux.Daemon", "SetAnime", (input,))
}
fn set_on_off(&self, status: bool) -> Result<(), dbus::Error> {
self.method_call("org.asuslinux.Daemon", "SetOnOff", (status,))
}
fn set_boot_on_off(&self, status: bool) -> Result<(), dbus::Error> {
self.method_call("org.asuslinux.Daemon", "SetBootOnOff", (status,))
}
}
+7 -8
View File
@@ -1,5 +1,5 @@
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/Charge -m None`, see https://github.com/diwic/dbus-rs // This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/Charge -m None`, see https://github.com/diwic/dbus-rs
use dbus as dbus; use dbus;
#[allow(unused_imports)] #[allow(unused_imports)]
use dbus::arg; use dbus::arg;
use dbus::blocking; use dbus::blocking;
@@ -9,15 +9,16 @@ pub trait OrgAsuslinuxDaemon {
fn limit(&self) -> Result<i16, dbus::Error>; fn limit(&self) -> Result<i16, dbus::Error>;
} }
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target=T>> OrgAsuslinuxDaemon for blocking::Proxy<'a, C> { impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
for blocking::Proxy<'a, C>
{
fn set_limit(&self, limit: u8) -> Result<(), dbus::Error> { fn set_limit(&self, limit: u8) -> Result<(), dbus::Error> {
self.method_call("org.asuslinux.Daemon", "SetLimit", (limit, )) self.method_call("org.asuslinux.Daemon", "SetLimit", (limit,))
} }
fn limit(&self) -> Result<i16, dbus::Error> { fn limit(&self) -> Result<i16, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "Limit", ()) self.method_call("org.asuslinux.Daemon", "Limit", ())
.and_then(|r: (i16, )| Ok(r.0, )) .and_then(|r: (i16,)| Ok(r.0))
} }
} }
@@ -34,9 +35,7 @@ impl arg::AppendAll for OrgAsuslinuxDaemonNotifyCharge {
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyCharge { impl arg::ReadAll for OrgAsuslinuxDaemonNotifyCharge {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> { fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgAsuslinuxDaemonNotifyCharge { Ok(OrgAsuslinuxDaemonNotifyCharge { limit: i.read()? })
limit: i.read()?,
})
} }
} }
+9 -12
View File
@@ -1,5 +1,5 @@
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -p /org/asuslinux/Gfx -m None -f org.asuslinux.Daemon -c blocking`, see https://github.com/diwic/dbus-rs // This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -p /org/asuslinux/Gfx -m None -f org.asuslinux.Daemon -c blocking`, see https://github.com/diwic/dbus-rs
use dbus as dbus; use dbus;
#[allow(unused_imports)] #[allow(unused_imports)]
use dbus::arg; use dbus::arg;
use dbus::blocking; use dbus::blocking;
@@ -10,20 +10,21 @@ pub trait OrgAsuslinuxDaemon {
fn set_vendor(&self, vendor: &str) -> Result<(), dbus::Error>; fn set_vendor(&self, vendor: &str) -> Result<(), dbus::Error>;
} }
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target=T>> OrgAsuslinuxDaemon for blocking::Proxy<'a, C> { impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
for blocking::Proxy<'a, C>
{
fn vendor(&self) -> Result<String, dbus::Error> { fn vendor(&self) -> Result<String, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "Vendor", ()) self.method_call("org.asuslinux.Daemon", "Vendor", ())
.and_then(|r: (String, )| Ok(r.0, )) .and_then(|r: (String,)| Ok(r.0))
} }
fn power(&self) -> Result<String, dbus::Error> { fn power(&self) -> Result<String, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "Power", ()) self.method_call("org.asuslinux.Daemon", "Power", ())
.and_then(|r: (String, )| Ok(r.0, )) .and_then(|r: (String,)| Ok(r.0))
} }
fn set_vendor(&self, vendor: &str) -> Result<(), dbus::Error> { fn set_vendor(&self, vendor: &str) -> Result<(), dbus::Error> {
self.method_call("org.asuslinux.Daemon", "SetVendor", (vendor, )) self.method_call("org.asuslinux.Daemon", "SetVendor", (vendor,))
} }
} }
@@ -40,9 +41,7 @@ impl arg::AppendAll for OrgAsuslinuxDaemonNotifyGfx {
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyGfx { impl arg::ReadAll for OrgAsuslinuxDaemonNotifyGfx {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> { fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgAsuslinuxDaemonNotifyGfx { Ok(OrgAsuslinuxDaemonNotifyGfx { vendor: i.read()? })
vendor: i.read()?,
})
} }
} }
@@ -64,9 +63,7 @@ impl arg::AppendAll for OrgAsuslinuxDaemonNotifyAction {
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyAction { impl arg::ReadAll for OrgAsuslinuxDaemonNotifyAction {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> { fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgAsuslinuxDaemonNotifyAction { Ok(OrgAsuslinuxDaemonNotifyAction { action: i.read()? })
action: i.read()?,
})
} }
} }
+24 -9
View File
@@ -1,29 +1,46 @@
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/Led -m None`, see https://github.com/diwic/dbus-rs // This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/Led -m None`, see https://github.com/diwic/dbus-rs
use dbus as dbus; use dbus;
#[allow(unused_imports)] #[allow(unused_imports)]
use dbus::arg; use dbus::arg;
use dbus::blocking; use dbus::blocking;
pub trait OrgAsuslinuxDaemon { pub trait OrgAsuslinuxDaemon {
fn set_led_mode(&self, data: &str) -> Result<(), dbus::Error>; fn set_led_mode(&self, data: &str) -> Result<(), dbus::Error>;
fn next_led_mode(&self) -> Result<(), dbus::Error>;
fn prev_led_mode(&self) -> Result<(), dbus::Error>;
fn led_mode(&self) -> Result<String, dbus::Error>; fn led_mode(&self) -> Result<String, dbus::Error>;
fn led_modes(&self) -> Result<String, dbus::Error>; fn led_modes(&self) -> Result<String, dbus::Error>;
fn led_brightness(&self) -> Result<i16, dbus::Error>;
} }
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target=T>> OrgAsuslinuxDaemon for blocking::Proxy<'a, C> { impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
for blocking::Proxy<'a, C>
{
fn set_led_mode(&self, data: &str) -> Result<(), dbus::Error> { fn set_led_mode(&self, data: &str) -> Result<(), dbus::Error> {
self.method_call("org.asuslinux.Daemon", "SetLedMode", (data, )) self.method_call("org.asuslinux.Daemon", "SetLedMode", (data,))
}
fn next_led_mode(&self) -> Result<(), dbus::Error> {
self.method_call("org.asuslinux.Daemon", "NextLedMode", ())
}
fn prev_led_mode(&self) -> Result<(), dbus::Error> {
self.method_call("org.asuslinux.Daemon", "PrevLedMode", ())
} }
fn led_mode(&self) -> Result<String, dbus::Error> { fn led_mode(&self) -> Result<String, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "LedMode", ()) self.method_call("org.asuslinux.Daemon", "LedMode", ())
.and_then(|r: (String, )| Ok(r.0, )) .and_then(|r: (String,)| Ok(r.0))
} }
fn led_modes(&self) -> Result<String, dbus::Error> { fn led_modes(&self) -> Result<String, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "LedModes", ()) self.method_call("org.asuslinux.Daemon", "LedModes", ())
.and_then(|r: (String, )| Ok(r.0, )) .and_then(|r: (String,)| Ok(r.0))
}
fn led_brightness(&self) -> Result<i16, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "LedBrightness", ())
.and_then(|r: (i16,)| Ok(r.0))
} }
} }
@@ -40,9 +57,7 @@ impl arg::AppendAll for OrgAsuslinuxDaemonNotifyLed {
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyLed { impl arg::ReadAll for OrgAsuslinuxDaemonNotifyLed {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> { fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgAsuslinuxDaemonNotifyLed { Ok(OrgAsuslinuxDaemonNotifyLed { data: i.read()? })
data: i.read()?,
})
} }
} }
+12 -1
View File
@@ -1,4 +1,4 @@
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/Profile -m None`, see https://github.com/diwic/dbus-rs // This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -p /org/asuslinux/Profile -m None -f org.asuslinux.Daemon -c blocking`, see https://github.com/diwic/dbus-rs
use dbus; use dbus;
#[allow(unused_imports)] #[allow(unused_imports)]
use dbus::arg; use dbus::arg;
@@ -6,6 +6,8 @@ use dbus::blocking;
pub trait OrgAsuslinuxDaemon { pub trait OrgAsuslinuxDaemon {
fn set_profile(&self, profile: &str) -> Result<(), dbus::Error>; fn set_profile(&self, profile: &str) -> Result<(), dbus::Error>;
fn next_profile(&self) -> Result<(), dbus::Error>;
fn active_profile_name(&self) -> Result<String, dbus::Error>;
fn profile(&self) -> Result<String, dbus::Error>; fn profile(&self) -> Result<String, dbus::Error>;
fn profiles(&self) -> Result<String, dbus::Error>; fn profiles(&self) -> Result<String, dbus::Error>;
} }
@@ -17,6 +19,15 @@ impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsusl
self.method_call("org.asuslinux.Daemon", "SetProfile", (profile,)) self.method_call("org.asuslinux.Daemon", "SetProfile", (profile,))
} }
fn next_profile(&self) -> Result<(), dbus::Error> {
self.method_call("org.asuslinux.Daemon", "NextProfile", ())
}
fn active_profile_name(&self) -> Result<String, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "ActiveProfileName", ())
.and_then(|r: (String,)| Ok(r.0))
}
fn profile(&self) -> Result<String, dbus::Error> { fn profile(&self) -> Result<String, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "Profile", ()) self.method_call("org.asuslinux.Daemon", "Profile", ())
.and_then(|r: (String,)| Ok(r.0)) .and_then(|r: (String,)| Ok(r.0))
+86
View File
@@ -0,0 +1,86 @@
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/RogBios -m None -o asus-nb/src/dbus_rogbios.rs`, see https://github.com/diwic/dbus-rs
use dbus;
#[allow(unused_imports)]
use dbus::arg;
use dbus::blocking;
pub trait OrgAsuslinuxDaemon {
fn set_dedicated_graphic_mode(&self, dedicated: bool) -> Result<(), dbus::Error>;
fn dedicated_graphic_mode(&self) -> Result<i16, dbus::Error>;
fn set_post_boot_sound(&self, on: bool) -> Result<(), dbus::Error>;
fn post_boot_sound(&self) -> Result<i16, dbus::Error>;
}
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
for blocking::Proxy<'a, C>
{
fn set_dedicated_graphic_mode(&self, dedicated: bool) -> Result<(), dbus::Error> {
self.method_call(
"org.asuslinux.Daemon",
"SetDedicatedGraphicMode",
(dedicated,),
)
}
fn dedicated_graphic_mode(&self) -> Result<i16, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "DedicatedGraphicMode", ())
.and_then(|r: (i16,)| Ok(r.0))
}
fn set_post_boot_sound(&self, on: bool) -> Result<(), dbus::Error> {
self.method_call("org.asuslinux.Daemon", "SetPostBootSound", (on,))
}
fn post_boot_sound(&self) -> Result<i16, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "PostBootSound", ())
.and_then(|r: (i16,)| Ok(r.0))
}
}
#[derive(Debug)]
pub struct OrgAsuslinuxDaemonNotifyDedicatedGraphicMode {
pub dedicated: bool,
}
impl arg::AppendAll for OrgAsuslinuxDaemonNotifyDedicatedGraphicMode {
fn append(&self, i: &mut arg::IterAppend) {
arg::RefArg::append(&self.dedicated, i);
}
}
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyDedicatedGraphicMode {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgAsuslinuxDaemonNotifyDedicatedGraphicMode {
dedicated: i.read()?,
})
}
}
impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyDedicatedGraphicMode {
const NAME: &'static str = "NotifyDedicatedGraphicMode";
const INTERFACE: &'static str = "org.asuslinux.Daemon";
}
#[derive(Debug)]
pub struct OrgAsuslinuxDaemonNotifyPostBootSound {
pub dedicated: bool,
}
impl arg::AppendAll for OrgAsuslinuxDaemonNotifyPostBootSound {
fn append(&self, i: &mut arg::IterAppend) {
arg::RefArg::append(&self.dedicated, i);
}
}
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyPostBootSound {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgAsuslinuxDaemonNotifyPostBootSound {
dedicated: i.read()?,
})
}
}
impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyPostBootSound {
const NAME: &'static str = "NotifyPostBootSound";
const INTERFACE: &'static str = "org.asuslinux.Daemon";
}
+18
View File
@@ -0,0 +1,18 @@
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/Supported -m None -o asus-nb/src/dbus_supported.rs`, see https://github.com/diwic/dbus-rs
use dbus;
#[allow(unused_imports)]
use dbus::arg;
use dbus::blocking;
pub trait OrgAsuslinuxDaemon {
fn supported_functions(&self) -> Result<String, dbus::Error>;
}
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
for blocking::Proxy<'a, C>
{
fn supported_functions(&self) -> Result<String, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "SupportedFunctions", ())
.and_then(|r: (String,)| Ok(r.0))
}
}
+2
View File
@@ -7,6 +7,7 @@ pub enum AuraError {
ParseSpeed, ParseSpeed,
ParseDirection, ParseDirection,
ParseBrightness, ParseBrightness,
ParseAnime,
} }
impl fmt::Display for AuraError { impl fmt::Display for AuraError {
@@ -17,6 +18,7 @@ impl fmt::Display for AuraError {
AuraError::ParseSpeed => write!(f, "Could not parse speed"), AuraError::ParseSpeed => write!(f, "Could not parse speed"),
AuraError::ParseDirection => write!(f, "Could not parse direction"), AuraError::ParseDirection => write!(f, "Could not parse direction"),
AuraError::ParseBrightness => write!(f, "Could not parse brightness"), AuraError::ParseBrightness => write!(f, "Could not parse brightness"),
AuraError::ParseAnime => write!(f, "Could not parse anime"),
} }
} }
} }
+6 -3
View File
@@ -23,12 +23,15 @@ pub mod anime_dbus;
/// Helper functions for the AniMe display /// Helper functions for the AniMe display
pub mod anime_matrix; pub mod anime_matrix;
pub mod error;
pub mod dbus_anime;
pub mod dbus_charge;
pub mod dbus_gfx; pub mod dbus_gfx;
pub mod dbus_ledmode; pub mod dbus_ledmode;
pub mod dbus_profile; pub mod dbus_profile;
pub mod dbus_charge; pub mod dbus_rogbios;
pub mod dbus_supported;
pub mod error;
// static LED_INIT1: [u8; 2] = [0x5d, 0xb9]; // static LED_INIT1: [u8; 2] = [0x5d, 0xb9];
// static LED_INIT2: &str = "]ASUS Tech.Inc."; // ] == 0x5d // static LED_INIT2: &str = "]ASUS Tech.Inc."; // ] == 0x5d
+3 -1
View File
@@ -75,7 +75,9 @@ fn parse_fan_curve(data: &str) -> Result<Curve, String> {
#[derive(Debug, Clone, Options, Serialize, Deserialize)] #[derive(Debug, Clone, Options, Serialize, Deserialize)]
pub struct ProfileCommand { pub struct ProfileCommand {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, pub help: bool,
#[options(help = "toggle to next profile in list")]
pub next: bool,
#[options(help = "create the profile if it doesn't exist")] #[options(help = "create the profile if it doesn't exist")]
pub create: bool, pub create: bool,
+6 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "asus-notify" name = "asus-notify"
version = "1.0.1" version = "2.0.4"
authors = ["Luke D Jones <luke@ljones.dev>"] authors = ["Luke D Jones <luke@ljones.dev>"]
edition = "2018" edition = "2018"
@@ -11,7 +11,11 @@ edition = "2018"
serde = "^1.0" serde = "^1.0"
serde_derive = "^1.0" serde_derive = "^1.0"
serde_json = "^1.0" serde_json = "^1.0"
notify-rust = "^4.0.0"
dbus = { version = "^0.8" } dbus = { version = "^0.8" }
asus-nb = { path = "../asus-nb" } asus-nb = { path = "../asus-nb" }
asus-nb-ctrl = { path = "../asus-nb-ctrl" } asus-nb-ctrl = { path = "../asus-nb-ctrl" }
[dependencies.notify-rust]
version = "^4.0.0"
default-features = false
features = ["z"]
+7 -1
View File
@@ -6,6 +6,8 @@ use std::error::Error;
use std::time::Duration; use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Version {}", env!("CARGO_PKG_VERSION"));
let mut cfg = Config::read_new()?; let mut cfg = Config::read_new()?;
let mut last_profile = String::new(); let mut last_profile = String::new();
@@ -81,7 +83,11 @@ fn do_thermal_notif(profile: &Profile, label: &str) -> Result<NotificationHandle
}; };
let x = Notification::new() let x = Notification::new()
.summary("ASUS ROG") .summary("ASUS ROG")
.body(&format!("Thermal profile changed to {}, turbo {}", label.to_uppercase(), turbo)) .body(&format!(
"Thermal profile changed to {}, turbo {}",
label.to_uppercase(),
turbo
))
.hint(Hint::Resident(true)) .hint(Hint::Resident(true))
.timeout(2000) .timeout(2000)
.hint(Hint::Category("device".into())) .hint(Hint::Category("device".into()))
-19
View File
@@ -1,19 +0,0 @@
[package]
name = "ctrl-gfx"
version = "2.1.0"
license = "MPL-2.0"
readme = "README.md"
authors = ["Luke <luke@ljones.dev>"]
description = "Fine control of laptop GPU"
edition = "2018"
[dependencies]
sysfs-class = "^0.1.2"
log = "^0.4"
zbus = { version = "1.1.1", optional = true }
zvariant = { version = "2.2.0", optional = true }
[features]
default = ["use-zbus"]
use-zbus = ["zbus", "zvariant"]
-1
View File
@@ -1,5 +1,4 @@
Section "ServerLayout" Section "ServerLayout"
Identifier "layout" Identifier "layout"
Option "AllowNVIDIAGPUScreens" Option "AllowNVIDIAGPUScreens"
Option "metamodes" "nvidia-auto-select +0+0 {AllowGSYNC=On, AllowGSYNCCompatible=On}"
EndSection EndSection
+50
View File
@@ -0,0 +1,50 @@
function _asusctl() {
local line
_arguments -C \
{-h,--help}'[print help message]' \
{-v,--version}'[print version number]' \
{-k,--kbd-bright}':[Set keyboard brightness (off, low, med, high)]' \
{-p,--pwr-profile}':[Set power profile (silent, normal, boost)]' \
{-c,--chg-limit}':[Set charging limit (20-100)]' \
': :((led-mode\:"Set the keyboard lighting from built-in modes" profile\:"Create and configure profiles" graphics\:"Set the graphics mode"))' \
'*::arg:->args'
case $line[1] in
led-mode)
_arguments ': :((static\:"set a single static colour"
breathe\:"pulse between one or two colours"
strobe\:"strobe through all colours"
rainbow\:"rainbow cycling in one of four directions"
star\:"rain pattern mimicking raindrops"
rain\:"rain pattern of three preset colours"
highlight\:"pressed keys are highlighted to fade"
laser\:"pressed keys generate horizontal laser"
ripple\:"pressed keys ripple outwards like a splash"
pulse\:"set a rapid pulse"
comet\:"set a vertical line zooming from left"
flash\:"set a wide vertical line zooming from left"
multi-static\:"4-zone multi-colour"))' \
{-h,--help}'[print help message]' \
'-c:[set the RGB value e.g, ff00ff]' \
'-s:[set the speed (low, med, high)]'
;;
profile)
_arguments {-h,--help}'[print help message]' \
{-c,--create}"[create the profile if it doesn't exist]" \
{-t,--turbo}':[enable or disable cpu turbo]' \
{-m,--min-percentage}':[set min cpu scaling (intel)]' \
{-M,--max-percentage}':[set max cpu scaling (intel)]' \
{-p,--preset}':[<silent, normal, boost>]' \
{-C,--curve}':[set fan curve]'
;;
graphics)
_arguments {-h,--help}'[print help message]' \
{-m,--mode}':[Set graphics mode (nvidia, hybrid, compute, integrated)]' \
{-g,--get}'[Get the current mode]' \
{-p,--pow}'[Get the current power status]' \
{-f,--force}'[Do not ask for confirmation]'
;;
esac
}
compdef _asusctl asusctl
+1 -1
View File
@@ -4,9 +4,9 @@ StartLimitInterval=200
StartLimitBurst=2 StartLimitBurst=2
[Service] [Service]
ExecStartPre=/usr/bin/sleep 2
ExecStart=/usr/bin/asus-notify ExecStart=/usr/bin/asus-notify
Restart=on-failure Restart=on-failure
Restart=always
RestartSec=1 RestartSec=1
Type=simple Type=simple