Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persist event id after reboot #161

Open
tceydeliler opened this issue Jan 4, 2017 · 8 comments

Comments

Projects
None yet
4 participants
@tceydeliler
Copy link

commented Jan 4, 2017

Hi,
I have a ubuntu laptop and I use USB keyboard.
If dont use "--device " switch I get nothing. To get keystrokes I have use this switch. But, ltough I put same USB port, device (/dev/input/event..) changes after restart.
Is there any way to use more than one device at the same time?
Or
Is there any way to fix event no?

@kernc

This comment has been minimized.

Copy link
Owner

commented Jan 4, 2017

Your USB keyboard isn't autodetected or the incorrect one (e.g. the built in one) is. Yes, those device ids might be changed at boot time by the kernel/udev.

Is there any way to use more than one device at the same time?
Or
Is there any way to fix event no?

Not without a pull request that does it.

@kernc kernc changed the title USB Keyboard problem Persist event id after reboot Jan 4, 2017

@rolfvreijdenberger

This comment has been minimized.

Copy link
Contributor

commented Jan 7, 2019

Hi @kernc,
I've done some work on using udev rules in combination with systemd unit files to allow the input device to be predictable via the udev rules and using a systemd service to reliably pick up that device and run logkeys with configurable settings as a service.

It would also allow a 'fix' to #38 by allowing multiple services to be started and log input from multiple keyboard devices (eg: onboard laptop keyboard and another usb device).

basically:

  • for every device: use udev rule to generate a reliable device name via device attribute matching. eg: /dev/input/logkeys-keyboard
  • use systemd services to start logkeys (with autorestart) using the reliable device name

At the moment they are just 'templates' showing how it can be done (in the same way that you can adjust the current files in the scripts directory) but I'm interested to do some more work on it if you can point me in the right direction.

let me know.

the udev rule:

# /etc/udev/rules.d/99-logkeys.rules
#
# This udev rule works together with the systemd system and service manager to 
# start and stop the logkeys program as a service.
# It provides some extra functionality by providing a starting point to be activated
# when an external keyboard is attached.
# The systemd service files can be found at /etc/systemd/system/
# one is 'logkeys.service' and the other is 'logkeys-alternate.service'
# 
# When using udev to get a match on a device, make matches as specific as possible.
# this prevents multiple events generated by the udev system to be matched.
# This is what you want since multiple matches might fire a script called via "RUN" to be
# called multiple times.
#
# use ENV{name}=="value" to match on environment variables when removing devices, 
# ATTRS are only available on adding
#
#  ACTION: add, bind, change, remove, unbind
#  SUBSYSTEMS: input, usb ..
#  ATTRS{name}=="value"
#  ENV{name}=="value"
#  SYMLINK+="symlink in /dev/ here"
#  RUN+="program invocation"
#
#
#
# helpful commands:
# udevadm monitor --environment --udev --kernel
# udevadm info -a -n <device-path>
# udevadm test $(udevadm info -q path -n device_name) 2>&1
# udevadm control --log-priority=debug
# ps auxf | grep logkeys
################################################################################

########################## fixed keyboard #########################################
# This is a fixed keyboard on a laptop
# this works together with /etc/systemd/system/logkeys.service
# and sets the correct input device up with a predictable name (instead of /dev/input/event<X>)
# find out the correct keyboard by checking:
# cat /dev/input/event<X> 
# untill you see output and then
# udevadm info -a -n /dev/input/event<X>
# with the correct input device to check the attributes for the device in the udev rules key froma
# then enable and start the logkeys.service via 
# systemctl enable logkeys.service
# systemctl start logkeys.service
SUBSYSTEMS=="input", ATTRS{name}=="AT Translated Set 2 keyboard", ATTRS{phys}=="isa0060/serio0/input0", SYMLINK+="input/logkeys"

########################## alternate keyboard #########################################
# it is possible to run logkeys multiple times via systemd. we can then create multiple
# service files that can be started and stopped via udev events for multiple keyboards that can be attached
# this is very useful if you are using a laptop with an external keyboard attached
# so you can always monitor the standard keyboard together with the external keyboard.
# make sure that the match is as exact as possible on start and stop.
# matching on SUBSYSTEM should always be done on 'input' since it's an input device

# on addition of the target keyboard (match it!) create a symlink and run the systemd service for the external keyboard
#ACTION=="add", SYMLINK+="input/logkeys-alternate", RUN+="/usr/bin/systemctl start logkeys-alternate.service"
#ACTION=="remove", RUN+="/usr/bin/systemctl stop logkeys-alternate.service"

# ewent keyboard
SUBSYSTEMS=="input", ATTRS{name}=="USB USB Keyboard", \
        SYMLINK+="input/logkeys-alternate", RUN+="/usr/bin/systemctl start logkeys-alternate.service"

################################################################################

and the systemd service file:

[Unit]
Description=keylogger service from https://github.com/kernc/logkeys

[Service]
Type=simple
# used together with /etc/udev/rules.d/99-logkeys.rule 
ExecStart=/usr/local/bin/logkeys -s -d /dev/input/logkeys --keymap /root/keymap-ewent-keyboard.txt --no-daemon
Restart=always
RestartSec=60


[Install]
WantedBy=multi-user.target```
@kernc

This comment has been minimized.

Copy link
Owner

commented Jan 8, 2019

Hello and welcome, @rolfvreijdenberger!

I think that's a wonderful idea! I'd be quite willing to merge a generic udev rule and a generic systemd service. What I mean by generic is that they both should match and work for all kinds of keyboards out of the box.

I think this can be achieved with an udev rule such as:

SUBSYSTEM=="input", \
    ENV{DEVNAME}=="/dev/input/event*", \
    PROGRAM="/usr/share/logkeys/check-if-keyboard.sh", \
    SYMLINK="logkeys-$result", \
    RUN+="/bin/systemctl start logkeys@%E{SYMLINK}.service"

where the PROGRAM exits with 0 if the related device is a keyed (...) keyboard device, or if not, the whole rule fails. Roughly something like this should do it:

check-if-keyboard.sh:

#!/bin/sh
set -e

event=${DEVNAME#/dev/input/}

# Ensure keyboard
grep -q '1[02]001[3Ff]' /sys/class/input/$event/device/capabilities/ev

# Print name to be used as $result
cat /sys/class/input/$event/device/name

And then in the systemd service use %I specifier:

ExecStart=/usr/bin/logkeys -s -d /dev/input/%I --no-daemon -o /var/log/logkeys/%i

Note, path /usr/bin/logkeys depends on $PREFIX chosen in ./configure step of the program compilation, so this would have to be a file generated from logkeys@.service.in template.

If you figure something out and can wrap it all in a nice PR, I'd sure have a look at it! 😃

@rolfvreijdenberger

This comment has been minimized.

Copy link
Contributor

commented Jan 8, 2019

a template unit file can only accept 1 parameter, of which the device would be the logical option. it would be my preferred way to go also.

then there is another parameter that's high on my list: the keyboard map (since it did not work out of the box for me). this would be nice if it was configurable also (allowing the user to do only limited adjustments to make it work.

The environment variable set in the udev rule can also be used to pass information to the unit file itself (if kickstarted from the shell file of from the udev rule), possibly providing some sort of user configurable hook to pass on the keymap.
this would make it so that the user would only need to adjust the udev rule to make it work.

I'm not sure how the keymaps are detected and/or/if one keymap is usable for all keyboards attached to a system.

Will look into it a bit more then 👍

any pointers on how to handle the differences between hotplug and coldplug devices? (this boils down to enabling a service and starting it or only starting the service).

@kernc

This comment has been minimized.

Copy link
Owner

commented Jan 8, 2019

then there is another parameter that's high on my list: the keyboard map (since it did not work out of the box for me). this would be nice if it was configurable also (allowing the user to do only limited adjustments to make it work.

I would opt for EnvironmentFile, so that the udev rule and systemd service can be left intact.

https://coreos.com/os/docs/latest/using-environment-variables-in-systemd-units.html

Then the user would be advised to edit the environment file, if needed, and enable the systemd service (which should be disabled by default).

I'm not sure how the keymaps are detected and/or/if one keymap is usable for all keyboards attached to a system.

I'd imagine most users type in their one chosen layout. Some people switch between two or more layouts, but I don't know how to handle that gracefully. I guess advanced users should be able to configure their system as they wish.

any pointers on how to handle the differences between hotplug and coldplug devices?

Indeed, I think once the service is enabled (and then started for the first time), it should work the same for all devices.

@rolfvreijdenberger

This comment has been minimized.

Copy link
Contributor

commented Jan 9, 2019

I would opt for EnvironmentFile, so that the udev rule and systemd service can be left intact

sounds good

I'd imagine most users type in their one chosen layout. Some people switch between two or more layouts, but I don't know how to handle that gracefully. I guess advanced users should be able to configure their system as they wish.

thanks for clarifying, I am not familiar with the usage patterns of logkeys and have configured logkeys with devices and keyboard maps myself. looking at the documentation is seems that it 'should work' by itself but logkeys has never done that for me. nothing big, configuring is easy.

Indeed, I think once the service is enabled (and then started for the first time), it should work the same for all devices.

detecting the onboard input device is done early in the boot sequence, so you can just start the service. there is no need to synch the service with a systemd target . In my example above, the goal is to detect the onboard and peripheral keyboards via udev. The onboard keyboard can always be started and enabled (before the multi-user.target as in the example), but enabling does not seem to be necessary since if it is detected we can start the service (start via udev event instead of via the 'enable' of systemd)
the peripheral keyboard is hotplugable (and detachable) and can thus be started at 'detection' time also without the need to be enabled (which is an auto start at system initialization time basically). so that service can be opportunistically started without being enabled also

@kernc

This comment has been minimized.

Copy link
Owner

commented Jan 11, 2019

I'm actually not familiar with systemd that much. 😊 What I meant is that I would prefer the service file to be installed (upon e.g. make install) but in latent, inactive state. So systemd doesn't start logkeys neither for onboard keyboard nor for keyboards plugged in anytime later, until the system admin at one time decides specifically to run sudo systemctl enable logkeys (or similar). Only after that should the keyboards (all kinds) be logged automatically.

@tomek-szczesny

This comment has been minimized.

Copy link

commented Mar 11, 2019

Hi,
I have a ubuntu laptop and I use USB keyboard.
If dont use "--device " switch I get nothing. To get keystrokes I have use this switch. But, ltough I put same USB port, device (/dev/input/event..) changes after restart.
Is there any way to use more than one device at the same time?
Or
Is there any way to fix event no?

Hi,
My new keyboard seems to be not auto detected by logkeys and event number indeed changes after each restart.
logkeys seems to be hard-coded to refuse using any other directory, including "by-id", which would totally fix this issue.
BUT I use these commands to work around this problem:

sudo ln -s /dev/input/by-id/usb-Logitech_USB_Receiver-if02-event-kbd /dev/input/keebord
sudo logkeys -d keebord -s -o /home/mctom/myass

What it does is it creates a softlink of my keyboard, from "by-id" directory to dev/input/something.
Then logkeys is fed something as its event file.
Works every time when I reboot my machine. Hope it helps!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.