From ea7ce494520ee5edda9b1be6450a5bfe5f8c6478 Mon Sep 17 00:00:00 2001 From: Louis-Alexander Kerst Date: Sun, 4 Oct 2026 18:38:14 +0200 Subject: [PATCH] Initial release of Predator Control 1.0.0 PredatorSense replacement for the Acer Predator Helios 16 (PH16-71) on Linux: - predatord: root service for profiles, fans (incl. temperature curves), keyboard RGB, lightbar and battery health; restores settings at boot and after resume, switches profiles on AC/battery changes - Qt desktop app with dashboard, fan curve editor and per-key RGB studio - Plasma 6 panel widget with quick controls - predatorctl command line tool - predator_wmi kernel module (DKMS) as a minimal WMI method bridge Co-Authored-By: Claude Opus 5.5 --- .gitignore | 8 + CHANGELOG.md | 18 + LICENSE | 117 +++ README.md | 156 +++ bin/predator-control | 10 + bin/predatorctl | 10 + bin/predatord | 10 + data/modules-load-predator-control.conf | 1 + data/predator-control.desktop | 19 + data/predator-control.svg | 15 + data/predatord.service | 15 + data/system-sleep-predator-control | 5 + docs/screenshots/fans.png | Bin 0 -> 65105 bytes docs/screenshots/home.png | Bin 0 -> 60583 bytes docs/screenshots/performance.png | Bin 0 -> 60034 bytes docs/screenshots/rgb.png | Bin 0 -> 132363 bytes install.sh | 108 +++ kernel/Makefile | 12 + kernel/dkms.conf | 7 + kernel/predator_wmi.c | 202 ++++ .../contents/ui/main.qml | 355 +++++++ .../org.predatorcontrol.panel/metadata.json | 21 + predator_control/__init__.py | 12 + predator_control/cli.py | 145 +++ predator_control/client.py | 65 ++ predator_control/daemon.py | 469 +++++++++ predator_control/gui/__init__.py | 0 predator_control/gui/app.py | 887 ++++++++++++++++++ predator_control/gui/theme.py | 79 ++ predator_control/gui/widgets.py | 390 ++++++++ predator_control/hardware.py | 359 +++++++ predator_control/keyboard.py | 139 +++ predator_control/layout.py | 115 +++ uninstall.sh | 25 + 34 files changed, 3774 insertions(+) create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100755 bin/predator-control create mode 100755 bin/predatorctl create mode 100755 bin/predatord create mode 100644 data/modules-load-predator-control.conf create mode 100644 data/predator-control.desktop create mode 100644 data/predator-control.svg create mode 100644 data/predatord.service create mode 100755 data/system-sleep-predator-control create mode 100644 docs/screenshots/fans.png create mode 100644 docs/screenshots/home.png create mode 100644 docs/screenshots/performance.png create mode 100644 docs/screenshots/rgb.png create mode 100755 install.sh create mode 100644 kernel/Makefile create mode 100644 kernel/dkms.conf create mode 100644 kernel/predator_wmi.c create mode 100644 plasmoid/org.predatorcontrol.panel/contents/ui/main.qml create mode 100644 plasmoid/org.predatorcontrol.panel/metadata.json create mode 100644 predator_control/__init__.py create mode 100644 predator_control/cli.py create mode 100644 predator_control/client.py create mode 100644 predator_control/daemon.py create mode 100644 predator_control/gui/__init__.py create mode 100644 predator_control/gui/app.py create mode 100644 predator_control/gui/theme.py create mode 100644 predator_control/gui/widgets.py create mode 100644 predator_control/hardware.py create mode 100644 predator_control/keyboard.py create mode 100644 predator_control/layout.py create mode 100755 uninstall.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c196b79 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.ko +*.o +*.mod* +.*.cmd +Module.symvers +modules.order +__pycache__/ +*.pyc diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6a0221e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,18 @@ +# Changelog + +## 1.0.0 – 2026-10-04 + +First release. + +### Added +- **predatord** system service: settings persistence, restore at boot and after resume, + automatic AC/battery profile switching, temperature-based fan curves, live state snapshot +- **Predator Control** desktop app (Qt/PySide6): dashboard, performance modes, fan control with + curve editor, RGB Studio (hardware effects, per-key painter with live preview, presets, + lightbar), battery health, firmware options +- **Plasma 6 panel widget** with quick controls that opens the app on the matching page +- **predatorctl** command line tool +- **predator_wmi** kernel module (DKMS) as a minimal WMI bridge for fans, lightbar, + battery health and firmware options +- Keyboard layouts: German ISO and US ANSI +- Installer and uninstaller for Arch-based distributions (generic `--no-deps` mode for others) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..17cb286 --- /dev/null +++ b/LICENSE @@ -0,0 +1,117 @@ +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + + c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + one line to give the program's name and an idea of what it does. Copyright (C) yyyy name of author + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. + +signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice diff --git a/README.md b/README.md new file mode 100644 index 0000000..3c4b460 --- /dev/null +++ b/README.md @@ -0,0 +1,156 @@ +# Predator Control + +An open-source **PredatorSense replacement for Linux**, built for the +**Acer Predator Helios 16 (PH16-71)** and tested on CachyOS with KDE Plasma 6. + +It gives you everything the Windows control center does – performance modes, +fan control, per-key keyboard RGB, the rear lightbar and battery health – as a +desktop app, a **Plasma panel widget**, and a command line tool. + +![Dashboard](docs/screenshots/home.png) + +## Features + +| Area | What you get | +|------|--------------| +| **Performance** | Eco / Quiet / Balanced / Performance / Turbo (ACPI platform profiles), separate profiles for AC and battery with automatic switching when you plug in or unplug | +| **Fans** | Auto, Max (cooler boost), manual speed per fan, or a **custom temperature curve** for CPU and GPU with drag-and-drop editor | +| **Keyboard RGB** | 12 hardware effects (static, breathing, rainbow wave, ripple, neon, rain, explosion, pulse, stars, meteor, aura, …), colour, brightness, hidden effect variants, presets | +| **RGB Studio** | Paint individual keys with the mouse, live preview on the keyboard, quick fills (WASD, arrows, F-row, numpad …), German ISO and US ANSI layouts | +| **Lightbar** | All rear lightbar effects with colour, brightness and speed – or let it follow the keyboard | +| **Battery** | 80 % charge limit, calibration, live health / cycles / power draw | +| **Firmware options** | Boot animation & sound, LCD overdrive, keyboard backlight timeout, USB charging while off | +| **Monitoring** | CPU/GPU temperatures, fan RPM, CPU load and clock, memory – without waking the dGPU | +| **Panel widget** | Click the icon in the Plasma panel to change everything quickly; buttons open the full app directly on the right page (e.g. RGB Studio). Middle-click cycles the performance mode | +| **Persistence** | All settings are restored at boot and after suspend/resume | + +

+ RGB Studio + Fan curves +

+ +## Supported hardware + +| Model | Keyboard MCU | Status | +|-------|--------------|--------| +| Acer Predator Helios 16 **PH16-71** | Chicony `04F2:011A` / `04F2:0117` | primary target | + +Other Predator/Helios models with the same keyboard controller and WMI +interfaces will likely work. Reports are welcome – please include the output of +`predatorctl status`, `lsusb | grep 04f2` and `cat /sys/class/dmi/id/product_name`. + +## Installation + +Requirements: a kernel with `acer-wmi` (any recent kernel), Python 3, PySide6, +DKMS and kernel headers. On Arch / CachyOS / Manjaro the installer pulls in everything. + +```bash +git clone https://git.mrblake.cc/MrBlake/Cachy-Predator-Keyboard.git +cd Cachy-Predator-Keyboard +sudo ./install.sh +``` + +Then: + +* **App:** start *Predator Control* from the application menu, or run `predator-control` +* **Panel widget:** right-click the panel → *Add or Manage Widgets…* → search for *Predator Control* + and drag it into the panel – or enable it under *System Tray Settings → Entries*. + If it does not show up yet, log out and back in. +* **CLI:** `predatorctl status` + +On other distributions install the dependencies yourself and run `sudo ./install.sh --no-deps`. + +**Secure Boot:** the kernel module is unsigned. With Secure Boot enforcing module +signatures you have to sign `predator_wmi` yourself (e.g. with `sbctl` or a MOK key). +Keyboard RGB and performance profiles work without the module. + +Uninstall with `sudo ./uninstall.sh` (add `--purge` to also delete your settings). + +## Usage + +### Panel widget + +| Action | Result | +|--------|--------| +| Left click | Opens the quick-settings popup | +| Middle click | Cycles to the next performance mode | +| *RGB Studio…* | Opens the app on the RGB page | +| *Manual* / *Curve* (fans) | Switches mode and opens the fan page | + +### Command line + +```bash +predatorctl status # overview +predatorctl profile performance # low-power | quiet | balanced | balanced-performance | performance +predatorctl profile-cycle +predatorctl fans auto | max | curve +predatorctl fans custom 60 80 # CPU 60 %, GPU 80 % +predatorctl kbd static ff0000 -b 255 # effect, colour, brightness (0-255) +predatorctl kbd off | on +predatorctl kbd-brightness +25 +predatorctl lightbar wave --color 00d4ff --speed 7 +predatorctl lightbar --sync on # lightbar follows the keyboard +predatorctl battery-limit on +predatorctl open rgb # open the app on a page +``` + +Tip: bind `predatorctl profile-cycle` or `predatorctl kbd-brightness +25` to a +keyboard shortcut in *System Settings → Shortcuts*. + +## How it works + +``` + Plasma widget ──┐ ┌── /sys/firmware/acpi/platform_profile (profiles) + Qt app ─────────┼── Unix socket ──► predatord (root) ──┼── /dev/hidrawN (keyboard MCU, USB HID) + predatorctl ────┘ state.json ◄──┘ └── predator_wmi kernel module ── ACPI WMI + (fans, lightbar, battery, firmware options) +``` + +* **predatord** – a small Python daemon running as root. It owns all hardware access, + stores settings in `/etc/predator-control/config.json`, writes a live state snapshot to + `/run/predator-control/state.json`, restores everything at boot/resume, switches + profiles on AC changes and runs the fan curve. Only root and members of the `wheel` + group may send commands (checked via `SO_PEERCRED`; configurable via `allowed_group`). +* **predator_wmi** – a ~200 line kernel module that binds to Acer's gaming, battery and + APGE WMI interfaces and exposes a single root-only sysfs attribute to call WMI methods. + All protocol knowledge stays in user space. +* **Keyboard** – talks directly to the keyboard MCU through hidraw (8-byte feature reports + plus a 512-byte per-key frame) – no kernel driver needed. +* **Temperatures and fan RPM** come from the mainline `acer-wmi` hwmon and `coretemp`. + +### Correcting the key map + +The LED matrix positions of a few keys (ISO `#` and `<`) are best guesses. If a key +lights up in the wrong place in the RGB Studio, create +`~/.config/predator-control/layout.json` with `{"": }` entries +(cell = column × 6 + row, row 0 = bottom row). + +## Troubleshooting + +| Problem | Fix | +|---------|-----| +| *"predatord is not running"* | `sudo systemctl enable --now predatord`, then `journalctl -u predatord` | +| *"permission denied"* | add yourself to `wheel`: `sudo usermod -aG wheel $USER`, log in again | +| Fans / lightbar / battery greyed out | the module is not loaded: `sudo modprobe predator_wmi`, check `dmesg` | +| Keyboard does not react | check `predatorctl status` and that `lsusb` shows `04f2:011a` or `04f2:0117` | +| Profile changes back on its own | another tool also manages `platform_profile` (e.g. *power-profiles-daemon* or *tuned*); disable automatic switching in either tool | +| Widget missing after install | log out and back in, or run `plasmashell --replace &` | + +## Credits + +The hardware protocols were reverse-engineered by others – this project would not exist without them: + +* [Venator](https://github.com/Exyons/Venator) – PH16-71 keyboard MCU protocol, lightbar, key map (GPL-2.0) +* [Linuwu-Sense](https://github.com/0x7375646F/Linuwu-Sense) – fan control, battery health and firmware option WMI calls (GPL-2.0) +* The mainline Linux `acer-wmi` driver – platform profiles and sensors + +## Disclaimer + +This is an independent community project. It is **not affiliated with, endorsed by or +supported by Acer Inc.** "Predator", "Helios" and "PredatorSense" are trademarks of +Acer Inc. The software talks directly to firmware interfaces – use it at your own risk, +especially custom fan curves: keep an eye on temperatures. + +## License + +[GPL-2.0-only](LICENSE) diff --git a/bin/predator-control b/bin/predator-control new file mode 100755 index 0000000..5789351 --- /dev/null +++ b/bin/predator-control @@ -0,0 +1,10 @@ +#!/usr/bin/python3 +import os +import sys + +_src = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) +sys.path.insert(0, _src if os.path.isdir(os.path.join(_src, "predator_control")) else "/usr/lib/predator-control") + +from predator_control.gui.app import main + +sys.exit(main()) diff --git a/bin/predatorctl b/bin/predatorctl new file mode 100755 index 0000000..fb8bc56 --- /dev/null +++ b/bin/predatorctl @@ -0,0 +1,10 @@ +#!/usr/bin/python3 +import os +import sys + +_src = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) +sys.path.insert(0, _src if os.path.isdir(os.path.join(_src, "predator_control")) else "/usr/lib/predator-control") + +from predator_control.cli import main + +sys.exit(main()) diff --git a/bin/predatord b/bin/predatord new file mode 100755 index 0000000..54b2c94 --- /dev/null +++ b/bin/predatord @@ -0,0 +1,10 @@ +#!/usr/bin/python3 +import os +import sys + +_src = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) +sys.path.insert(0, _src if os.path.isdir(os.path.join(_src, "predator_control")) else "/usr/lib/predator-control") + +from predator_control.daemon import main + +sys.exit(main()) diff --git a/data/modules-load-predator-control.conf b/data/modules-load-predator-control.conf new file mode 100644 index 0000000..a7f6b24 --- /dev/null +++ b/data/modules-load-predator-control.conf @@ -0,0 +1 @@ +predator_wmi diff --git a/data/predator-control.desktop b/data/predator-control.desktop new file mode 100644 index 0000000..18ba3cb --- /dev/null +++ b/data/predator-control.desktop @@ -0,0 +1,19 @@ +[Desktop Entry] +Type=Application +Name=Predator Control +GenericName=Laptop Control Center +Comment=Performance modes, fans, keyboard RGB, lightbar and battery for Acer Predator laptops +Exec=predator-control +Icon=predator-control +Categories=System;Settings;HardwareSettings; +Keywords=acer;predator;helios;rgb;keyboard;fan;turbo;battery;predatorsense; +StartupWMClass=predator-control +Actions=RGB;Fans; + +[Desktop Action RGB] +Name=RGB Studio +Exec=predator-control --page rgb + +[Desktop Action Fans] +Name=Fan Control +Exec=predator-control --page fans diff --git a/data/predator-control.svg b/data/predator-control.svg new file mode 100644 index 0000000..a51cdb4 --- /dev/null +++ b/data/predator-control.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/data/predatord.service b/data/predatord.service new file mode 100644 index 0000000..ef64682 --- /dev/null +++ b/data/predatord.service @@ -0,0 +1,15 @@ +[Unit] +Description=Predator Control daemon (performance, fans, RGB, battery) +After=systemd-modules-load.service systemd-udevd.service + +[Service] +Type=simple +ExecStartPre=-/usr/bin/modprobe predator_wmi +ExecStart=/usr/bin/predatord +Restart=on-failure +RestartSec=2 +RuntimeDirectory=predator-control +RuntimeDirectoryMode=0755 + +[Install] +WantedBy=multi-user.target diff --git a/data/system-sleep-predator-control b/data/system-sleep-predator-control new file mode 100755 index 0000000..c3c9212 --- /dev/null +++ b/data/system-sleep-predator-control @@ -0,0 +1,5 @@ +#!/bin/sh +# Re-apply keyboard, lightbar, fan and profile settings after resume. +case "$1" in + post) systemctl kill --signal=USR1 predatord.service 2>/dev/null || true ;; +esac diff --git a/docs/screenshots/fans.png b/docs/screenshots/fans.png new file mode 100644 index 0000000000000000000000000000000000000000..05b19a7163d5dbd8fdc317b52c7365142d5f9566 GIT binary patch literal 65105 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 literal 0 HcmV?d00001 diff --git a/docs/screenshots/home.png b/docs/screenshots/home.png new file mode 100644 index 0000000000000000000000000000000000000000..c198308a5fee9e6c5b667b6f566bd6f83b01e2ee GIT binary patch literal 60583 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 TQw#FJKad+&jjt46c8vZ9SkrUl literal 0 HcmV?d00001 diff --git a/docs/screenshots/performance.png b/docs/screenshots/performance.png new file mode 100644 index 0000000000000000000000000000000000000000..d8239afe1f6359dd1fa36d57fc4ead77632a1dff GIT binary patch literal 60034 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 NSLd@%^nYEx^B|Vk+T-=d4pb)R1mWp_D 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 HU%&q!Q1yp| literal 0 HcmV?d00001 diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..2941d8e --- /dev/null +++ b/install.sh @@ -0,0 +1,108 @@ +#!/usr/bin/env bash +# Predator Control installer. +# sudo ./install.sh install / upgrade +# sudo ./install.sh --no-deps skip package installation (non-Arch distros) +set -euo pipefail + +VERSION="1.0.0" +MODULE="predator-wmi" +SRC="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PREFIX="/usr" +LIBDIR="$PREFIX/lib/predator-control" +INSTALL_DEPS=1 +[[ "${1:-}" == "--no-deps" ]] && INSTALL_DEPS=0 + +c_ok() { printf '\e[32m✔\e[0m %s\n' "$*"; } +c_info() { printf '\e[36m→\e[0m %s\n' "$*"; } +c_warn() { printf '\e[33m!\e[0m %s\n' "$*"; } +die() { printf '\e[31m✘ %s\e[0m\n' "$*" >&2; exit 1; } + +[[ $EUID -eq 0 ]] || die "Please run as root: sudo ./install.sh" + +if ! grep -qi acer /sys/class/dmi/id/sys_vendor 2>/dev/null; then + c_warn "This does not look like an Acer laptop ($(cat /sys/class/dmi/id/sys_vendor 2>/dev/null))." + read -rp "Continue anyway? [y/N] " a; [[ "$a" =~ ^[yY] ]] || exit 1 +fi + +# ------------------------------------------------------------------ dependencies +if [[ $INSTALL_DEPS -eq 1 ]]; then + if command -v pacman >/dev/null; then + KPKG="$(pacman -Qoq "/usr/lib/modules/$(uname -r)/vmlinuz" 2>/dev/null || echo linux)" + PKGS=(python pyside6 dkms base-devel "${KPKG}-headers") + grep -q clang /proc/version && PKGS+=(clang lld llvm) + c_info "Installing dependencies: ${PKGS[*]}" + pacman -S --needed --noconfirm "${PKGS[@]}" + else + c_warn "Not an Arch-based system – install manually: python3, PySide6, dkms, kernel headers, make, gcc/clang" + fi +fi + +# ------------------------------------------------------------------ kernel module +c_info "Building kernel module predator_wmi" +if lsmod | grep -q '^predator_wmi'; then modprobe -r predator_wmi || true; fi +if command -v dkms >/dev/null; then + for v in $(dkms status -m "$MODULE" 2>/dev/null | sed -n 's|^[^/]*/\([^,:]*\).*|\1|p' | sort -u); do + dkms remove -m "$MODULE" -v "$v" --all >/dev/null 2>&1 || true + done + rm -rf "/usr/src/$MODULE-$VERSION" + install -d "/usr/src/$MODULE-$VERSION" + install -m644 "$SRC"/kernel/{predator_wmi.c,Makefile,dkms.conf} "/usr/src/$MODULE-$VERSION/" + dkms add -m "$MODULE" -v "$VERSION" + dkms install -m "$MODULE" -v "$VERSION" || die "DKMS build failed – see /var/lib/dkms/$MODULE/$VERSION/build/make.log" + c_ok "Module installed via DKMS (rebuilt automatically on kernel updates)" +else + make -C "$SRC/kernel" clean >/dev/null 2>&1 || true + make -C "$SRC/kernel" + install -Dm644 "$SRC/kernel/predator_wmi.ko" "/lib/modules/$(uname -r)/updates/predator_wmi.ko" + depmod -a + c_warn "DKMS not found – module installed for the running kernel only. Re-run after kernel updates." +fi +install -Dm644 "$SRC/data/modules-load-predator-control.conf" /etc/modules-load.d/predator-control.conf +if ! modprobe predator_wmi; then + c_warn "Could not load predator_wmi. If Secure Boot is enabled, the module must be signed." + c_warn "Fan control, lightbar and battery features need this module; keyboard RGB and profiles work without it." +fi + +# ------------------------------------------------------------------ application +c_info "Installing application" +rm -rf "$LIBDIR" +install -d "$LIBDIR/predator_control/gui" +install -m644 "$SRC"/predator_control/*.py "$LIBDIR/predator_control/" +install -m644 "$SRC"/predator_control/gui/*.py "$LIBDIR/predator_control/gui/" +python3 -m compileall -q "$LIBDIR" || true +for b in predatord predatorctl predator-control; do install -Dm755 "$SRC/bin/$b" "$PREFIX/bin/$b"; done +install -Dm644 "$SRC/data/predator-control.svg" "$PREFIX/share/icons/hicolor/scalable/apps/predator-control.svg" +install -Dm644 "$SRC/data/predator-control.desktop" "$PREFIX/share/applications/predator-control.desktop" +install -Dm644 "$SRC/data/predatord.service" "$PREFIX/lib/systemd/system/predatord.service" +install -Dm755 "$SRC/data/system-sleep-predator-control" "$PREFIX/lib/systemd/system-sleep/predator-control" + +PLASMOID="$PREFIX/share/plasma/plasmoids/org.predatorcontrol.panel" +rm -rf "$PLASMOID" +install -d "$PLASMOID/contents/ui" +install -m644 "$SRC/plasmoid/org.predatorcontrol.panel/metadata.json" "$PLASMOID/" +install -m644 "$SRC/plasmoid/org.predatorcontrol.panel/contents/ui/"*.qml "$PLASMOID/contents/ui/" +gtk-update-icon-cache -q -t "$PREFIX/share/icons/hicolor" 2>/dev/null || true +c_ok "Application, panel widget and service files installed" + +# ------------------------------------------------------------------ service +systemctl daemon-reload +systemctl enable predatord.service >/dev/null 2>&1 +systemctl restart predatord.service +sleep 1 +systemctl is-active --quiet predatord.service && c_ok "Service predatord is running" \ + || c_warn "predatord failed to start – check: journalctl -u predatord" + +USER_NAME="${SUDO_USER:-}" +if [[ -n "$USER_NAME" ]] && ! id -nG "$USER_NAME" | tr ' ' '\n' | grep -qx wheel; then + c_warn "User '$USER_NAME' is not in group 'wheel' – only wheel members may control the daemon." + c_warn "Add yourself with: sudo usermod -aG wheel $USER_NAME (then log out and back in)" +fi + +cat <-/predator_call + * + * write: " " e.g. "20 0300ff00010000ff0302000000000000" + * read : "ok buf " | "ok int " | "ok none" | "err " + * + * The read returns the result of the most recent write. All protocol + * knowledge lives in userspace (predator-control daemon); this module only + * moves bytes between sysfs and wmidev_evaluate_method(). + * + * Interfaces (PH16-71): + * 7A4DDFE7-... WMBH AcerGamingFunction (fans, lightbar, misc settings) + * 79772EC5-... WMBE Battery health (80 % limit, calibration) + * 61EF69EA-... WMAA APGE action (USB charging, backlight timeout) + */ + +#include +#include +#include +#include +#if __has_include() +#include +#endif +#include +#include +#include +#include +#include +#include + +#define PWMI_MAX_IN 64 +#define PWMI_MAX_OUT 256 + +struct pwmi_dev { + struct wmi_device *wdev; + struct mutex lock; + int last_err; + u8 last_type; /* 0 none, 1 buffer, 2 integer */ + size_t last_len; + u8 last_out[PWMI_MAX_OUT]; + u64 last_int; +}; + +static ssize_t predator_call_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pwmi_dev *p = dev_get_drvdata(dev); + struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer in; + union acpi_object *obj; + u8 inbuf[PWMI_MAX_IN]; + const char *s = buf, *end = buf + count; + unsigned int method = 0; + size_t n = 0; + acpi_status status; + int hi, lo; + + /* method id (decimal) */ + while (s < end && isspace(*s)) + s++; + if (s >= end || !isdigit(*s)) + return -EINVAL; + while (s < end && isdigit(*s)) { + method = method * 10 + (*s - '0'); + if (method > 0xffff) + return -EINVAL; + s++; + } + while (s < end && isspace(*s)) + s++; + + /* hex payload */ + while (s + 1 < end && !isspace(*s)) { + hi = hex_to_bin(s[0]); + lo = hex_to_bin(s[1]); + if (hi < 0 || lo < 0 || n >= PWMI_MAX_IN) + return -EINVAL; + inbuf[n++] = (hi << 4) | lo; + s += 2; + } + while (s < end && isspace(*s)) + s++; + if (s != end) + return -EINVAL; + + in.length = n; + in.pointer = inbuf; + + mutex_lock(&p->lock); + p->last_type = 0; + p->last_len = 0; + p->last_err = 0; + + status = wmidev_evaluate_method(p->wdev, 0, method, &in, &out); + if (ACPI_FAILURE(status)) { + p->last_err = -EIO; + goto unlock; + } + + obj = out.pointer; + if (obj && obj->type == ACPI_TYPE_BUFFER) { + p->last_type = 1; + p->last_len = min_t(size_t, obj->buffer.length, PWMI_MAX_OUT); + memcpy(p->last_out, obj->buffer.pointer, p->last_len); + } else if (obj && obj->type == ACPI_TYPE_INTEGER) { + p->last_type = 2; + p->last_int = obj->integer.value; + } + kfree(out.pointer); +unlock: + mutex_unlock(&p->lock); + return p->last_err ? p->last_err : count; +} + +static ssize_t predator_call_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pwmi_dev *p = dev_get_drvdata(dev); + ssize_t len; + + mutex_lock(&p->lock); + if (p->last_err) + len = sysfs_emit(buf, "err %d\n", p->last_err); + else if (p->last_type == 1) + len = sysfs_emit(buf, "ok buf %*phN\n", (int)p->last_len, + p->last_out); + else if (p->last_type == 2) + len = sysfs_emit(buf, "ok int %016llx\n", p->last_int); + else + len = sysfs_emit(buf, "ok none\n"); + mutex_unlock(&p->lock); + return len; +} +static DEVICE_ATTR_ADMIN_RW(predator_call); + +static struct attribute *pwmi_attrs[] = { + &dev_attr_predator_call.attr, + NULL, +}; +ATTRIBUTE_GROUPS(pwmi); + +static int pwmi_probe(struct wmi_device *wdev, const void *ctx) +{ + struct pwmi_dev *p; + + p = devm_kzalloc(&wdev->dev, sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + p->wdev = wdev; + mutex_init(&p->lock); + dev_set_drvdata(&wdev->dev, p); + return 0; +} + +static const struct wmi_device_id pwmi_id_table[] = { + { .guid_string = "7A4DDFE7-5B5D-40B4-8595-4408E0CC7F56" }, + { .guid_string = "79772EC5-04B1-4BFD-843C-61E7F77B6CC9" }, + { .guid_string = "61EF69EA-865C-4BC3-A502-A0DEBA0CB531" }, + { } +}; +MODULE_DEVICE_TABLE(wmi, pwmi_id_table); + +static struct wmi_driver pwmi_driver = { + .driver = { + .name = "predator_wmi", + .dev_groups = pwmi_groups, + }, + .id_table = pwmi_id_table, + .probe = pwmi_probe, + .no_singleton = true, +}; + +static const struct dmi_system_id pwmi_dmi[] = { + { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer") } }, + { } +}; + +static int __init pwmi_init(void) +{ + if (!dmi_check_system(pwmi_dmi)) + return -ENODEV; + return wmi_driver_register(&pwmi_driver); +} + +static void __exit pwmi_exit(void) +{ + wmi_driver_unregister(&pwmi_driver); +} + +module_init(pwmi_init); +module_exit(pwmi_exit); + +MODULE_AUTHOR("predator-control"); +MODULE_DESCRIPTION("WMI method bridge for Acer Predator laptops"); +MODULE_LICENSE("GPL"); diff --git a/plasmoid/org.predatorcontrol.panel/contents/ui/main.qml b/plasmoid/org.predatorcontrol.panel/contents/ui/main.qml new file mode 100644 index 0000000..0328fa5 --- /dev/null +++ b/plasmoid/org.predatorcontrol.panel/contents/ui/main.qml @@ -0,0 +1,355 @@ +/* + * Predator Control – Plasma panel widget. + * + * Reads the state snapshot written by predatord (/run/predator-control/state.json) + * and sends commands through the `predatorctl` CLI. + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +import QtQuick +import QtQuick.Layouts +import org.kde.plasma.plasmoid +import org.kde.plasma.core as PlasmaCore +import org.kde.plasma.components as PC3 +import org.kde.plasma.extras as PlasmaExtras +import org.kde.plasma.plasma5support as P5Support +import org.kde.kirigami as Kirigami + +PlasmoidItem { + id: root + + property var st: null + property string lastError: "" + readonly property bool ok: st !== null + readonly property string stateCmd: "cat /run/predator-control/state.json" + + readonly property var profiles: [ + { key: "low-power", label: "Eco" }, + { key: "quiet", label: "Quiet" }, + { key: "balanced", label: "Balanced" }, + { key: "balanced-performance", label: "Perf." }, + { key: "performance", label: "Turbo" } + ] + readonly property var swatches: ["#00d4ff", "#0057ff", "#7a00ff", "#ff00c8", + "#ff0033", "#ff6a00", "#ffd000", "#3cff00", "#ffffff"] + + function profileLabel(key) { + const names = { "low-power": "Eco", "quiet": "Quiet", "balanced": "Balanced", + "balanced-performance": "Performance", "performance": "Turbo" } + return names[key] || key || "–" + } + function temp(v) { return v ? Math.round(v) + " °C" : "off" } + + function run(args) { + // unique suffix so the executable engine runs identical commands again + runner.connectSource("predatorctl " + args + " #" + Date.now()) + } + function openPage(page) { + run("open " + page) + root.expanded = false + } + + Plasmoid.icon: "predator-control" + Plasmoid.status: PlasmaCore.Types.ActiveStatus + toolTipMainText: "Predator Control" + toolTipSubText: ok + ? profileLabel(st.profile) + " · CPU " + temp(st.sensors.cpu_temp) + " · GPU " + temp(st.sensors.gpu_temp) + + "\nFans " + (st.sensors.cpu_fan || 0) + " / " + (st.sensors.gpu_fan || 0) + " RPM" + : "Service predatord not running" + + P5Support.DataSource { + id: reader + engine: "executable" + connectedSources: [root.stateCmd] + interval: root.expanded ? 1500 : 5000 + onNewData: (source, data) => { + if (data["exit code"] !== 0) { root.st = null; return } + try { root.st = JSON.parse(data["stdout"]) } catch (e) { } + } + } + + P5Support.DataSource { + id: runner + engine: "executable" + onNewData: (source, data) => { + disconnectSource(source) + root.lastError = data["exit code"] !== 0 ? (data["stderr"] || "").trim() : "" + refresh.restart() + } + } + + Timer { + id: refresh + interval: 300 + onTriggered: { + reader.disconnectSource(root.stateCmd) + reader.connectSource(root.stateCmd) + } + } + + compactRepresentation: MouseArea { + Layout.minimumWidth: Kirigami.Units.iconSizes.small + hoverEnabled: true + acceptedButtons: Qt.LeftButton | Qt.MiddleButton + onClicked: mouse => { + if (mouse.button === Qt.MiddleButton) root.run("profile-cycle") + else root.expanded = !root.expanded + } + Kirigami.Icon { + anchors.fill: parent + source: "predator-control" + active: parent.containsMouse + } + } + + fullRepresentation: PlasmaExtras.Representation { + id: full + Layout.preferredWidth: Kirigami.Units.gridUnit * 24 + Layout.preferredHeight: content.implicitHeight + header.implicitHeight + Kirigami.Units.largeSpacing * 2 + Layout.minimumWidth: Kirigami.Units.gridUnit * 20 + + header: PlasmaExtras.PlasmoidHeading { + RowLayout { + anchors.fill: parent + Kirigami.Icon { + source: "predator-control" + Layout.preferredWidth: Kirigami.Units.iconSizes.medium + Layout.preferredHeight: Kirigami.Units.iconSizes.medium + } + ColumnLayout { + spacing: 0 + Layout.fillWidth: true + Kirigami.Heading { level: 3; text: "Predator Control" } + PC3.Label { + opacity: 0.7 + text: root.ok ? root.profileLabel(root.st.profile) + " mode" : "Service not running" + } + } + PC3.ToolButton { + icon.name: "configure" + text: "Open" + display: PC3.AbstractButton.IconOnly + PC3.ToolTip.text: "Open Predator Control" + PC3.ToolTip.visible: hovered + onClicked: root.openPage("home") + } + } + } + + PlasmaExtras.PlaceholderMessage { + anchors.centerIn: parent + width: parent.width - Kirigami.Units.gridUnit * 2 + visible: !root.ok + iconName: "dialog-warning" + text: "predatord is not running" + explanation: "Start it with: sudo systemctl enable --now predatord" + } + + ColumnLayout { + id: content + visible: root.ok + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.margins: Kirigami.Units.smallSpacing + spacing: Kirigami.Units.smallSpacing + + // ---------------------------------------------------------- sensors + GridLayout { + columns: 4 + Layout.fillWidth: true + columnSpacing: Kirigami.Units.smallSpacing + Repeater { + model: root.ok ? [ + { t: "CPU", v: root.temp(root.st.sensors.cpu_temp) }, + { t: "GPU", v: root.temp(root.st.sensors.gpu_temp) }, + { t: "CPU fan", v: (root.st.sensors.cpu_fan || 0) + " rpm" }, + { t: "GPU fan", v: (root.st.sensors.gpu_fan || 0) + " rpm" } + ] : [] + delegate: ColumnLayout { + Layout.fillWidth: true + spacing: 0 + PC3.Label { + Layout.alignment: Qt.AlignHCenter + text: modelData.v + font.bold: true + font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.25 + } + PC3.Label { + Layout.alignment: Qt.AlignHCenter + text: modelData.t + opacity: 0.7 + font: Kirigami.Theme.smallFont + } + } + } + } + + // ---------------------------------------------------------- performance + Kirigami.Heading { level: 5; text: "Performance mode"; opacity: 0.8; Layout.topMargin: Kirigami.Units.smallSpacing } + RowLayout { + Layout.fillWidth: true + spacing: 2 + Repeater { + model: root.profiles + delegate: PC3.Button { + Layout.fillWidth: true + text: modelData.label + checkable: true + checked: root.ok && root.st.profile === modelData.key + enabled: root.ok && root.st.profile_choices.indexOf(modelData.key) >= 0 + onClicked: root.run("profile " + modelData.key) + } + } + } + + // ---------------------------------------------------------- fans + Kirigami.Heading { level: 5; text: "Fans"; opacity: 0.8; Layout.topMargin: Kirigami.Units.smallSpacing } + RowLayout { + Layout.fillWidth: true + spacing: 2 + Repeater { + model: [{ k: "auto", l: "Auto" }, { k: "max", l: "Max" }, { k: "curve", l: "Curve" }, { k: "custom", l: "Manual" }] + delegate: PC3.Button { + Layout.fillWidth: true + text: modelData.l + checkable: true + checked: root.ok && root.st.config.fans.mode === modelData.k + onClicked: { + root.run("fans " + modelData.k) + if (modelData.k === "custom" || modelData.k === "curve") root.openPage("fans") + } + } + } + } + + // ---------------------------------------------------------- keyboard + RowLayout { + Layout.fillWidth: true + Layout.topMargin: Kirigami.Units.smallSpacing + Kirigami.Heading { level: 5; text: "Keyboard lighting"; opacity: 0.8; Layout.fillWidth: true } + PC3.Switch { + checked: root.ok && root.st.config.keyboard.effect !== "off" + onToggled: root.run("kbd " + (checked ? "on" : "off")) + } + } + RowLayout { + Layout.fillWidth: true + PC3.ComboBox { + id: effectBox + Layout.fillWidth: true + textRole: "label" + valueRole: "key" + model: { + const out = [] + if (!root.ok) return out + const fx = root.st.keyboard_effects + for (const k in fx) if (k !== "off") out.push({ key: k, label: fx[k][0] }) + return out + } + currentIndex: root.ok ? Math.max(0, indexOfValue(root.st.config.keyboard.effect)) : 0 + onActivated: root.run("kbd " + currentValue) + } + PC3.Button { + icon.name: "color-management" + text: "RGB Studio…" + onClicked: root.openPage("rgb") + } + } + RowLayout { + Layout.fillWidth: true + spacing: Kirigami.Units.smallSpacing + Repeater { + model: root.swatches + delegate: Rectangle { + Layout.preferredWidth: Kirigami.Units.gridUnit * 1.3 + Layout.preferredHeight: Kirigami.Units.gridUnit * 1.3 + radius: width / 2 + color: modelData + border.width: root.ok && root.st.config.keyboard.color.toLowerCase() === modelData ? 3 : 1 + border.color: Kirigami.Theme.textColor + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + let fx = root.st.config.keyboard.effect + const usesColor = root.st.keyboard_effects[fx] && root.st.keyboard_effects[fx][1] + if (!usesColor) fx = "static" + root.run("kbd " + fx + " " + modelData.substring(1)) + } + } + } + } + Item { Layout.fillWidth: true } + } + RowLayout { + Layout.fillWidth: true + Kirigami.Icon { source: "brightness-low"; Layout.preferredWidth: Kirigami.Units.iconSizes.small; Layout.preferredHeight: Kirigami.Units.iconSizes.small } + PC3.Slider { + id: kbdBright + Layout.fillWidth: true + from: 0; to: 255; stepSize: 5 + value: root.ok ? root.st.config.keyboard.brightness : 0 + onPressedChanged: if (!pressed) root.run("kbd-brightness " + Math.round(value)) + } + Kirigami.Icon { source: "brightness-high"; Layout.preferredWidth: Kirigami.Units.iconSizes.small; Layout.preferredHeight: Kirigami.Units.iconSizes.small } + } + + // ---------------------------------------------------------- lightbar + RowLayout { + Layout.fillWidth: true + Layout.topMargin: Kirigami.Units.smallSpacing + Kirigami.Heading { level: 5; text: "Lightbar"; opacity: 0.8; Layout.fillWidth: true } + PC3.CheckBox { + text: "Follow keyboard" + checked: root.ok && root.st.config.lightbar.sync_keyboard + onToggled: root.run("lightbar --sync " + (checked ? "on" : "off")) + } + PC3.Switch { + checked: root.ok && root.st.lightbar_effective.mode !== "off" + enabled: root.ok && !root.st.config.lightbar.sync_keyboard + onToggled: root.run("lightbar " + (checked ? "static" : "off")) + } + } + + // ---------------------------------------------------------- battery + RowLayout { + Layout.fillWidth: true + Layout.topMargin: Kirigami.Units.smallSpacing + Kirigami.Icon { + source: root.ok && root.st.battery.ac_online ? "battery-charging" : "battery" + Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium + Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium + } + PC3.Label { + Layout.fillWidth: true + text: root.ok ? root.st.battery.capacity + " % · " + (root.st.battery.ac_online ? "plugged in" : "on battery") : "" + } + PC3.CheckBox { + text: "Limit to 80 %" + enabled: root.ok && root.st.battery_limit !== null + checked: root.ok && root.st.battery_limit === true + onToggled: root.run("battery-limit " + (checked ? "on" : "off")) + } + } + + PC3.Label { + Layout.fillWidth: true + visible: root.lastError !== "" + text: root.lastError + color: Kirigami.Theme.negativeTextColor + wrapMode: Text.Wrap + font: Kirigami.Theme.smallFont + } + + PC3.Button { + Layout.fillWidth: true + Layout.topMargin: Kirigami.Units.smallSpacing + icon.name: "preferences-system" + text: "Open Predator Control" + onClicked: root.openPage("home") + } + } + } +} diff --git a/plasmoid/org.predatorcontrol.panel/metadata.json b/plasmoid/org.predatorcontrol.panel/metadata.json new file mode 100644 index 0000000..c3cf8d5 --- /dev/null +++ b/plasmoid/org.predatorcontrol.panel/metadata.json @@ -0,0 +1,21 @@ +{ + "KPackageStructure": "Plasma/Applet", + "KPlugin": { + "Authors": [ + { + "Name": "Predator Control contributors" + } + ], + "Category": "System Information", + "Description": "Quick controls for Acer Predator laptops: performance mode, fans, keyboard RGB, lightbar and battery", + "Icon": "predator-control", + "Id": "org.predatorcontrol.panel", + "License": "GPL-2.0-only", + "Name": "Predator Control", + "Version": "1.0.0", + "Website": "https://git.mrblake.cc/MrBlake/Cachy-Predator-Keyboard" + }, + "X-Plasma-API-Minimum-Version": "6.0", + "X-Plasma-NotificationArea": "true", + "X-Plasma-NotificationAreaCategory": "Hardware" +} diff --git a/predator_control/__init__.py b/predator_control/__init__.py new file mode 100644 index 0000000..7fcc9bf --- /dev/null +++ b/predator_control/__init__.py @@ -0,0 +1,12 @@ +"""Predator Control – a PredatorSense replacement for the Acer Predator Helios 16 (PH16-71) on Linux.""" + +import os + +__version__ = "1.0.0" + +APP_NAME = "Predator Control" +RUN_DIR = os.environ.get("PREDATOR_CONTROL_RUN_DIR", "/run/predator-control") +SOCKET_PATH = RUN_DIR + "/control.sock" +STATE_PATH = RUN_DIR + "/state.json" +CONFIG_DIR = os.environ.get("PREDATOR_CONTROL_CONFIG_DIR", "/etc/predator-control") +CONFIG_PATH = CONFIG_DIR + "/config.json" diff --git a/predator_control/cli.py b/predator_control/cli.py new file mode 100644 index 0000000..a1b867c --- /dev/null +++ b/predator_control/cli.py @@ -0,0 +1,145 @@ +"""predatorctl – command line interface for Predator Control. + +Examples: + predatorctl status + predatorctl profile performance + predatorctl fans max | auto | custom 60 70 | curve + predatorctl kbd static '#ff0000' --brightness 255 + predatorctl kbd off + predatorctl lightbar wave --color '#00ffcc' --speed 7 + predatorctl battery-limit on + predatorctl open rgb (opens the main window on a given page) +""" + +import argparse +import json +import os +import subprocess +import sys + +from .client import Client, DaemonError, read_state + + +def _bool(v): + return v.lower() in ("1", "on", "true", "yes") + + +def main(argv=None): + p = argparse.ArgumentParser(prog="predatorctl", description="Predator Control CLI") + sub = p.add_subparsers(dest="cmd", required=True) + + sub.add_parser("status", help="show status") + sp = sub.add_parser("state", help="raw state as JSON") + sp.add_argument("--cached", action="store_true", help="read state.json instead of asking the daemon") + sub.add_parser("restore", help="re-apply saved settings") + + sp = sub.add_parser("profile", help="set power profile") + sp.add_argument("profile") + sp = sub.add_parser("profile-cycle", help="switch to the next profile") + + sp = sub.add_parser("fans", help="fan mode") + sp.add_argument("mode", choices=["auto", "max", "custom", "curve"]) + sp.add_argument("cpu", nargs="?", type=int) + sp.add_argument("gpu", nargs="?", type=int) + + sp = sub.add_parser("kbd", help="keyboard lighting (effect name, 'on' or 'off')") + sp.add_argument("effect") + sp.add_argument("color", nargs="?") + sp.add_argument("--brightness", "-b", type=int) + sp = sub.add_parser("kbd-brightness", help="keyboard brightness 0-255 or +/-step") + sp.add_argument("value") + sp = sub.add_parser("preset", help="load a keyboard preset") + sp.add_argument("name") + + sp = sub.add_parser("lightbar", help="Lightbar") + sp.add_argument("mode", nargs="?") + sp.add_argument("--color", "-c") + sp.add_argument("--brightness", "-b", type=int) + sp.add_argument("--speed", "-s", type=int) + sp.add_argument("--sync", choices=["on", "off"]) + + sp = sub.add_parser("battery-limit", help="80 %% charge limit") + sp.add_argument("value", choices=["on", "off"]) + + sp = sub.add_parser("open", help="open the main window") + sp.add_argument("page", nargs="?", default="home") + + a = p.parse_args(argv) + + if a.cmd == "open": + subprocess.Popen(["predator-control", "--page", a.page], start_new_session=True, + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + return 0 + if a.cmd == "state" and a.cached: + print(json.dumps(read_state())) + return 0 + + c = Client() + try: + if a.cmd == "status": + st = c.call("state") + s, b = st["sensors"], st["battery"] + lbl = st["profile_labels"].get(st["profile"], st["profile"]) + print("Profile: %s" % lbl) + print("CPU: %s °C %s %% fan %s RPM" % (s["cpu_temp"], st["cpu_load"], s["cpu_fan"])) + print("GPU: %s fan %s RPM" % ("%s °C" % s["gpu_temp"] if s["gpu_temp"] else "asleep", s["gpu_fan"])) + print("Fan mode: %s" % st["config"]["fans"]["mode"]) + print("Battery: %s %% (%s), AC: %s" % (b.get("capacity"), b.get("status"), "yes" if b["ac_online"] else "no")) + k = st["config"]["keyboard"] + print("Keyboard: %s %s brightness %s" % (k["effect"], k["color"], k["brightness"])) + for k, v in st["errors"].items(): + print("Error [%s]: %s" % (k, v)) + elif a.cmd == "state": + print(json.dumps(c.call("state"))) + elif a.cmd == "restore": + c.call("restore") + elif a.cmd == "profile": + c.call("set_profile", profile=a.profile) + elif a.cmd == "profile-cycle": + st = c.call("state") + ch = st["profile_choices"] + nxt = ch[(ch.index(st["profile"]) + 1) % len(ch)] if st["profile"] in ch else ch[0] + c.call("set_profile", profile=nxt) + print(st["profile_labels"].get(nxt, nxt)) + elif a.cmd == "fans": + args = {"mode": a.mode} + if a.cpu is not None: + args["cpu"] = a.cpu + if a.gpu is not None: + args["gpu"] = a.gpu + c.call("set_fans", **args) + elif a.cmd == "kbd": + args = {"effect": a.effect} + if a.color: + args["color"] = a.color if a.color.startswith("#") else "#" + a.color + if a.brightness is not None: + args["brightness"] = a.brightness + c.call("set_keyboard", **args) + elif a.cmd == "kbd-brightness": + cur = c.call("state")["config"]["keyboard"]["brightness"] + v = a.value + val = cur + int(v) if v[0] in "+-" else int(v) + c.call("set_keyboard", brightness=max(0, min(255, val))) + elif a.cmd == "preset": + c.call("load_preset", name=a.name) + elif a.cmd == "lightbar": + args = {"mode": a.mode} if a.mode else {} + if a.color: + args["color"] = a.color if a.color.startswith("#") else "#" + a.color + if a.brightness is not None: + args["brightness"] = a.brightness + if a.speed is not None: + args["speed"] = a.speed + if a.sync: + args["sync_keyboard"] = a.sync == "on" + c.call("set_lightbar", **args) + elif a.cmd == "battery-limit": + c.call("set_battery_limit", enabled=_bool(a.value)) + except DaemonError as e: + print("Error: %s" % e, file=sys.stderr) + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/predator_control/client.py b/predator_control/client.py new file mode 100644 index 0000000..d50d1af --- /dev/null +++ b/predator_control/client.py @@ -0,0 +1,65 @@ +"""Client for the predatord socket.""" + +import json +import socket + +from . import SOCKET_PATH, STATE_PATH + + +class DaemonError(RuntimeError): + pass + + +class Client: + def __init__(self, path=SOCKET_PATH, timeout=10): + self.path = path + self.timeout = timeout + self._sock = None + self._file = None + + def _connect(self): + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + s.settimeout(self.timeout) + try: + s.connect(self.path) + except OSError as e: + s.close() + raise DaemonError("cannot reach the predatord service (%s). " + "Check 'systemctl status predatord'." % e) from e + self._sock = s + self._file = s.makefile("rwb") + + def close(self): + if self._sock: + self._file.close() + self._sock.close() + self._sock = self._file = None + + def call(self, cmd, **args): + for attempt in (0, 1): + if self._sock is None: + self._connect() + try: + self._file.write((json.dumps({"cmd": cmd, "args": args}) + "\n").encode()) + self._file.flush() + line = self._file.readline() + if not line: + raise OSError("connection closed") + break + except OSError: + self.close() + if attempt: + raise DaemonError("lost connection to the service") + res = json.loads(line) + if not res.get("ok"): + raise DaemonError(res.get("error", "unknown error")) + return res.get("result") + + +def read_state(): + """Read the latest state snapshot (no socket needed).""" + try: + with open(STATE_PATH) as f: + return json.load(f) + except (OSError, ValueError): + return None diff --git a/predator_control/daemon.py b/predator_control/daemon.py new file mode 100644 index 0000000..a02f56c --- /dev/null +++ b/predator_control/daemon.py @@ -0,0 +1,469 @@ +"""predatord – privileged background service. + +* line-based JSON protocol over a Unix socket (root and members of the allowed group only) +* writes a state snapshot to /run/predator-control/state.json every 1.5 s + (read by the Plasma panel widget) +* restores settings at boot and after resume +* switches power profiles when the charger is plugged in / unplugged +* drives the fans along a user-defined temperature curve +""" + +import copy +import grp +import json +import os +import pwd +import signal +import socket +import socketserver +import struct +import sys +import threading +import time +import traceback + +from . import CONFIG_DIR, CONFIG_PATH, SOCKET_PATH, STATE_PATH, __version__ +from . import hardware as hw +from .keyboard import EFFECTS, NUM_CELLS, Keyboard + +DEFAULT_CONFIG = { + "allowed_group": "wheel", + "profile": {"ac": "balanced", "battery": "quiet", "auto_switch": True}, + "fans": { + "mode": "auto", # auto | max | custom | curve + "cpu": 50, "gpu": 50, + "curve": { + "cpu": [[45, 0], [60, 35], [72, 55], [82, 75], [90, 100]], + "gpu": [[45, 0], [60, 35], [70, 55], [78, 75], [85, 100]], + }, + }, + "keyboard": { + "effect": "static", "color": "#00c8ff", "brightness": 200, "effect_id": 0, + "frame": "", # 384 bytes as hex (perkey) + }, + "lightbar": { + "mode": "static", "color": "#00c8ff", "brightness": 200, "speed": 5, + "direction": 1, "sync_keyboard": True, + }, + "battery": {"limit": None}, # None = leave the firmware state alone + "keyboard_presets": {}, +} + + +def hex_to_rgb(s): + s = s.lstrip("#") + return tuple(int(s[i:i + 2], 16) for i in (0, 2, 4)) + + +def merge(base, upd): + for k, v in upd.items(): + if isinstance(v, dict) and isinstance(base.get(k), dict): + merge(base[k], v) + else: + base[k] = v + return base + + +def interp(points, x): + pts = sorted(points) + if not pts: + return 0 + if x <= pts[0][0]: + return pts[0][1] + for (x0, y0), (x1, y1) in zip(pts, pts[1:]): + if x <= x1: + return y0 + (y1 - y0) * (x - x0) / max(1e-6, x1 - x0) + return pts[-1][1] + + +def log(*a): + print(*a, flush=True) + + +class Daemon: + def __init__(self): + self.lock = threading.RLock() + self.kbd = Keyboard() + self.cpuload = CpuLoadProxy() + self.config = self._load_config() + self.errors = {} + self.last_ac = None + self.curve_applied = None + self.kbd_present = False + self.state = {} + self.battery_limit = None + self._ticks = 0 + + # ---------------------------------------------------------- Configuration + def _load_config(self): + cfg = copy.deepcopy(DEFAULT_CONFIG) + try: + with open(CONFIG_PATH) as f: + merge(cfg, json.load(f)) + except FileNotFoundError: + pass + except Exception as e: + log("Invalid configuration, using defaults:", e) + return cfg + + def save_config(self): + os.makedirs(CONFIG_DIR, exist_ok=True) + tmp = CONFIG_PATH + ".tmp" + with open(tmp, "w") as f: + json.dump(self.config, f, indent=2) + os.replace(tmp, CONFIG_PATH) + + # ---------------------------------------------------------- Applying + def _try(self, key, fn, *a, **kw): + try: + r = fn(*a, **kw) + self.errors.pop(key, None) + return r + except Exception as e: + if self.errors.get(key) != str(e): + log("[%s] %s" % (key, e)) + self.errors[key] = str(e) + return None + + def apply_keyboard(self, cfg=None): + k = cfg or self.config["keyboard"] + frame = bytes.fromhex(k.get("frame") or "") if k["effect"] == "perkey" else None + self._try("keyboard", self.kbd.apply, k["effect"], hex_to_rgb(k["color"]), + k["brightness"], frame, int(k.get("effect_id") or 0)) + if self.config["lightbar"].get("sync_keyboard") and cfg is None: + self.apply_lightbar() + + def lightbar_effective(self): + lb = dict(self.config["lightbar"]) + if lb.get("sync_keyboard"): + k = self.config["keyboard"] + lb["brightness"] = k["brightness"] + if k["effect"] == "off": + lb["mode"] = "off" + elif k["effect"] in ("rainbow", "neon"): + lb["mode"] = "rainbow" if k["effect"] == "rainbow" else "neon" + elif k["effect"] == "breathing": + lb["mode"], lb["color"] = "breathing", k["color"] + elif k["effect"] == "perkey": + pass # keep the lightbar's own setting + else: + lb["mode"], lb["color"] = "static", k["color"] + return lb + + def apply_lightbar(self): + lb = self.lightbar_effective() + self._try("lightbar", hw.set_lightbar, lb["mode"], hex_to_rgb(lb["color"]), + lb["brightness"], lb["speed"], lb["direction"]) + + def apply_fans(self): + f = self.config["fans"] + self.curve_applied = None + if f["mode"] == "curve": + self.fan_curve_tick(force=True) + else: + self._try("fans", hw.set_fans, f["mode"], f["cpu"], f["gpu"]) + + def apply_profile_for_power(self, ac): + p = self.config["profile"] + target = p["ac"] if ac else p["battery"] + if target in hw.profile_choices(): + self._try("profile", hw.set_profile, target) + + def restore(self): + log("Restoring settings") + bat = hw.battery() + if self.config["profile"].get("auto_switch"): + self.apply_profile_for_power(bat.get("ac_online", True)) + self.apply_fans() + if self.kbd.available(): + self.apply_keyboard() + else: + self.apply_lightbar() + lim = self.config["battery"].get("limit") + if lim is not None and hw.wmi_available(hw.GUID_BATTERY): + self._try("battery", hw.set_battery_limit, lim) + self.refresh_battery_limit() + + def refresh_battery_limit(self): + if hw.wmi_available(hw.GUID_BATTERY): + try: + self.battery_limit = hw.get_battery_limit() + except Exception: + self.battery_limit = None + + # ---------------------------------------------------------- Background + def fan_curve_tick(self, force=False): + f = self.config["fans"] + if f["mode"] != "curve": + return + s = hw.sensors() + cpu_t = s.get("cpu_temp") or 0 + gpu_t = s.get("gpu_temp") or cpu_t + cpu = int(round(interp(f["curve"]["cpu"], cpu_t) / 5) * 5) + gpu = int(round(interp(f["curve"]["gpu"], gpu_t) / 5) * 5) + if s.get("dgpu_active") is False: + gpu = min(gpu, cpu) + target = (cpu, gpu) + prev = self.curve_applied + # hysteresis: ramp up immediately, ramp down only after a >=10 % drop + if not force and prev is not None: + if all(t <= p and p - t < 10 for t, p in zip(target, prev)) or target == prev: + return + self._try("fans", hw.set_fans, "custom", cpu, gpu) + self.curve_applied = target + + def build_state(self): + s = hw.sensors() + bat = hw.battery() + st = { + "version": __version__, + "time": time.time(), + "sensors": s, + "cpu_load": self.cpuload.value, + "cpu_freq": hw.cpu_freq_mhz(), + "memory": hw.mem_usage(), + "battery": bat, + "profile": hw.get_profile(), + "profile_choices": hw.profile_choices(), + "profile_labels": hw.PROFILE_LABELS, + "config": self.config, + "lightbar_effective": self.lightbar_effective(), + "fan_curve_applied": self.curve_applied, + "battery_limit": self.battery_limit, + "available": { + "keyboard": self.kbd_present, + "wmi": hw.wmi_available(hw.GUID_GAMING), + "battery_wmi": hw.wmi_available(hw.GUID_BATTERY), + }, + "errors": dict(self.errors), + "keyboard_effects": {k: [v[2], v[1]] for k, v in EFFECTS.items()}, # [label, uses colour] + "lightbar_modes": {k: v[1] for k, v in hw.LIGHTBAR_MODES.items()}, + } + return st + + def loop(self): + while True: + try: + self.cpuload.sample() + with self.lock: + present = self.kbd.available() + if present and not self.kbd_present: + # keyboard (re)appeared, e.g. after resume + if self.kbd_present is not None: + time.sleep(0.5) + self.apply_keyboard() + self.kbd_present = present + ac = hw.battery().get("ac_online", True) + if self.last_ac is not None and ac != self.last_ac: + log("Power source changed:", "AC" if ac else "battery") + if self.config["profile"].get("auto_switch"): + self.apply_profile_for_power(ac) + self.last_ac = ac + self.fan_curve_tick() + self._ticks += 1 + if self._ticks % 40 == 0: + self.refresh_battery_limit() + self.state = self.build_state() + write_state(self.state) + except Exception: + traceback.print_exc() + time.sleep(1.5) + + # ---------------------------------------------------------- Commands + def handle(self, req): + cmd = req.get("cmd") + a = req.get("args", {}) or {} + with self.lock: + if cmd == "ping": + return {"version": __version__} + if cmd == "state": + self.state = self.build_state() + return self.state + if cmd == "restore": + self.restore() + return {} + if cmd == "set_profile": + hw.set_profile(a["profile"]) + # a manual choice becomes the profile for the current power source + ac = hw.battery().get("ac_online", True) + self.config["profile"]["ac" if ac else "battery"] = a["profile"] + self.save_config() + return {} + if cmd == "set_profile_policy": + merge(self.config["profile"], {k: a[k] for k in ("ac", "battery", "auto_switch") if k in a}) + self.save_config() + if self.config["profile"]["auto_switch"]: + self.apply_profile_for_power(hw.battery().get("ac_online", True)) + return {} + if cmd == "set_fans": + merge(self.config["fans"], {k: a[k] for k in ("mode", "cpu", "gpu", "curve") if k in a}) + self.save_config() + self.apply_fans() + return self._result("fans") + if cmd == "set_keyboard": + k = self.config["keyboard"] + if a.get("effect") == "on": + a["effect"] = k.get("last_effect") or "static" + if a.get("effect") == "off" and k["effect"] != "off": + k["last_effect"] = k["effect"] + for key in ("effect", "color", "brightness", "effect_id", "frame"): + if key in a: + k[key] = a[key] + if k["effect"] not in EFFECTS: + raise ValueError("unknown effect") + if a.get("frame") is not None and len(bytes.fromhex(a["frame"])) != NUM_CELLS * 3: + raise ValueError("frame must be %d bytes" % (NUM_CELLS * 3)) + if a.get("save", True): + self.save_config() + self.apply_keyboard() + return self._result("keyboard") + if cmd == "preview_keyboard": + # preview without saving (e.g. while painting in the RGB studio) + k = dict(self.config["keyboard"]) + k.update({x: a[x] for x in ("effect", "color", "brightness", "frame", "effect_id") if x in a}) + self.apply_keyboard(k) + return self._result("keyboard") + if cmd == "set_lightbar": + for key in ("mode", "color", "brightness", "speed", "direction", "sync_keyboard"): + if key in a: + self.config["lightbar"][key] = a[key] + if self.config["lightbar"]["mode"] not in hw.LIGHTBAR_MODES: + raise ValueError("unknown lightbar mode") + self.save_config() + self.apply_lightbar() + return self._result("lightbar") + if cmd == "save_preset": + self.config["keyboard_presets"][a["name"]] = dict(self.config["keyboard"]) + self.save_config() + return {} + if cmd == "delete_preset": + self.config["keyboard_presets"].pop(a["name"], None) + self.save_config() + return {} + if cmd == "load_preset": + self.config["keyboard"] = dict(self.config["keyboard_presets"][a["name"]]) + self.save_config() + self.apply_keyboard() + return self._result("keyboard") + if cmd == "set_battery_limit": + hw.set_battery_limit(bool(a["enabled"])) + self.config["battery"]["limit"] = bool(a["enabled"]) + self.save_config() + self.refresh_battery_limit() + return {} + if cmd == "set_battery_calibration": + hw.set_battery_calibration(bool(a["enabled"])) + return {} + if cmd == "get_firmware": + out = {} + for name, (getter, _s, label) in hw.FIRMWARE_OPTIONS.items(): + try: + out[name] = {"label": label, "value": getter()} + except Exception as e: + out[name] = {"label": label, "value": None, "error": str(e)} + for name, getter in (("battery_limit", hw.get_battery_limit), + ("battery_calibration", hw.get_battery_calibration)): + try: + out[name] = {"value": getter()} + except Exception as e: + out[name] = {"value": None, "error": str(e)} + return out + if cmd == "set_firmware": + name = a["name"] + if name not in hw.FIRMWARE_OPTIONS: + raise ValueError("unknown option") + hw.FIRMWARE_OPTIONS[name][1](a["value"]) + return {} + raise ValueError("unknown command: %s" % cmd) + + def _result(self, key): + if key in self.errors: + raise RuntimeError(self.errors[key]) + return {} + + +class CpuLoadProxy: + def __init__(self): + self._c = hw.CpuLoad() + self.value = None + + def sample(self): + v = self._c.sample() + if v is not None: + self.value = v + + +def write_state(state): + tmp = STATE_PATH + ".tmp" + with open(tmp, "w") as f: + json.dump(state, f) + os.chmod(tmp, 0o644) + os.replace(tmp, STATE_PATH) + + +def peer_allowed(sock, group): + creds = sock.getsockopt(socket.SOL_SOCKET, socket.SO_PEERCRED, struct.calcsize("3i")) + _pid, uid, gid = struct.unpack("3i", creds) + if uid == 0: + return True + try: + g = grp.getgrnam(group) + except KeyError: + return False + if gid == g.gr_gid: + return True + try: + user = pwd.getpwuid(uid).pw_name + except KeyError: + return False + return user in g.gr_mem or pwd.getpwuid(uid).pw_gid == g.gr_gid + + +def make_handler(daemon): + class Handler(socketserver.StreamRequestHandler): + def handle(self): + if not peer_allowed(self.request, daemon.config.get("allowed_group", "wheel")): + self.wfile.write(b'{"ok": false, "error": "permission denied (user not in allowed group)"}\n') + return + for line in self.rfile: + try: + req = json.loads(line) + res = {"ok": True, "result": daemon.handle(req)} + except Exception as e: + res = {"ok": False, "error": str(e)} + self.wfile.write((json.dumps(res) + "\n").encode()) + self.wfile.flush() + return Handler + + +class Server(socketserver.ThreadingMixIn, socketserver.UnixStreamServer): + daemon_threads = True + + +def main(): + if os.geteuid() != 0: + sys.exit("predatord must run as root") + os.makedirs(os.path.dirname(SOCKET_PATH), exist_ok=True) + os.chmod(os.path.dirname(SOCKET_PATH), 0o755) + try: + os.unlink(SOCKET_PATH) + except FileNotFoundError: + pass + + d = Daemon() + d.kbd_present = None + log("predatord %s started" % __version__) + d.restore() + d.kbd_present = d.kbd.available() + + server = Server(SOCKET_PATH, make_handler(d)) + os.chmod(SOCKET_PATH, 0o666) # access is checked via SO_PEERCRED + + signal.signal(signal.SIGTERM, lambda *_: (server.server_close(), sys.exit(0))) + signal.signal(signal.SIGUSR1, lambda *_: threading.Thread(target=lambda: (d.lock.acquire(), d.restore(), d.lock.release())).start()) + threading.Thread(target=d.loop, daemon=True).start() + server.serve_forever() + + +if __name__ == "__main__": + main() diff --git a/predator_control/gui/__init__.py b/predator_control/gui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/predator_control/gui/app.py b/predator_control/gui/app.py new file mode 100644 index 0000000..522964b --- /dev/null +++ b/predator_control/gui/app.py @@ -0,0 +1,887 @@ +"""Predator Control main window.""" + +import argparse +import os +import sys +import threading + +from PySide6.QtCore import QObject, Qt, QTimer, Signal +from PySide6.QtGui import QColor, QIcon +from PySide6.QtNetwork import QLocalServer, QLocalSocket +from PySide6.QtWidgets import (QApplication, QButtonGroup, QCheckBox, QComboBox, QFrame, + QGridLayout, QHBoxLayout, QInputDialog, QLabel, QListWidget, + QListWidgetItem, QMainWindow, QMessageBox, QPushButton, + QScrollArea, QSlider, QSpinBox, QStackedWidget, QTabWidget, + QVBoxLayout, QWidget) + +from .. import APP_NAME, __version__, layout +from ..client import Client, DaemonError, read_state +from . import theme +from .widgets import Bar, Card, ColorRow, CurveEditor, Gauge, KeyboardPainter + +PAGES = [ + ("home", "Dashboard"), + ("performance", "Performance"), + ("fans", "Fans"), + ("rgb", "RGB Studio"), + ("battery", "Battery"), + ("system", "System"), +] + +PROFILE_INFO = { + "low-power": ("Eco", "Maximum battery life, lowest power limits."), + "quiet": ("Quiet", "Low noise for office work and video."), + "balanced": ("Balanced", "Everyday mix of performance and acoustics."), + "balanced-performance": ("Performance", "Higher power limits for gaming."), + "performance": ("Turbo", "Maximum CPU/GPU power, fans run loud."), +} + + +# ------------------------------------------------------------------ backend + +class Backend(QObject): + """Runs daemon commands in worker threads so the UI never blocks.""" + + finished = Signal(str, object, str) # command, result, error + + def run(self, cmd, **args): + def work(): + c = Client() + try: + res, err = c.call(cmd, **args), "" + except (DaemonError, OSError, ValueError) as e: + res, err = None, str(e) + finally: + c.close() + self.finished.emit(cmd, res, err) + threading.Thread(target=work, daemon=True).start() + + def call(self, cmd, **args): + c = Client() + try: + return c.call(cmd, **args) + finally: + c.close() + + +def _title(text, sub=None): + w = QWidget() + lay = QVBoxLayout(w) + lay.setContentsMargins(0, 0, 0, 8) + lay.setSpacing(2) + t = QLabel(text) + t.setObjectName("pageTitle") + lay.addWidget(t) + if sub: + s = QLabel(sub) + s.setObjectName("pageSub") + s.setWordWrap(True) + lay.addWidget(s) + return w + + +def _slider(lo, hi, val=0): + s = QSlider(Qt.Horizontal) + s.setRange(lo, hi) + s.setValue(val) + return s + + +def _muted(text): + l = QLabel(text) + l.setObjectName("muted") + l.setWordWrap(True) + return l + + +class Page(QScrollArea): + def __init__(self, win): + super().__init__() + self.win = win + self.setWidgetResizable(True) + inner = QWidget() + inner.setObjectName("page") + self.lay = QVBoxLayout(inner) + self.lay.setContentsMargins(32, 28, 32, 28) + self.lay.setSpacing(16) + self.setWidget(inner) + + def update_state(self, st): + pass + + +# ------------------------------------------------------------------ pages + +class HomePage(Page): + def __init__(self, win): + super().__init__(win) + self.lay.addWidget(_title("Dashboard", "Live system monitoring")) + grid = QGridLayout() + grid.setSpacing(16) + self.g_cpu = Gauge("CPU", "°C", 105, warn=90) + self.g_gpu = Gauge("GPU", "°C", 100, warn=85) + self.g_cfan = Gauge("CPU fan", "RPM", 7000) + self.g_gfan = Gauge("GPU fan", "RPM", 7000) + for i, g in enumerate((self.g_cpu, self.g_gpu, self.g_cfan, self.g_gfan)): + c = Card() + c.body.addWidget(g) + c.setMinimumHeight(210) + grid.addWidget(c, 0, i) + self.lay.addLayout(grid) + + row = QHBoxLayout() + row.setSpacing(16) + load = Card("System") + self.b_load = Bar("CPU load") + self.b_freq = Bar("CPU clock (avg)") + self.b_mem = Bar("Memory") + self.b_sys = Bar("Chassis temperature") + for b in (self.b_load, self.b_freq, self.b_mem, self.b_sys): + load.body.addWidget(b) + row.addWidget(load, 3) + + quick = Card("Mode") + self.l_profile = QLabel("–") + self.l_profile.setObjectName("big") + quick.body.addWidget(self.l_profile) + self.l_fans = _muted("") + quick.body.addWidget(self.l_fans) + self.l_bat = _muted("") + quick.body.addWidget(self.l_bat) + b = QPushButton("Next profile") + b.setObjectName("primary") + b.clicked.connect(self._cycle) + quick.body.addWidget(b) + quick.body.addStretch(1) + row.addWidget(quick, 2) + self.lay.addLayout(row) + self.lay.addStretch(1) + + def _cycle(self): + st = self.win.state + if not st: + return + ch = st["profile_choices"] + nxt = ch[(ch.index(st["profile"]) + 1) % len(ch)] if st["profile"] in ch else ch[0] + self.win.backend.run("set_profile", profile=nxt) + + def update_state(self, st): + s = st["sensors"] + self.g_cpu.set_value(s.get("cpu_temp")) + self.g_gpu.set_value(s.get("gpu_temp"), "" if s.get("gpu_temp") else "dGPU asleep") + self.g_cfan.set_value(s.get("cpu_fan")) + self.g_gfan.set_value(s.get("gpu_fan")) + load = st.get("cpu_load") or 0 + self.b_load.set_value(load / 100, "%.0f %%" % load) + f = st.get("cpu_freq") or 0 + self.b_freq.set_value(f / 5500, "%.2f GHz" % (f / 1000)) + m = st.get("memory") or {} + self.b_mem.set_value((m.get("percent") or 0) / 100, "%s / %s GB" % (m.get("used_gb"), m.get("total_gb"))) + t = s.get("sys_temp") or 0 + self.b_sys.set_value(t / 100, "%s °C" % (t or "–")) + self.l_profile.setText(PROFILE_INFO.get(st["profile"], (st["profile"],))[0]) + self.l_fans.setText("Fans: %s" % st["config"]["fans"]["mode"].capitalize()) + b = st["battery"] + self.l_bat.setText("Battery %s %% · %s" % (b.get("capacity"), "AC" if b.get("ac_online") else "on battery")) + + +class PerformancePage(Page): + def __init__(self, win): + super().__init__(win) + self.lay.addWidget(_title("Performance", "Choose an operating mode. Uses the firmware's ACPI platform profiles.")) + card = Card("Operating mode") + row = QHBoxLayout() + row.setSpacing(12) + self.group = QButtonGroup(self) + self.group.setExclusive(True) + self.buttons = {} + for key, (name, desc) in PROFILE_INFO.items(): + b = QPushButton(name) + b.setObjectName("profileTurbo" if key == "performance" else "profile") + b.setCheckable(True) + b.setToolTip(desc) + b.clicked.connect(lambda _=False, k=key: win.backend.run("set_profile", profile=k)) + self.group.addButton(b) + self.buttons[key] = b + row.addWidget(b) + card.body.addLayout(row) + self.desc = _muted("") + card.body.addWidget(self.desc) + self.lay.addWidget(card) + + pol = Card("Automatic switching") + self.auto = QCheckBox("Switch the profile automatically when plugging in / unplugging the charger") + self.auto.toggled.connect(self._policy) + pol.body.addWidget(self.auto) + g = QGridLayout() + self.ac = QComboBox() + self.bat = QComboBox() + for k, (name, _d) in PROFILE_INFO.items(): + self.ac.addItem(name, k) + self.bat.addItem(name, k) + self.ac.activated.connect(self._policy) + self.bat.activated.connect(self._policy) + g.addWidget(QLabel("On AC power"), 0, 0) + g.addWidget(self.ac, 0, 1) + g.addWidget(QLabel("On battery"), 1, 0) + g.addWidget(self.bat, 1, 1) + g.setColumnStretch(2, 1) + pol.body.addLayout(g) + pol.body.addWidget(_muted("Choosing a mode above also stores it for the current power source. " + "Tip: the Predator/Turbo key cycles the firmware profiles as well.")) + self.lay.addWidget(pol) + self.lay.addStretch(1) + + def _policy(self, *_): + self.win.backend.run("set_profile_policy", auto_switch=self.auto.isChecked(), + ac=self.ac.currentData(), battery=self.bat.currentData()) + + def update_state(self, st): + for k, b in self.buttons.items(): + b.setEnabled(k in st["profile_choices"]) + b.setChecked(k == st["profile"]) + self.desc.setText(PROFILE_INFO.get(st["profile"], ("", ""))[1]) + p = st["config"]["profile"] + for w, v in ((self.auto, p["auto_switch"]),): + w.blockSignals(True) + w.setChecked(v) + w.blockSignals(False) + for combo, key in ((self.ac, "ac"), (self.bat, "battery")): + if not combo.view().isVisible(): + combo.blockSignals(True) + combo.setCurrentIndex(max(0, combo.findData(p[key]))) + combo.blockSignals(False) + + +class FansPage(Page): + MODES = [("auto", "Auto", "Firmware controls the fans."), + ("max", "Max", "Both fans at full speed (cooler boost)."), + ("custom", "Manual", "Fixed speed for each fan."), + ("curve", "Curve", "Speed follows your temperature curve.")] + + def __init__(self, win): + super().__init__(win) + self.lay.addWidget(_title("Fans", "Fan control via the Acer gaming WMI interface")) + top = Card("Fan mode") + row = QHBoxLayout() + self.group = QButtonGroup(self) + self.mode_btns = {} + for key, name, desc in self.MODES: + b = QPushButton(name) + b.setObjectName("profile") + b.setCheckable(True) + b.setToolTip(desc) + b.clicked.connect(lambda _=False, k=key: self._set_mode(k)) + self.group.addButton(b) + self.mode_btns[key] = b + row.addWidget(b) + top.body.addLayout(row) + self.rpm = _muted("") + top.body.addWidget(self.rpm) + self.lay.addWidget(top) + + self.manual = Card("Manual speed") + g = QGridLayout() + self.s_cpu = _slider(0, 100, 50) + self.s_gpu = _slider(0, 100, 50) + self.l_cpu = QLabel() + self.l_gpu = QLabel() + for i, (name, s, l) in enumerate((("CPU fan", self.s_cpu, self.l_cpu), ("GPU fan", self.s_gpu, self.l_gpu))): + s.setSingleStep(5) + s.setPageStep(10) + s.valueChanged.connect(lambda v, l=l: l.setText("%d %%" % v if v else "auto")) + s.sliderReleased.connect(self._apply_manual) + g.addWidget(QLabel(name), i, 0) + g.addWidget(s, i, 1) + g.addWidget(l, i, 2) + g.setColumnStretch(1, 1) + self.manual.body.addLayout(g) + self.manual.body.addWidget(_muted("0 % leaves that fan under firmware control.")) + self.lay.addWidget(self.manual) + + self.curve = Card("Fan curves") + self.c_cpu = CurveEditor("CPU (package temperature)") + self.c_gpu = CurveEditor("GPU (dGPU temperature)") + self.c_cpu.changed.connect(lambda pts: self._apply_curve("cpu", pts)) + self.c_gpu.changed.connect(lambda pts: self._apply_curve("gpu", pts)) + h = QHBoxLayout() + h.addWidget(self.c_cpu) + h.addWidget(self.c_gpu) + self.curve.body.addLayout(h) + self.curve_info = _muted("") + self.curve.body.addWidget(self.curve_info) + self.curve.body.addWidget(_muted("Drag the points. The daemon evaluates the curve every 1.5 s, " + "ramps up immediately and ramps down with 10 % hysteresis.")) + self.lay.addWidget(self.curve) + self.lay.addStretch(1) + + def _set_mode(self, mode): + args = {"mode": mode} + if mode == "custom": + args.update(cpu=self.s_cpu.value(), gpu=self.s_gpu.value()) + self.win.backend.run("set_fans", **args) + + def _apply_manual(self): + self.win.backend.run("set_fans", mode="custom", cpu=self.s_cpu.value(), gpu=self.s_gpu.value()) + + def _apply_curve(self, which, pts): + curve = dict(self.win.state["config"]["fans"]["curve"]) if self.win.state else {} + curve[which] = pts + self.win.backend.run("set_fans", curve=curve, mode="curve") + + def update_state(self, st): + f = st["config"]["fans"] + for k, b in self.mode_btns.items(): + b.setChecked(k == f["mode"]) + s = st["sensors"] + self.rpm.setText("CPU fan %s RPM · GPU fan %s RPM · CPU %s °C · GPU %s" % ( + s.get("cpu_fan"), s.get("gpu_fan"), s.get("cpu_temp"), + ("%s °C" % s["gpu_temp"]) if s.get("gpu_temp") else "asleep")) + self.manual.setVisible(f["mode"] == "custom") + self.curve.setVisible(f["mode"] == "curve") + for sl, key in ((self.s_cpu, "cpu"), (self.s_gpu, "gpu")): + if not sl.isSliderDown(): + sl.blockSignals(True) + sl.setValue(f[key]) + sl.blockSignals(False) + self.l_cpu.setText("%d %%" % self.s_cpu.value() if self.s_cpu.value() else "auto") + self.l_gpu.setText("%d %%" % self.s_gpu.value() if self.s_gpu.value() else "auto") + self.c_cpu.set_points(f["curve"]["cpu"]) + self.c_gpu.set_points(f["curve"]["gpu"]) + self.c_cpu.set_current(s.get("cpu_temp")) + self.c_gpu.set_current(s.get("gpu_temp")) + ap = st.get("fan_curve_applied") + self.curve_info.setText("Current target: CPU %s %% · GPU %s %%" % tuple(ap) if ap else "") + + +class RgbPage(Page): + def __init__(self, win): + super().__init__(win) + self.lay.addWidget(_title("RGB Studio", "Keyboard effects, per-key painting and the rear lightbar")) + tabs = QTabWidget() + tabs.addTab(self._effects_tab(), "Keyboard effects") + tabs.addTab(self._perkey_tab(), "Per-key editor") + tabs.addTab(self._lightbar_tab(), "Lightbar") + self.tabs = tabs + self.lay.addWidget(tabs) + self.lay.addStretch(1) + self._preview_timer = QTimer(self) + self._preview_timer.setSingleShot(True) + self._preview_timer.setInterval(120) + self._preview_timer.timeout.connect(self._send_preview) + self._loaded_frame = None + + # ---- effects + def _effects_tab(self): + w = QWidget() + lay = QHBoxLayout(w) + lay.setContentsMargins(0, 12, 0, 0) + lay.setSpacing(16) + left = Card("Effect") + self.effects = QListWidget() + self.effects.setMinimumWidth(220) + self.effects.itemClicked.connect(self._effect_clicked) + left.body.addWidget(self.effects) + lay.addWidget(left, 1) + + right = Card("Settings") + right.body.addWidget(QLabel("Colour")) + self.color = ColorRow() + self.color.colorChosen.connect(lambda c: self.win.backend.run("set_keyboard", color=c.name())) + right.body.addWidget(self.color) + right.body.addSpacing(8) + right.body.addWidget(QLabel("Brightness")) + self.bright = _slider(0, 255, 200) + self.bright.sliderReleased.connect(lambda: self.win.backend.run("set_keyboard", brightness=self.bright.value())) + right.body.addWidget(self.bright) + right.body.addSpacing(8) + h = QHBoxLayout() + h.addWidget(QLabel("Effect variant (raw ID, 0 = default)")) + self.variant = QSpinBox() + self.variant.setRange(0, 255) + self.variant.setDisplayIntegerBase(16) + self.variant.setPrefix("0x") + self.variant.editingFinished.connect(lambda: self.win.backend.run("set_keyboard", effect_id=self.variant.value())) + h.addWidget(self.variant) + h.addStretch(1) + right.body.addLayout(h) + right.body.addWidget(_muted("Many effects have hidden variants with other speeds or directions " + "(e.g. 0x07 for ripple, 0x14 for explosion).")) + right.body.addSpacing(8) + right.body.addWidget(QLabel("Presets")) + pr = QHBoxLayout() + self.presets = QComboBox() + self.presets.setMinimumWidth(180) + pr.addWidget(self.presets, 1) + for text, fn in (("Load", self._load_preset), ("Save as…", self._save_preset), ("Delete", self._delete_preset)): + b = QPushButton(text) + b.clicked.connect(fn) + pr.addWidget(b) + right.body.addLayout(pr) + right.body.addStretch(1) + lay.addWidget(right, 2) + return w + + def _effect_clicked(self, item): + self.win.backend.run("set_keyboard", effect=item.data(Qt.UserRole), effect_id=0) + + def _save_preset(self): + name, ok = QInputDialog.getText(self, "Save preset", "Name:") + if ok and name.strip(): + self.win.backend.run("save_preset", name=name.strip()) + + def _load_preset(self): + if self.presets.currentText(): + self.win.backend.run("load_preset", name=self.presets.currentText()) + + def _delete_preset(self): + if self.presets.currentText(): + self.win.backend.run("delete_preset", name=self.presets.currentText()) + + # ---- per key + def _perkey_tab(self): + w = QWidget() + lay = QVBoxLayout(w) + lay.setContentsMargins(0, 12, 0, 0) + lay.setSpacing(12) + card = Card() + tools = QHBoxLayout() + tools.addWidget(QLabel("Brush")) + self.brush = ColorRow() + self.brush.colorChosen.connect(lambda c: setattr(self.painter, "brush", QColor(c))) + tools.addWidget(self.brush, 1) + tools.addWidget(QLabel("Layout")) + self.layout_combo = QComboBox() + for k, v in layout.VARIANTS.items(): + self.layout_combo.addItem(v, k) + tools.addWidget(self.layout_combo) + card.body.addLayout(tools) + self.painter = KeyboardPainter() + self.painter.brush = QColor(self.brush.current) + self.layout_combo.setCurrentIndex(max(0, self.layout_combo.findData(self.painter.variant))) + self.layout_combo.currentIndexChanged.connect(lambda: self.painter.set_variant(self.layout_combo.currentData())) + self.painter.painted.connect(self._painted) + self.painter.picked.connect(lambda c: (self.brush.set_color(c), setattr(self.painter, "brush", QColor(c)))) + card.body.addWidget(self.painter) + card.body.addWidget(_muted("Left click / drag paints · right click picks a key's colour · " + "changes are previewed live on the keyboard")) + g = QHBoxLayout() + g.addWidget(QLabel("Fill:")) + b = QPushButton("All") + b.clicked.connect(lambda: self.painter.fill(range(128), self.painter.brush)) + g.addWidget(b) + for name, cells in layout.GROUPS.items(): + b = QPushButton(name) + b.clicked.connect(lambda _=False, c=cells: self.painter.fill(c, self.painter.brush)) + g.addWidget(b) + b = QPushButton("Clear") + b.clicked.connect(lambda: self.painter.fill(range(128), QColor(0, 0, 0))) + g.addWidget(b) + g.addStretch(1) + card.body.addLayout(g) + act = QHBoxLayout() + act.addStretch(1) + self.live = QCheckBox("Live preview") + self.live.setChecked(True) + act.addWidget(self.live) + b = QPushButton("Discard") + b.clicked.connect(self._discard) + act.addWidget(b) + b = QPushButton("Apply && save") + b.setObjectName("primary") + b.clicked.connect(self._save_frame) + act.addWidget(b) + card.body.addLayout(act) + lay.addWidget(card) + return w + + def _painted(self): + if self.live.isChecked(): + self._preview_timer.start() + + def _send_preview(self): + self.win.backend.run("preview_keyboard", effect="perkey", frame=self.painter.frame_hex()) + + def _save_frame(self): + self.win.backend.run("set_keyboard", effect="perkey", frame=self.painter.frame_hex()) + + def _discard(self): + self._loaded_frame = None + self.win.backend.run("restore") + + # ---- lightbar + def _lightbar_tab(self): + w = QWidget() + lay = QVBoxLayout(w) + lay.setContentsMargins(0, 12, 0, 0) + card = Card("Rear lightbar") + self.lb_sync = QCheckBox("Follow the keyboard (colour, brightness and effect)") + self.lb_sync.toggled.connect(lambda v: self.win.backend.run("set_lightbar", sync_keyboard=v)) + card.body.addWidget(self.lb_sync) + g = QGridLayout() + g.setVerticalSpacing(12) + self.lb_mode = QComboBox() + self.lb_mode.activated.connect(lambda: self.win.backend.run("set_lightbar", mode=self.lb_mode.currentData())) + g.addWidget(QLabel("Effect"), 0, 0) + g.addWidget(self.lb_mode, 0, 1) + self.lb_color = ColorRow() + self.lb_color.colorChosen.connect(lambda c: self.win.backend.run("set_lightbar", color=c.name())) + g.addWidget(QLabel("Colour"), 1, 0) + g.addWidget(self.lb_color, 1, 1) + self.lb_bright = _slider(0, 255, 200) + self.lb_bright.sliderReleased.connect(lambda: self.win.backend.run("set_lightbar", brightness=self.lb_bright.value())) + g.addWidget(QLabel("Brightness"), 2, 0) + g.addWidget(self.lb_bright, 2, 1) + self.lb_speed = _slider(1, 10, 5) + self.lb_speed.sliderReleased.connect(lambda: self.win.backend.run("set_lightbar", speed=self.lb_speed.value())) + g.addWidget(QLabel("Speed"), 3, 0) + g.addWidget(self.lb_speed, 3, 1) + g.setColumnStretch(1, 1) + self.lb_controls = QWidget() + self.lb_controls.setLayout(g) + card.body.addWidget(self.lb_controls) + lay.addWidget(card) + lay.addStretch(1) + return w + + def update_state(self, st): + k = st["config"]["keyboard"] + effects = st.get("keyboard_effects", {}) + if self.effects.count() != len(effects): + self.effects.clear() + for key, (label, _uses_color) in effects.items(): + it = QListWidgetItem(label) + it.setData(Qt.UserRole, key) + self.effects.addItem(it) + for i in range(self.effects.count()): + it = self.effects.item(i) + if it.data(Qt.UserRole) == k["effect"] and not it.isSelected(): + self.effects.setCurrentItem(it) + self.color.set_color(QColor(k["color"])) + if not self.bright.isSliderDown(): + self.bright.setValue(k["brightness"]) + if not self.variant.hasFocus(): + self.variant.setValue(int(k.get("effect_id") or 0)) + names = sorted(st["config"].get("keyboard_presets", {})) + if names != [self.presets.itemText(i) for i in range(self.presets.count())]: + self.presets.clear() + self.presets.addItems(names) + if self._loaded_frame != k.get("frame"): + self._loaded_frame = k.get("frame") + self.painter.load_frame(k.get("frame")) + + lb = st["config"]["lightbar"] + modes = st.get("lightbar_modes", {}) + if self.lb_mode.count() != len(modes): + self.lb_mode.clear() + for key, label in modes.items(): + self.lb_mode.addItem(label, key) + if not self.lb_mode.view().isVisible(): + self.lb_mode.setCurrentIndex(max(0, self.lb_mode.findData(lb["mode"]))) + self.lb_sync.blockSignals(True) + self.lb_sync.setChecked(bool(lb.get("sync_keyboard"))) + self.lb_sync.blockSignals(False) + self.lb_controls.setEnabled(not lb.get("sync_keyboard")) + self.lb_color.set_color(QColor(lb["color"])) + if not self.lb_bright.isSliderDown(): + self.lb_bright.setValue(lb["brightness"]) + if not self.lb_speed.isSliderDown(): + self.lb_speed.setValue(lb["speed"]) + + +class BatteryPage(Page): + def __init__(self, win): + super().__init__(win) + self.lay.addWidget(_title("Battery", "Battery status and health features")) + row = QHBoxLayout() + row.setSpacing(16) + info = Card("Status") + self.cap = QLabel("–") + self.cap.setObjectName("big") + info.body.addWidget(self.cap) + self.details = _muted("") + info.body.addWidget(self.details) + info.body.addStretch(1) + row.addWidget(info, 1) + health = Card("Battery health") + self.limit = QCheckBox("Limit charging to 80 %") + self.limit.clicked.connect(lambda v: self._set("set_battery_limit", v)) + health.body.addWidget(self.limit) + health.body.addWidget(_muted("Recommended when the laptop is mostly plugged in – greatly extends battery life.")) + health.body.addSpacing(10) + self.calib = QCheckBox("Battery calibration running") + self.calib.clicked.connect(self._calibrate) + health.body.addWidget(self.calib) + health.body.addWidget(_muted("Calibration fully charges, discharges and recharges the battery to re-learn its " + "capacity. Keep the charger connected; it can take several hours.")) + health.body.addStretch(1) + row.addWidget(health, 2) + self.lay.addLayout(row) + self.lay.addStretch(1) + self._fw_loaded = False + + def _set(self, cmd, v): + self.win.backend.run(cmd, enabled=bool(v)) + QTimer.singleShot(800, self.refresh) + + def _calibrate(self, v): + if v and QMessageBox.question(self, "Battery calibration", + "Start battery calibration now? Keep the charger connected.") != QMessageBox.Yes: + self.calib.setChecked(False) + return + self._set("set_battery_calibration", v) + + def refresh(self): + self.win.backend.run("get_firmware") + + def firmware(self, fw): + for box, key in ((self.limit, "battery_limit"), (self.calib, "battery_calibration")): + v = fw.get(key, {}) + box.setEnabled(v.get("value") is not None) + box.setChecked(bool(v.get("value"))) + box.setToolTip(v.get("error", "")) + + def showEvent(self, e): + super().showEvent(e) + self.refresh() + + def update_state(self, st): + b = st["battery"] + if not b.get("present"): + self.cap.setText("No battery") + return + self.cap.setText("%s %%" % b.get("capacity")) + lines = ["Status: %s" % b.get("status"), + "Power source: %s" % ("AC adapter" if b.get("ac_online") else "battery"), + "Power draw: %s W" % b.get("power_w"), + "Health: %s %% of design capacity" % b.get("health"), + "Charge cycles: %s" % b.get("cycles")] + self.details.setText("\n".join(lines)) + + +class SystemPage(Page): + def __init__(self, win): + super().__init__(win) + self.lay.addWidget(_title("System", "Firmware options and service status")) + self.fw_card = Card("Firmware options") + self.fw_boxes = {} + self.fw_area = QVBoxLayout() + self.fw_card.body.addLayout(self.fw_area) + self.fw_card.body.addWidget(_muted("Values are stored in the laptop firmware (EC/BIOS).")) + self.lay.addWidget(self.fw_card) + + svc = Card("Status") + self.status = _muted("") + svc.body.addWidget(self.status) + h = QHBoxLayout() + b = QPushButton("Re-apply all settings") + b.clicked.connect(lambda: win.backend.run("restore")) + h.addWidget(b) + h.addStretch(1) + svc.body.addLayout(h) + self.lay.addWidget(svc) + + about = Card("About") + about.body.addWidget(QLabel("%s %s" % (APP_NAME, __version__))) + about.body.addWidget(_muted("Open-source PredatorSense alternative for the Acer Predator Helios 16 (PH16-71). " + "Protocols based on the work of the Venator and Linuwu-Sense projects. " + "Not affiliated with Acer.")) + self.lay.addWidget(about) + self.lay.addStretch(1) + + def showEvent(self, e): + super().showEvent(e) + self.win.backend.run("get_firmware") + + def firmware(self, fw): + for name, info in fw.items(): + if "label" not in info: + continue + if name == "usb_charging": + w = self.fw_boxes.get(name) + if w is None: + row = QHBoxLayout() + row.addWidget(QLabel(info["label"])) + w = QComboBox() + for val, text in ((0, "Off"), (10, "Until battery 10 %"), (20, "Until battery 20 %"), (30, "Until battery 30 %")): + w.addItem(text, val) + w.activated.connect(lambda _=0, w=w: self.win.backend.run("set_firmware", name="usb_charging", value=w.currentData())) + row.addWidget(w) + row.addStretch(1) + self.fw_area.addLayout(row) + self.fw_boxes[name] = w + w.setEnabled(info.get("value") is not None) + if info.get("value") is not None: + w.setCurrentIndex(max(0, w.findData(info["value"]))) + w.setToolTip(info.get("error", "")) + continue + box = self.fw_boxes.get(name) + if box is None: + box = QCheckBox(info["label"]) + box.clicked.connect(lambda v, n=name: self.win.backend.run("set_firmware", name=n, value=bool(v))) + self.fw_area.addWidget(box) + self.fw_boxes[name] = box + box.setEnabled(info.get("value") is not None) + box.setChecked(bool(info.get("value"))) + box.setToolTip(info.get("error", "") or "") + + def update_state(self, st): + a = st["available"] + yes = lambda v: "✔" if v else "✘" + lines = ["%s Service predatord %s" % (yes(True), st.get("version")), + "%s RGB keyboard (hidraw)" % yes(a.get("keyboard")), + "%s WMI bridge (kernel module predator_wmi)" % yes(a.get("wmi"))] + for k, v in st.get("errors", {}).items(): + lines.append("⚠ %s: %s" % (k, v)) + self.status.setText("\n".join(lines)) + + +# ------------------------------------------------------------------ window + +class MainWindow(QMainWindow): + def __init__(self, page="home"): + super().__init__() + self.setWindowTitle(APP_NAME) + self.setWindowIcon(QIcon.fromTheme("predator-control")) + self.resize(1240, 820) + self.setMinimumSize(980, 640) + self.state = None + self.backend = Backend() + self.backend.finished.connect(self._done) + + root = QWidget() + root.setObjectName("root") + h = QHBoxLayout(root) + h.setContentsMargins(0, 0, 0, 0) + h.setSpacing(0) + side = QFrame() + side.setObjectName("sidebar") + side.setFixedWidth(220) + sl = QVBoxLayout(side) + sl.setContentsMargins(14, 22, 14, 18) + sl.setSpacing(4) + brand = QLabel("PREDATOR") + brand.setObjectName("brand") + sl.addWidget(brand) + sub = QLabel("CONTROL CENTER") + sub.setObjectName("brandSub") + sl.addWidget(sub) + sl.addSpacing(22) + self.stack = QStackedWidget() + self.nav = QButtonGroup(self) + self.pages = {} + classes = {"home": HomePage, "performance": PerformancePage, "fans": FansPage, + "rgb": RgbPage, "battery": BatteryPage, "system": SystemPage} + for key, label in PAGES: + b = QPushButton(label) + b.setObjectName("nav") + b.setCheckable(True) + b.clicked.connect(lambda _=False, k=key: self.show_page(k)) + self.nav.addButton(b) + sl.addWidget(b) + pg = classes[key](self) + self.pages[key] = (pg, b) + self.stack.addWidget(pg) + sl.addStretch(1) + self.footer = QLabel("") + self.footer.setObjectName("muted") + self.footer.setWordWrap(True) + sl.addWidget(self.footer) + h.addWidget(side) + right = QVBoxLayout() + right.setContentsMargins(0, 0, 0, 0) + self.banner = QLabel() + self.banner.setObjectName("error") + self.banner.setWordWrap(True) + self.banner.setStyleSheet("padding:10px 32px;background:#2a0f16;") + self.banner.hide() + right.addWidget(self.banner) + right.addWidget(self.stack) + h.addLayout(right, 1) + self.setCentralWidget(root) + self.statusBar().showMessage("Ready") + + self.timer = QTimer(self) + self.timer.timeout.connect(self.refresh) + self.timer.start(1500) + self.show_page(page) + self.refresh() + + def show_page(self, key): + if key not in self.pages: + key = "home" + pg, b = self.pages[key] + b.setChecked(True) + self.stack.setCurrentWidget(pg) + if self.state: + pg.update_state(self.state) + + def refresh(self): + st = read_state() + if not st: + self.banner.setText("The predatord service is not running. Start it with: " + "sudo systemctl enable --now predatord") + self.banner.show() + return + self.banner.hide() + self.state = st + self.stack.currentWidget().update_state(st) + s = st["sensors"] + self.footer.setText("%s\nCPU %s °C · GPU %s" % ( + PROFILE_INFO.get(st["profile"], (st["profile"],))[0], s.get("cpu_temp"), + ("%s °C" % s["gpu_temp"]) if s.get("gpu_temp") else "off")) + + def _done(self, cmd, result, err): + if err: + self.statusBar().showMessage("Error: %s" % err, 8000) + elif cmd == "get_firmware": + self.pages["system"][0].firmware(result) + self.pages["battery"][0].firmware(result) + return + else: + self.statusBar().showMessage("Applied", 2000) + QTimer.singleShot(250, self.refresh) + + +def main(argv=None): + ap = argparse.ArgumentParser(prog="predator-control") + ap.add_argument("--page", default="home", choices=[p for p, _ in PAGES]) + args, qt_args = ap.parse_known_args(argv) + + app = QApplication([sys.argv[0]] + qt_args) + app.setApplicationName("predator-control") + app.setApplicationDisplayName(APP_NAME) + app.setDesktopFileName("predator-control") + app.setStyle("Fusion") + app.setStyleSheet(theme.QSS) + + # single instance: forward the requested page to a running window + name = "predator-control-%d" % os.getuid() + sock = QLocalSocket() + sock.connectToServer(name) + if sock.waitForConnected(300): + sock.write(args.page.encode()) + sock.waitForBytesWritten(300) + sock.disconnectFromServer() + return 0 + QLocalServer.removeServer(name) + server = QLocalServer() + server.listen(name) + + win = MainWindow(args.page) + + def incoming(): + c = server.nextPendingConnection() + if c.waitForReadyRead(500): + win.show_page(bytes(c.readAll()).decode().strip()) + win.showNormal() + win.raise_() + win.activateWindow() + server.newConnection.connect(incoming) + + win.show() + return app.exec() + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/predator_control/gui/theme.py b/predator_control/gui/theme.py new file mode 100644 index 0000000..6c9b743 --- /dev/null +++ b/predator_control/gui/theme.py @@ -0,0 +1,79 @@ +"""Colours and the Qt style sheet (dark, PredatorSense-inspired).""" + +BG = "#0a0e13" +SIDEBAR = "#0d1219" +SURFACE = "#121a24" +SURFACE2 = "#182230" +BORDER = "#223043" +TEXT = "#e6edf3" +MUTED = "#8593a6" +ACCENT = "#00d4ff" +ACCENT_DIM = "#0a6f8a" +WARN = "#ffb020" +DANGER = "#ff3b5c" +TRACK = "#1c2735" +GRID = "#1b2532" +KEY = "#151d28" +KEY_BORDER = "#2a3a50" + +QSS = f""" +* {{ color: {TEXT}; font-size: 10pt; }} +QMainWindow, QWidget#root {{ background: {BG}; }} +QWidget#page {{ background: {BG}; }} +QScrollArea, QScrollArea > QWidget > QWidget {{ background: transparent; border: none; }} +QFrame#sidebar {{ background: {SIDEBAR}; border-right: 1px solid {BORDER}; }} +QLabel#brand {{ font-size: 15pt; font-weight: 700; color: {ACCENT}; letter-spacing: 2px; }} +QLabel#brandSub {{ color: {MUTED}; font-size: 8pt; letter-spacing: 3px; }} +QPushButton#nav {{ + text-align: left; padding: 11px 16px; border: none; border-radius: 8px; + background: transparent; color: {MUTED}; font-size: 10.5pt; +}} +QPushButton#nav:hover {{ background: {SURFACE}; color: {TEXT}; }} +QPushButton#nav:checked {{ background: {SURFACE2}; color: {ACCENT}; border-left: 3px solid {ACCENT}; }} +QLabel#pageTitle {{ font-size: 18pt; font-weight: 700; }} +QLabel#pageSub {{ color: {MUTED}; }} +QFrame#card {{ background: {SURFACE}; border: 1px solid {BORDER}; border-radius: 14px; }} +QLabel#cardTitle {{ color: {MUTED}; font-size: 9pt; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; }} +QLabel#big {{ font-size: 20pt; font-weight: 700; }} +QLabel#muted {{ color: {MUTED}; }} +QLabel#error {{ color: {DANGER}; }} +QPushButton {{ + background: {SURFACE2}; border: 1px solid {BORDER}; border-radius: 8px; padding: 8px 14px; +}} +QPushButton:hover {{ border-color: {ACCENT_DIM}; }} +QPushButton:pressed {{ background: {BORDER}; }} +QPushButton:checked {{ background: {ACCENT_DIM}; border-color: {ACCENT}; color: white; }} +QPushButton:disabled {{ color: {MUTED}; }} +QPushButton#primary {{ background: {ACCENT}; color: #00131a; font-weight: 700; border: none; }} +QPushButton#primary:hover {{ background: #4de1ff; }} +QPushButton#profile, QPushButton#profileTurbo {{ + padding: 16px 10px; border-radius: 12px; font-size: 11pt; font-weight: 600; min-width: 110px; +}} +QPushButton#profile:checked {{ background: {ACCENT_DIM}; border: 2px solid {ACCENT}; }} +QPushButton#profileTurbo:checked {{ background: #6b1022; border: 2px solid {DANGER}; }} +QPushButton#swatch {{ border-radius: 14px; border: 2px solid {BORDER}; padding: 0; }} +QPushButton#swatch:hover {{ border-color: {TEXT}; }} +QComboBox, QSpinBox {{ + background: {SURFACE2}; border: 1px solid {BORDER}; border-radius: 8px; padding: 6px 10px; min-height: 20px; +}} +QComboBox QAbstractItemView {{ background: {SURFACE2}; selection-background-color: {ACCENT_DIM}; border: 1px solid {BORDER}; }} +QSlider::groove:horizontal {{ height: 6px; background: {TRACK}; border-radius: 3px; }} +QSlider::sub-page:horizontal {{ background: {ACCENT}; border-radius: 3px; }} +QSlider::handle:horizontal {{ + background: {TEXT}; width: 16px; height: 16px; margin: -6px 0; border-radius: 8px; +}} +QCheckBox {{ spacing: 10px; }} +QCheckBox::indicator {{ width: 36px; height: 20px; border-radius: 10px; background: {TRACK}; border: 1px solid {BORDER}; }} +QCheckBox::indicator:checked {{ background: {ACCENT}; border-color: {ACCENT}; }} +QTabWidget::pane {{ border: none; }} +QTabBar::tab {{ + background: transparent; color: {MUTED}; padding: 10px 18px; border: none; + border-bottom: 2px solid transparent; font-weight: 600; +}} +QTabBar::tab:selected {{ color: {ACCENT}; border-bottom: 2px solid {ACCENT}; }} +QListWidget {{ background: {SURFACE2}; border: 1px solid {BORDER}; border-radius: 8px; padding: 4px; }} +QListWidget::item {{ padding: 8px; border-radius: 6px; }} +QListWidget::item:selected {{ background: {ACCENT_DIM}; color: white; }} +QStatusBar {{ background: {SIDEBAR}; color: {MUTED}; border-top: 1px solid {BORDER}; }} +QToolTip {{ background: {SURFACE2}; color: {TEXT}; border: 1px solid {BORDER}; }} +""" diff --git a/predator_control/gui/widgets.py b/predator_control/gui/widgets.py new file mode 100644 index 0000000..7981cc0 --- /dev/null +++ b/predator_control/gui/widgets.py @@ -0,0 +1,390 @@ +"""Custom widgets: gauges, fan curve editor, per-key keyboard painter, colour swatches.""" + +from PySide6.QtCore import QPointF, QRectF, Qt, Signal +from PySide6.QtGui import QColor, QFont, QPainter, QPainterPath, QPen +from PySide6.QtWidgets import (QColorDialog, QFrame, QHBoxLayout, QLabel, QPushButton, + QSizePolicy, QVBoxLayout, QWidget) + +from .. import layout +from . import theme + + +class Card(QFrame): + """Rounded panel with an optional title.""" + + def __init__(self, title=None, parent=None): + super().__init__(parent) + self.setObjectName("card") + self.body = QVBoxLayout(self) + self.body.setContentsMargins(18, 16, 18, 16) + self.body.setSpacing(10) + if title: + t = QLabel(title) + t.setObjectName("cardTitle") + self.body.addWidget(t) + + +class Gauge(QWidget): + """Circular gauge (270° arc).""" + + def __init__(self, title, unit, maximum=100, warn=None, parent=None): + super().__init__(parent) + self.title, self.unit, self.maximum, self.warn = title, unit, maximum, warn + self.value = None + self.sub = "" + self.setMinimumSize(150, 150) + self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + + def set_value(self, value, sub=""): + self.value, self.sub = value, sub + self.update() + + def paintEvent(self, _): + p = QPainter(self) + p.setRenderHint(QPainter.Antialiasing) + side = min(self.width(), self.height()) - 16 + r = QRectF((self.width() - side) / 2, (self.height() - side) / 2, side, side) + pen = QPen(QColor(theme.TRACK), max(8, side / 14), Qt.SolidLine, Qt.RoundCap) + p.setPen(pen) + p.drawArc(r, -45 * 16, 270 * 16) + if self.value is not None: + frac = max(0.0, min(1.0, self.value / self.maximum)) + col = QColor(theme.ACCENT) + if self.warn and self.value >= self.warn: + col = QColor(theme.DANGER) + elif self.warn and self.value >= self.warn * 0.85: + col = QColor(theme.WARN) + pen.setColor(col) + p.setPen(pen) + p.drawArc(r, 225 * 16, int(-270 * 16 * frac)) + p.setPen(QColor(theme.TEXT)) + f = QFont(self.font()) + f.setPointSizeF(max(10, side / 7)) + f.setBold(True) + p.setFont(f) + txt = "–" if self.value is None else ("%d" % round(self.value)) + p.drawText(r.adjusted(0, -side * 0.08, 0, -side * 0.08), Qt.AlignCenter, txt) + f.setPointSizeF(max(7, side / 16)) + f.setBold(False) + p.setFont(f) + p.setPen(QColor(theme.MUTED)) + p.drawText(r.adjusted(0, side * 0.22, 0, 0), Qt.AlignHCenter | Qt.AlignVCenter, self.unit) + p.setPen(QColor(theme.TEXT)) + p.drawText(QRectF(r.left(), r.bottom() - side * 0.2, r.width(), side * 0.2), + Qt.AlignHCenter | Qt.AlignVCenter, self.title) + if self.sub: + p.setPen(QColor(theme.MUTED)) + p.drawText(QRectF(r.left(), r.bottom() - side * 0.05, r.width(), side * 0.2), + Qt.AlignHCenter | Qt.AlignTop, self.sub) + + +class Bar(QWidget): + """Thin labelled progress bar.""" + + def __init__(self, title, parent=None): + super().__init__(parent) + self.title = title + self.value, self.text = 0, "" + self.setMinimumHeight(38) + + def set_value(self, frac, text): + self.value, self.text = max(0.0, min(1.0, frac or 0)), text + self.update() + + def paintEvent(self, _): + p = QPainter(self) + p.setRenderHint(QPainter.Antialiasing) + p.setPen(QColor(theme.MUTED)) + p.drawText(QRectF(0, 0, self.width(), 18), Qt.AlignLeft | Qt.AlignVCenter, self.title) + p.setPen(QColor(theme.TEXT)) + p.drawText(QRectF(0, 0, self.width(), 18), Qt.AlignRight | Qt.AlignVCenter, self.text) + track = QRectF(0, 24, self.width(), 8) + p.setPen(Qt.NoPen) + p.setBrush(QColor(theme.TRACK)) + p.drawRoundedRect(track, 4, 4) + p.setBrush(QColor(theme.ACCENT)) + p.drawRoundedRect(QRectF(0, 24, self.width() * self.value, 8), 4, 4) + + +class CurveEditor(QWidget): + """Drag-and-drop fan curve: temperature (°C) -> fan speed (%).""" + + changed = Signal(list) + T_MIN, T_MAX = 30, 100 + + def __init__(self, title, parent=None): + super().__init__(parent) + self.title = title + self.points = [[45, 0], [60, 35], [72, 55], [82, 75], [90, 100]] + self.current_temp = None + self._drag = None + self.setMinimumHeight(220) + self.setMouseTracking(True) + + def set_points(self, pts): + if self._drag is None: + self.points = sorted([list(p) for p in pts]) + self.update() + + def set_current(self, temp): + self.current_temp = temp + self.update() + + def _plot(self): + return QRectF(44, 26, self.width() - 60, self.height() - 56) + + def _to_px(self, t, s): + r = self._plot() + return QPointF(r.left() + (t - self.T_MIN) / (self.T_MAX - self.T_MIN) * r.width(), + r.bottom() - s / 100 * r.height()) + + def _from_px(self, pos): + r = self._plot() + t = self.T_MIN + (pos.x() - r.left()) / r.width() * (self.T_MAX - self.T_MIN) + s = (r.bottom() - pos.y()) / r.height() * 100 + return t, s + + def paintEvent(self, _): + p = QPainter(self) + p.setRenderHint(QPainter.Antialiasing) + r = self._plot() + p.setPen(QColor(theme.TEXT)) + p.drawText(QRectF(0, 0, self.width(), 20), Qt.AlignLeft | Qt.AlignVCenter, self.title) + grid = QPen(QColor(theme.GRID), 1) + p.setPen(grid) + for s in range(0, 101, 25): + a = self._to_px(self.T_MIN, s) + p.drawLine(QPointF(r.left(), a.y()), QPointF(r.right(), a.y())) + p.setPen(QColor(theme.MUTED)) + p.drawText(QRectF(0, a.y() - 8, 38, 16), Qt.AlignRight | Qt.AlignVCenter, "%d%%" % s) + p.setPen(grid) + for t in range(self.T_MIN, self.T_MAX + 1, 10): + a = self._to_px(t, 0) + p.drawLine(QPointF(a.x(), r.top()), QPointF(a.x(), r.bottom())) + p.setPen(QColor(theme.MUTED)) + p.drawText(QRectF(a.x() - 20, r.bottom() + 4, 40, 16), Qt.AlignCenter, "%d°" % t) + p.setPen(grid) + if self.current_temp: + a = self._to_px(max(self.T_MIN, min(self.T_MAX, self.current_temp)), 0) + p.setPen(QPen(QColor(theme.WARN), 1, Qt.DashLine)) + p.drawLine(QPointF(a.x(), r.top()), QPointF(a.x(), r.bottom())) + pts = sorted(self.points) + path = QPainterPath(self._to_px(self.T_MIN, pts[0][1])) + for t, s in pts: + path.lineTo(self._to_px(t, s)) + path.lineTo(self._to_px(self.T_MAX, pts[-1][1])) + fill = QPainterPath(path) + fill.lineTo(self._to_px(self.T_MAX, 0)) + fill.lineTo(self._to_px(self.T_MIN, 0)) + c = QColor(theme.ACCENT) + c.setAlpha(40) + p.fillPath(fill, c) + p.setPen(QPen(QColor(theme.ACCENT), 2.5)) + p.drawPath(path) + p.setBrush(QColor(theme.BG)) + for i, (t, s) in enumerate(pts): + p.setPen(QPen(QColor(theme.TEXT if i == self._drag else theme.ACCENT), 2.5)) + p.drawEllipse(self._to_px(t, s), 6, 6) + if i == self._drag: + p.drawText(self._to_px(t, s) + QPointF(10, -10), "%d° → %d%%" % (t, s)) + + def mousePressEvent(self, e): + for i, (t, s) in enumerate(sorted(self.points)): + d = self._to_px(t, s) - e.position() + if abs(d.x()) < 12 and abs(d.y()) < 12: + self.points = sorted(self.points) + self._drag = i + self.update() + return + + def mouseMoveEvent(self, e): + if self._drag is None: + return + t, s = self._from_px(e.position()) + i = self._drag + lo = self.points[i - 1][0] + 1 if i > 0 else self.T_MIN + hi = self.points[i + 1][0] - 1 if i < len(self.points) - 1 else self.T_MAX + self.points[i] = [int(max(lo, min(hi, round(t)))), int(max(0, min(100, round(s / 5) * 5)))] + self.update() + + def mouseReleaseEvent(self, _): + if self._drag is not None: + self._drag = None + self.update() + self.changed.emit([list(p) for p in self.points]) + + +class KeyboardPainter(QWidget): + """Draws the keyboard and lets the user paint keys with the current colour.""" + + painted = Signal() + picked = Signal(QColor) + + def __init__(self, parent=None): + super().__init__(parent) + self.variant = layout.default_variant() + self.keys = layout.keys(self.variant) + self.colors = {} # cell -> QColor + self.brush = QColor(theme.ACCENT) + self._painting = False + self._hover = None + self.setMouseTracking(True) + self.setMinimumHeight(260) + self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) + + def set_variant(self, variant): + self.variant = variant + self.keys = layout.keys(variant) + self.update() + + def heightForWidth(self, w): + kw, kh = layout.size(self.keys) + return int(w * kh / kw) + + def hasHeightForWidth(self): + return True + + def _scale(self): + kw, kh = layout.size(self.keys) + s = min((self.width() - 8) / kw, (self.height() - 8) / kh) + ox = (self.width() - kw * s) / 2 + oy = (self.height() - kh * s) / 2 + return s, ox, oy + + def _rect(self, k, s, ox, oy): + _l, _c, x, y, w, h = k + g = s * 0.08 + return QRectF(ox + x * s + g / 2, oy + y * s + g / 2, w * s - g, h * s - g) + + def _key_at(self, pos): + s, ox, oy = self._scale() + for k in self.keys: + if self._rect(k, s, ox, oy).contains(pos): + return k + return None + + def paintEvent(self, _): + p = QPainter(self) + p.setRenderHint(QPainter.Antialiasing) + s, ox, oy = self._scale() + f = QFont(self.font()) + for k in self.keys: + label, cell = k[0], k[1] + r = self._rect(k, s, ox, oy) + col = self.colors.get(cell, QColor(0, 0, 0)) + base = QColor(theme.KEY) + p.setPen(QPen(QColor(theme.TEXT) if k is self._hover else QColor(theme.KEY_BORDER), 1.5)) + p.setBrush(base) + p.drawRoundedRect(r, s * 0.12, s * 0.12) + # glow of the key colour + glow = QColor(col) + glow.setAlpha(210 if (col.red() + col.green() + col.blue()) > 0 else 0) + p.setPen(Qt.NoPen) + p.setBrush(glow) + p.drawRoundedRect(r.adjusted(3, 3, -3, -3), s * 0.1, s * 0.1) + lum = 0.299 * col.red() + 0.587 * col.green() + 0.114 * col.blue() + p.setPen(QColor("#0b0f14") if lum > 150 else QColor(theme.TEXT)) + f.setPointSizeF(max(6, s * (0.22 if len(label) <= 2 else 0.16))) + p.setFont(f) + p.drawText(r, Qt.AlignCenter, label) + + def _paint_at(self, pos, button): + k = self._key_at(pos) + if not k: + return + if button == Qt.RightButton: + self.picked.emit(QColor(self.colors.get(k[1], QColor(0, 0, 0)))) + return + if self.colors.get(k[1]) != self.brush: + self.colors[k[1]] = QColor(self.brush) + self.update() + self.painted.emit() + + def mousePressEvent(self, e): + self._painting = e.button() == Qt.LeftButton + self._paint_at(e.position(), e.button()) + + def mouseMoveEvent(self, e): + k = self._key_at(e.position()) + if k is not self._hover: + self._hover = k + self.update() + if self._painting: + self._paint_at(e.position(), Qt.LeftButton) + + def mouseReleaseEvent(self, _): + self._painting = False + + def leaveEvent(self, _): + self._hover = None + self.update() + + def fill(self, cells, color): + for c in cells: + self.colors[c] = QColor(color) + self.update() + self.painted.emit() + + def frame_hex(self): + out = bytearray(128 * 3) + for c, col in self.colors.items(): + if 0 <= c < 128: + out[c * 3:c * 3 + 3] = bytes((col.red(), col.green(), col.blue())) + return out.hex() + + def load_frame(self, hexstr): + self.colors = {} + try: + data = bytes.fromhex(hexstr or "") + except ValueError: + data = b"" + for c in range(min(128, len(data) // 3)): + self.colors[c] = QColor(data[c * 3], data[c * 3 + 1], data[c * 3 + 2]) + self.update() + + +PRESET_COLORS = ["#00d4ff", "#0057ff", "#7a00ff", "#ff00c8", "#ff0033", "#ff6a00", + "#ffd000", "#3cff00", "#00ff9c", "#ffffff"] + + +class ColorRow(QWidget): + """Row of colour swatches plus a 'custom colour' button.""" + + colorChosen = Signal(QColor) + + def __init__(self, parent=None): + super().__init__(parent) + lay = QHBoxLayout(self) + lay.setContentsMargins(0, 0, 0, 0) + lay.setSpacing(6) + self.current = QColor(PRESET_COLORS[0]) + for c in PRESET_COLORS: + b = QPushButton() + b.setObjectName("swatch") + b.setFixedSize(28, 28) + b.setStyleSheet("QPushButton#swatch{background:%s;}" % c) + b.setToolTip(c) + b.clicked.connect(lambda _=False, c=c: self._choose(QColor(c))) + lay.addWidget(b) + self.custom = QPushButton("Custom…") + self.custom.clicked.connect(self._dialog) + lay.addWidget(self.custom) + self.preview = QLabel() + self.preview.setFixedSize(46, 28) + lay.addWidget(self.preview) + lay.addStretch(1) + self.set_color(self.current) + + def _dialog(self): + c = QColorDialog.getColor(self.current, self, "Choose colour") + if c.isValid(): + self._choose(c) + + def _choose(self, c): + self.set_color(c) + self.colorChosen.emit(c) + + def set_color(self, c): + self.current = QColor(c) + self.preview.setStyleSheet("background:%s;border-radius:6px;border:1px solid %s;" + % (self.current.name(), theme.BORDER)) diff --git a/predator_control/hardware.py b/predator_control/hardware.py new file mode 100644 index 0000000..c49917f --- /dev/null +++ b/predator_control/hardware.py @@ -0,0 +1,359 @@ +"""Access to power profiles, sensors, fans, battery, lightbar and firmware options. + +WMI calls go through the predator_wmi kernel module (sysfs attribute predator_call). +Wire formats come from Linuwu-Sense and Venator (both reverse-engineered from PredatorSense). +""" + +import glob +import os +import struct +import threading +import time + +GUID_GAMING = "7A4DDFE7-5B5D-40B4-8595-4408E0CC7F56" # WMBH +GUID_BATTERY = "79772EC5-04B1-4BFD-843C-61E7F77B6CC9" # WMBE +GUID_APGE = "61EF69EA-865C-4BC3-A502-A0DEBA0CB531" # WMAA + +PLATFORM_PROFILE = "/sys/firmware/acpi/platform_profile" +PLATFORM_CHOICES = "/sys/firmware/acpi/platform_profile_choices" + +PROFILE_LABELS = { + "low-power": "Eco", + "quiet": "Quiet", + "balanced": "Balanced", + "balanced-performance": "Performance", + "performance": "Turbo", +} + +LIGHTBAR_MODES = { + "off": (0x00, "Off"), + "static": (0xFF, "Static"), + "breathing": (0x01, "Breathing"), + "neon": (0x02, "Neon"), + "rainbow": (0x03, "Rainbow"), + "wave": (0x04, "Wave"), + "ripple": (0x05, "Ripple"), + "scanner": (0x06, "Scanner"), + "strobe": (0x07, "Strobe"), +} + + +def _read(path, default=None): + try: + with open(path) as f: + return f.read().strip() + except OSError: + return default + + +def _read_int(path, default=None): + v = _read(path) + try: + return int(v) + except (TypeError, ValueError): + return default + + +def _write(path, value): + with open(path, "w") as f: + f.write(str(value)) + + +# --------------------------------------------------------------- WMI bridge + +class WMIError(RuntimeError): + pass + + +_wmi_lock = threading.Lock() + + +def wmi_available(guid=GUID_GAMING): + return bool(glob.glob("/sys/bus/wmi/devices/%s-*/predator_call" % guid)) + + +def wmi_call(guid, method, data=b""): + """Call a WMI method. Returns bytes, int or None.""" + paths = glob.glob("/sys/bus/wmi/devices/%s-*/predator_call" % guid) + if not paths: + raise WMIError("kernel module predator_wmi is not loaded") + path = paths[0] + with _wmi_lock: + try: + _write(path, "%d %s" % (method, bytes(data).hex())) + except OSError as e: + raise WMIError("WMI method %d failed: %s" % (method, e)) from e + res = _read(path, "err -5").split() + if res[0] != "ok": + raise WMIError("WMI method %d: %s" % (method, " ".join(res))) + if res[1] == "buf": + return bytes.fromhex(res[2]) if len(res) > 2 else b"" + if res[1] == "int": + return int(res[2], 16) + return None + + +def _as_u64(res): + if isinstance(res, int): + return res + if isinstance(res, (bytes, bytearray)): + return int.from_bytes(bytes(res[:8]).ljust(8, b"\0"), "little") + return 0 + + +def gaming_u64(method, value, in_size=8): + return _as_u64(wmi_call(GUID_GAMING, method, value.to_bytes(in_size, "little"))) + + +# --------------------------------------------------------------- Profiles + +def profile_choices(): + c = _read(PLATFORM_CHOICES, "") + return c.split() if c else [] + + +def get_profile(): + return _read(PLATFORM_PROFILE) + + +def set_profile(name): + if name not in profile_choices(): + raise ValueError("profile not available: %s" % name) + _write(PLATFORM_PROFILE, name) + + +# --------------------------------------------------------------- Sensors + +def _hwmon(name): + for h in glob.glob("/sys/class/hwmon/hwmon*"): + if _read(h + "/name") == name: + return h + return None + + +class CpuLoad: + def __init__(self): + self._last = None + + def sample(self): + line = _read("/proc/stat", "").splitlines()[0].split()[1:] + vals = [int(x) for x in line] + idle = vals[3] + vals[4] + total = sum(vals) + pct = None + if self._last: + dt = total - self._last[0] + di = idle - self._last[1] + pct = round(100.0 * (dt - di) / dt, 1) if dt > 0 else 0.0 + self._last = (total, idle) + return pct + + +def cpu_freq_mhz(): + freqs = [_read_int(p) for p in glob.glob( + "/sys/devices/system/cpu/cpu[0-9]*/cpufreq/scaling_cur_freq")] + freqs = [f for f in freqs if f] + return round(sum(freqs) / len(freqs) / 1000) if freqs else None + + +def mem_usage(): + info = {} + for line in _read("/proc/meminfo", "").splitlines(): + k, v = line.split(":", 1) + info[k] = int(v.split()[0]) + total = info.get("MemTotal", 0) + avail = info.get("MemAvailable", 0) + return {"total_gb": round(total / 1048576, 1), + "used_gb": round((total - avail) / 1048576, 1), + "percent": round(100.0 * (total - avail) / total, 1) if total else None} + + +def dgpu_active(): + """True if the NVIDIA dGPU is awake (checked without waking it up).""" + for dev in glob.glob("/sys/bus/pci/devices/*"): + if _read(dev + "/vendor") == "0x10de" and (_read(dev + "/class") or "").startswith("0x03"): + return _read(dev + "/power_state") == "D0" + return None + + +def sensors(): + out = {"cpu_temp": None, "gpu_temp": None, "sys_temp": None, + "cpu_fan": None, "gpu_fan": None} + core = _hwmon("coretemp") + if core: + pkg = None + for lbl in glob.glob(core + "/temp*_label"): + if _read(lbl, "").startswith("Package"): + pkg = _read_int(lbl.replace("_label", "_input")) + out["cpu_temp"] = round(pkg / 1000, 1) if pkg else None + acer = _hwmon("acer") + if acer: + g = _read_int(acer + "/temp2_input") + s = _read_int(acer + "/temp3_input") + out["gpu_temp"] = round(g / 1000, 1) if g else None + out["sys_temp"] = round(s / 1000, 1) if s else None + out["cpu_fan"] = _read_int(acer + "/fan1_input") + out["gpu_fan"] = _read_int(acer + "/fan2_input") + out["dgpu_active"] = dgpu_active() + return out + + +# --------------------------------------------------------------- Fans + +FAN_BEHAVIOR = 14 +FAN_SPEED = 16 + + +def _fan_val(percent, index): + return ((int(percent) * 25600 // 100) & 0xFF00) + index + + +def set_fans(mode, cpu=0, gpu=0): + """mode: 'auto' | 'max' | 'custom' (cpu/gpu in percent, 0 = that fan stays automatic).""" + if mode == "auto" or (mode == "custom" and cpu == 0 and gpu == 0): + gaming_u64(FAN_BEHAVIOR, 0x410009) + elif mode == "max": + gaming_u64(FAN_BEHAVIOR, 0x820009) + elif mode == "custom": + cpu = max(0, min(100, int(cpu))) + gpu = max(0, min(100, int(gpu))) + if cpu == 0: + gaming_u64(FAN_BEHAVIOR, 0x10001) + gaming_u64(FAN_BEHAVIOR, 0xC00008) + gaming_u64(FAN_SPEED, _fan_val(gpu, 4)) + elif gpu == 0: + gaming_u64(FAN_BEHAVIOR, 0x400008) + gaming_u64(FAN_BEHAVIOR, 0x30001) + gaming_u64(FAN_SPEED, _fan_val(cpu, 1)) + else: + gaming_u64(FAN_BEHAVIOR, 0xC30009) + gaming_u64(FAN_SPEED, _fan_val(cpu, 1)) + gaming_u64(FAN_SPEED, _fan_val(gpu, 4)) + else: + raise ValueError("unknown fan mode: %s" % mode) + + +# --------------------------------------------------------------- Lightbar + +def set_lightbar(mode="static", color=(0, 200, 255), brightness=200, speed=5, direction=1): + code = LIGHTBAR_MODES[mode][0] + r, g, b = (max(0, min(255, int(c))) for c in color) + buf = bytes([code, max(1, min(10, int(speed))), max(0, min(255, int(brightness))), + 0, int(direction) & 0xFF, r, g, b, 0x03, 0x02]).ljust(16, b"\0") + res = wmi_call(GUID_GAMING, 20, buf) + if isinstance(res, (bytes, bytearray)) and res and res[0] != 0: + raise WMIError("lightbar mode rejected by firmware (0x%02x)" % res[0]) + + +# --------------------------------------------------------------- Battery + +def battery(): + bat = next(iter(glob.glob("/sys/class/power_supply/BAT*")), None) + ac = next((p for p in glob.glob("/sys/class/power_supply/*") + if _read(p + "/type") == "Mains"), None) + out = {"present": bool(bat), "ac_online": _read_int(ac + "/online", 0) == 1 if ac else True} + if not bat: + return out + cur = _read_int(bat + "/current_now") + volt = _read_int(bat + "/voltage_now") + pwr = _read_int(bat + "/power_now") + if pwr is None and cur is not None and volt is not None: + pwr = cur * volt // 1_000_000 + full = _read_int(bat + "/charge_full") or _read_int(bat + "/energy_full") + design = _read_int(bat + "/charge_full_design") or _read_int(bat + "/energy_full_design") + out.update({ + "capacity": _read_int(bat + "/capacity"), + "status": _read(bat + "/status"), + "power_w": round(pwr / 1_000_000, 1) if pwr is not None else None, + "cycles": _read_int(bat + "/cycle_count"), + "health": round(100.0 * full / design, 1) if full and design else None, + }) + return out + + +def _battery_status(): + res = wmi_call(GUID_BATTERY, 20, bytes([1, 1, 0, 0])) + if not isinstance(res, (bytes, bytearray)) or len(res) < 5: + raise WMIError("unexpected reply from the battery interface") + return res + + +def get_battery_limit(): + return _battery_status()[3] == 1 + + +def get_battery_calibration(): + return _battery_status()[4] == 1 + + +def _battery_set(function, value): + res = wmi_call(GUID_BATTERY, 21, bytes([1, function, 1 if value else 0, 0, 0, 0, 0, 0])) + if isinstance(res, (bytes, bytearray)) and res and res[0] != 0: + raise WMIError("battery setting rejected by firmware (0x%02x)" % res[0]) + + +def set_battery_limit(enabled): + _battery_set(1, enabled) + + +def set_battery_calibration(enabled): + _battery_set(2, enabled) + + +# --------------------------------------------------------------- Firmware options + +def get_boot_sound(): + v = gaming_u64(23, 0x02, in_size=4) + if v & 0xFF: + raise WMIError("Status 0x%02x" % (v & 0xFF)) + return ((v >> 8) & 0xFF) == 2 + + +def set_boot_sound(enabled): + v = gaming_u64(22, ((2 if enabled else 1) << 8) | 0x02) + if v & 0xFF: + raise WMIError("boot sound setting rejected (0x%02x)" % (v & 0xFF)) + + +def get_lcd_overdrive(): + v = gaming_u64(9, 0x10, in_size=4) + if v & 0xFF: + raise WMIError("Status 0x%02x" % (v & 0xFF)) + return bool((v >> 8) & 0xFF) + + +def set_lcd_overdrive(enabled): + v = gaming_u64(8, 0x10 | ((1 << 48) if enabled else 0)) + if v & 0xFF: + raise WMIError("LCD overdrive setting rejected (0x%02x)" % (v & 0xFF)) + + +_USB_GET = {663296: 0, 659200: 10, 1314560: 20, 1969920: 30} +_USB_SET = {0: 663300, 10: 659204, 20: 1314564, 30: 1969924} + + +def get_usb_charging(): + v = _as_u64(wmi_call(GUID_APGE, 2, (4).to_bytes(8, "little"))) + return _USB_GET.get(v) + + +def set_usb_charging(level): + wmi_call(GUID_APGE, 1, _USB_SET[int(level)].to_bytes(8, "little")) + + +def get_kbd_timeout(): + v = _as_u64(wmi_call(GUID_APGE, 2, (0x88401).to_bytes(8, "little"))) + return {0x1E0000080000: True, 0x80000: False}.get(v) + + +def set_kbd_timeout(enabled): + wmi_call(GUID_APGE, 1, (0x1E0000088402 if enabled else 0x88402).to_bytes(8, "little")) + + +FIRMWARE_OPTIONS = { + # name: (getter, setter, label) + "boot_sound": (get_boot_sound, set_boot_sound, "Boot animation & sound"), + "lcd_overdrive": (get_lcd_overdrive, set_lcd_overdrive, "LCD overdrive (faster pixel response)"), + "kbd_timeout": (get_kbd_timeout, set_kbd_timeout, "Turn keyboard backlight off after 30 s idle"), + "usb_charging": (get_usb_charging, set_usb_charging, "USB charging while powered off"), +} diff --git a/predator_control/keyboard.py b/predator_control/keyboard.py new file mode 100644 index 0000000..cee4cd4 --- /dev/null +++ b/predator_control/keyboard.py @@ -0,0 +1,139 @@ +"""Per-key RGB keyboard (Chicony MCU 04F2:0117/011A, interface 3, vendor page FF02) via hidraw. + +Protocol (from PredatorSense USB captures, see the Venator project): + * 8-byte feature reports p1..p6 , checksum = 0xFF - (sum & 0xFF) + * 512-byte output report carrying the per-key framebuffer (128 cells x {0,R,G,B}) +""" + +import fcntl +import glob +import os +import threading + +ACER_VID = 0x04F2 +KNOWN_PIDS = (0x0117, 0x011A) +LED_INTERFACE = 3 +NUM_CELLS = 128 + +OP_BEGIN = 0x88 +OP_MODE_ZONE = 0xB1 +OP_MODE_PERKEY = 0x12 +OP_SET_COLOR = 0x14 +OP_APPLY = 0x08 +SUB_APPLY = 0x02 +MODE_TAG = 0x05 +FLAG_DEFAULT = 0x01 +SCOPE_ZONE = 0x01 +SCOPE_PERKEY = 0x08 + +# name -> (EFF byte, uses colour?, display name) +EFFECTS = { + "static": (0x01, True, "Static"), + "breathing": (0x02, True, "Breathing"), + "rainbow": (0x03, False, "Rainbow wave"), + "snake": (0x05, True, "Snake"), + "ripple": (0x06, True, "Ripple (reactive)"), + "neon": (0x08, False, "Neon"), + "rain": (0x0A, True, "Rain"), + "explosion": (0x12, True, "Explosion"), + "pulse": (0x25, True, "Pulse (reactive)"), + "stars": (0x26, True, "Stars"), + "meteor": (0x27, True, "Meteor (reactive)"), + "aura": (0x28, True, "Aura (reactive)"), + "perkey": (0x33, False, "Custom (per key)"), + "off": (0x01, False, "Off"), +} + + +def _ioc(direction, type_, nr, size): + return (direction << 30) | (size << 16) | (ord(type_) << 8) | nr + + +def HIDIOCSFEATURE(length): + return _ioc(3, "H", 0x06, length) # _IOC_WRITE|_IOC_READ + + +def checksum(body7): + return (0xFF - (sum(body7) & 0xFF)) & 0xFF + + +def find_hidraw(): + """Path of the hidraw node of the LED interface, or None.""" + for node in sorted(glob.glob("/sys/class/hidraw/hidraw*")): + try: + with open(os.path.join(node, "device", "uevent")) as f: + uevent = f.read() + except OSError: + continue + hid_id = next((l.split("=", 1)[1] for l in uevent.splitlines() + if l.startswith("HID_ID=")), "") + parts = hid_id.split(":") + if len(parts) != 3: + continue + vid, pid = int(parts[1], 16), int(parts[2], 16) + if vid != ACER_VID or pid not in KNOWN_PIDS: + continue + devpath = os.path.realpath(os.path.join(node, "device")) + # .../1-7:1.3/0003:04F2:011A.0004 -> interface number from the parent + iface = os.path.basename(os.path.dirname(devpath)).rsplit(".", 1)[-1] + if iface == str(LED_INTERFACE): + return "/dev/" + os.path.basename(node) + return None + + +class Keyboard: + def __init__(self): + self._lock = threading.Lock() + + @property + def path(self): + return find_hidraw() + + def available(self): + return self.path is not None + + def _cmd(self, fd, op, p1=0, p2=0, p3=0, p4=0, p5=0, p6=0): + body = [op, p1, p2, p3, p4, p5, p6] + buf = bytearray([0] + body + [checksum(body)]) + fcntl.ioctl(fd, HIDIOCSFEATURE(len(buf)), buf) + + def apply(self, effect="static", color=(255, 255, 255), brightness=200, + frame=None, effect_id=0): + """Apply a hardware effect or (effect='perkey') a per-key image. + + frame: bytes/list with 128*3 RGB values (perkey only). + effect_id: optional raw EFF byte (effect variants with other speed/direction). + """ + path = self.path + if not path: + raise RuntimeError("RGB keyboard (hidraw) not found") + brightness = max(0, min(255, int(brightness))) + r, g, b = (max(0, min(255, int(c))) for c in color) + with self._lock: + fd = os.open(path, os.O_RDWR) + try: + self._cmd(fd, OP_BEGIN) + if effect == "perkey": + data = bytes(frame or bytes(NUM_CELLS * 3)) + data = data[:NUM_CELLS * 3].ljust(NUM_CELLS * 3, b"\0") + self._cmd(fd, OP_MODE_PERKEY, 0, 0, 8, 0, 0, 0) + out = bytearray(1 + NUM_CELLS * 4) + for i in range(NUM_CELLS): + out[1 + i * 4 + 1:1 + i * 4 + 4] = data[i * 3:i * 3 + 3] + os.write(fd, bytes(out)) + self._cmd(fd, OP_APPLY, SUB_APPLY, 0x33, MODE_TAG, + brightness, SCOPE_PERKEY, FLAG_DEFAULT) + return + self._cmd(fd, OP_MODE_ZONE) + if effect == "off" or brightness == 0: + self._cmd(fd, OP_APPLY, SUB_APPLY, 0x01, MODE_TAG, 0, + SCOPE_ZONE, FLAG_DEFAULT) + return + if effect not in EFFECTS: + raise ValueError("Unknown effect: %s" % effect) + self._cmd(fd, OP_SET_COLOR, 0, 0, r, g, b, 0) + eff = effect_id or EFFECTS[effect][0] + self._cmd(fd, OP_APPLY, SUB_APPLY, eff, MODE_TAG, brightness, + SCOPE_ZONE, FLAG_DEFAULT) + finally: + os.close(fd) diff --git a/predator_control/layout.py b/predator_control/layout.py new file mode 100644 index 0000000..3e05921 --- /dev/null +++ b/predator_control/layout.py @@ -0,0 +1,115 @@ +"""Physical keyboard layouts of the PH16-71 mapped to the 128 LED cells of the keyboard MCU. + +cell = column * 6 + row (row 0 = bottom row). The mapping is based on the keymap +recorded by the Venator project (GPL-2.0). Corrections can be placed in +~/.config/predator-control/layout.json as {"