From d096bab7c798800bd5166d28cfde3e819d363eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Drahn=C3=ADk?= Date: Fri, 10 Feb 2023 00:23:16 +0100 Subject: [PATCH] Take into consideration display rotation when is not Rotation lock used --- README.md | 41 +++--------- asus_fliplock.py | 159 ++++++++++++++++++++++++++++++++++------------- conf/default.py | 23 +++++-- install.sh | 14 ++++- requirements.txt | 0 5 files changed, 157 insertions(+), 80 deletions(-) create mode 100644 requirements.txt diff --git a/README.md b/README.md index c1d8744..ec6ecfe 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,22 @@ # Asus fliplock driver [![License: GPLv2](https://img.shields.io/badge/License-GPL_v2-blue.svg)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) - +![Maintainer](https://img.shields.io/badge/maintainer-ldrahnik-blue) If you find the project useful, do not forget to give project a [![GitHub stars](https://img.shields.io/github/stars/asus-linux-drivers/asus-fliplock-driver.svg?style=flat-square)](https://github.com/asus-linux-drivers/asus-fliplock-driver/stargazers) People already did! ![gif preview](./preview.gif) -## TODO: +## Features -- [x] (Configurable support of flip key mapping) -- [x] (Disable backlight of keyboard in tablet mode and use latest level of backlight when is mode changed back to laptop; numpad backlight does the same; history may be done for example via optional file [`brightness_hw_changed`](https://patchwork.kernel.org/project/platform-driver-x86/patch/20170129134252.6185-1-hdegoede@redhat.com/) or temp file located in `/tmp`) -- [x] (Disable backlight of capslock led in tablet mode and use latest level of backlight when is mode changed back to laptop; numpad backlight does the same) -- [x] (When after laptop start does not exist device `Intel HID switches` yet (driver will try find again every 5s) use for first change mode device `Asus WMI hotkeys` and listen for configurable key (in my case `KEY_PROG2`) then is imediatelly added device `Intel HID switches`) +- Disable backlight of keyboard in tablet mode and use latest level of backlight when is mode changed back to laptop; NumberPad backlight does the same; CapsLock led too; history may be done for example via optional file [`brightness_hw_changed`](https://patchwork.kernel.org/project/platform-driver-x86/patch/20170129134252.6185-1-hdegoede@redhat.com/) or temp file located in `/tmp` +- When does not exist device `Intel HID switches` yet, driver will try find again every 5s and use for first flip event from `Asus WMI hotkeys` instead +- Customizable scripts for each display rotation (inverted, left-up, right-up and default) +- Touchpad rotates by default +- Configurable support of flip key mapping, by default `EV_KEY.KEY_PROG2`
-Install required packages - -- Debian / Ubuntu / Linux Mint / Pop!_OS / Zorin OS: -``` -sudo apt install libevdev2 python3-libevdev git -``` - -- Arch Linux / Manjaro: -``` -sudo pacman -S libevdev python-libevdev git -``` - -- Fedora: -``` -sudo dnf install libevdev python-libevdev git -``` - - -Now you can get the latest ASUS fliplock driver for Linux from Git and install it using the following commands. +You can get the latest ASUS fliplock driver for Linux from Git and install it using the following commands. ``` git clone https://github.com/asus-linux-drivers/asus-fliplock-driver cd asus-fliplock-driver @@ -52,11 +35,6 @@ To activate logger, do in a console: LOG=DEBUG sudo -E ./asus_fliplock.py ``` -For some operating systems with boot failure (Pop!OS, Mint, ElementaryOS, SolusOS), before installing, please uncomment in the asus_fliplock.service file, this following property and adjust its value: -``` -# ExecStartPre=/bin/sleep 2 -``` - ## Credits Thank you very much all the contributors of [asus-touchpad-numpad-driver](https://github.com/mohamed-badaoui/asus-touchpad-numpad-driver) for your work. @@ -64,5 +42,6 @@ Thank you very much all the contributors of [asus-touchpad-numpad-driver](https: ## Existing similar projects - [bash] https://github.com/alesya-h/linux_detect_tablet_mode +- [bash] https://gist.github.com/ACamposPT/6794aa02a6e5e341f123d447b3645b93 -Why was this project created? Easier installation/uinstallation and usage of python libevdev. +Why was this project created? Easy installation/uninstallation and implementation of handling touchpad rotation together with customizable possibility for each display rotation state. Aimed for Asus laptops. \ No newline at end of file diff --git a/asus_fliplock.py b/asus_fliplock.py index 51f5dab..f7aabd5 100755 --- a/asus_fliplock.py +++ b/asus_fliplock.py @@ -5,13 +5,14 @@ import os import re import sys +import time +import subprocess from typing import Optional - from libevdev import Device, EV_SW # Setup logging -# LOG=DEBUG sudo -E ./asus_fliplock.py # all messages -# LOG=ERROR sudo -E ./asus_fliplock.py # only error messages +# LOG=DEBUG sudo -E ./asus_fliplock.py "default" # all messages +# LOG=ERROR sudo -E ./asus_fliplock.py "default" # only error messages logging.basicConfig() log = logging.getLogger('Asus fliplock') log.setLevel(os.environ.get('LOG', 'INFO')) @@ -23,17 +24,19 @@ fliplock_layouts = importlib.import_module('conf.'+ layout) +touchpad_name: Optional[str] = None +touchpad_id = 0 switches: Optional[str] = None wmi_hotkeys: Optional[str] = None - +touchpad_detected = 0 switches_detected = 0 wmi_hotkeys_detected = 0 def search_devices(): - global switches, switches_detected - global wmi_hotkeys, wmi_hotkeys_detected + global touchpad_name, touchpad_id, switches, wmi_hotkeys + global touchpad_detected, switches_detected, wmi_hotkeys_detected tries = 5 @@ -44,8 +47,14 @@ def search_devices(): lines = f.readlines() for line in lines: + # Look for the touchpad + if touchpad_detected == 0 and ("Name=\"ASUE" in line or "Name=\"ELAN" in line) and "Touchpad" in line: + touchpad_detected = 1 + log.info('Detecting touchpad from string: \"%s\"', line.strip()) + touchpad_name = line.split("\"")[1] + # Look for the device switches - if re.search("switches",line): + if re.search("switches", line): switches_detected = 1 log.debug('Detect switches from %s', line.strip()) @@ -70,7 +79,7 @@ def search_devices(): log.debug('Set switches id %s from %s', switches, line.strip()) break - if switches_detected == 2 and wmi_hotkeys_detected == 2: + if switches_detected == 2 and wmi_hotkeys_detected == 2 and touchpad_detected == 1: break if switches_detected != 2: @@ -91,6 +100,99 @@ def search_devices(): fd_t_wmi_hotkeys = open('/dev/input/event' + str(wmi_hotkeys), 'rb') d_t_wmi_hotkeys = Device(fd_t_wmi_hotkeys) +def execute_cmd(cmd): + try: + os.system(cmd) + except OSError as e: + log.error(e) + + +def execute_cmds_in_array(cmds): + for cmd in cmds: + execute_cmd(cmd) + + +def change_touchpad_orientation(orientation): + global touchpad_name, touchpad_id + + transform_matrix = False + if orientation == "normal": + transform_matrix = "1 0 0 0 1 0 0 0 1" + elif orientation == "bottom-up": + transform_matrix = "-1 0 1 0 -1 1 0 0 1" + elif orientation == "right-up": + transform_matrix = "0 1 0 -1 0 1 0 0 1" + elif orientation == "left-up": + transform_matrix = "0 -1 1 1 0 0 0 0 1" + + if transform_matrix: + transform_matrix_name = "Coordinate Transformation Matrix" + touchpad_id_regexp = "(?<=id=).*(?=\\t)" + + try: + cmd_touchpad_id = "xinput | grep '" + touchpad_name + "'" + touchpad_row_with_id = subprocess.check_output(cmd_touchpad_id, shell=True) + touchpad_row_with_id_decoded = touchpad_row_with_id.decode() + matches = re.findall(touchpad_id_regexp, touchpad_row_with_id_decoded) + if matches: + touchpad_id = matches[0] + + if touchpad_id: + if orientation != "bottom-up": + cmd_enable_touchpad = "xinput set-prop {} 'Device Enabled' 1".format(touchpad_id) + log.debug(cmd_enable_touchpad) + subprocess.check_output(cmd_enable_touchpad, shell=True) + else: + cmd_disable_touchpad = "xinput set-prop {} 'Device Enabled' 0".format(touchpad_id) + log.debug(cmd_disable_touchpad) + subprocess.check_output(cmd_disable_touchpad, shell=True) + + cmd_rotate_touchpad = "xinput set-prop '" + touchpad_name + "' '" + transform_matrix_name + "' " + transform_matrix + log.debug(cmd_rotate_touchpad) + subprocess.check_output(cmd_rotate_touchpad, shell=True) + except subprocess.CalledProcessError as e: + log.error(e.output) + + +def execute_cmds_according_to_accelerometer_orientation(): + + # inverted when is orientation not recognized + orientation = "bottom-up" + orientation_regexp = "(?<=orientation: ).*?(?=\))" + + try: + monitor_sensors = subprocess.Popen("monitor-sensor", shell=True, stdout=subprocess.PIPE) + + for line in monitor_sensors.stdout: + utf8_line = line.decode() + matches = re.findall(orientation_regexp, utf8_line) + if matches: + orientation = matches[0] + log.debug(utf8_line) + break + + except subprocess.CalledProcessError as e: + log.error(e.output) + + # change by default matrix of touchpad + # run custom commands from conf + if orientation == "bottom-up": + change_touchpad_orientation(orientation) + execute_cmds_in_array(fliplock_layouts.orientation_bottom_up_actions) + elif orientation == "right-up": + change_touchpad_orientation(orientation) + execute_cmds_in_array(fliplock_layouts.orientation_right_up_actions) + elif orientation == "left-up": + change_touchpad_orientation(orientation) + execute_cmds_in_array(fliplock_layouts.orientation_left_up_actions) + elif orientation == "normal": + change_touchpad_orientation(orientation) + execute_cmds_in_array(fliplock_layouts.orientation_normal_actions) + + +# run for first time when is service started +execute_cmds_according_to_accelerometer_orientation() + # If mode has been changed, do something if switches is None and wmi_hotkeys is not None: @@ -101,26 +203,13 @@ def search_devices(): if switches is not None: break - if e.matches(fliplock_layouts.flip_key) and e.value == 1: - - for cmd in fliplock_layouts.to_tablet_mode_actions: - - try: - os.system(cmd) - except e: - log.error(e) - - elif e.matches(fliplock_layouts.flip_key) and e.value == 0: - - for cmd in fliplock_layouts.to_laptop_mode_actions: - - try: - os.system(cmd) - except e: - log.error(e) + if e.matches(fliplock_layouts.flip_key): + time.sleep(2) + execute_cmds_according_to_accelerometer_orientation() search_devices() + if switches is not None: fd_t_switches = open('/dev/input/event' + str(switches), 'rb') @@ -130,20 +219,6 @@ def search_devices(): log.debug(e) - if e.matches(EV_SW.SW_TABLET_MODE) and e.value == 1: - - for cmd in fliplock_layouts.to_tablet_mode_actions: - - try: - os.system(cmd) - except e: - log.error(e) - - elif e.matches(EV_SW.SW_TABLET_MODE) and e.value == 0: - - for cmd in fliplock_layouts.to_laptop_mode_actions: - - try: - os.system(cmd) - except e: - log.error(e) \ No newline at end of file + if e.matches(EV_SW.SW_TABLET_MODE): + time.sleep(2) + execute_cmds_according_to_accelerometer_orientation() \ No newline at end of file diff --git a/conf/default.py b/conf/default.py index 72be912..68d2a4a 100644 --- a/conf/default.py +++ b/conf/default.py @@ -1,15 +1,30 @@ from libevdev import EV_KEY -to_tablet_mode_actions = [ +orientation_bottom_up_actions = [ "cat /sys/class/leds/asus::kbd_backlight/brightness | sudo tee /tmp/kbd_backlight_brightness", "echo 0 | sudo tee /sys/class/leds/asus::kbd_backlight/brightness", "cat /sys/class/leds/input3\:\:capslock/brightness | sudo tee /tmp/input3_capslock_brightness", "echo 0 | sudo tee /sys/class/leds/input3\:\:capslock/brightness" ] -to_laptop_mode_actions = [ - "cat /tmp/kbd_backlight_brightness | sudo tee /sys/class/leds/asus::kbd_backlight/brightness", - "cat /tmp/input3_capslock_brightness | sudo tee /sys/class/leds/input3\:\:capslock/brightness" +orientation_left_up_actions = [ + "sudo rm -f /tmp/kbd_backlight_brightness", + "sudo rm -f /tmp/input3_capslock_brightness" + # TODO: enable touchpad (is disabled by default for every rotation probably) + #"xinput set-prop 17 'Device Enabled' 0" +] + +orientation_right_up_actions = [ + "sudo rm -f /tmp/kbd_backlight_brightness", + "sudo rm -f /tmp/input3_capslock_brightness", + # TODO: enable touchpad (is disabled by default for every rotation probably) +] + +orientation_normal_actions = [ + # backward setting up saved backlight brightness (only in case inverted was previous state! otherwise tmp file does not exist) + "test -f /tmp/kbd_backlight_brightness && cat /tmp/kbd_backlight_brightness | sudo tee /sys/class/leds/asus::kbd_backlight/brightness", + # backward setting up saved capslock led (only in case inverted was previous state! otherwise tmp file does not exist) + "test -f /tmp/input3_capslock_brightness && cat /tmp/input3_capslock_brightness | sudo tee /sys/class/leds/input3\:\:capslock/brightness" ] flip_key = EV_KEY.KEY_PROG2 \ No newline at end of file diff --git a/install.sh b/install.sh index 277b331..e93bf1c 100755 --- a/install.sh +++ b/install.sh @@ -8,11 +8,19 @@ then fi if [[ $(apt install 2>/dev/null) ]]; then - echo 'apt is here' && apt -y install libevdev2 python3-libevdev + echo 'apt is here' && apt -y install libevdev2 python3-libevdev iio-sensor-proxy elif [[ $(pacman -h 2>/dev/null) ]]; then - echo 'pacman is here' && pacman --noconfirm -S libevdev python-libevdev + echo 'pacman is here' && pacman --noconfirm -S libevdev python-libevdev iio-sensor-proxy elif [[ $(dnf install 2>/dev/null) ]]; then - echo 'dnf is here' && dnf -y install libevdev python-libevdev + echo 'dnf is here' && dnf -y install libevdev python-libevdev iio-sensor-proxy +fi + +python3 -m pip install -r requirements.txt + +# Checking if the pip dependencies are successfuly loaded +if [[ $? != 0 ]]; then + echo "pip dependencies via file requirements.txt cannot be loaded correctly." + exit 1 fi if [[ -d conf/__pycache__ ]] ; then diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e69de29