#!/bin/bash # SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021-present Fewtarius # 2021-present pkegg . /etc/profile set -e set -o pipefail LOG="/var/log/$(basename "$0").log" ### Summary # This script listens to volume keys and adjusts volume # Fn + Volume up/down will adjust brightness ### # Event examples for reference # type 1 (EV_KEY), code 114 (KEY_VOLUMEDOWN), value 1 # type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 1 VOL_EVENT='*(KEY_VOLUME*, value *' # This matches all volume events VOL_UP='*UP), value *' # Differentiate 'up' volume event VOL_DOWN='*DOWN), value *' #Differentiate 'down' volume event V_FUNC_KEYA_EVENT='*('${DEVICE_FUNC_KEYA_MODIFIER}'), value *' V_FUNC_KEYB_EVENT='*('${DEVICE_FUNC_KEYB_MODIFIER}'), value *' # Matches if a button was pressed (1), released (0) or held down (2) PRESS='value [1-9]' RELEASE='value 0' # Volume repeat VOLUME_REPEAT_MOD=4 # Brightness repeat BRIGHTNESS_REPEAT_MOD=4 # Variable to keep track of Fn being currently pressed FUNCA_PRESSED=no FUNCB_PRESSED=no CONTROLLER_DISCONNECTED="*error reading: No such device" DEVICE_DISCONNECTED="*error reading: No such device" get_devices() { KJDEVS=false FOUNDKEYS=false FOUNDJOY=false RETRY=5 while [ ${KJDEVS} = false ] do # Detect input devices automatically for DEV in /dev/input/ev* do unset SUPPORTS SUPPORTS=$(udevadm info ${DEV} | awk '/ID_INPUT_KEY=|ID_INPUT_JOYSTICK=/ {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 echo "Found Keyboard: ${DEVICE}" 2>&1 >${LOG} FOUNDKEYS=true elif [[ "${SUPPORTS}" =~ ID_INPUT_JOYSTICK ]] then echo "Found Joystick: ${DEVICE}" 2>&1 >${LOG} FOUNDJOY=true fi fi done if [ "${FOUNDKEYS}" = "true" ] && [ "${FOUNDJOY}" = "true" ] then echo "Found all of the needed devices." 2>&1 >${LOG} KJDEVS=true break fi if [ "${RETRY}" -ge 5 ] then echo "Did not find all of the needed devices, but that may be OK. Breaking." 2>&1 >${LOG} 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 ||: # Logic: # - Listen to any input device events to get volume keys (not part of the joystick api) # - Switch statement keeps high level cases to only 'volume' and 'V function key' # this is to avoid processing for other events or creating a lot of cases as this will be called # for all button pushes # - Using 'read' means the loop is idle when no button is pressed ( for INPUT_DEVICE in ${INPUT_DEVICES[@]} do evtest "${INPUT_DEVICE}" 2>&1 & done wait ) | while read line; do case $line in (${CONTROLLER_DISCONNECTED}) echo "Reloading due to ${CONTROLLER_DEVICE} reattach..." >${LOG} 2>&1 get_devices ;; (${DEVICE_DISCONNECTED}) echo "Reloading due to ${DEVICE} reattach..." >${LOG} 2>&1 get_devices ;; (${VOL_EVENT}) # We don't care when you 'let go' ('release') the volume button if [[ "$line" =~ ${RELEASE} ]]; then REPEAT_NUM=0 continue fi # Setup for 'brightness' if Fn pressed if [[ "${FUNCA_PRESSED}" == "yes" ]]; then COMMAND="/usr/bin/brightness" UP="up" DOWN="down" REPEAT_MOD=${BRIGHTNESS_REPEAT_MOD} elif [[ "${FUNCB_PRESSED}" == "yes" ]]; then if [[ "${line}" == ${VOL_UP} ]]; then COMMAND="/usr/bin/say" UP="-b" else COMMAND="/usr/bin/wifictl" WIFISTATE=$(get_setting wifi.enabled) if [ "${WIFISTATE}" = 0 ] then DOWN="reconnect" /usr/bin/say "WIFI On" else DOWN="disable" /usr/bin/say "WIFI Off" fi fi else # Default to 'volume' if Fn a or b is not pressed COMMAND="/usr/bin/volume" UP="+" DOWN="-" REPEAT_MOD=${VOLUME_REPEAT_MOD} fi REPEAT_NUM=$(( ${REPEAT_NUM} + 1 )) # This isn't time to evaluate repeat so just skip if [[ "$line" == ${REPEAT_PRESS} && $(( ${REPEAT_NUM} % ${REPEAT_MOD} )) != "0" ]]; then continue fi INCREMENT_AMOUNT=5 if [[ "${REPEAT_NUM}" -gt "20" ]]; then INCREMENT_AMOUNT=10 fi # Run the commands to adjust volume/brightness if [[ "${line}" == ${VOL_UP} ]]; then ${COMMAND} ${UP} ${INCREMENT_AMOUNT} > /dev/null read -t 0.1 elif [[ "${line}" == ${VOL_DOWN} ]]; then ${COMMAND} ${DOWN} ${INCREMENT_AMOUNT} > /dev/null read -t 0.1 fi ;; (${V_FUNC_KEYA_EVENT}) #Reset the number of repeats when Fn is pressed/release # as repeat speed is different between volume/brightness REPEAT_NUM=0 if [[ "${line}" =~ ${PRESS} ]]; then FUNCA_PRESSED=yes elif [[ "${line}" =~ ${RELEASE} ]]; then FUNCA_PRESSED=no fi ;; (${V_FUNC_KEYB_EVENT}) #Reset the number of repeats when Fn is pressed/release # as repeat speed is different between volume/brightness REPEAT_NUM=0 if [[ "${line}" =~ ${PRESS} ]]; then FUNCB_PRESSED=yes elif [[ "${line}" =~ ${RELEASE} ]]; then FUNCB_PRESSED=no fi ;; esac done