diff --git a/CHANGELOG.md b/CHANGELOG.md index dcc786c6..60cebb75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 + `BREAKING:` plain `Image` with time period is changed and old anime configs break as a result (sorry) ### BREAKING CHANGES - Graphics control: - + graphics control is pulled out of asusd and moved to new crate; supergfxctl + + graphics control is pulled out of asusd and moved to new package; https://gitlab.com/asus-linux/supergfxctl - Proflies: + profiles now depend on power-profile-daemon plus kernel patches for support of platform_profile - if your system supports fan-curves you will also require upcoming kernel patches for this diff --git a/Cargo.lock b/Cargo.lock index 4f71a8f8..03220719 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1069,9 +1069,8 @@ dependencies = [ [[package]] name = "supergfxctl" version = "2.0.0" +source = "git+https://gitlab.com/asus-linux/supergfxctl.git?tag=2.0.0#3f040cd3ec334242631122cd038aa361cc860be6" dependencies = [ - "env_logger", - "gumdrop", "log", "logind-zbus", "serde", diff --git a/Cargo.toml b/Cargo.toml index abc0d8d9..40cd341e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["asusctl", "asus-notify", "daemon", "daemon-user", "rog-supported", "rog-dbus", "rog-anime", "rog-aura", "rog-profiles", "supergfx"] +members = ["asusctl", "asus-notify", "daemon", "daemon-user", "rog-supported", "rog-dbus", "rog-anime", "rog-aura", "rog-profiles"] [profile.release] lto = true diff --git a/Makefile b/Makefile index 5bc05dd0..c0e7265d 100644 --- a/Makefile +++ b/Makefile @@ -15,11 +15,7 @@ BIN_C := asusctl BIN_D := asusd BIN_U := asusd-user BIN_N := asus-notify -BIN_SD := supergfxd -BIN_SC := supergfxctl LEDCFG := asusd-ledmodes.toml -X11CFG := 90-nvidia-screen-G05.conf -PMRULES := 90-asusd-nvidia-pm.rules SRC := Cargo.toml Cargo.lock Makefile $(shell find -type f -wholename '**/src/*.rs') @@ -71,13 +67,6 @@ install: $(INSTALL_DATA) "./data/completions/asusctl.fish" "$(DESTDIR)$(datarootdir)/fish/vendor_completions.d/asusctl.fish" cd rog-anime/data && find "./anime" -type f -exec install -Dm 755 "{}" "$(DESTDIR)$(datarootdir)/asusd/{}" \; - $(INSTALL_PROGRAM) "./target/release/$(BIN_SD)" "$(DESTDIR)$(bindir)/$(BIN_SD)" - $(INSTALL_PROGRAM) "./target/release/$(BIN_SC)" "$(DESTDIR)$(bindir)/$(BIN_SC)" - $(INSTALL_DATA) "./supergfx/data/$(BIN_SD).service" "$(DESTDIR)$(libdir)/systemd/system/$(BIN_SD).service" - $(INSTALL_DATA) "./supergfx/data/org.supergfxctl.Daemon.conf" "$(DESTDIR)$(datarootdir)/dbus-1/system.d/org.supergfxctl.Daemon.conf" - $(INSTALL_DATA) "./supergfx/data/$(X11CFG)" "$(DESTDIR)$(datarootdir)/X11/xorg.conf.d/$(X11CFG)" - $(INSTALL_DATA) "./supergfx/data/$(PMRULES)" "$(DESTDIR)$(libdir)/udev/rules.d/$(PMRULES)" - uninstall: rm -f "$(DESTDIR)$(bindir)/$(BIN_C)" rm -f "$(DESTDIR)$(bindir)/$(BIN_D)" @@ -101,10 +90,6 @@ uninstall: rm -f "$(DESTDIR)$(zshcpl)/_asusctl" rm -f "$(DESTDIR)$(datarootdir)/fish/vendor_completions.d/asusctl.fish" rm -rf "$(DESTDIR)$(datarootdir)/asusd" - rm -f "$(DESTDIR)$(bindir)/$(BIN_SC)" - rm -f "$(DESTDIR)$(bindir)/$(BIN_SD)" - rm -f "$(DESTDIR)$(libdir)/systemd/system/$(BIN_SD).service" - rm -f "$(DESTDIR)$(datarootdir)/dbus-1/system.d/org.supergfxctl.Daemon.conf" update: cargo update diff --git a/asus-notify/Cargo.toml b/asus-notify/Cargo.toml index 81c1238d..5bb57b2c 100644 --- a/asus-notify/Cargo.toml +++ b/asus-notify/Cargo.toml @@ -14,7 +14,7 @@ rog_dbus = { path = "../rog-dbus" } rog_aura = { path = "../rog-aura" } rog_supported = { path = "../rog-supported" } rog_profiles = { path = "../rog-profiles" } -supergfxctl = { path = "../supergfx" } +supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git", tag = "2.0.0" } [dependencies.notify-rust] version = "^4.3" diff --git a/asusctl/Cargo.toml b/asusctl/Cargo.toml index 31a31713..8d2fbe07 100644 --- a/asusctl/Cargo.toml +++ b/asusctl/Cargo.toml @@ -15,7 +15,7 @@ rog_profiles = { path = "../rog-profiles" } rog_supported = { path = "../rog-supported" } daemon = { path = "../daemon" } gumdrop = "^0.8" -supergfxctl = { path = "../supergfx" } +supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git", tag = "2.0.0" } [dev-dependencies] tinybmp = "^0.2.3" diff --git a/rog-dbus/Cargo.toml b/rog-dbus/Cargo.toml index a997bd46..81b7a443 100644 --- a/rog-dbus/Cargo.toml +++ b/rog-dbus/Cargo.toml @@ -14,7 +14,7 @@ rog_anime = { path = "../rog-anime" } rog_aura = { path = "../rog-aura" } rog_profiles = { path = "../rog-profiles" } rog_supported = { path = "../rog-supported" } -supergfxctl = { path = "../supergfx" } +supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git", tag = "2.0.0" } zbus = "^1.9" zbus_macros = "^1.9" zvariant = "^2.8" diff --git a/supergfx/Cargo.toml b/supergfx/Cargo.toml deleted file mode 100644 index 7c0a93f3..00000000 --- a/supergfx/Cargo.toml +++ /dev/null @@ -1,49 +0,0 @@ -[package] -name = "supergfxctl" -version = "2.0.0" -license = "MPL-2.0" -readme = "README.md" -authors = ["Luke "] -repository = "https://gitlab.com/asus-linux/asusctl" -homepage = "https://gitlab.com/asus-linux/asusctl" -documentation = "https://docs.rs/rog-anime" -description = "Types useful for fancy keyboards on ASUS ROG laptops" -keywords = ["graphics", "nvidia", "switching"] -edition = "2018" -exclude = ["data"] - -[features] -daemon = ["env_logger"] -cli = ["gumdrop"] -default = ["daemon", "cli"] - -[lib] -name = "supergfxctl" -path = "src/lib.rs" - -[[bin]] -name = "supergfxd" -path = "src/daemon.rs" -required-features = ["daemon"] - -[[bin]] -name = "supergfxctl" -path = "src/cli.rs" -required-features = ["cli"] -default-features = ["cli"] - -[dependencies] -serde = "^1.0" -serde_derive = "^1.0" -serde_json = "^1.0" -log = "^0.4" - -zbus = "^1.9.1" -zvariant = "^2.8" -zvariant_derive = "^2.8" -logind-zbus = "^0.7.1" - -sysfs-class = "^0.1.2" - -env_logger = { version = "^0.8", optional = true } -gumdrop = { version = "^0.8", optional = true } \ No newline at end of file diff --git a/supergfx/LICENSE b/supergfx/LICENSE deleted file mode 100644 index a612ad98..00000000 --- a/supergfx/LICENSE +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/supergfx/Makefile b/supergfx/Makefile deleted file mode 100644 index fb4f47ae..00000000 --- a/supergfx/Makefile +++ /dev/null @@ -1,74 +0,0 @@ -VERSION := $(shell grep -Pm1 'version = "(\d.\d.\d)"' daemon/Cargo.toml | cut -d'"' -f2) - -INSTALL = install -INSTALL_PROGRAM = ${INSTALL} -D -m 0755 -INSTALL_DATA = ${INSTALL} -D -m 0644 - -prefix = /usr -exec_prefix = $(prefix) -bindir = $(exec_prefix)/bin -datarootdir = $(prefix)/share -libdir = $(exec_prefix)/lib - -BIN_SD := supergfxd -BIN_SC := supergfxctl -X11CFG := 90-nvidia-screen-G05.conf -PMRULES := 90-asusd-nvidia-pm.rules - -SRC := Cargo.toml Cargo.lock Makefile $(shell find -type f -wholename '**/src/*.rs') - -DEBUG ?= 0 -ifeq ($(DEBUG),0) - ARGS += --release - TARGET = release -endif - -VENDORED ?= 0 -ifeq ($(VENDORED),1) - ARGS += --frozen -endif - -all: build - -clean: - cargo clean - -distclean: - rm -rf .cargo vendor vendor.tar.xz - -install: - $(INSTALL_PROGRAM) "./target/release/$(BIN_SD)" "$(DESTDIR)$(bindir)/$(BIN_SD)" - $(INSTALL_PROGRAM) "./target/release/$(BIN_SC)" "$(DESTDIR)$(bindir)/$(BIN_SC)" - $(INSTALL_DATA) "./data/$(BIN_SD).service" "$(DESTDIR)$(libdir)/systemd/system/$(BIN_SD).service" - $(INSTALL_DATA) "./data/org.supergfxctl.Daemon.conf" "$(DESTDIR)$(datarootdir)/dbus-1/system.d/org.supergfxctl.Daemon.conf" - $(INSTALL_DATA) "./data/$(X11CFG)" "$(DESTDIR)$(datarootdir)/X11/xorg.conf.d/$(X11CFG)" - $(INSTALL_DATA) "./data/$(PMRULES)" "$(DESTDIR)$(libdir)/udev/rules.d/$(PMRULES)" - -uninstall: - rm -f "$(DESTDIR)$(bindir)/$(BIN_SC)" - rm -f "$(DESTDIR)$(bindir)/$(BIN_SD)" - rm -f "$(DESTDIR)$(libdir)/systemd/system/$(BIN_SD).service" - rm -f "$(DESTDIR)$(datarootdir)/dbus-1/system.d/org.supergfxctl.Daemon.conf" - rm -f "$(DESTDIR)$(datarootdir)/X11/xorg.conf.d/$(X11CFG)" - rm -f "$(DESTDIR)$(libdir)/udev/rules.d/$(PMRULES)" - -update: - cargo update - -vendor: - mkdir -p .cargo - cargo vendor | head -n -1 > .cargo/config - echo 'directory = "vendor"' >> .cargo/config - mv .cargo/config ./cargo-config - rm -rf .cargo - tar pcfJ vendor_asusctl_$(VERSION).tar.xz vendor - rm -rf vendor - -build: -ifeq ($(VENDORED),1) - @echo "version = $(VERSION)" - tar pxf vendor_asusctl_$(VERSION).tar.xz -endif - cargo build $(ARGS) - -.PHONY: all clean distclean install uninstall update build diff --git a/supergfx/data/90-asusd-nvidia-pm.rules b/supergfx/data/90-asusd-nvidia-pm.rules deleted file mode 100644 index ba3cefef..00000000 --- a/supergfx/data/90-asusd-nvidia-pm.rules +++ /dev/null @@ -1,7 +0,0 @@ -# Enable runtime PM for NVIDIA VGA/3D controller devices on driver bind -ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="auto" -ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="auto" - -# Disable runtime PM for NVIDIA VGA/3D controller devices on driver unbind -ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="on" -ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="on" diff --git a/supergfx/data/90-nvidia-screen-G05.conf b/supergfx/data/90-nvidia-screen-G05.conf deleted file mode 100644 index 7e561fc5..00000000 --- a/supergfx/data/90-nvidia-screen-G05.conf +++ /dev/null @@ -1,4 +0,0 @@ -Section "ServerLayout" - Identifier "layout" - Option "AllowNVIDIAGPUScreens" -EndSection diff --git a/supergfx/data/org.supergfxctl.Daemon.conf b/supergfx/data/org.supergfxctl.Daemon.conf deleted file mode 100644 index 77fa6276..00000000 --- a/supergfx/data/org.supergfxctl.Daemon.conf +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/supergfx/data/supergfxd.service b/supergfx/data/supergfxd.service deleted file mode 100644 index 16f8f591..00000000 --- a/supergfx/data/supergfxd.service +++ /dev/null @@ -1,19 +0,0 @@ -[Unit] -Description=SUPERGFX -StartLimitInterval=200 -StartLimitBurst=2 -Before=multi-user.target - -[Service] -Environment=IS_SUPERGFX_SERVICE=1 -ExecStart=/usr/bin/supergfxd -Restart=on-failure -Restart=always -RestartSec=1 -Type=dbus -BusName=org.supergfxctl.Daemon -SELinuxContext=system_u:system_r:unconfined_t:s0 -#SELinuxContext=system_u:object_r:modules_object_t:s0 - -[Install] -WantedBy=multi-user.target \ No newline at end of file diff --git a/supergfx/src/cli.rs b/supergfx/src/cli.rs deleted file mode 100644 index ae0369d0..00000000 --- a/supergfx/src/cli.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! Basic CLI tool to control the `supergfxd` daemon - -use std::{env::args, sync::mpsc::channel}; -use supergfxctl::{ - gfx_vendors::{GfxRequiredUserAction, GfxVendors}, - special::{get_asus_gsync_gfx_mode, has_asus_gsync_gfx_mode}, - zbus_proxy::GfxProxy, -}; - -use gumdrop::Options; -use zbus::Connection; - -#[derive(Default, Options)] -struct CliStart { - #[options(help = "print help message")] - help: bool, - #[options( - meta = "", - help = "Set graphics mode: " - )] - mode: Option, - #[options(help = "Get the current mode")] - get: bool, - #[options(help = "Get the current power status")] - pow: bool, - #[options(help = "Do not ask for confirmation")] - force: bool, -} - -fn main() -> Result<(), Box> { - let args: Vec = args().skip(1).collect(); - - match CliStart::parse_args_default(&args) { - Ok(command) => { - do_gfx(command)?; - } - Err(err) => { - eprintln!("source {}", err); - std::process::exit(2); - } - } - - Ok(()) -} - -fn do_gfx(command: CliStart) -> Result<(), Box> { - if command.mode.is_none() && !command.get && !command.pow && !command.force || command.help { - println!("{}", command.self_usage()); - } - - let conn = Connection::new_system()?; - let proxy = GfxProxy::new(&conn)?; - - let (tx, rx) = channel(); - proxy.connect_notify_action(tx)?; - - if let Some(mode) = command.mode { - if has_asus_gsync_gfx_mode() && get_asus_gsync_gfx_mode()? == 1 { - println!("You can not change modes until you turn dedicated/G-Sync off and reboot"); - std::process::exit(-1); - } - - println!("If anything fails check `journalctl -b -u supergfxd`\n"); - println!("Note that nvidia-drm.modeset=0 is required in kernel cmdline to enable the nvidia drivers to be unloaded on demand`\n"); - - proxy.gfx_write_mode(&mode).map_err(|err|{ - println!("Graphics mode change error. You may be in an invalid state."); - println!("Check mode with `-g` and switch to opposite\nmode to correct it, e.g: if integrated, switch to hybrid, or if nvidia, switch to integrated.\n"); - err - })?; - - loop { - proxy.next_signal()?; - - if let Ok(res) = rx.try_recv() { - match res { - GfxRequiredUserAction::Integrated => { - println!( - "You must change to Integrated before you can change to {}", - <&str>::from(mode) - ); - } - GfxRequiredUserAction::Logout | GfxRequiredUserAction::Reboot => { - println!( - "Graphics mode changed to {}. User action required is: {}", - <&str>::from(mode), - <&str>::from(&res) - ); - } - GfxRequiredUserAction::None => { - println!("Graphics mode changed to {}", <&str>::from(mode)); - } - } - } - std::process::exit(0) - } - } - if command.get { - let res = proxy.gfx_get_mode()?; - println!("Current graphics mode: {}", <&str>::from(res)); - } - if command.pow { - let res = proxy.gfx_get_pwr()?; - println!("Current power status: {}", <&str>::from(&res)); - } - - Ok(()) -} diff --git a/supergfx/src/config.rs b/supergfx/src/config.rs deleted file mode 100644 index 1967d2db..00000000 --- a/supergfx/src/config.rs +++ /dev/null @@ -1,86 +0,0 @@ -use log::{error, warn}; -use serde_derive::{Deserialize, Serialize}; -use std::fs::{File, OpenOptions}; -use std::io::{Read, Write}; - -use crate::gfx_vendors::GfxVendors; - -#[derive(Deserialize, Serialize)] -pub struct GfxConfig { - #[serde(skip)] - config_path: String, - /// The current mode set, also applies on boot - pub gfx_mode: GfxVendors, - /// Only for informational purposes - #[serde(skip)] - pub gfx_tmp_mode: Option, - /// Set if graphics management is enabled - pub gfx_managed: bool, - /// Set if vfio option is enabled. This requires the vfio drivers to be built as modules - pub gfx_vfio_enable: bool, -} - -impl GfxConfig { - fn new(config_path: String) -> Self { - Self { - config_path, - gfx_mode: GfxVendors::Hybrid, - gfx_tmp_mode: None, - gfx_managed: true, - gfx_vfio_enable: false, - } - } - - /// `load` will attempt to read the config, and panic if the dir is missing - pub fn load(config_path: String) -> Self { - let mut file = OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(&config_path) - .unwrap_or_else(|_| panic!("The directory {} is missing", config_path)); // okay to cause panic here - let mut buf = String::new(); - let mut config; - if let Ok(read_len) = file.read_to_string(&mut buf) { - if read_len == 0 { - config = Self::new(config_path); - } else if let Ok(data) = serde_json::from_str(&buf) { - config = data; - config.config_path = config_path; - } else { - warn!("Could not deserialise {}", config_path); - panic!("Please remove {} then restart service", config_path); - } - } else { - config = Self::new(config_path) - } - config.write(); - config - } - - pub fn read(&mut self) { - let mut file = OpenOptions::new() - .read(true) - .open(&self.config_path) - .unwrap_or_else(|err| panic!("Error reading {}: {}", self.config_path, err)); - let mut buf = String::new(); - if let Ok(l) = file.read_to_string(&mut buf) { - if l == 0 { - warn!("File is empty {}", self.config_path); - } else { - let mut x: Self = serde_json::from_str(&buf) - .unwrap_or_else(|_| panic!("Could not deserialise {}", self.config_path)); - // copy over serde skipped values - x.gfx_tmp_mode = self.gfx_tmp_mode; - *self = x; - } - } - } - - pub fn write(&self) { - let mut file = File::create(&self.config_path).expect("Couldn't overwrite config"); - let json = serde_json::to_string_pretty(self).expect("Parse config to JSON failed"); - file.write_all(json.as_bytes()) - .unwrap_or_else(|err| error!("Could not write config: {}", err)); - } -} diff --git a/supergfx/src/controller.rs b/supergfx/src/controller.rs deleted file mode 100644 index 67632b30..00000000 --- a/supergfx/src/controller.rs +++ /dev/null @@ -1,706 +0,0 @@ -use ::zbus::Connection; -use log::{error, info, warn}; -use logind_zbus::{ - types::{SessionClass, SessionInfo, SessionState, SessionType}, - ManagerProxy, SessionProxy, -}; -use std::{io::Write, ops::Add, path::Path, time::Instant}; -use std::{process::Command, thread::sleep, time::Duration}; -use std::{str::FromStr, sync::mpsc}; -use std::{sync::Arc, sync::Mutex}; -use sysfs_class::RuntimePM; -use sysfs_class::{PciDevice, SysClass}; - -use crate::{ - error::GfxError, - special::{get_asus_gsync_gfx_mode, has_asus_gsync_gfx_mode}, - system::{GraphicsDevice, PciBus}, - *, -}; - -use super::config::GfxConfig; -use super::gfx_vendors::{GfxPower, GfxRequiredUserAction, GfxVendors}; - -const THREAD_TIMEOUT_MSG: &str = "GFX: thread time exceeded 3 minutes, exiting"; -const NVIDIA_RUNTIME_STATUS_PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status"; - -pub struct CtrlGraphics { - bus: PciBus, - _amd: Vec, - _intel: Vec, - nvidia: Vec, - #[allow(dead_code)] - other: Vec, - config: Arc>, - thread_kill: Arc>>>, -} - -impl CtrlGraphics { - pub fn new(config: Arc>) -> std::io::Result { - let bus = PciBus::new()?; - info!("GFX: Rescanning PCI bus"); - bus.rescan()?; - let devs = PciDevice::all()?; - - let functions = |parent: &PciDevice| -> Vec { - let mut functions = Vec::new(); - if let Some(parent_slot) = parent.id().split('.').next() { - for func in devs.iter() { - if let Some(func_slot) = func.id().split('.').next() { - if func_slot == parent_slot { - info!("GFX: {}: Function for {}", func.id(), parent.id()); - functions.push(func.clone()); - } - } - } - } - functions - }; - - let mut amd = Vec::new(); - let mut intel = Vec::new(); - let mut nvidia = Vec::new(); - let mut other = Vec::new(); - for dev in devs.iter() { - let c = dev.class().map_err(|err| { - error!( - "GFX: device error: {}, {}", - dev.path().to_string_lossy(), - err - ); - err - })?; - if 0x03 == (c >> 16) & 0xFF { - match dev.vendor()? { - 0x1002 => { - info!("GFX: {}: AMD graphics", dev.id()); - amd.push(GraphicsDevice::new(dev.id().to_owned(), functions(dev))); - } - 0x10DE => { - info!("GFX: {}: NVIDIA graphics", dev.id()); - dev.set_runtime_pm(sysfs_class::RuntimePowerManagement::On)?; - nvidia.push(GraphicsDevice::new(dev.id().to_owned(), functions(dev))); - } - 0x8086 => { - info!("GFX: {}: Intel graphics", dev.id()); - intel.push(GraphicsDevice::new(dev.id().to_owned(), functions(dev))); - } - vendor => { - info!("GFX: {}: Other({:X}) graphics", dev.id(), vendor); - other.push(GraphicsDevice::new(dev.id().to_owned(), functions(dev))); - } - } - } - } - - Ok(CtrlGraphics { - bus, - _amd: amd, - _intel: intel, - nvidia, - other, - config, - thread_kill: Arc::new(Mutex::new(None)), - }) - } - - /// Force reinit of all state, including reset of device state - pub fn reload(&mut self) -> Result<(), GfxError> { - self.auto_power()?; - info!("GFX: Reloaded gfx mode: {:?}", self.get_gfx_mode()?); - Ok(()) - } - - pub fn bus(&self) -> PciBus { - self.bus.clone() - } - - pub fn devices(&self) -> Vec { - self.nvidia.clone() - } - - /// Save the selected `Vendor` mode to config - fn save_gfx_mode(vendor: GfxVendors, config: Arc>) { - if let Ok(mut config) = config.lock() { - config.gfx_mode = vendor; - config.write(); - } - } - - /// Associated method to get which vendor mode is set - pub(super) fn get_gfx_mode(&self) -> Result { - if let Ok(config) = self.config.lock() { - if let Some(mode) = config.gfx_tmp_mode { - return Ok(mode); - } - return Ok(config.gfx_mode); - } - // TODO: Error here - Ok(GfxVendors::Hybrid) - } - - pub(super) fn get_runtime_status() -> Result { - let path = Path::new(NVIDIA_RUNTIME_STATUS_PATH); - if path.exists() { - let buf = std::fs::read_to_string(path) - .map_err(|err| GfxError::Read(path.to_string_lossy().to_string(), err))?; - Ok(GfxPower::from_str(&buf)?) - } else { - Ok(GfxPower::Off) - } - } - - /// Some systems have a fallback service to load nouveau if nvidia fails - fn toggle_fallback_service(vendor: GfxVendors) -> Result<(), GfxError> { - let action = if vendor == GfxVendors::Nvidia { - info!("GFX: Enabling nvidia-fallback.service"); - "enable" - } else { - info!("GFX: Disabling nvidia-fallback.service"); - "disable" - }; - - let status = Command::new("systemctl") - .arg(action) - .arg("nvidia-fallback.service") - .status() - .map_err(|err| GfxError::Command("systemctl".into(), err))?; - - if !status.success() { - // Error is ignored in case this service is removed - warn!( - "systemctl: {} (ignore warning if service does not exist!)", - status - ); - } - - Ok(()) - } - - /// Write the appropriate xorg config for the chosen mode - fn write_xorg_conf(vendor: GfxVendors) -> Result<(), GfxError> { - let text = if vendor == GfxVendors::Nvidia { - [PRIMARY_GPU_BEGIN, PRIMARY_GPU_NVIDIA, PRIMARY_GPU_END].concat() - } else { - [PRIMARY_GPU_BEGIN, PRIMARY_GPU_END].concat() - }; - - if !Path::new(XORG_PATH).exists() { - std::fs::create_dir(XORG_PATH).map_err(|err| GfxError::Write(XORG_PATH.into(), err))?; - } - - let file = XORG_PATH.to_string().add(XORG_FILE); - info!("GFX: Writing {}", file); - let mut file = std::fs::OpenOptions::new() - .create(true) - .truncate(true) - .write(true) - .open(&file) - .map_err(|err| GfxError::Write(file, err))?; - - file.write_all(&text) - .and_then(|_| file.sync_all()) - .map_err(|err| GfxError::Write(MODPROBE_PATH.into(), err))?; - Ok(()) - } - - /// Creates the full modprobe.conf required for vfio pass-through - fn get_vfio_conf(devices: &[GraphicsDevice]) -> Vec { - let mut vifo = MODPROBE_VFIO.to_vec(); - for (d_count, dev) in devices.iter().enumerate() { - for (f_count, func) in dev.functions().iter().enumerate() { - let vendor = func.vendor().unwrap(); - let device = func.device().unwrap(); - unsafe { - vifo.append(format!("{:x}", vendor).as_mut_vec()); - } - vifo.append(&mut vec![b':']); - unsafe { - vifo.append(format!("{:x}", device).as_mut_vec()); - } - if f_count < dev.functions().len() - 1 { - vifo.append(&mut vec![b',']); - } - } - if d_count < dev.functions().len() - 1 { - vifo.append(&mut vec![b',']); - } - } - let mut conf = MODPROBE_INTEGRATED.to_vec(); - conf.append(&mut vifo); - conf - } - - fn write_modprobe_conf(vendor: GfxVendors, devices: &[GraphicsDevice]) -> Result<(), GfxError> { - info!("GFX: Writing {}", MODPROBE_PATH); - let content = match vendor { - GfxVendors::Nvidia | GfxVendors::Hybrid => { - let mut base = MODPROBE_BASE.to_vec(); - base.append(&mut MODPROBE_DRM_MODESET.to_vec()); - base - } - GfxVendors::Vfio => Self::get_vfio_conf(devices), - GfxVendors::Integrated => MODPROBE_INTEGRATED.to_vec(), - GfxVendors::Compute => MODPROBE_BASE.to_vec(), - }; - - let mut file = std::fs::OpenOptions::new() - .create(true) - .truncate(true) - .write(true) - .open(MODPROBE_PATH) - .map_err(|err| GfxError::Path(MODPROBE_PATH.into(), err))?; - - file.write_all(&content) - .and_then(|_| file.sync_all()) - .map_err(|err| GfxError::Write(MODPROBE_PATH.into(), err))?; - - Ok(()) - } - - fn unbind_remove_nvidia(devices: &[GraphicsDevice]) -> Result<(), GfxError> { - // Unbind NVIDIA graphics devices and their functions - let unbinds = devices.iter().map(|dev| dev.unbind()); - // Remove NVIDIA graphics devices and their functions - let removes = devices.iter().map(|dev| dev.remove()); - unbinds - .chain(removes) - .collect::>() - .map_err(|err| GfxError::Command("device unbind error".into(), err)) - } - - fn unbind_only(devices: &[GraphicsDevice]) -> Result<(), GfxError> { - let unbinds = devices.iter().map(|dev| dev.unbind()); - unbinds - .collect::>() - .map_err(|err| GfxError::Command("device unbind error".into(), err)) - } - - /// Add or remove driver modules - fn do_driver_action(driver: &str, action: &str) -> Result<(), GfxError> { - let mut cmd = Command::new(action); - cmd.arg(driver); - - let mut count = 0; - const MAX_TRIES: i32 = 6; - loop { - if count > MAX_TRIES { - let msg = format!("{} {} failed for unknown reason", action, driver); - error!("GFX: {}", msg); - return Ok(()); //Err(GfxError::Modprobe(msg)); - } - - let output = cmd - .output() - .map_err(|err| GfxError::Command(format!("{:?}", cmd), err))?; - if !output.status.success() { - if output - .stderr - .ends_with("is not currently loaded\n".as_bytes()) - { - return Ok(()); - } - if output.stderr.ends_with("is builtin.\n".as_bytes()) { - return Err(GfxError::VfioBuiltin); - } - if output.stderr.ends_with("Permission denied\n".as_bytes()) { - warn!( - "{} {} failed: {:?}", - action, - driver, - String::from_utf8_lossy(&output.stderr) - ); - warn!("GFX: It may be safe to ignore the above error, run `lsmod |grep {}` to confirm modules loaded", driver); - return Ok(()); - } - if String::from_utf8_lossy(&output.stderr) - .contains(&format!("Module {} not found", driver)) - { - return Err(GfxError::MissingModule(driver.into())); - } - if count >= MAX_TRIES { - let msg = format!( - "{} {} failed: {:?}", - action, - driver, - String::from_utf8_lossy(&output.stderr) - ); - return Err(GfxError::Modprobe(msg)); - } - } else if output.status.success() { - return Ok(()); - } - - count += 1; - std::thread::sleep(std::time::Duration::from_millis(50)); - } - } - - fn do_display_manager_action(action: &str) -> Result<(), GfxError> { - let mut cmd = Command::new("systemctl"); - cmd.arg(action); - cmd.arg(DISPLAY_MANAGER); - - let status = cmd - .status() - .map_err(|err| GfxError::Command(format!("{:?}", cmd), err))?; - if !status.success() { - let msg = format!( - "systemctl {} {} failed: {:?}", - action, DISPLAY_MANAGER, status - ); - return Err(GfxError::DisplayManagerAction(msg, status)); - } - Ok(()) - } - - fn wait_display_manager_state(state: &str) -> Result<(), GfxError> { - let mut cmd = Command::new("systemctl"); - cmd.arg("is-active"); - cmd.arg(DISPLAY_MANAGER); - - let mut count = 0; - - while count <= (4 * 3) { - // 3 seconds max - let output = cmd - .output() - .map_err(|err| GfxError::Command(format!("{:?}", cmd), err))?; - if output.stdout.starts_with(state.as_bytes()) { - return Ok(()); - } - std::thread::sleep(std::time::Duration::from_millis(250)); - count += 1; - } - Err(GfxError::DisplayManagerTimeout(state.into())) - } - - /// Determine if we need to logout/thread. Integrated<->Vfio mode does not - /// require logout. - fn is_logout_required(&self, vendor: GfxVendors) -> GfxRequiredUserAction { - if let Ok(config) = self.config.lock() { - let current = config.gfx_mode; - // Modes that can switch without logout - if matches!( - current, - GfxVendors::Integrated | GfxVendors::Vfio | GfxVendors::Compute - ) && matches!( - vendor, - GfxVendors::Integrated | GfxVendors::Vfio | GfxVendors::Compute - ) { - return GfxRequiredUserAction::None; - } - // Modes that require a switch to integrated first - if matches!(current, GfxVendors::Nvidia | GfxVendors::Hybrid) - && matches!(vendor, GfxVendors::Compute | GfxVendors::Vfio) - { - return GfxRequiredUserAction::Integrated; - } - } - GfxRequiredUserAction::Logout - } - - /// Do a full setup flow for the chosen mode: - /// - /// Tasks: - /// - rescan for devices - /// - write xorg config - /// - write modprobe config - /// + add drivers - /// + or remove drivers and devices - /// - /// The daemon needs direct access to this function when it detects that the - /// bios has G-Sync switch is enabled - pub fn do_mode_setup_tasks( - vendor: GfxVendors, - vfio_enable: bool, - devices: &[GraphicsDevice], - bus: &PciBus, - ) -> Result<(), GfxError> { - // Rescan before doing remove or add drivers - bus.rescan()?; - // Make sure the power management is set to auto for nvidia devices - let devs = PciDevice::all()?; - for dev in devs.iter() { - let c = dev.class().map_err(|err| { - error!( - "GFX: device error: {}, {}", - dev.path().to_string_lossy(), - err - ); - err - })?; - if 0x03 == (c >> 16) & 0xFF && dev.vendor()? == 0x10DE { - info!("GFX: {}: NVIDIA graphics, setting PM to auto", dev.id()); - dev.set_runtime_pm(sysfs_class::RuntimePowerManagement::On)?; - } - } - // Only these modes should have xorg config - if matches!( - vendor, - GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Integrated - ) { - Self::write_xorg_conf(vendor)?; - } - - // Write different modprobe to enable boot control to work - Self::write_modprobe_conf(vendor, devices)?; - - match vendor { - GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => { - if vfio_enable { - for driver in VFIO_DRIVERS.iter() { - Self::do_driver_action(driver, "rmmod")?; - } - } - for driver in NVIDIA_DRIVERS.iter() { - Self::do_driver_action(driver, "modprobe")?; - } - } - GfxVendors::Vfio => { - if vfio_enable { - Self::do_driver_action("nouveau", "rmmod")?; - for driver in NVIDIA_DRIVERS.iter() { - Self::do_driver_action(driver, "rmmod")?; - } - Self::unbind_only(devices)?; - Self::do_driver_action("vfio-pci", "modprobe")?; - } else { - return Err(GfxError::VfioDisabled); - } - } - GfxVendors::Integrated => { - Self::do_driver_action("nouveau", "rmmod")?; - if vfio_enable { - for driver in VFIO_DRIVERS.iter() { - Self::do_driver_action(driver, "rmmod")?; - } - } - for driver in NVIDIA_DRIVERS.iter() { - Self::do_driver_action(driver, "rmmod")?; - } - Self::unbind_remove_nvidia(devices)?; - } - } - Ok(()) - } - - /// Check if the user has any graphical uiser sessions that are active or online - fn graphical_user_sessions_exist( - connection: &Connection, - sessions: &[SessionInfo], - ) -> Result { - for session in sessions { - let session_proxy = SessionProxy::new(connection, session)?; - if session_proxy.get_class()? == SessionClass::User { - match session_proxy.get_type()? { - SessionType::X11 | SessionType::Wayland | SessionType::MIR => { - match session_proxy.get_state()? { - SessionState::Online | SessionState::Active => return Ok(true), - SessionState::Closing | SessionState::Invalid => {} - } - } - _ => {} - } - } - } - Ok(false) - } - - /// Spools until all user sessions are ended then switches to requested mode - fn create_mode_change_thread( - vendor: GfxVendors, - devices: Vec, - bus: PciBus, - thread_stop: mpsc::Receiver, - config: Arc>, - ) -> Result { - info!("GFX: display-manager thread started"); - - const SLEEP_PERIOD: Duration = Duration::from_millis(100); - let start_time = Instant::now(); - - let connection = Connection::new_system()?; - let manager = ManagerProxy::new(&connection)?; - let mut sessions = manager.list_sessions()?; - - loop { - let tmp = manager.list_sessions()?; - if !tmp.iter().eq(&sessions) { - info!("GFX thread: Sessions list changed"); - sessions = tmp; - } - - if !Self::graphical_user_sessions_exist(&connection, &sessions)? { - break; - } - - if let Ok(stop) = thread_stop.try_recv() { - if stop { - return Ok("Graphics mode change was cancelled".into()); - } - } - // exit if 3 minutes pass - if Instant::now().duration_since(start_time).as_secs() > 180 { - warn!("{}", THREAD_TIMEOUT_MSG); - return Err(GfxError::DisplayManagerTimeout(THREAD_TIMEOUT_MSG.into())); - } - - // Don't spin at max speed - sleep(SLEEP_PERIOD); - } - - info!("GFX thread: all graphical user sessions ended, continuing"); - Self::do_display_manager_action("stop")?; - Self::wait_display_manager_state("inactive")?; - - let mut mode_to_save = vendor; - // Need to change to integrated before we can change to vfio or compute - if let Ok(mut config) = config.try_lock() { - // Since we have a lock, reset tmp to none. This thread should only ever run - // for Integrated, Hybrid, or Nvidia. Tmp is also only for informational - config.gfx_tmp_mode = None; - // - let vfio_enable = config.gfx_vfio_enable; - - // Failsafe. In the event this loop is run with a switch from nvidia in use - // to vfio or compute do a forced switch to integrated instead to prevent issues - if matches!(vendor, GfxVendors::Compute | GfxVendors::Vfio) - && matches!(config.gfx_mode, GfxVendors::Nvidia | GfxVendors::Hybrid) - { - Self::do_mode_setup_tasks(GfxVendors::Integrated, vfio_enable, &devices, &bus)?; - Self::do_display_manager_action("restart")?; - mode_to_save = GfxVendors::Integrated; - } else { - Self::do_mode_setup_tasks(vendor, vfio_enable, &devices, &bus)?; - Self::do_display_manager_action("restart")?; - } - } - - // Save selected mode in case of reboot - Self::save_gfx_mode(mode_to_save, config); - info!("GFX thread: display-manager started"); - - let v: &str = vendor.into(); - info!("GFX thread: Graphics mode changed to {} successfully", v); - Ok(format!("Graphics mode changed to {} successfully", v)) - } - - /// Before starting a new thread the old one *must* be cancelled - fn cancel_mode_change_thread(&self) { - if let Ok(lock) = self.thread_kill.lock() { - if let Some(tx) = lock.as_ref() { - // Cancel the running thread - info!("GFX: Cancelling previous thread"); - tx.send(true) - .map_err(|err| { - warn!("GFX thread: {}", err); - }) - .ok(); - } - } - } - - /// The thread is used only in cases where a logout is required - fn setup_mode_change_thread(&mut self, vendor: GfxVendors) { - let config = self.config.clone(); - let devices = self.nvidia.clone(); - let bus = self.bus.clone(); - let (tx, rx) = mpsc::channel(); - if let Ok(mut lock) = self.thread_kill.lock() { - *lock = Some(tx); - } - let thread_kill = self.thread_kill.clone(); - - std::thread::spawn(move || { - Self::create_mode_change_thread(vendor, devices, bus, rx, config) - .map_err(|err| { - error!("GFX: {}", err); - }) - .ok(); - // clear the tx/rx when done - if let Ok(mut lock) = thread_kill.try_lock() { - *lock = None; - } - }); - } - - /// Initiates a mode change by starting a thread that will wait until all - /// graphical sessions are exited before performing the tasks required - /// to switch modes. - /// - /// For manually calling (not on boot/startup) via dbus - pub fn set_gfx_mode(&mut self, vendor: GfxVendors) -> Result { - if has_asus_gsync_gfx_mode() { - if let Ok(gsync) = get_asus_gsync_gfx_mode() { - if gsync == 1 { - return Err(GfxError::AsusGsyncModeActive); - } - } - } - - let vfio_enable = if let Ok(config) = self.config.try_lock() { - config.gfx_vfio_enable - } else { - false - }; - - if !vfio_enable && matches!(vendor, GfxVendors::Vfio) { - return Err(GfxError::VfioDisabled); - } - - // Must always cancel any thread running - self.cancel_mode_change_thread(); - // determine which method we need here - let action_required = self.is_logout_required(vendor); - - match action_required { - GfxRequiredUserAction::Logout => { - info!("GFX: mode change requires a logout to complete"); - self.setup_mode_change_thread(vendor); - } - GfxRequiredUserAction::Reboot => { - info!("GFX: mode change requires reboot"); - let devices = self.nvidia.clone(); - let bus = self.bus.clone(); - Self::do_mode_setup_tasks(vendor, vfio_enable, &devices, &bus)?; - info!("GFX: Graphics mode changed to {}", <&str>::from(vendor)); - } - GfxRequiredUserAction::Integrated => { - info!("GFX: mode change requires user to be in Integrated mode first"); - } - GfxRequiredUserAction::None => { - info!("GFX: mode change does not require logout"); - let devices = self.nvidia.clone(); - let bus = self.bus.clone(); - Self::do_mode_setup_tasks(vendor, vfio_enable, &devices, &bus)?; - info!("GFX: Graphics mode changed to {}", <&str>::from(vendor)); - if let Ok(mut config) = self.config.try_lock() { - config.gfx_tmp_mode = None; - if matches!(vendor, GfxVendors::Vfio | GfxVendors::Compute) { - config.gfx_tmp_mode = Some(vendor); - } - } - } - } - - Ok(action_required) - } - - /// Used only on boot to set correct mode - fn auto_power(&mut self) -> Result<(), GfxError> { - let vendor = self.get_gfx_mode()?; - let devices = self.nvidia.clone(); - let bus = self.bus.clone(); - - let vfio_enable = if let Ok(config) = self.config.try_lock() { - config.gfx_vfio_enable - } else { - false - }; - - Self::do_mode_setup_tasks(vendor, vfio_enable, &devices, &bus)?; - Self::toggle_fallback_service(vendor)?; - Ok(()) - } -} diff --git a/supergfx/src/daemon.rs b/supergfx/src/daemon.rs deleted file mode 100644 index 5d684497..00000000 --- a/supergfx/src/daemon.rs +++ /dev/null @@ -1,105 +0,0 @@ -use std::{ - env, - error::Error, - sync::{Arc, Mutex}, -}; - -use log::{error, info, warn, LevelFilter}; -use std::io::Write; -use supergfxctl::{ - config::GfxConfig, - controller::CtrlGraphics, - error::GfxError, - gfx_vendors::GfxVendors, - special::{get_asus_gsync_gfx_mode, has_asus_gsync_gfx_mode}, - CONFIG_PATH, DBUS_DEST_NAME, -}; -use zbus::{fdo, Connection, ObjectServer}; - -pub fn main() -> Result<(), Box> { - let mut logger = env_logger::Builder::new(); - logger - .target(env_logger::Target::Stdout) - .format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args())) - .filter(None, LevelFilter::Info) - .init(); - - let is_service = match env::var_os("IS_SUPERGFX_SERVICE") { - Some(val) => val == "1", - None => false, - }; - - if !is_service { - println!("supergfxd schould be only run from the right systemd service"); - println!( - "do not run in your terminal, if you need an logs please use journalctl -b -u supergfxd" - ); - println!("supergfxd will now exit"); - return Ok(()); - } - - start_daemon() -} - -fn start_daemon() -> Result<(), Box> { - // Start zbus server - let connection = Connection::new_system()?; - fdo::DBusProxy::new(&connection)?.request_name( - DBUS_DEST_NAME, - fdo::RequestNameFlags::ReplaceExisting.into(), - )?; - - let mut object_server = ObjectServer::new(&connection); - - let config = GfxConfig::load(CONFIG_PATH.into()); - let enable_gfx_switching = config.gfx_managed; - let config = Arc::new(Mutex::new(config)); - - // Graphics switching requires some checks on boot specifically for g-sync capable laptops - if enable_gfx_switching { - match CtrlGraphics::new(config.clone()) { - Ok(mut ctrl) => { - // Need to check if a laptop has the dedicated gfx switch - if has_asus_gsync_gfx_mode() { - do_asus_laptop_checks(&ctrl, config)?; - } - - ctrl.reload() - .unwrap_or_else(|err| error!("Gfx controller: {}", err)); - ctrl.add_to_server(&mut object_server); - } - Err(err) => { - error!("Gfx control: {}", err); - } - } - } - - // Loop to check errors and iterate zbus server - loop { - if let Err(err) = object_server.try_handle_next() { - error!("{}", err); - } - } -} - -fn do_asus_laptop_checks( - ctrl: &CtrlGraphics, - config: Arc>, -) -> Result<(), GfxError> { - if let Ok(ded) = get_asus_gsync_gfx_mode() { - if let Ok(config) = config.lock() { - if ded == 1 { - warn!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode"); - let devices = ctrl.devices(); - let bus = ctrl.bus(); - CtrlGraphics::do_mode_setup_tasks(GfxVendors::Nvidia, false, &devices, &bus)?; - } else if ded == 0 { - info!("Dedicated GFX toggle is off"); - let devices = ctrl.devices(); - let bus = ctrl.bus(); - CtrlGraphics::do_mode_setup_tasks(config.gfx_mode, false, &devices, &bus)?; - } - } - } - Ok(()) -} diff --git a/supergfx/src/error.rs b/supergfx/src/error.rs deleted file mode 100644 index bc261774..00000000 --- a/supergfx/src/error.rs +++ /dev/null @@ -1,68 +0,0 @@ -use std::fmt; -use std::{error, process::ExitStatus}; - -#[derive(Debug)] -pub enum GfxError { - ParseVendor, - DisplayManagerAction(String, ExitStatus), - DisplayManagerTimeout(String), - AsusGsyncModeActive, - VfioBuiltin, - VfioDisabled, - MissingModule(String), - Modprobe(String), - Command(String, std::io::Error), - Path(String, std::io::Error), - Read(String, std::io::Error), - Write(String, std::io::Error), - Io(std::io::Error), - Zbus(zbus::Error), -} - -impl fmt::Display for GfxError { - // This trait requires `fmt` with this exact signature. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - GfxError::ParseVendor => write!(f, "Could not parse vendor name"), - GfxError::DisplayManagerAction(action, status) => { - write!(f, "Display-manager action {} failed: {}", action, status) - } - GfxError::DisplayManagerTimeout(state) => { - write!(f, "Timed out waiting for display-manager {} state", state) - } - GfxError::AsusGsyncModeActive => write!( - f, - "Can not switch gfx modes when dedicated/G-Sync mode is active" - ), - GfxError::VfioBuiltin => write!( - f, - "Can not switch to vfio mode if the modules are built in to kernel" - ), - GfxError::VfioDisabled => { - write!(f, "Can not switch to vfio mode if disabled in config file") - } - GfxError::MissingModule(m) => write!(f, "The module {} is missing", m), - GfxError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail), - GfxError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error), - GfxError::Path(path, error) => write!(f, "Path {}: {}", path, error), - GfxError::Read(path, error) => write!(f, "Read {}: {}", path, error), - GfxError::Write(path, error) => write!(f, "Write {}: {}", path, error), - GfxError::Io(detail) => write!(f, "std::io error: {}", detail), - GfxError::Zbus(detail) => write!(f, "Zbus error: {}", detail), - } - } -} - -impl error::Error for GfxError {} - -impl From for GfxError { - fn from(err: zbus::Error) -> Self { - GfxError::Zbus(err) - } -} - -impl From for GfxError { - fn from(err: std::io::Error) -> Self { - GfxError::Io(err) - } -} diff --git a/supergfx/src/gfx_vendors.rs b/supergfx/src/gfx_vendors.rs deleted file mode 100644 index f16200a8..00000000 --- a/supergfx/src/gfx_vendors.rs +++ /dev/null @@ -1,103 +0,0 @@ -use serde_derive::{Deserialize, Serialize}; -use std::str::FromStr; -use zvariant_derive::Type; - -use crate::error::GfxError; - -#[derive(Debug, Type, PartialEq, Copy, Clone, Deserialize, Serialize)] -pub enum GfxPower { - Active, - Suspended, - Off, - Unknown, -} - -impl FromStr for GfxPower { - type Err = GfxError; - - fn from_str(s: &str) -> Result { - match s.to_lowercase().trim() { - "active" => Ok(GfxPower::Active), - "suspended" => Ok(GfxPower::Suspended), - "off" => Ok(GfxPower::Off), - _ => Ok(GfxPower::Unknown), - } - } -} - -impl From<&GfxPower> for &str { - fn from(gfx: &GfxPower) -> &'static str { - match gfx { - GfxPower::Active => "active", - GfxPower::Suspended => "suspended", - GfxPower::Off => "off", - GfxPower::Unknown => "unknown", - } - } -} - -#[derive(Debug, Type, PartialEq, Copy, Clone, Deserialize, Serialize)] -pub enum GfxVendors { - Nvidia, - Integrated, - Compute, - Vfio, - Hybrid, -} - -impl FromStr for GfxVendors { - type Err = GfxError; - - fn from_str(s: &str) -> Result { - match s.to_lowercase().as_str() { - "nvidia" => Ok(GfxVendors::Nvidia), - "hybrid" => Ok(GfxVendors::Hybrid), - "compute" => Ok(GfxVendors::Compute), - "vfio" => Ok(GfxVendors::Vfio), - "integrated" => Ok(GfxVendors::Integrated), - "nvidia\n" => Ok(GfxVendors::Nvidia), - "hybrid\n" => Ok(GfxVendors::Hybrid), - "compute\n" => Ok(GfxVendors::Compute), - "vfio\n" => Ok(GfxVendors::Vfio), - "integrated\n" => Ok(GfxVendors::Integrated), - _ => Err(GfxError::ParseVendor), - } - } -} - -impl From<&GfxVendors> for &str { - fn from(gfx: &GfxVendors) -> &'static str { - match gfx { - GfxVendors::Nvidia => "nvidia", - GfxVendors::Hybrid => "hybrid", - GfxVendors::Compute => "compute", - GfxVendors::Vfio => "vfio", - GfxVendors::Integrated => "integrated", - } - } -} - -impl From for &str { - fn from(gfx: GfxVendors) -> &'static str { - (&gfx).into() - } -} - -#[derive(Debug, Type, PartialEq, Copy, Clone, Deserialize, Serialize)] -pub enum GfxRequiredUserAction { - Logout, - Reboot, - Integrated, - None, -} - -impl From<&GfxRequiredUserAction> for &str { - fn from(gfx: &GfxRequiredUserAction) -> &'static str { - match gfx { - GfxRequiredUserAction::Logout => "logout", - GfxRequiredUserAction::Reboot => "reboot", - GfxRequiredUserAction::Integrated => "switch to integrated first", - GfxRequiredUserAction::None => "no action", - } - } -} diff --git a/supergfx/src/lib.rs b/supergfx/src/lib.rs deleted file mode 100644 index 30194af4..00000000 --- a/supergfx/src/lib.rs +++ /dev/null @@ -1,77 +0,0 @@ -/// The configuration for graphics. This should be saved and loaded on boot. -pub mod config; -/// Control functions for setting graphics. -pub mod controller; -/// Error: 404 -pub mod error; -/// Mode names, follows what distros defined as common. -pub mod gfx_vendors; -/// Special-case functions for check/read/write of key functions on unique laptops -/// such as the G-Sync mode available on some ASUS ROG laptops -pub mod special; -/// System interface helpers. -pub mod system; -/// Defined DBUS Interface for supergfxctl -pub mod zbus_iface; -/// Defined DBUS Proxy for supergfxctl -pub mod zbus_proxy; - -/// Helper to expose the current crate version to external code -pub const VERSION: &str = env!("CARGO_PKG_VERSION"); -/// Generic path that is used to save the daemon config state -pub const CONFIG_PATH: &str = "/etc/supergfxd.conf"; -/// Destination name to be used in the daemon when setting up DBUS connection -pub const DBUS_DEST_NAME: &str = "org.supergfxctl.Daemon"; -/// Interface path name. Should be common across daemon and client. -pub const DBUS_IFACE_PATH: &str = "/org/supergfxctl/Gfx"; - -const NVIDIA_DRIVERS: [&str; 4] = ["nvidia_drm", "nvidia_modeset", "nvidia_uvm", "nvidia"]; - -const VFIO_DRIVERS: [&str; 5] = [ - "vfio-pci", - "vfio_iommu_type1", - "vfio_virqfd", - "vfio_mdev", - "vfio", -]; - -const DISPLAY_MANAGER: &str = "display-manager.service"; - -const MODPROBE_PATH: &str = "/etc/modprobe.d/supergfxd.conf"; - -static MODPROBE_BASE: &[u8] = br#"# Automatically generated by supergfxd -blacklist nouveau -alias nouveau off -options nvidia NVreg_DynamicPowerManagement=0x02 -"#; - -static MODPROBE_DRM_MODESET: &[u8] = br#" -options nvidia-drm modeset=1 -"#; - -static MODPROBE_INTEGRATED: &[u8] = br#"# Automatically generated by supergfxd -blacklist i2c_nvidia_gpu -blacklist nvidia -blacklist nvidia-drm -blacklist nvidia-modeset -blacklist nouveau -alias nouveau off -"#; - -static MODPROBE_VFIO: &[u8] = br#"options vfio-pci ids="#; - -const XORG_FILE: &str = "90-nvidia-primary.conf"; -const XORG_PATH: &str = "/etc/X11/xorg.conf.d/"; - -static PRIMARY_GPU_BEGIN: &[u8] = br#"# Automatically generated by supergfxd -Section "OutputClass" - Identifier "nvidia" - MatchDriver "nvidia-drm" - Driver "nvidia" - Option "AllowEmptyInitialConfiguration" "true""#; - -static PRIMARY_GPU_NVIDIA: &[u8] = br#" - Option "PrimaryGPU" "true""#; - -static PRIMARY_GPU_END: &[u8] = br#" -EndSection"#; diff --git a/supergfx/src/special.rs b/supergfx/src/special.rs deleted file mode 100644 index ee1ef4d5..00000000 --- a/supergfx/src/special.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::{fs::OpenOptions, io::Read, path::Path}; - -use crate::error::GfxError; - -static ASUS_SWITCH_GRAPHIC_MODE: &str = - "/sys/firmware/efi/efivars/AsusSwitchGraphicMode-607005d5-3f75-4b2e-98f0-85ba66797a3e"; - -pub fn has_asus_gsync_gfx_mode() -> bool { - Path::new(ASUS_SWITCH_GRAPHIC_MODE).exists() -} - -pub fn get_asus_gsync_gfx_mode() -> Result { - let path = ASUS_SWITCH_GRAPHIC_MODE; - let mut file = OpenOptions::new() - .read(true) - .open(path) - .map_err(|err| GfxError::Path(path.into(), err))?; - - let mut data = Vec::new(); - file.read_to_end(&mut data) - .map_err(|err| GfxError::Read(path.into(), err))?; - - let idx = data.len() - 1; - Ok(data[idx] as i8) -} diff --git a/supergfx/src/system.rs b/supergfx/src/system.rs deleted file mode 100644 index ce1ddf67..00000000 --- a/supergfx/src/system.rs +++ /dev/null @@ -1,160 +0,0 @@ -use log::{error, info, warn}; -use std::fs::read_to_string; -use std::{fs::write, io, path::PathBuf}; -use sysfs_class::{PciDevice, SysClass}; - -pub struct Module { - pub name: String, -} - -impl Module { - fn parse(line: &str) -> io::Result { - let mut parts = line.split(' '); - - let name = parts - .next() - .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "module name not found"))?; - - Ok(Module { - name: name.to_string(), - }) - } - - pub fn all() -> io::Result> { - let mut modules = Vec::new(); - - let data = read_to_string("/proc/modules")?; - for line in data.lines() { - let module = Module::parse(line)?; - modules.push(module); - } - - Ok(modules) - } -} - -#[derive(Clone)] -pub struct PciBus { - path: PathBuf, -} - -impl PciBus { - pub fn new() -> io::Result { - let path = PathBuf::from("/sys/bus/pci"); - if path.is_dir() { - Ok(PciBus { path }) - } else { - Err(io::Error::new( - io::ErrorKind::NotFound, - "pci directory not found", - )) - } - } - - /// Will rescan the device tree, which adds all removed devices back - pub fn rescan(&self) -> io::Result<()> { - write(self.path.join("rescan"), "1") - } -} - -#[derive(Clone)] -pub struct GraphicsDevice { - _id: String, - functions: Vec, -} - -impl GraphicsDevice { - pub fn new(id: String, functions: Vec) -> GraphicsDevice { - GraphicsDevice { _id: id, functions } - } - - pub fn exists(&self) -> bool { - self.functions.iter().any(|func| func.path().exists()) - } - - pub fn functions(&self) -> &[PciDevice] { - &self.functions - } - - pub fn unbind(&self) -> Result<(), std::io::Error> { - for func in self.functions.iter() { - if func.path().exists() { - match func.driver() { - Ok(driver) => { - info!("{}: Unbinding {}", driver.id(), func.id()); - unsafe { - driver.unbind(func).map_err(|err| { - error!("gfx unbind: {}", err); - err - })?; - } - } - Err(err) => match err.kind() { - io::ErrorKind::NotFound => (), - _ => { - error!("gfx driver: {:?}, {}", func.path(), err); - return Err(err); - } - }, - } - } - } - Ok(()) - } - - pub fn rebind(&self) -> Result<(), std::io::Error> { - for func in self.functions.iter() { - if func.path().exists() { - match func.driver() { - Ok(driver) => { - info!("{}: Binding {}", driver.id(), func.id()); - unsafe { - driver.bind(func).map_err(|err| { - error!("gfx bind: {}", err); - err - })?; - } - } - Err(err) => match err.kind() { - io::ErrorKind::NotFound => (), - _ => { - error!("gfx driver: {:?}, {}", func.path(), err); - return Err(err); - } - }, - } - } - } - Ok(()) - } - - pub fn remove(&self) -> Result<(), std::io::Error> { - for func in self.functions.iter() { - if func.path().exists() { - match func.driver() { - Ok(driver) => { - error!("{}: in use by {}", func.id(), driver.id()); - } - Err(why) => match why.kind() { - std::io::ErrorKind::NotFound => { - info!("{}: Removing", func.id()); - unsafe { - // ignore errors and carry on - if let Err(err) = func.remove() { - error!("gfx remove: {}", err); - } - } - } - _ => { - error!("Remove device failed"); - } - }, - } - } else { - warn!("{}: Already removed", func.id()); - } - } - info!("Removed all gfx devices"); - Ok(()) - } -} diff --git a/supergfx/src/zbus_iface.rs b/supergfx/src/zbus_iface.rs deleted file mode 100644 index c6fd371c..00000000 --- a/supergfx/src/zbus_iface.rs +++ /dev/null @@ -1,61 +0,0 @@ -use ::zbus::dbus_interface; -use log::{error, info, warn}; -use zvariant::ObjectPath; - -use crate::{ - gfx_vendors::{GfxPower, GfxRequiredUserAction, GfxVendors}, - DBUS_IFACE_PATH, -}; - -use super::controller::CtrlGraphics; - -#[dbus_interface(name = "org.supergfxctl.Daemon")] -impl CtrlGraphics { - fn vendor(&self) -> zbus::fdo::Result { - self.get_gfx_mode().map_err(|err| { - error!("GFX: {}", err); - zbus::fdo::Error::Failed(format!("GFX fail: {}", err)) - }) - } - - fn power(&self) -> zbus::fdo::Result { - Self::get_runtime_status().map_err(|err| { - error!("GFX: {}", err); - zbus::fdo::Error::Failed(format!("GFX fail: {}", err)) - }) - } - - fn set_vendor(&mut self, vendor: GfxVendors) -> zbus::fdo::Result { - info!("GFX: Switching gfx mode to {}", <&str>::from(vendor)); - let msg = self.set_gfx_mode(vendor).map_err(|err| { - error!("GFX: {}", err); - zbus::fdo::Error::Failed(format!("GFX fail: {}", err)) - })?; - - self.notify_action(&msg) - .unwrap_or_else(|err| warn!("GFX: {}", err)); - - self.notify_gfx(&vendor) - .unwrap_or_else(|err| warn!("GFX: {}", err)); - - Ok(msg) - } - - #[dbus_interface(signal)] - fn notify_gfx(&self, vendor: &GfxVendors) -> zbus::Result<()> {} - - #[dbus_interface(signal)] - fn notify_action(&self, action: &GfxRequiredUserAction) -> zbus::Result<()> {} -} - -impl CtrlGraphics { - pub fn add_to_server(self, server: &mut zbus::ObjectServer) { - server - .at(&ObjectPath::from_str_unchecked(DBUS_IFACE_PATH), self) - .map_err(|err| { - warn!("GFX: CtrlGraphics: add_to_server {}", err); - err - }) - .ok(); - } -} diff --git a/supergfx/src/zbus_proxy.rs b/supergfx/src/zbus_proxy.rs deleted file mode 100644 index 21edaafa..00000000 --- a/supergfx/src/zbus_proxy.rs +++ /dev/null @@ -1,117 +0,0 @@ -//! # DBus interface proxy for: `org.asuslinux.Gfx` -//! -//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection data. -//! Source: `Interface '/org/supergfxctl/Gfx' from service 'org.asuslinux.Daemon' on system bus`. -//! -//! You may prefer to adapt it, instead of using it verbatim. -//! -//! More information can be found in the -//! [Writing a client proxy](https://zeenix.pages.freedesktop.org/zbus/client.html) -//! section of the zbus documentation. -//! -//! This DBus object implements -//! [standard DBus interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html), -//! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used: -//! -//! * [`zbus::fdo::PropertiesProxy`] -//! * [`zbus::fdo::IntrospectableProxy`] -//! * [`zbus::fdo::PeerProxy`] -//! -//! …consequently `zbus-xmlgen` did not generate code for the above interfaces. - -use std::sync::mpsc::{Sender}; - -use zbus::{dbus_proxy, Connection, Message, Result}; - -use crate::{ - gfx_vendors::{GfxPower, GfxRequiredUserAction, GfxVendors}, - DBUS_IFACE_PATH, -}; - -#[dbus_proxy(interface = "org.supergfxctl.Daemon")] -trait Daemon { - /// Power method - fn power(&self) -> zbus::Result; - - /// SetVendor method - fn set_vendor(&self, vendor: &GfxVendors) -> zbus::Result; - - /// Vendor method - fn vendor(&self) -> zbus::Result; - - /// NotifyAction signal - #[dbus_proxy(signal)] - fn notify_action(&self, action: GfxRequiredUserAction) -> zbus::Result<()>; - - /// NotifyGfx signal - #[dbus_proxy(signal)] - fn notify_gfx(&self, vendor: GfxVendors) -> zbus::Result<()>; -} - -pub struct GfxProxy<'a>(pub DaemonProxy<'a>); - -impl<'a> GfxProxy<'a> { - #[inline] - pub fn new(conn: &Connection) -> Result { - let proxy = DaemonProxy::new_for(conn, "org.supergfxctl.Daemon", DBUS_IFACE_PATH)?; - Ok(GfxProxy(proxy)) - } - - #[inline] - pub fn new_for(conn: &Connection, destination: &'a str, path: &'a str) -> Result { - let proxy = DaemonProxy::new_for(conn, destination, path)?; - Ok(GfxProxy(proxy)) - } - - #[inline] - pub fn new_for_owned(conn: Connection, destination: String, path: String) -> Result { - let proxy = DaemonProxy::new_for_owned(conn, destination, path)?; - Ok(GfxProxy(proxy)) - } - - #[inline] - pub fn proxy(&self) -> &DaemonProxy<'a> { - &self.0 - } - - #[inline] - pub fn gfx_get_pwr(&self) -> Result { - self.0.power() - } - - #[inline] - pub fn gfx_get_mode(&self) -> Result { - self.0.vendor() - } - - #[inline] - pub fn gfx_write_mode(&self, vendor: &GfxVendors) -> Result { - self.0.set_vendor(vendor) - } - - #[inline] - pub fn connect_notify_action( - &self, - send: Sender, - ) -> zbus::fdo::Result<()> { - self.0.connect_notify_action(move |data| { - send.send(data) - .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; - Ok(()) - }) - } - - #[inline] - pub fn connect_notify_gfx(&self, send: Sender) -> zbus::fdo::Result<()> { - self.0.connect_notify_gfx(move |data| { - send.send(data) - .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?; - Ok(()) - }) - } - - #[inline] - pub fn next_signal(&self) -> Result> { - self.0.next_signal() - } -}