diff options
-rw-r--r-- | README.md | 34 | ||||
-rw-r--r-- | kvm-input.rules | 20 | ||||
-rwxr-xr-x | kvm-plugged-in.sh | 23 | ||||
-rwxr-xr-x | kvm-udev-trigger.sh | 26 | ||||
-rwxr-xr-x | kvm-user-daemon.sh | 48 |
5 files changed, 151 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..8243d3c --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +# README for kvm-mapping +This `kvm-mapping` project is designed to make it easy to run a script in my user session when the kvm output goes to this machine. Specifically, I want keyboard mappings restored for easy switching between layouts 'us,us(dvorak)'. + +## Upstream +This project's upstream is at <https://bgstack15.ddns.net/cgit/kvm-mapping/> + +## Alternatives +None. Original idea and implementation. + +## Reason for existence +Custom solution for myself that might be useful in alternate ways or as an example of the various concepts. Also, putting this in scm acts as a backup. + +## Using + +* Set up the scripts in `/usr/local/bin`. +* Set up the udev rule in `/etc/udev/rules.d/`. +* Modify `kvm-plugged-in.sh` to run whatever you want. +* Set up your X session to run `kvm-user-daemon.sh` at startup. In ~/.fluxbox/startup this would look like: + + /usr/local/bin/kvm-user-daemon.sh 1>/dev/null 2>&1 & + +Logging of the user daemon happens to ~/log/kvm or ~/.log/kvm, whichever exists or you can set `LOGFILE` before running. + +## Dependencies + +* xinput, setxkbmap, udev, plecho (bgscripts) + +## Building +Not implemented yet; there is nothing to build. Just deploy manually. + +## References + +1. <https://superuser.com/questions/305723/using-udev-rules-to-run-a-script-on-usb-insertion> +2. <https://unix.stackexchange.com/questions/71348/why-doesnt-this-udev-rule-trigger-upon-removal-of-the-device> diff --git a/kvm-input.rules b/kvm-input.rules new file mode 100644 index 0000000..d1e6ec1 --- /dev/null +++ b/kvm-input.rules @@ -0,0 +1,20 @@ +# File: /etc/udev/rules.d/kvm-input.rules +# Location: vm2 +# Author: bgstack15 +# Startdate: 2023-01-11-4 11:18 +# Title: Udev rule for detecting kvm switched input +# Project: kvm-mapping +# Purpose: run script when my USB keyboard is plugged in, i.e., when the kvm is switched to this output +# History: +# Usage: +# After making changes: `sudo udevadm control --reload` +# Reference: +# IBM Corp. SK-8815 keyboard that is on my USB kvm +# lsusb +# https://superuser.com/questions/305723/using-udev-rules-to-run-a-script-on-usb-insertion +# Improve: +# Documentation: +# This invokes the script three times, so the trigger script must look for DEVTYPE="usb_device" because I couldn't find a way to do that here with an ATTRS +# Dependencies: +# /usr/local/bin/kvm-udev-trigger.sh +ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="04b3", ATTRS{idProduct}=="301b", RUN+="/usr/local/bin/kvm-udev-trigger.sh" diff --git a/kvm-plugged-in.sh b/kvm-plugged-in.sh new file mode 100755 index 0000000..ee1958c --- /dev/null +++ b/kvm-plugged-in.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# File: /usr/local/bin/kvm-plugged-in.sh +# Location: vm2 +# Author: bgstack15 +# Startdate: 2023-01-11-4 14:32 +# Title: Script that runs in user context when kvm is plugged in +# Project: kvm-mapping +# Purpose: for vm2, run my keyboard input script. +# History: +# Usage: +# called by kvm-user-daemon.sh when the trigger file is made by the udev rule+script +# Reference: +# https://unix.stackexchange.com/questions/71348/why-doesnt-this-udev-rule-trigger-upon-removal-of-the-device +# Improve: +# Dependencies: +# xinput and setxkbmap +# running in user context, with XAUTHORITY and DISPLAY and probably more env vars +# Documentation: +# The contents can be whatever you want. On vm2, I want to set my keyboard mappings. +for word in $( xinput list | sed -r -n -e 's/.*USB.*Keyboard.*id=([0-9]+).*keyboard.*/\1/p;' ) ; +do + setxkbmap -device ${word} -option grp:switch,grp:shifts_toggle -layout 'us,us(dvorak)' +done diff --git a/kvm-udev-trigger.sh b/kvm-udev-trigger.sh new file mode 100755 index 0000000..af7e84b --- /dev/null +++ b/kvm-udev-trigger.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# File: /usr/locla/bin/kvm-udev-trigger.sh +# Location: vm2 +# Author: bgstack15 +# Startdate: 2023-01-11-4 11:39 +# Title: Reaction script for Udev detecting kvm input +# Project: kvm-mapping +# Purpose: When triggered from udev, touch the file that the per-user daemon listens for +# History: +# Usage: +# when run by udev rule, make file that per-user daemons watch for +# Reference: +# Improve: +# Dependencies: +# /etc/udev/rules.d/kvm-input.rules +# ~bin/kvm-mapping-daemon.sh running in user session, from ~/.fluxbox/startup probably +# logger +# Dependencies: +KVMFILE=/run/kvm/kvmfile +KVMDIR="$( dirname "${KVMFILE}" )" +test "${DEVTYPE}" = "usb_device" && { + ! test -d "${KVMDIR}" && mkdir -p "${KVMDIR}" + chmod 0777 "${KVMDIR}" + echo "kvm input detected!" | logger --priority user.notice + touch "${KVMFILE}" ; chmod 0666 "${KVMFILE}" +} diff --git a/kvm-user-daemon.sh b/kvm-user-daemon.sh new file mode 100755 index 0000000..017644e --- /dev/null +++ b/kvm-user-daemon.sh @@ -0,0 +1,48 @@ +#!/bin/sh +# File: /usr/local/bin/kvm-user-daemon.sh +# Location: vm2 +# Author: bgstack15 +# Startdate: 2023-01-11-4 11:37 +# Title: KVM user daemon +# Project: kvm-mapping +# Purpose: daemon that runs inside user session and runs a script when specific USB device is plugged in +# History: +# Usage: +# Run at start of session, such as in ~/.fluxbox/startup +# Reference: +# original design (at least my third time) of stdout/stderr timestamps and logging +# Improve: +# Dependencies: +# Documentation: +test -z "${LOGFILE}" && test -d ~/log && LOGFILE=~/log/kvm +test -z "${LOGFILE}" && test -d ~/.log && LOGFILE=~/.log/kvm +test -z "${LOGFILE}" && export LOGFILE=/tmp/kvm-log +KVMFILE=/run/kvm/kvmfile +STOPFILE=/tmp/stop-kvm # touch this file to stop the daemons for all users +# The user should set RUNSCRIPT, which is what should happen when the kvm is switched to this output. +test -z "${RUNSCRIPT}" && RUNSCRIPT=~/bin/kvm-plugged-in.sh +! test -x "${RUNSCRIPT}" && RUNSCRIPT=/usr/local/bin/kvm-plugged-in.sh +# Crazy nesting allows stdout, stderr prepended with timestamps and "STDERR", both to normal streams and to the logfile. +{ + { + { + # Safety valve. When this file exists, the loop stops. + while ! test -f "${STOPFILE}" ; + do + sleep 1 + test -f "${KVMFILE}" && { + #env + #echo "sample error" 1>&2 + echo "kvm input detected, running \"${RUNSCRIPT}\"" + "${RUNSCRIPT}" + # delay a few seconds, because switching inputs fastis unlikely and not recommended, and so that any other user daemons looking for it can find it and also react. + { sleep 3 ; rm -f "${KVMFILE}" ; } + } + done + } 2>&3 1>&4 + } 3>&1 1>&4 | plecho "STDERR:" | tee -a "${LOGFILE}" 1>&2 +} 4>&1 | plecho | tee -a "${LOGFILE}" +# Delay a few seconds so other daemons can also find it and stop +sleep 3 ; rm "${STOPFILE}" 1>/dev/null 2>&1 +# exit 0 with this nop +: |