From c34fb3a98b2ec485b0d144736b7efe76604f9799 Mon Sep 17 00:00:00 2001 From: spycat88 Date: Sat, 11 Oct 2025 22:31:52 +0100 Subject: [PATCH 1/2] packages: introduce rocknix-input-sense to replace our bash version --- .../packages/sysutils/system-utils/package.mk | 3 - .../system-utils/sources/scripts/input_sense | 460 ------------------ .../tools/rocknix-input-sense/package.mk | 14 + .../rocknix-input-sense/sources/Makefile | 38 ++ .../rocknix-input-sense/sources/input-sense.c | 402 +++++++++++++++ .../system.d/input-sense.service} | 6 +- .../ROCKNIX/packages/virtual/image/package.mk | 2 +- 7 files changed, 457 insertions(+), 468 deletions(-) delete mode 100755 projects/ROCKNIX/packages/sysutils/system-utils/sources/scripts/input_sense create mode 100644 projects/ROCKNIX/packages/tools/rocknix-input-sense/package.mk create mode 100644 projects/ROCKNIX/packages/tools/rocknix-input-sense/sources/Makefile create mode 100644 projects/ROCKNIX/packages/tools/rocknix-input-sense/sources/input-sense.c rename projects/ROCKNIX/packages/{sysutils/system-utils/system.d/input.service => tools/rocknix-input-sense/system.d/input-sense.service} (62%) diff --git a/projects/ROCKNIX/packages/sysutils/system-utils/package.mk b/projects/ROCKNIX/packages/sysutils/system-utils/package.mk index d867af9a152..25003ce6d65 100644 --- a/projects/ROCKNIX/packages/sysutils/system-utils/package.mk +++ b/projects/ROCKNIX/packages/sysutils/system-utils/package.mk @@ -10,7 +10,6 @@ PKG_LONGDESC="Hardware button support scripts." PKG_TOOLCHAIN="manual" makeinstall_target() { - mkdir -p ${INSTALL}/usr/lib/autostart/common cp ${PKG_DIR}/sources/autostart/common/* ${INSTALL}/usr/lib/autostart/common @@ -18,7 +17,6 @@ makeinstall_target() { cp ${PKG_DIR}/sources/scripts/fancontrol ${INSTALL}/usr/bin cp ${PKG_DIR}/sources/scripts/headphone_sense ${INSTALL}/usr/bin cp ${PKG_DIR}/sources/scripts/hdmi_sense ${INSTALL}/usr/bin - cp ${PKG_DIR}/sources/scripts/input_sense ${INSTALL}/usr/bin cp ${PKG_DIR}/sources/scripts/ledcontrol ${INSTALL}/usr/bin cp ${PKG_DIR}/sources/scripts/analog_sticks_ledcontrol ${INSTALL}/usr/bin cp ${PKG_DIR}/sources/scripts/battery_led_status ${INSTALL}/usr/bin @@ -38,4 +36,3 @@ makeinstall_target() { mkdir -p ${INSTALL}/usr/config cp ${PKG_DIR}/sources/config/fancontrol.conf ${INSTALL}/usr/config/fancontrol.conf.sample } - diff --git a/projects/ROCKNIX/packages/sysutils/system-utils/sources/scripts/input_sense b/projects/ROCKNIX/packages/sysutils/system-utils/sources/scripts/input_sense deleted file mode 100755 index f24d3715a80..00000000000 --- a/projects/ROCKNIX/packages/sysutils/system-utils/sources/scripts/input_sense +++ /dev/null @@ -1,460 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: GPL-2.0 -# Copyright (C) 2021-22 pkegg -# Copyright (C) 2022-24 JELOS (https://github.com/JustEnoughLinuxOS) -# Copyright (C) 2024-present ROCKNIX (https://github.com/ROCKNIX) - -. /etc/profile - -# Remove or comment out 'set -e' so the script doesn't exit on a single error: -# set -e -set -o pipefail - -### Summary -# This script listens to input events and takes actions. -### - -### Enable logging -case $(get_setting system.loglevel) in - verbose) - DEBUG=true - ;; - *) - DEBUG=false - ;; -esac - -### Define matching values from evtest, but allow them to be overridden in system.cfg. -KEY_VOLUME_UP=$(get_setting key.volume.up) -[ -z "${KEY_VOLUME_UP}" ] && KEY_VOLUME_UP='KEY_VOLUME*UP' - -KEY_VOLUME_DOWN=$(get_setting key.volume.down) -[ -z "${KEY_VOLUME_DOWN}" ] && KEY_VOLUME_DOWN='KEY_VOLUME*DOWN' - -FUNCTION_VOLUME_UP_EVENT='*('${KEY_VOLUME_UP}'), value *' -FUNCTION_VOLUME_DOWN_EVENT='*('${KEY_VOLUME_DOWN}'), value *' - -FUNCTION_POWER_RELEASED_EVENT='*(KEY_POWER), value 0' -FUNCTION_POWER_PRESSED_EVENT='*(KEY_POWER), value 1' - -FUNCTION_LID_OPEN_EVENT='*(SW_LID), value 0' -FUNCTION_LID_CLOSE_EVENT='*(SW_LID), value 1' - -### Define matching function hotkeys from controller values, but allow them to be overridden in system.cfg. -KEYA_MODIFIER=$(get_setting key.function.a) -[ -z "${KEYA_MODIFIER}" ] && KEYA_MODIFIER="${DEVICE_FUNC_KEYA_MODIFIER}" - -KEYB_MODIFIER=$(get_setting key.function.b) -[ -z "${KEYB_MODIFIER}" ] && KEYB_MODIFIER="${DEVICE_FUNC_KEYB_MODIFIER}" - -FUNCTION_MODIFIER_A_EVENT='*('${KEYA_MODIFIER}'), value *' -FUNCTION_MODIFIER_B_EVENT='*('${KEYB_MODIFIER}'), value *' - -BTN_HOTKEY_A_MODIFIER=$(get_setting key.hotkey.a) -[ -z "${BTN_HOTKEY_A_MODIFIER}" ] && BTN_HOTKEY_A_MODIFIER="BTN_TL" - -BTN_HOTKEY_B_MODIFIER=$(get_setting key.hotkey.b) -[ -z "${BTN_HOTKEY_B_MODIFIER}" ] && BTN_HOTKEY_B_MODIFIER="BTN_SELECT" - -BTN_HOTKEY_C_MODIFIER=$(get_setting key.hotkey.c) -[ -z "${BTN_HOTKEY_C_MODIFIER}" ] && BTN_HOTKEY_C_MODIFIER="BTN_START" - -HOTKEY_A_PRESSED=false -HOTKEY_B_PRESSED=false -HOTKEY_C_PRESSED=false - -FUNCTION_HOTKEY_A_EVENT='*('${BTN_HOTKEY_A_MODIFIER}'), value *' -FUNCTION_HOTKEY_B_EVENT='*('${BTN_HOTKEY_B_MODIFIER}'), value *' -FUNCTION_HOTKEY_C_EVENT='*('${BTN_HOTKEY_C_MODIFIER}'), value *' - -FUNCTION_HOTKEY_BTN_WEST_EVENT="*(BTN_WEST), value 1*" -FUNCTION_HOTKEY_BTN_EAST_EVENT="*(BTN_EAST), value 1*" - -FUNCTION_HOTKEY_TOUCH_EVENT="*(BTN_TOUCH), value 1*" - -TOUCHSCREEN_EVENTS=$(get_setting key.touchscreen.events) -if [ -z "${TOUCHSCREEN_EVENTS}" ] || [ "${TOUCHSCREEN_EVENTS}" = "0" ]; then - TOUCHSCREEN_EVENTS=false -else - TOUCHSCREEN_EVENTS=true -fi - -### Define static values for dpad buttons and as a hat. -FUNCTION_HOTKEY_DPAD_UP_EVENT="*(BTN_DPAD_UP), value 1*" -FUNCTION_HOTKEY_DPAD_DOWN_EVENT="*(BTN_DPAD_DOWN), value 1*" -FUNCTION_HOTKEY_DPAD_RIGHT_EVENT="*(BTN_DPAD_RIGHT), value 1*" -FUNCTION_HOTKEY_DPAD_LEFT_EVENT="*(BTN_DPAD_LEFT), value 1*" - -FUNCTION_HOTKEY_HAT_UP_EVENT="*(ABS_HAT0Y), value -1*" -FUNCTION_HOTKEY_HAT_DOWN_EVENT="*(ABS_HAT0Y), value 1*" -FUNCTION_HOTKEY_HAT_RIGHT_EVENT="*(ABS_HAT0X), value 1*" -FUNCTION_HOTKEY_HAT_LEFT_EVENT="*(ABS_HAT0X), value -1*" - -DPAD_EVENTS=$(get_setting key.dpad.events) -if [ -z "${DPAD_EVENTS}" ] || [ "${DPAD_EVENTS}" = "0" ]; then - DPAD_EVENTS=false -else - DPAD_EVENTS=true -fi - -CONTROLLER_DISCONNECTED="*error reading: No such device" -DEVICE_DISCONNECTED="*error reading: No such device" - -### Matches if a button was pressed (1), released (0) or held down (2) -PRESS='value 1' -REPEAT='value 2' -RELEASE='value 0' - -### Function buttons should be defined as not pressed for later matching. -FN_A_PRESSED=false -FN_B_PRESSED=false - -### Volume repeat variables -VOLUME_REPEAT_DELAY=0.3 # Initial delay before repeating starts (seconds) -VOLUME_REPEAT_INTERVAL=0.1 # Interval between repeats (seconds) -VOLUME_UP_PRESSED=false -VOLUME_DOWN_PRESSED=false -VOLUME_REPEAT_PID="" - -### Allow actions to be overridden in system.cfg -FN_A_ACTION_UP="$(get_setting key.function.a.up)" -FN_A_ACTION_DOWN="$(get_setting key.function.a.down)" -FN_B_ACTION_UP="$(get_setting key.function.b.up)" -FN_B_ACTION_DOWN="$(get_setting key.function.b.down)" -FN_AB_ACTION_UP="$(get_setting key.function.ab.up)" -FN_AB_ACTION_DOWN="$(get_setting key.function.ab.down)" - -### Set sane defaults to manage volume, brightness, wireless on/off, and led on/off. -[ -z "${FN_A_ACTION_UP}" ] && FN_A_ACTION_UP="brightness up" -[ -z "${FN_A_ACTION_DOWN}" ] && FN_A_ACTION_DOWN="brightness down" -[ -z "${FN_B_ACTION_UP}" ] && FN_B_ACTION_UP="ledcontrol" -[ -z "${FN_B_ACTION_DOWN}" ] && FN_B_ACTION_DOWN="ledcontrol poweroff" -[ -z "${FN_AB_ACTION_UP}" ] && FN_AB_ACTION_UP="wifictl enable" -[ -z "${FN_AB_ACTION_DOWN}" ] && FN_AB_ACTION_DOWN="wifictl disable" - -### Volume repeat function -start_volume_repeat() { - local direction=$1 - - # Stop any existing volume repeat - stop_volume_repeat - - # Initial volume adjustment - volume ${direction} - - # Start background process for repeating volume adjustments - ( - sleep ${VOLUME_REPEAT_DELAY} - while true; do - # Check if button is still pressed before adjusting - if { [ "${direction}" = "up" ] && [ "${VOLUME_UP_PRESSED}" = true ]; } || \ - { [ "${direction}" = "down" ] && [ "${VOLUME_DOWN_PRESSED}" = true ]; }; then - volume ${direction} - sleep ${VOLUME_REPEAT_INTERVAL} - else - break - fi - done - ) & - - VOLUME_REPEAT_PID=$! - ${DEBUG} && log $0 "Started volume repeat (${direction}) with PID: ${VOLUME_REPEAT_PID}" -} - -stop_volume_repeat() { - if [ -n "${VOLUME_REPEAT_PID}" ]; then - kill ${VOLUME_REPEAT_PID} 2>/dev/null - wait ${VOLUME_REPEAT_PID} 2>/dev/null - ${DEBUG} && log $0 "Stopped volume repeat with PID: ${VOLUME_REPEAT_PID}" - fi - VOLUME_REPEAT_PID="" -} - -### Simple functions to execute button actions, including global kill. -execute_kill() { - if [ -e "/tmp/.process-kill-data" ]; then - TO_KILL="$(cat /tmp/.process-kill-data)" - ${DEBUG} && log $0 "Execute: killall ${TO_KILL}" - killall ${TO_KILL} 2>/dev/null - fi -} - -execute_action() { - ${DEBUG} && log $0 "${1}|${FN_A_PRESSED}|${FN_B_PRESSED}|${DPAD_UP_PRESSED}|${DPAD_DOWN_PRESSED}|${DPAD_RIGHT_PRESSED}|${DPAD_LEFT_PRESSED}" - if [ "${FN_A_PRESSED}" = true ] && [ "${FN_B_PRESSED}" = true ]; then - ${DEBUG} && log $0 "Executing FN_AB action" - case ${1} in - up) - ${DEBUG} && log $0 "FN_AB (${FN_AB_ACTION_UP})" - ${FN_AB_ACTION_UP} - ;; - down) - ${DEBUG} && log $0 "FN_AB (${FN_AB_ACTION_DOWN})" - ${FN_AB_ACTION_DOWN} - ;; - esac - elif [ "${FN_A_PRESSED}" = true ] && [ "${FN_B_PRESSED}" = false ]; then - ${DEBUG} && log $0 "Executing FN_A action" - case ${1} in - up) - ${DEBUG} && log $0 "FN_A (${FN_A_ACTION_UP})" - ${FN_A_ACTION_UP} - ;; - down) - ${DEBUG} && log $0 "FN_A (${FN_A_ACTION_DOWN})" - ${FN_A_ACTION_DOWN} - ;; - esac - elif [ "${FN_A_PRESSED}" = false ] && [ "${FN_B_PRESSED}" = true ]; then - ${DEBUG} && log $0 "Executing FN_B action" - case ${1} in - up) - ${DEBUG} && log $0 "FN_B (${FN_B_ACTION_UP})" - ${FN_B_ACTION_UP} - ;; - down) - ${DEBUG} && log $0 "FN_B (${FN_B_ACTION_DOWN})" - ${FN_B_ACTION_DOWN} - ;; - esac - else - # If neither FN_A nor FN_B is pressed, treat it as a volume control - volume ${1} - fi -} - -### Search the system for useful devices to monitor for inputs. -INPUT_DEVICES=() - -get_devices() { - local KJDEVS=false - local FOUNDKEYS=false - local FOUNDJOY=false - local FOUNDTOUCH=false - local RETRY=5 - - while [ ${KJDEVS} = false ]; do - for DEV in /dev/input/ev* - do - unset SUPPORTS - SUPPORTS=$(udevadm info ${DEV} | awk '/ID_INPUT_KEY=|ID_INPUT_JOYSTICK=|ID_INPUT_TOUCHSCREEN=/ {print $2}') - if [ -n "${SUPPORTS}" ]; then - DEVICE=$(udevadm info ${DEV} | awk 'BEGIN {FS="="} /DEVNAME=/ {print $2}') - INPUT_DEVICES+=("${DEVICE}") - if [[ "${SUPPORTS}" =~ ID_INPUT_KEY ]]; then - ${DEBUG} && log $0 "Found Keyboard: ${DEVICE}" - FOUNDKEYS=true - elif [[ "${SUPPORTS}" =~ ID_INPUT_TOUCHSCREEN ]]; then - ${DEBUG} && log $0 "Found Touchscreen: ${DEVICE}" - FOUNDTOUCH=true - elif [[ "${SUPPORTS}" =~ ID_INPUT_JOYSTICK ]]; then - ${DEBUG} && log $0 "Found Joystick: ${DEVICE}" - FOUNDJOY=true - fi - fi - done - - if [ "${FOUNDKEYS}" = "true" ] && [ "${FOUNDJOY}" = "true" ]; then - ${DEBUG} && log $0 "Found all needed devices." - KJDEVS=true - break - fi - - if [ "${RETRY}" -ge 5 ]; then - ${DEBUG} && log $0 "Did not find all needed devices, but continuing anyway." - ${DEBUG} && log $0 "Did not find all of the needed devices, but that may be OK. Breaking." - break - else - RETRY=$(( RETRY + 1 )) - fi - - sleep 1 - done -} - -get_devices - -# If the input devices change, it may be a new controller -# so handle it here. -mkcontroller 2>/dev/null || : - -# ------------------------------------------------------------------ -# Turn OFF 'exit on error' *now* so a single evtest crash won't kill -# the entire script. We still keep 'pipefail' for partial debugging. -# ------------------------------------------------------------------ -set +e - -### Start multiple evtest loops, each continuously restarted on failure. Take action when a known pattern of keys are pressed together. -( - for INPUT_DEVICE in "${INPUT_DEVICES[@]}"; do - ( - while true - do - evtest "${INPUT_DEVICE}" 2>&1 - # If evtest exits, wait briefly and restart - echo "evtest for ${INPUT_DEVICE} died; restarting in 1 second..." >&2 - sleep 1 - done - ) & - done - - wait # Wait for all background loops (they never end unless forcibly stopped) -) | while read line; do - - # Parse lines from any evtest instance: - case ${line} in - (${CONTROLLER_DISCONNECTED}) - ${DEBUG} && log $0 "Reloading due to ${CONTROLLER_DEVICE} reattach..." - get_devices - ;; - (${DEVICE_DISCONNECTED}) - ${DEBUG} && log $0 "Reloading due to ${DEVICE} reattach..." - get_devices - ;; - (${FUNCTION_MODIFIER_A_EVENT}) - if [[ "${line}" =~ ${PRESS} ]]; then - ${DEBUG} && log $0 "${FUNCTION_MODIFIER_A_EVENT}: Pressed" - FN_A_PRESSED=true - elif [[ "${line}" =~ ${RELEASE} ]]; then - ${DEBUG} && log $0 "${FUNCTION_MODIFIER_A_EVENT}: Released" - FN_A_PRESSED=false - fi - ;; - (${FUNCTION_MODIFIER_B_EVENT}) - if [[ "${line}" =~ ${PRESS} ]]; then - ${DEBUG} && log $0 "${FUNCTION_MODIFIER_B_EVENT}: Pressed" - FN_B_PRESSED=true - elif [[ "${line}" =~ ${RELEASE} ]]; then - ${DEBUG} && log $0 "${FUNCTION_MODIFIER_B_EVENT}: Released" - FN_B_PRESSED=false - fi - ;; - (${FUNCTION_VOLUME_UP_EVENT}) - if [[ "${line}" =~ ${PRESS} ]]; then - ${DEBUG} && log $0 "Volume Up: Pressed" - VOLUME_UP_PRESSED=true - # Only start volume repeat if no function keys are pressed - if [ "${FN_A_PRESSED}" = false ] && [ "${FN_B_PRESSED}" = false ]; then - start_volume_repeat up - else - # If function keys are pressed, use the original behavior - execute_action up - fi - elif [[ "${line}" =~ ${RELEASE} ]]; then - ${DEBUG} && log $0 "Volume Up: Released" - VOLUME_UP_PRESSED=false - stop_volume_repeat - fi - ;; - (${FUNCTION_VOLUME_DOWN_EVENT}) - if [[ "${line}" =~ ${PRESS} ]]; then - ${DEBUG} && log $0 "Volume Down: Pressed" - VOLUME_DOWN_PRESSED=true - # Only start volume repeat if no function keys are pressed - if [ "${FN_A_PRESSED}" = false ] && [ "${FN_B_PRESSED}" = false ]; then - start_volume_repeat down - else - # If function keys are pressed, use the original behavior - execute_action down - fi - elif [[ "${line}" =~ ${RELEASE} ]]; then - ${DEBUG} && log $0 "Volume Down: Released" - VOLUME_DOWN_PRESSED=false - stop_volume_repeat - fi - ;; - (${FUNCTION_POWER_PRESSED_EVENT}) - ${DEBUG} && log $0 "${FUNCTION_POWER_PRESSED_EVENT}: Pressed" - /usr/bin/rocknix-fake-suspend power & - ;; - (${FUNCTION_LID_CLOSE_EVENT}) - ${DEBUG} && log $0 "${FUNCTION_LID_CLOSE_EVENT}: Close" - /usr/bin/rocknix-fake-suspend lid close & - ;; - (${FUNCTION_LID_OPEN_EVENT}) - ${DEBUG} && log $0 "${FUNCTION_LID_OPEN_EVENT}: Open" - /usr/bin/rocknix-fake-suspend lid open & - ;; - esac - - # Hotkey logic - case ${line} in - (${FUNCTION_HOTKEY_A_EVENT}) - if [[ "${line}" =~ ${PRESS} ]]; then - ${DEBUG} && log $0 "${FUNCTION_HOTKEY_A_EVENT}: Pressed" - HOTKEY_A_PRESSED=true - elif [[ "${line}" =~ ${RELEASE} ]]; then - ${DEBUG} && log $0 "${FUNCTION_HOTKEY_A_EVENT}: Released" - HOTKEY_A_PRESSED=false - fi - ;; - (${FUNCTION_HOTKEY_B_EVENT}) - if [[ "${line}" =~ ${PRESS} ]]; then - ${DEBUG} && log $0 "${FUNCTION_HOTKEY_B_EVENT}: Pressed" - HOTKEY_B_PRESSED=true - # Example: if A and C are also pressed => kill something - if [ "${HOTKEY_A_PRESSED}" = true ] && [ "${HOTKEY_C_PRESSED}" = true ]; then - execute_kill - fi - elif [[ "${line}" =~ ${RELEASE} ]]; then - ${DEBUG} && log $0 "${FUNCTION_HOTKEY_B_EVENT}: Released" - HOTKEY_B_PRESSED=false - fi - ;; - (${FUNCTION_HOTKEY_C_EVENT}) - if [[ "${line}" =~ ${PRESS} ]]; then - ${DEBUG} && log $0 "${FUNCTION_HOTKEY_C_EVENT}: Pressed" - HOTKEY_C_PRESSED=true - # Example: if A and B are also pressed => kill something - if [ "${HOTKEY_A_PRESSED}" = true ] && [ "${HOTKEY_B_PRESSED}" = true ]; then - execute_kill - fi - elif [[ "${line}" =~ ${RELEASE} ]]; then - ${DEBUG} && log $0 "${FUNCTION_HOTKEY_C_EVENT}: Released" - HOTKEY_C_PRESSED=false - fi - ;; - (${FUNCTION_HOTKEY_DPAD_UP_EVENT}|${FUNCTION_HOTKEY_HAT_UP_EVENT}) - if [ "${FN_A_PRESSED}" = true ] && [ "${DPAD_EVENTS}" = true ]; then - ${DEBUG} && log $0 "${FUNCTION_HOTKEY_DPAD_UP_EVENT}${FUNCTION_HOTKEY_HAT_UP_EVENT}: Volume Up" - volume up - fi - ;; - (${FUNCTION_HOTKEY_DPAD_DOWN_EVENT}|${FUNCTION_HOTKEY_HAT_DOWN_EVENT}) - if [ "${FN_A_PRESSED}" = true ] && [ "${DPAD_EVENTS}" = true ]; then - ${DEBUG} && log $0 "${FUNCTION_HOTKEY_DPAD_DOWN_EVENT}${FUNCTION_HOTKEY_HAT_DOWN_EVENT}: Volume Down" - volume down - fi - ;; - (${FUNCTION_HOTKEY_DPAD_RIGHT_EVENT}|${FUNCTION_HOTKEY_HAT_RIGHT_EVENT}) - if [ "${FN_A_PRESSED}" = true ] && [ "${DPAD_EVENTS}" = true ]; then - ${DEBUG} && log $0 "${FUNCTION_HOTKEY_DPAD_RIGHT_EVENT}${FUNCTION_HOTKEY_HAT_RIGHT_EVENT}: Brightness Up" - brightness up - fi - ;; - (${FUNCTION_HOTKEY_DPAD_LEFT_EVENT}|${FUNCTION_HOTKEY_HAT_LEFT_EVENT}) - if [ "${FN_A_PRESSED}" = true ] && [ "${DPAD_EVENTS}" = true ]; then - ${DEBUG} && log $0 "${FUNCTION_HOTKEY_DPAD_LEFT_EVENT}${FUNCTION_HOTKEY_HAT_LEFT_EVENT}: Brightness Down" - brightness down - fi - ;; - (${FUNCTION_HOTKEY_TOUCH_EVENT}) - if [ "${FN_A_PRESSED}" = true ] && [ "${TOUCHSCREEN_EVENTS}" = true ]; then - ${DEBUG} && log $0 "${FUNCTION_HOTKEY_TOUCH_EVENT}: Toggle Touchscreen Keyboard" - kill -34 $(pidof wvkbd-mobintl) - fi - ;; - (${FUNCTION_HOTKEY_BTN_EAST_EVENT}) - if [ "${FN_A_PRESSED}" = true ]; then - ${DEBUG} && log $0 "${FUNCTION_HOTKEY_BTN_EAST_EVENT}: Screenshot Taken" - /usr/bin/rocknix-screenshot - fi - ;; - (${FUNCTION_HOTKEY_BTN_WEST_EVENT}) - if [ "${FN_A_PRESSED}" = true ]; then - ${DEBUG} && log $0 "${FUNCTION_HOTKEY_BTN_WEST_EVENT}: Config MangoHud" - /usr/bin/mangohud_set toggle - fi - ;; - esac -done diff --git a/projects/ROCKNIX/packages/tools/rocknix-input-sense/package.mk b/projects/ROCKNIX/packages/tools/rocknix-input-sense/package.mk new file mode 100644 index 00000000000..61378f845a4 --- /dev/null +++ b/projects/ROCKNIX/packages/tools/rocknix-input-sense/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 ROCKNIX (https://github.com/ROCKNIX) + +PKG_NAME="rocknix-input-sense" +PKG_VERSION="1.0" +PKG_LICENSE="GPL" +PKG_SITE="https://rocknix.org" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain libevdev" +PKG_LONGDESC="ROCKNIX input sense application" + +post_install() { + enable_service input-sense.service +} diff --git a/projects/ROCKNIX/packages/tools/rocknix-input-sense/sources/Makefile b/projects/ROCKNIX/packages/tools/rocknix-input-sense/sources/Makefile new file mode 100644 index 00000000000..164a2640b35 --- /dev/null +++ b/projects/ROCKNIX/packages/tools/rocknix-input-sense/sources/Makefile @@ -0,0 +1,38 @@ +# Source files to be compiled +SRCS=input-sense.c + +# Generate object file names from source files by replacing .c with .o +OBJS=$(SRCS:.c=.o) + +# Name of the final executable +TARGET=input-sense + +# Installation directory +PREFIX=/usr +BINDIR=$(PREFIX)/bin + +# Libraries to link against +LDLIBS = -levdev + +# Declare phony targets that don't represent actual files +.PHONY: all clean install + +# Default target that builds everything +all: $(TARGET) + +# Link object files to create the final executable +$(TARGET): $(OBJS) + $(CC) $(OBJS) -o $(TARGET) $(LDFLAGS) $(LDLIBS) + +# Generic rule for compiling .c files into .o files +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +# Install the executable +install: $(TARGET) + install -d $(DESTDIR)$(BINDIR) + install -m 755 $(TARGET) $(DESTDIR)$(BINDIR) + +# Clean target removes all generated files +clean: + rm -f $(OBJS) $(TARGET) diff --git a/projects/ROCKNIX/packages/tools/rocknix-input-sense/sources/input-sense.c b/projects/ROCKNIX/packages/tools/rocknix-input-sense/sources/input-sense.c new file mode 100644 index 00000000000..0bed53ccf9a --- /dev/null +++ b/projects/ROCKNIX/packages/tools/rocknix-input-sense/sources/input-sense.c @@ -0,0 +1,402 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2024-present ROCKNIX (https://github.com/ROCKNIX) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// --- Defines --- +#define MAX_DEVICES 10 +#define ES_CONF "/storage/.config/system/configs/system.cfg" + +// --- Global State & Configuration --- +static bool DEBUG_MODE = false; + +// Modifier key states +static bool FN_A_PRESSED = false; +static bool FN_B_PRESSED = false; +static bool HOTKEY_A_PRESSED = false; +static bool HOTKEY_B_PRESSED = false; +static bool HOTKEY_C_PRESSED = false; + +// Feature flags +static bool TOUCHSCREEN_EVENTS_ENABLED = false; +static bool DPAD_EVENTS_ENABLED = false; + +// Mapped key codes from config +static int KEY_VOLUME_UP_CODE = KEY_VOLUMEUP; +static int KEY_VOLUME_DOWN_CODE = KEY_VOLUMEDOWN; +static int KEY_POWER_CODE = KEY_POWER; +static int SW_LID_CODE = SW_LID; +static int KEYA_MODIFIER_CODE = -1; +static int KEYB_MODIFIER_CODE = -1; +static int BTN_HOTKEY_A_MODIFIER_CODE = BTN_TL; +static int BTN_HOTKEY_B_MODIFIER_CODE = BTN_SELECT; +static int BTN_HOTKEY_C_MODIFIER_CODE = BTN_START; + + +// --- Utility Functions --- + +/** + * @brief Prints a message to stdout if DEBUG_MODE is enabled. + */ +static void log_msg(const char *format, ...) { + if (DEBUG_MODE) { + va_list args; + va_start(args, format); + vprintf(format, args); + va_end(args); + } +} + +/** + * @brief Executes a shell command using system(). + */ +static void execute_command(const char *command) { + if (!command || strlen(command) == 0) return; + log_msg("Executing command: %s\n", command); + system(command); +} + +/** + * @brief Converts a string key name (e.g., "BTN_SELECT") to its Linux integer code. + * @return The integer code, or -1 if not found. + */ +static int get_code_from_name(const char *name) { + if (!name || strlen(name) == 0) return -1; + int code = libevdev_event_code_from_name(EV_KEY, name); + if (code != -1) return code; + code = libevdev_event_code_from_name(EV_SW, name); + if (code != -1) return code; + fprintf(stderr, "Warning: Key name '%s' not found by libevdev.\n", name); + return -1; +} + + +// --- Configuration File Parser --- + +/** + * @brief Searches a file for a key and returns its value. + * @note The caller is responsible for freeing the returned string. + * @return Allocated string with the value, or NULL if not found. + */ +static char* find_value_for_key(const char* filepath, const char* full_key) { + FILE* f = fopen(filepath, "r"); + if (!f) return NULL; + + char* line = NULL; + size_t len = 0; + char* result = NULL; + char search_pattern[256]; + snprintf(search_pattern, sizeof(search_pattern), "%s=", full_key); + size_t pattern_len = strlen(search_pattern); + + while (getline(&line, &len, f) != -1) { + if (strncmp(line, search_pattern, pattern_len) == 0) { + char* value_start = line + pattern_len; + value_start[strcspn(value_start, "\r\n")] = 0; // Trim newline + result = strdup(value_start); + break; + } + } + + free(line); + fclose(f); + return result; +} + +/** + * @brief Gets a setting from ES_CONF, mimicking the shell function's priority. + * @note The caller is responsible for freeing the returned string. + * @return Allocated string with the value, or NULL if not found. + */ +static char* get_setting(const char* key) { + char* result = NULL; + char full_key[256]; + + // 1. Try the key directly (e.g., "system.loglevel") + result = find_value_for_key(ES_CONF, key); + if (result) return result; + + // 2. Try with "system." prefix if it doesn't have one + if (strncmp(key, "system.", 7) != 0) { + snprintf(full_key, sizeof(full_key), "system.%s", key); + result = find_value_for_key(ES_CONF, full_key); + if (result) return result; + } + + // 3. Try with "global." prefix + snprintf(full_key, sizeof(full_key), "global.%s", key); + result = find_value_for_key(ES_CONF, full_key); + if (result) return result; + + // 4. Try the key name without any prefix + const char* key_part = strrchr(key, '.'); + if (key_part && *(key_part + 1) != '\0') { + result = find_value_for_key(ES_CONF, key_part + 1); + } + + return result; +} + + +// --- Core Logic --- + +/** + * @brief Reads /tmp/.process-kill-data and kills the specified process. + */ +static void execute_kill() { + FILE *f = fopen("/tmp/.process-kill-data", "r"); + if (f) { + char to_kill[256] = {0}; + if (fgets(to_kill, sizeof(to_kill) - 1, f)) { + to_kill[strcspn(to_kill, "\r\n")] = 0; + if (strlen(to_kill) > 0) { + char kill_cmd[300]; + snprintf(kill_cmd, sizeof(kill_cmd), "killall %s 2>/dev/null", to_kill); + execute_command(kill_cmd); + } + } + fclose(f); + } +} + +/** + * @brief Executes actions based on which function keys are held down. + */ +static void execute_action(const char* direction) { + log_msg("Action Trigger: %s | FN_A:%d | FN_B:%d\n", direction, FN_A_PRESSED, FN_B_PRESSED); + + char* action = NULL; + char key[64]; // Buffer for the setting key + + // Check for FN key combinations first + if (FN_A_PRESSED && FN_B_PRESSED) { + snprintf(key, sizeof(key), "key.function.ab.%s", direction); + action = get_setting(key); + } else if (FN_A_PRESSED) { + snprintf(key, sizeof(key), "key.function.a.%s", direction); + action = get_setting(key); + } else if (FN_B_PRESSED) { + snprintf(key, sizeof(key), "key.function.b.%s", direction); + action = get_setting(key); + } + + // If an action was found in the config, execute it. + // Otherwise, fall back to the default volume command. + if (action && strlen(action) > 0) { + execute_command(action); + } else { + char cmd[32]; + snprintf(cmd, sizeof(cmd), "volume %s", direction); + execute_command(cmd); + } + free(action); // Safely free memory (free(NULL) is safe) +} + +/** + * @brief Reads the config file and populates all global setting variables. + */ +static void load_configuration() { + char* temp_setting; + + temp_setting = get_setting("system.loglevel"); + if (temp_setting && strcmp(temp_setting, "verbose") == 0) { + DEBUG_MODE = true; + printf("Verbose logging enabled.\n"); + } + free(temp_setting); + + temp_setting = get_setting("key.volume.up"); + if (temp_setting) { KEY_VOLUME_UP_CODE = get_code_from_name(temp_setting); free(temp_setting); } + + temp_setting = get_setting("key.volume.down"); + if (temp_setting) { KEY_VOLUME_DOWN_CODE = get_code_from_name(temp_setting); free(temp_setting); } + + temp_setting = get_setting("key.function.a"); + if (temp_setting) { KEYA_MODIFIER_CODE = get_code_from_name(temp_setting); free(temp_setting); } + + temp_setting = get_setting("key.function.b"); + if (temp_setting) { KEYB_MODIFIER_CODE = get_code_from_name(temp_setting); free(temp_setting); } + + temp_setting = get_setting("key.hotkey.a"); + if (temp_setting) { BTN_HOTKEY_A_MODIFIER_CODE = get_code_from_name(temp_setting); free(temp_setting); } + + temp_setting = get_setting("key.hotkey.b"); + if (temp_setting) { BTN_HOTKEY_B_MODIFIER_CODE = get_code_from_name(temp_setting); free(temp_setting); } + + temp_setting = get_setting("key.hotkey.c"); + if (temp_setting) { BTN_HOTKEY_C_MODIFIER_CODE = get_code_from_name(temp_setting); free(temp_setting); } + + temp_setting = get_setting("key.touchscreen.events"); + if (temp_setting && strcmp(temp_setting, "0") != 0) TOUCHSCREEN_EVENTS_ENABLED = true; + free(temp_setting); + + temp_setting = get_setting("key.dpad.events"); + if (temp_setting && strcmp(temp_setting, "0") != 0) DPAD_EVENTS_ENABLED = true; + free(temp_setting); + + log_msg("Config loaded. VOL_UP:%d, VOL_DOWN:%d, FN_A:%d, FN_B:%d\n", + KEY_VOLUME_UP_CODE, KEY_VOLUME_DOWN_CODE, KEYA_MODIFIER_CODE, KEYB_MODIFIER_CODE); +} + + +// --- Device and Event Handling --- + +/** + * @brief Scans /dev/input for usable event devices and opens them. + * @return The number of devices opened. + */ +static int find_and_open_devices(int fds[], int max_fds) { + DIR *dir; + struct dirent *entry; + int count = 0; + + if ((dir = opendir("/dev/input")) == NULL) { + perror("Error opening /dev/input"); + return 0; + } + + while ((entry = readdir(dir)) != NULL && count < max_fds) { + if (strncmp(entry->d_name, "event", 5) == 0) { + char path[512]; + snprintf(path, sizeof(path), "/dev/input/%s", entry->d_name); + int fd = open(path, O_RDONLY | O_NONBLOCK); + if (fd < 0) continue; + + // Check if device has keys, switches, or absolute axes (for joysticks) + unsigned long ev_bits[EV_MAX / (sizeof(long) * 8) + 1] = {0}; + ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits); + if ((ev_bits[0] & (1 << EV_KEY)) || (ev_bits[0] & (1 << EV_SW)) || (ev_bits[0] & (1 << EV_ABS))) { + fds[count++] = fd; + log_msg("Monitoring device: %s\n", path); + } else { + close(fd); + } + } + } + closedir(dir); + return count; +} + +/** + * @brief Processes a single input event and takes action if necessary. + */ +static void process_event(const struct input_event *ev) { + // Modifier key state updates + if (ev->type == EV_KEY) { + if (ev->code == KEYA_MODIFIER_CODE) { FN_A_PRESSED = ev->value; log_msg("FN_A state: %d\n", ev->value); } + if (ev->code == KEYB_MODIFIER_CODE) { FN_B_PRESSED = ev->value; log_msg("FN_B state: %d\n", ev->value); } + if (ev->code == BTN_HOTKEY_A_MODIFIER_CODE) { HOTKEY_A_PRESSED = ev->value; log_msg("HOTKEY_A state: %d\n", ev->value); } + if (ev->code == BTN_HOTKEY_B_MODIFIER_CODE) { HOTKEY_B_PRESSED = ev->value; log_msg("HOTKEY_B state: %d\n", ev->value); } + if (ev->code == BTN_HOTKEY_C_MODIFIER_CODE) { HOTKEY_C_PRESSED = ev->value; log_msg("HOTKEY_C state: %d\n", ev->value); } + } + + // Handle actions that occur only on press (value=1) or HAT events + if (ev->value == 1 || ev->type == EV_ABS) { + // System-level actions (Volume, Power) + if (ev->type == EV_KEY && ev->code == KEY_VOLUME_UP_CODE) execute_action("up"); + if (ev->type == EV_KEY && ev->code == KEY_VOLUME_DOWN_CODE) execute_action("down"); + if (ev->type == EV_KEY && ev->code == KEY_POWER_CODE) execute_command("/usr/bin/rocknix-fake-suspend power &"); + + // Hotkey combinations + if (HOTKEY_A_PRESSED && HOTKEY_B_PRESSED && ev->code == BTN_HOTKEY_C_MODIFIER_CODE) execute_kill(); + if (HOTKEY_A_PRESSED && HOTKEY_C_PRESSED && ev->code == BTN_HOTKEY_B_MODIFIER_CODE) execute_kill(); + + // FN+A combinations + if (FN_A_PRESSED) { + if (ev->type == EV_KEY && ev->code == BTN_EAST) execute_command("/usr/bin/rocknix-screenshot"); + if (ev->type == EV_KEY && ev->code == BTN_WEST) execute_command("/usr/bin/mangohud_set toggle"); + if (TOUCHSCREEN_EVENTS_ENABLED && ev->type == EV_KEY && ev->code == BTN_TOUCH) execute_command("kill -34 $(pidof wvkbd-mobintl)"); + if (DPAD_EVENTS_ENABLED) { + if (ev->type == EV_KEY && ev->code == BTN_DPAD_UP) execute_command("volume up"); + if (ev->type == EV_KEY && ev->code == BTN_DPAD_DOWN) execute_command("volume down"); + if (ev->type == EV_KEY && ev->code == BTN_DPAD_RIGHT) execute_command("brightness up"); + if (ev->type == EV_KEY && ev->code == BTN_DPAD_LEFT) execute_command("brightness down"); + if (ev->type == EV_ABS && ev->code == ABS_HAT0Y && ev->value == -1) execute_command("volume up"); + if (ev->type == EV_ABS && ev->code == ABS_HAT0Y && ev->value == 1) execute_command("volume down"); + if (ev->type == EV_ABS && ev->code == ABS_HAT0X && ev->value == 1) execute_command("brightness up"); + if (ev->type == EV_ABS && ev->code == ABS_HAT0X && ev->value == -1) execute_command("brightness down"); + } + } + } + + // Lid switch (value 1=closed, 0=open) + if (ev->type == EV_SW && ev->code == SW_LID_CODE) { + if (ev->value == 1) execute_command("/usr/bin/rocknix-fake-suspend lid close &"); + if (ev->value == 0) execute_command("/usr/bin/rocknix-fake-suspend lid open &"); + } +} + + +// --- Main Application Loop --- + +int main(void) { + int fds[MAX_DEVICES]; + int device_count; + + load_configuration(); + execute_command("mkcontroller 2>/dev/null || :"); + + while (1) { + device_count = find_and_open_devices(fds, MAX_DEVICES); + if (device_count == 0) { + fprintf(stderr, "No input devices found. Retrying in 5 seconds...\n"); + sleep(5); + continue; + } + printf("Monitoring %d devices. Waiting for events...\n", device_count); + + bool devices_changed = false; + while (!devices_changed) { + fd_set read_fds; + FD_ZERO(&read_fds); + int max_fd = 0; + for (int i = 0; i < device_count; i++) { + FD_SET(fds[i], &read_fds); + if (fds[i] > max_fd) max_fd = fds[i]; + } + + // Wait for an event on any device + int result = select(max_fd + 1, &read_fds, NULL, NULL, NULL); + if (result < 0 && errno != EINTR) { + perror("select() error"); + devices_changed = true; // Break inner loop to rescan + continue; + } + + for (int i = 0; i < device_count; i++) { + if (FD_ISSET(fds[i], &read_fds)) { + struct input_event ev; + ssize_t bytes = read(fds[i], &ev, sizeof(ev)); + if (bytes < (ssize_t)sizeof(ev)) { + // Error or device disconnected + fprintf(stderr, "Error reading from device fd %d. Assuming disconnect.\n", fds[i]); + devices_changed = true; + break; + } else { + process_event(&ev); + } + } + } + } + + // Cleanup FDs before rescanning + for (int i = 0; i < device_count; i++) close(fds[i]); + printf("Device change detected. Rescanning devices...\n"); + execute_command("mkcontroller 2>/dev/null || :"); + sleep(1); + } + + return 0; // Unreachable +} diff --git a/projects/ROCKNIX/packages/sysutils/system-utils/system.d/input.service b/projects/ROCKNIX/packages/tools/rocknix-input-sense/system.d/input-sense.service similarity index 62% rename from projects/ROCKNIX/packages/sysutils/system-utils/system.d/input.service rename to projects/ROCKNIX/packages/tools/rocknix-input-sense/system.d/input-sense.service index fc8fcdd47ee..89448360cfa 100644 --- a/projects/ROCKNIX/packages/sysutils/system-utils/system.d/input.service +++ b/projects/ROCKNIX/packages/tools/rocknix-input-sense/system.d/input-sense.service @@ -1,14 +1,12 @@ [Unit] -Description=Volume button service +Description=ROCKNIX input-sense service After=headphones.service Before=rocknix.target StartLimitIntervalSec=0 [Service] Environment=HOME=/storage -ExecStart=/usr/bin/input_sense -Restart=always -RestartSec=1 +ExecStart=/usr/bin/input-sense [Install] WantedBy=multi-user.target diff --git a/projects/ROCKNIX/packages/virtual/image/package.mk b/projects/ROCKNIX/packages/virtual/image/package.mk index 714c9c137de..cb54e951595 100644 --- a/projects/ROCKNIX/packages/virtual/image/package.mk +++ b/projects/ROCKNIX/packages/virtual/image/package.mk @@ -13,7 +13,7 @@ PKG_DEPENDS_TARGET="toolchain squashfs-tools:host dosfstools:host fakeroot:host ${BOOTLOADER} busybox umtprd util-linux usb-modeswitch unzip poppler jq socat \ p7zip file initramfs grep wget util-linux btrfs-progs zstd lz4 empty lzo libzip \ bash coreutils system-utils autostart quirks powerstate gnupg \ - gzip six xmlstarlet pyudev dialog dbus-python network rocknix" + gzip six xmlstarlet pyudev dialog dbus-python network rocknix rocknix-input-sense" PKG_UI="emulationstation es-themes textviewer" From 27e93ced3bb3cd676f1f2ca963a027f12b8a3a9b Mon Sep 17 00:00:00 2001 From: spycat88 Date: Sun, 12 Oct 2025 00:26:17 +0100 Subject: [PATCH 2/2] rocknix-input-sense: fix loading keys from enviroment --- .../rocknix-input-sense/sources/input-sense.c | 76 +++++++++++++------ .../system.d/input-sense.service | 4 +- 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/projects/ROCKNIX/packages/tools/rocknix-input-sense/sources/input-sense.c b/projects/ROCKNIX/packages/tools/rocknix-input-sense/sources/input-sense.c index 0bed53ccf9a..4b532eda04d 100644 --- a/projects/ROCKNIX/packages/tools/rocknix-input-sense/sources/input-sense.c +++ b/projects/ROCKNIX/packages/tools/rocknix-input-sense/sources/input-sense.c @@ -205,7 +205,8 @@ static void execute_action(const char* direction) { } /** - * @brief Reads the config file and populates all global setting variables. + * @brief Reads the config file and populates all global setting variables, + * using environment variables as fallbacks for function keys. */ static void load_configuration() { char* temp_setting; @@ -217,27 +218,58 @@ static void load_configuration() { } free(temp_setting); - temp_setting = get_setting("key.volume.up"); - if (temp_setting) { KEY_VOLUME_UP_CODE = get_code_from_name(temp_setting); free(temp_setting); } - - temp_setting = get_setting("key.volume.down"); - if (temp_setting) { KEY_VOLUME_DOWN_CODE = get_code_from_name(temp_setting); free(temp_setting); } - - temp_setting = get_setting("key.function.a"); - if (temp_setting) { KEYA_MODIFIER_CODE = get_code_from_name(temp_setting); free(temp_setting); } - - temp_setting = get_setting("key.function.b"); - if (temp_setting) { KEYB_MODIFIER_CODE = get_code_from_name(temp_setting); free(temp_setting); } - - temp_setting = get_setting("key.hotkey.a"); - if (temp_setting) { BTN_HOTKEY_A_MODIFIER_CODE = get_code_from_name(temp_setting); free(temp_setting); } - - temp_setting = get_setting("key.hotkey.b"); - if (temp_setting) { BTN_HOTKEY_B_MODIFIER_CODE = get_code_from_name(temp_setting); free(temp_setting); } - - temp_setting = get_setting("key.hotkey.c"); - if (temp_setting) { BTN_HOTKEY_C_MODIFIER_CODE = get_code_from_name(temp_setting); free(temp_setting); } - + // --- Macro Definitions --- + + // Macro for keys that ONLY read from the config file. + #define LOAD_KEY(config_key, var_name) \ + do { \ + temp_setting = get_setting(config_key); \ + if (temp_setting) { \ + var_name = get_code_from_name(temp_setting); \ + log_msg("Loaded %s: %s -> %d\n", config_key, temp_setting, var_name); \ + free(temp_setting); \ + } \ + } while (0) + + // Macro for keys that check config file FIRST, then an environment variable. + #define LOAD_KEY_WITH_ENV_FALLBACK(config_key, var_name, env_var_name) \ + do { \ + char* key_name_str = NULL; \ + temp_setting = get_setting(config_key); \ + if (temp_setting && strlen(temp_setting) > 0) { \ + key_name_str = temp_setting; \ + } else { \ + free(temp_setting); \ + char* env_val = getenv(env_var_name); \ + if (env_val && strlen(env_val) > 0) { \ + key_name_str = strdup(env_val); \ + } \ + } \ + if (key_name_str) { \ + var_name = get_code_from_name(key_name_str); \ + log_msg("Loaded %s (fallback %s): %s -> %d\n", config_key, env_var_name, key_name_str, var_name); \ + free(key_name_str); \ + } \ + } while (0) + + // --- Key Loading --- + + // Load standard keys (no fallback) + LOAD_KEY("key.volume.up", KEY_VOLUME_UP_CODE); + LOAD_KEY("key.volume.down", KEY_VOLUME_DOWN_CODE); + LOAD_KEY("key.hotkey.a", BTN_HOTKEY_A_MODIFIER_CODE); + LOAD_KEY("key.hotkey.b", BTN_HOTKEY_B_MODIFIER_CODE); + LOAD_KEY("key.hotkey.c", BTN_HOTKEY_C_MODIFIER_CODE); + + // Load function keys WITH environment variable fallbacks + LOAD_KEY_WITH_ENV_FALLBACK("key.function.a", KEYA_MODIFIER_CODE, "DEVICE_FUNC_KEYA_MODIFIER"); + LOAD_KEY_WITH_ENV_FALLBACK("key.function.b", KEYB_MODIFIER_CODE, "DEVICE_FUNC_KEYB_MODIFIER"); + + // Undefine the macros to keep the namespace clean + #undef LOAD_KEY + #undef LOAD_KEY_WITH_ENV_FALLBACK + + // Load feature flags temp_setting = get_setting("key.touchscreen.events"); if (temp_setting && strcmp(temp_setting, "0") != 0) TOUCHSCREEN_EVENTS_ENABLED = true; free(temp_setting); diff --git a/projects/ROCKNIX/packages/tools/rocknix-input-sense/system.d/input-sense.service b/projects/ROCKNIX/packages/tools/rocknix-input-sense/system.d/input-sense.service index 89448360cfa..83aa05093e6 100644 --- a/projects/ROCKNIX/packages/tools/rocknix-input-sense/system.d/input-sense.service +++ b/projects/ROCKNIX/packages/tools/rocknix-input-sense/system.d/input-sense.service @@ -6,7 +6,9 @@ StartLimitIntervalSec=0 [Service] Environment=HOME=/storage -ExecStart=/usr/bin/input-sense +ExecStart=/bin/bash -c "source /etc/profile && exec /usr/bin/input-sense" +Restart=always +RestartSec=2 [Install] WantedBy=multi-user.target