mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b3a555cab9 | |||
| cf13b4f71b | |||
| cd0b9fe350 | |||
| 82900f4645 | |||
| 703bba9ffd | |||
| 73706154a4 | |||
| c9b2a0c777 | |||
| 54cc51fe5d | |||
| 81645d0777 | |||
| d61c180ee5 | |||
| a668800fd9 | |||
| 3bdc11c994 | |||
| b496139063 | |||
| 607483629a | |||
| 5c8d138cef | |||
| e3db1f7c4c | |||
| de3b803f14 | |||
| 0558f919c4 | |||
| 68ea73c847 | |||
| 96ddb7132d | |||
| d36ac44603 | |||
| 5d06c87943 | |||
| 588e3c0102 | |||
| 6ce32c1cab | |||
| a23c51e5db | |||
| 3845071ba3 | |||
| a48b3634bf | |||
| 806882b2e9 | |||
| 9ac3c46fe6 | |||
| 6817a1c027 | |||
| cf2be1b12b | |||
| 9ffeb19c8c | |||
| a7f6e8bd24 | |||
| f61f62c219 | |||
| bb70fd7b71 | |||
| b80c860b7a | |||
| 3c7544f034 | |||
| 6746c2b654 | |||
| 8d59f89438 | |||
| 5753160e91 | |||
| 622cd9d943 | |||
| 2daa7f0811 | |||
| 05c53df0ed | |||
| a7419cbc4c | |||
| 67ad38a7e6 | |||
| e572ae2c62 |
+50
-1
@@ -6,7 +6,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
# [2.0.0] - 2020-09-21
|
# [2.2.1] - 2021-01-27
|
||||||
|
### Added
|
||||||
|
- Add ROG Zephyrus M15 LED config
|
||||||
|
### Changed
|
||||||
|
- Bugfixes
|
||||||
|
- Fix reboot/restartx status for GFX switching
|
||||||
|
- Update readme
|
||||||
|
- Change CLI arg tag for fan modes
|
||||||
|
- Make dracut include the nvidia modules in initramfs
|
||||||
|
|
||||||
|
# [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
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -5,6 +5,12 @@ 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.
|
||||||
|
|
||||||
|
**NOTICE:**
|
||||||
|
The following is *not* required for 5.11 kernel versions, as this version includes
|
||||||
|
all the required patches.
|
||||||
|
---
|
||||||
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 +29,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
|
||||||
|
|
||||||
@@ -51,13 +57,17 @@ will probably suffer another rename once it becomes generic enough to do so.
|
|||||||
- [X] Set battery charge limit (with kernel supporting this)
|
- [X] Set battery charge limit (with kernel supporting this)
|
||||||
- [X] Fancy fan control on G14 + G15 thanks to @Yarn1
|
- [X] Fancy fan control on G14 + G15 thanks to @Yarn1
|
||||||
- [X] Graphics mode switching between iGPU, dGPU, and On-Demand
|
- [X] Graphics mode switching between iGPU, dGPU, and On-Demand
|
||||||
|
- [X] Toggle bios setting for boot/POST sound
|
||||||
|
- [X] Toggle bios setting for "dedicated gfx" mode on supported laptops (g-sync)
|
||||||
|
|
||||||
# FUNCTIONS
|
# FUNCTIONS
|
||||||
|
|
||||||
## Graphics switching
|
## Graphics switching
|
||||||
|
|
||||||
A new feature has been added to enable switching graphics modes. This can be disabled
|
A new feature has been added to enable switching graphics modes. This can be disabled
|
||||||
in the config with `"manage_gfx": false,`. Please be aware it is a work in progress.
|
in the config with `"manage_gfx": false,`. Additionally there is an extra setting
|
||||||
|
for laptops capable of g-sync dedicated gfx mode to enable the graphics switching
|
||||||
|
to switch on dedicated gfx for "nvidia" mode.
|
||||||
|
|
||||||
The CLI option for this does not require root until it asks for it, and provides
|
The CLI option for this does not require root until it asks for it, and provides
|
||||||
instructions.
|
instructions.
|
||||||
@@ -74,13 +84,11 @@ 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
|
||||||
to stop dracut including the nvidia modules in the ramdisk.
|
to stop dracut including the nvidia modules in the ramdisk. This is espeically
|
||||||
|
true if you manually installed the nvidia drivers.
|
||||||
|
|
||||||
```
|
```
|
||||||
# filename /etc/dracut.conf.d/90-nvidia-dracut-G05.conf
|
# filename /etc/dracut.conf.d/90-nvidia-dracut-G05.conf
|
||||||
@@ -118,16 +126,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 +154,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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "asus-nb-ctrl"
|
name = "asus-nb-ctrl"
|
||||||
version = "2.0.2"
|
version = "2.2.1"
|
||||||
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
@@ -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();
|
||||||
|
|||||||
@@ -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(())
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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: add_to_server {}", 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,6 +1,8 @@
|
|||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use crate::error::RogError;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum GfxError {
|
pub enum GfxError {
|
||||||
ParseVendor,
|
ParseVendor,
|
||||||
@@ -28,3 +30,9 @@ impl fmt::Display for GfxError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl error::Error for GfxError {}
|
impl error::Error for GfxError {}
|
||||||
|
|
||||||
|
impl From<GfxError> for RogError {
|
||||||
|
fn from(err: GfxError) -> Self {
|
||||||
|
RogError::GfxSwitching(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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::{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,39 @@ 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 ZbusAdd for CtrlGraphics {
|
||||||
|
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||||
|
server
|
||||||
|
.at(
|
||||||
|
&"/org/asuslinux/Gfx"
|
||||||
|
.try_into()
|
||||||
|
.expect("Couldn't add to zbus"),
|
||||||
|
self,
|
||||||
|
)
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("CtrlGraphics: add_to_server {}", err);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Reloadable for CtrlGraphics {
|
||||||
|
fn reload(&mut self) -> Result<(), RogError> {
|
||||||
|
self.auto_power()?;
|
||||||
|
info!("Reloaded gfx mode: {:?}", CtrlGraphics::get_vendor()?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
||||||
@@ -127,13 +150,12 @@ impl CtrlGraphics {
|
|||||||
cmd.arg("-u");
|
cmd.arg("-u");
|
||||||
initfs_cmd = Some(cmd);
|
initfs_cmd = Some(cmd);
|
||||||
info!("Using initramfs update command 'update-initramfs'");
|
info!("Using initramfs update command 'update-initramfs'");
|
||||||
|
} else if Path::new(DRACUT_PATH).exists() {
|
||||||
|
let mut cmd = Command::new("dracut");
|
||||||
|
cmd.arg("-f");
|
||||||
|
initfs_cmd = Some(cmd);
|
||||||
|
info!("Using initramfs update command 'dracut'");
|
||||||
}
|
}
|
||||||
// } else if Path::new(DRACUT_PATH).exists() {
|
|
||||||
// let mut cmd = Command::new("dracut");
|
|
||||||
// cmd.arg("-f");
|
|
||||||
// initfs_cmd = Some(cmd);
|
|
||||||
// info!("Using initramfs update command 'dracut'");
|
|
||||||
// }
|
|
||||||
|
|
||||||
Ok(CtrlGraphics {
|
Ok(CtrlGraphics {
|
||||||
bus,
|
bus,
|
||||||
@@ -142,27 +164,11 @@ impl CtrlGraphics {
|
|||||||
nvidia,
|
nvidia,
|
||||||
other,
|
other,
|
||||||
initfs_cmd,
|
initfs_cmd,
|
||||||
|
config,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "use-zbus")]
|
fn get_prime_discrete() -> Result<String, RogError> {
|
||||||
pub fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
|
||||||
server
|
|
||||||
.at(&"/org/asuslinux/Gfx".try_into().unwrap(), self)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reload(&mut self) -> Result<(), Box<dyn Error>> {
|
|
||||||
self.auto_power()?;
|
|
||||||
info!("Reloaded gfx mode: {:?}", CtrlGraphics::get_vendor()?);
|
|
||||||
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> {
|
|
||||||
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))?
|
||||||
.trim()
|
.trim()
|
||||||
@@ -170,51 +176,75 @@ impl CtrlGraphics {
|
|||||||
Ok(s)
|
Ok(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_prime_discrete(mode: &str) -> Result<(), GfxError> {
|
fn set_prime_discrete(mode: &str) -> Result<(), RogError> {
|
||||||
std::fs::write(PRIME_DISCRETE_PATH, mode)
|
std::fs::write(PRIME_DISCRETE_PATH, mode)
|
||||||
.map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))?;
|
.map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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, RogError> {
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_switching_prime_modes(vendor: &GfxVendors) -> Result<bool, GfxError> {
|
fn is_switching_prime_modes(&self, vendor: &GfxVendors) -> Result<bool, RogError> {
|
||||||
let prev_mode = GfxVendors::from_str(&Self::get_vendor()?)?;
|
let prev_mode = GfxVendors::from_str(&Self::get_vendor()?)?;
|
||||||
let x = (prev_mode == GfxVendors::Hybrid || prev_mode == GfxVendors::Nvidia)
|
if prev_mode == GfxVendors::Integrated
|
||||||
&& (*vendor == GfxVendors::Hybrid || *vendor == GfxVendors::Nvidia);
|
&& (*vendor == GfxVendors::Hybrid || *vendor == GfxVendors::Nvidia)
|
||||||
Ok(x)
|
{
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
if (prev_mode == GfxVendors::Hybrid || prev_mode == GfxVendors::Nvidia)
|
||||||
|
&& *vendor == GfxVendors::Integrated
|
||||||
|
{
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
if let Ok(config) = self.config.clone().try_lock() {
|
||||||
|
if CtrlRogBios::has_dedicated_gfx_toggle() && config.gfx_nv_mode_is_dedicated {
|
||||||
|
if prev_mode == GfxVendors::Hybrid && *vendor == GfxVendors::Nvidia {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
if *vendor == GfxVendors::Hybrid && prev_mode == GfxVendors::Nvidia {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write out config files if required, enable/disable relevant services, and update the ramdisk
|
pub fn set_gfx_config(vendor: GfxVendors) -> Result<(), RogError> {
|
||||||
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 +257,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,44 +324,69 @@ impl CtrlGraphics {
|
|||||||
status
|
status
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write out config files if required, enable/disable relevant services, and update the ramdisk
|
||||||
|
fn set(&mut self, vendor: GfxVendors) -> Result<String, RogError> {
|
||||||
|
// Switching from hybrid to/from nvidia shouldn't require a ramdisk update
|
||||||
|
// or a reboot.
|
||||||
|
let reboot = self.is_switching_prime_modes(&vendor)?;
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::set_gfx_config(vendor.clone())?;
|
||||||
|
|
||||||
let mut required_action = GfxCtrlAction::None;
|
let mut required_action = GfxCtrlAction::None;
|
||||||
if !no_reboot {
|
if reboot {
|
||||||
info!("Updating initramfs");
|
info!("Updating initramfs");
|
||||||
if let Some(cmd) = self.initfs_cmd.as_mut() {
|
if let Some(cmd) = self.initfs_cmd.as_mut() {
|
||||||
|
// If switching to Nvidia dedicated we need these modules included
|
||||||
|
if Path::new(DRACUT_PATH).exists() && vendor == GfxVendors::Nvidia {
|
||||||
|
cmd.arg("--add-drivers");
|
||||||
|
cmd.arg("nvidia nvidia-drm nvidia-modeset nvidia-uvm");
|
||||||
|
info!("System uses dracut, forcing nvidia modules to be included in init");
|
||||||
|
}
|
||||||
|
|
||||||
let status = cmd
|
let status = cmd
|
||||||
.status()
|
.status()
|
||||||
.map_err(|err| GfxError::Write(format!("{:?}", cmd), err))?;
|
.map_err(|err| GfxError::Write(format!("{:?}", cmd), err))?;
|
||||||
if !status.success() {
|
if !status.success() {
|
||||||
error!("Ram disk update failed");
|
error!("Ram disk update failed");
|
||||||
|
return Ok("Ram disk update failed".into());
|
||||||
} else {
|
} else {
|
||||||
info!("Successfully updated iniramfs");
|
info!("Successfully updated iniramfs");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
required_action = GfxCtrlAction::Reboot;
|
required_action = GfxCtrlAction::Reboot;
|
||||||
} else if no_reboot {
|
} else if !reboot {
|
||||||
required_action = GfxCtrlAction::RestartX;
|
required_action = GfxCtrlAction::RestartX;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(required_action.into())
|
Ok(required_action.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn get_power(&self) -> Option<bool> {
|
fn get_runtime_status() -> Result<String, RogError> {
|
||||||
// if self.can_switch() {
|
|
||||||
// return Some(self.nvidia.iter().any(GraphicsDevice::exists));
|
|
||||||
// }
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
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<(), RogError> {
|
||||||
// self.switchable_or_fail()?;
|
|
||||||
|
|
||||||
if power {
|
if power {
|
||||||
info!("Enabling graphics power");
|
info!("Enabling graphics power");
|
||||||
self.bus
|
self.bus
|
||||||
@@ -357,7 +408,7 @@ impl CtrlGraphics {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn auto_power(&self) -> Result<(), GfxError> {
|
fn auto_power(&self) -> Result<(), RogError> {
|
||||||
let vendor = CtrlGraphics::get_vendor()?;
|
let vendor = CtrlGraphics::get_vendor()?;
|
||||||
self.set_power(vendor != "integrated")
|
self.set_power(vendor != "integrated")
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
|
||||||
+191
-26
@@ -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 log::{info, warn};
|
use crate::{
|
||||||
use std::convert::TryInto;
|
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::{error, info, warn};
|
||||||
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,10 @@ 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();
|
.map_err(|err| {
|
||||||
|
error!("DbusKbdBacklight: add_to_server {}", err);
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,10 +110,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 +124,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 +171,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 +184,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 +249,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 +279,37 @@ 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 {
|
||||||
led_node: Self::get_node_failover(id_product, None, Self::scan_led_node).ok(),
|
// Using `ok` here so we can continue without keyboard features but
|
||||||
kbd_node: Self::get_node_failover(id_product, condev_iface, Self::scan_kbd_node).ok(),
|
// still get brightness control at least... maybe...
|
||||||
|
led_node: Some(Self::get_node_failover(
|
||||||
|
id_product,
|
||||||
|
None,
|
||||||
|
Self::scan_led_node,
|
||||||
|
)?),
|
||||||
|
kbd_node: Some(Self::get_node_failover(
|
||||||
|
id_product,
|
||||||
|
condev_iface,
|
||||||
|
Self::scan_kbd_node,
|
||||||
|
)?),
|
||||||
// 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 +318,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 +359,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 +393,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 +431,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 +489,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 {
|
||||||
|
|||||||
@@ -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
@@ -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");
|
||||||
|
CtrlGraphics::set_gfx_config(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);
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
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;
|
||||||
|
|
||||||
|
use crate::ctrl_gfx::error::GfxError;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum RogError {
|
pub enum RogError {
|
||||||
@@ -19,6 +21,9 @@ pub enum RogError {
|
|||||||
FanCurve(CurveError),
|
FanCurve(CurveError),
|
||||||
DoTask(String),
|
DoTask(String),
|
||||||
MissingFunction(String),
|
MissingFunction(String),
|
||||||
|
MissingLedBrightNode(String, std::io::Error),
|
||||||
|
ReloadFail(String),
|
||||||
|
GfxSwitching(GfxError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for RogError {
|
impl fmt::Display for RogError {
|
||||||
@@ -39,6 +44,9 @@ 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),
|
||||||
|
RogError::GfxSwitching(deets) => write!(f, "Graphics switching error: {}", deets),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
+220
-34
@@ -1,28 +1,32 @@
|
|||||||
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(
|
||||||
pwr_profile: Option<FanLevel>,
|
meta = "",
|
||||||
#[options(meta = "CHRG", help = "<20-100>")]
|
help = "<silent, normal, boost>, set fan mode independent of profile"
|
||||||
|
)]
|
||||||
|
fan_mode: Option<FanLevel>,
|
||||||
|
#[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 +40,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 +62,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 +75,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 +112,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.fan_mode.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 let Some(fan_level) = parsed.pwr_profile {
|
|
||||||
writer.write_fan_mode(fan_level.into())?;
|
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.fan_mode {
|
||||||
|
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 +302,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",
|
||||||
)?;
|
)?;
|
||||||
@@ -139,16 +322,19 @@ fn do_gfx(
|
|||||||
)?;
|
)?;
|
||||||
std::process::exit(1)
|
std::process::exit(1)
|
||||||
}
|
}
|
||||||
_ => std::process::exit(-1),
|
_ => {
|
||||||
|
println!("{}", Red.paint(&format!("\n{}\n", res.as_str())),);
|
||||||
|
std::process::exit(-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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 {
|
||||||
|
|||||||
@@ -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
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "asus-nb"
|
name = "asus-nb"
|
||||||
version = "2.0.2"
|
version = "2.2.1"
|
||||||
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"
|
||||||
@@ -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
@@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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!();
|
||||||
|
|||||||
@@ -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
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
@@ -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()?,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()?,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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";
|
||||||
|
}
|
||||||
@@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|
||||||
|
|||||||
@@ -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"]
|
||||||
@@ -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()))
|
||||||
|
|||||||
@@ -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,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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ prod_family = "Zephyrus M"
|
|||||||
board_names = ["GU502GV"]
|
board_names = ["GU502GV"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
||||||
|
|
||||||
|
[[led_modes]]
|
||||||
|
prod_family = "ROG Zephyrus M15"
|
||||||
|
board_names = ["GU502LW"]
|
||||||
|
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_modes]]
|
||||||
prod_family = "Zephyrus"
|
prod_family = "Zephyrus"
|
||||||
board_names = ["GM501GM", "GX531"]
|
board_names = ["GM501GM", "GX531"]
|
||||||
|
|||||||
Reference in New Issue
Block a user