249 lines
7.2 KiB
Plaintext
249 lines
7.2 KiB
Plaintext
\input texinfo
|
||
@settitle Actkbd Manual 1.0
|
||
|
||
@copying
|
||
Copyright @copyright{} 2024 Zsombor Barna
|
||
@end copying
|
||
|
||
@titlepage
|
||
@title Actkbd Manual
|
||
@page
|
||
@vskip 0pt plus 1filll
|
||
@insertcopying
|
||
@end titlepage
|
||
|
||
@contents
|
||
|
||
@node Top
|
||
@top Actkbd Manual
|
||
|
||
This manual is for actkbd
|
||
(version @value{VERSION}, @value{UPDATED}).
|
||
@menu
|
||
* Setup on Linux::
|
||
* Example config::
|
||
* Supported Platforms::
|
||
* Internals::
|
||
* Index:: Complete index.
|
||
@end menu
|
||
|
||
@node Setup on Linux
|
||
@chapter Setup on Linux
|
||
|
||
@node Finding a device
|
||
@section Finding a device
|
||
|
||
To use actkbd, first you need to find a suitable device. This method won't persist through reboots
|
||
because the device numbers can change even just by a plug-unplug cycle.
|
||
|
||
Figuring out which keyboard corresponds to which event device will require device listing compare between unplugged and plugged states.
|
||
Even then, it's possible that you need to try guessing.
|
||
Here's part of the output of xinput on my setup.
|
||
|
||
@itemize
|
||
@item
|
||
SINO WEALTH USB KEYBOARD Consumer Control id=19
|
||
@item
|
||
SINO WEALTH USB KEYBOARD id=20
|
||
@item
|
||
SINO WEALTH USB KEYBOARD System Control id=21
|
||
@item
|
||
SINO WEALTH USB KEYBOARD Keyboard id=22
|
||
@end itemize
|
||
|
||
One of my keyboards is so cursed, it adds 4(!) keyboards (and a mouse, too...):
|
||
|
||
This keyboard is a Modecom Volcano Hammer, so no correlation between device name and brand name.
|
||
|
||
As another example My Lenovo Preferred Pro 2 keyboard shows up as a Chicony one:
|
||
|
||
@itemize
|
||
@item
|
||
CHICONY USB NetVista Full Width Keyboard id=12
|
||
@end itemize
|
||
|
||
At least it doesn't add 4 devices so it's unambiguous.
|
||
|
||
The id number in xinput's output corresponds to the number they occupy in /dev/input/eventXX.
|
||
|
||
@node Configuring systemd
|
||
@section Configuring systemd
|
||
|
||
Put a service file by the name actkbd@@.service into $HOME/.config/systemd/user .
|
||
The @@ in the name is essential. It will be needed to automatically construct the service name
|
||
for the specific device name.
|
||
|
||
@example
|
||
[Unit]
|
||
Description=Run actkbd on a keyboard
|
||
BindTo=%i.device
|
||
After=%i.device
|
||
|
||
[Service]
|
||
Type=simple
|
||
TimeoutStartSec=10
|
||
ExecStart=/path/to/actkbd -d /%I -c /path/to/config.scm
|
||
@end example
|
||
|
||
Replace /path/to/ with whatever your system has.
|
||
|
||
Test the service by
|
||
|
||
@example
|
||
systemctl --user start actkbd@@preferred-device.service
|
||
@end example
|
||
|
||
Check its status with
|
||
|
||
@example
|
||
systemctl --user status actkbd@@preferred-device.service
|
||
@end example
|
||
|
||
Explanation: The After is not necessarily needed. BindTo makes the service automatically shut down when you unplug the device.
|
||
It's a simple service, because it isn't actkbd that ``daemonizes'' itself, but systemd will do that. I added a timeout,
|
||
but that part isn't really needed, either.
|
||
|
||
@node Permanent device identifiers
|
||
@section Permanent device identifiers
|
||
|
||
To autostart actkbd on a given device, you need to find identifying information on the device.
|
||
|
||
I recommend using udevadm, but lsusb works fine, too. In this section, I will only detail the udevadm method.
|
||
|
||
Make sure you found the correct /dev/input/eventXX name of your device.
|
||
|
||
Then type in the following:
|
||
|
||
@example
|
||
udevadm info --query=path --name=/dev/input/eventXX
|
||
@end example
|
||
|
||
This will give you the full path to the device. The full path looks like this:
|
||
|
||
@example
|
||
/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.5/1-1.5.5/1-1.5.5:1.0/0003:258A:1006.0034/input/input83/event19
|
||
@end example
|
||
|
||
Out of the above, 1006 is the value of ATTRS@{id/product@}, and 258a is the value of ATTRS@{id/vendor@}.
|
||
|
||
These will be the identifiers needed for udev to autostart the program.
|
||
|
||
If your device is like mine, you cannot identify the device exactly, and udev will start a service for every device.
|
||
|
||
@node Configuring udev
|
||
@section Configuring udev
|
||
|
||
You will need to put a file like the one below into /dev/udev/rules.d/
|
||
|
||
A file name like 30-actkbdkeyboard.rules will suffice.
|
||
|
||
@example
|
||
ACTION=="add", SUBSYSTEM=="input", \
|
||
ATTRS@{idVendor@}=="YOUR_idVendor", ATTRS@{idProduct@}=="YOUR_idProduct", \
|
||
OWNER="YOUR-USERNAME", \
|
||
TAG+="systemd", \
|
||
PROGRAM="/usr/bin/systemd-escape -p --template=actkbd.service $env@{DEVNAME@}", \
|
||
ENV@{SYSTEMD_USER_WANTS@}+="%c"
|
||
@end example
|
||
|
||
Explanation: ACTION determines when the rule applies, and SUBSYSTEM describes that this rule only affects the input subsystem.
|
||
The ATTRS@{*@} apply further conditions. If you don't need the ATTRS line with the "capabilities/led", delete the line.
|
||
You need to change OWNER to your username, and replace sino@.service with the service name you'll use for the systemd unit.
|
||
The PROGRAM line constructs the service name that udev will ask systemd to start, and the asking will happen at the last line.
|
||
|
||
Now you'll need to reboot your system. I found no way to avoid that. Udevadm and system
|
||
|
||
@node Example config
|
||
@chapter Example config
|
||
|
||
@lisp
|
||
;; you can just use modules like in regular guile
|
||
|
||
(define-syntax-rule (callback key arg body ...)
|
||
(bind key (lambda arg
|
||
body ...)))
|
||
|
||
(define-syntax-rule (on-release key body ...)
|
||
(bind key (lambda (type)
|
||
(when (= type 0)
|
||
body)
|
||
...)))
|
||
|
||
;; key A
|
||
(on-release 30
|
||
(system "notify-send oof")
|
||
(exit))
|
||
|
||
;; key Left Control
|
||
(callback 29 (type)
|
||
;; we turn on the led on key press and turn it off when released
|
||
(when (or (= type 1) (= type 0))
|
||
(led 0 (= type 1))))
|
||
@end lisp
|
||
|
||
@node Supported Platforms
|
||
@chapter Supported Platforms
|
||
|
||
Currently only the following platforms are supported:
|
||
|
||
@itemize
|
||
@item
|
||
Linux
|
||
@end itemize
|
||
|
||
Platform-specific information:
|
||
@node Linux
|
||
@section Linux
|
||
|
||
To run actkbd under Linux you need to have the event interface available. In
|
||
most cases, it is already loaded, but loading the `evdev' kernel module will be
|
||
sufficient:
|
||
|
||
@example
|
||
modprobe evdev
|
||
@end example
|
||
|
||
On Linux it is recommended that actkbd is launched using udev rules and through
|
||
systemd. This allows the user to use a different configuration for each keyboard
|
||
and assign them to a user, as long as udev can tell the devices apart. This
|
||
method is far more reliable and flexible than using an init script, as it allows
|
||
for proper support of hotplug events and removes the probability of the
|
||
auto-detection code getting confused and causing problems. Assigning a device to
|
||
a user makes the user able to run actkbd without special privileges.
|
||
|
||
In most Linux systems the device nodes to use are named /dev/input/eventX, where
|
||
X is a decimal unsigned number, e.g. /dev/input/event0. If the /proc filesystem
|
||
is mounted and accessible, actkbd should be able to detect a usable keyboard
|
||
device. You should not need to manually specify one, unless there are multiple
|
||
keyboards present.
|
||
|
||
Several special buttons (like the power switch) may appear as input
|
||
devices as well. Please take extra care when specifying the input device.
|
||
|
||
On Linux:
|
||
@itemize
|
||
@item
|
||
KEY_CNT is 768 (0x300)
|
||
@item
|
||
LED_CNT is 16 (0x10)
|
||
@end itemize
|
||
|
||
@node Internals
|
||
@chapter Internals
|
||
|
||
Actkbd uses a simple lookup table for now. The table's code is in guile.c.
|
||
|
||
Please note that the platform specific code is contained in <platform>.c
|
||
(e.g. linux.c). This file implements a generic interface to keyboard events,
|
||
hiding each system's intricacies from the rest of code. It is also the file that
|
||
has to be written/ported to add support for a new platform.
|
||
|
||
For any additional details the best documentation is probably the source code
|
||
itself.
|
||
|
||
@node Index
|
||
@unnumbered Index
|
||
|
||
@printindex cp
|
||
@bye
|