rfkill triggered by libevdev_uinput_create_from_device
My laptop has a device that shows up in evdev as the following:
# evtest /dev/input/event10
Input driver version is 1.0.1
Input device ID: bus 0x19 vendor 0x17aa product 0x5054 version 0x4101
Input device name: "ThinkPad Extra Buttons"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 113 (KEY_MUTE)
...
Event code 634 (?)
Event type 4 (EV_MSC)
Event code 4 (MSC_SCAN)
Event type 5 (EV_SW)
Event code 3 (SW_RFKILL_ALL) state 1
Properties:
Testing ... (interrupt to exit)
When I use libevdev_uinput_create_from_device
to create a uinput device based on this device, rfkill immediately triggers and shuts off my Wi-Fi and Bluetooth radios.
I've noticed that the state of the SW_RFKILL_ALL
switch on the new uinput device is set to 0 regardless of the state of the physical device when libevdev_uinput_create_from_device
is called, and I'm guessing that this is the reason rfkill is triggered. Furthermore, I can't seem to set the value of SW_RFKILL_ALL
on the uinput device using libevdev_set_event_value
. See the following snippet:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <libevdev/libevdev.h>
#include <libevdev/libevdev-uinput.h>
int main(int argc, char *argv[]) {
int rc;
int fd = open("/dev/input/event10", O_RDONLY | O_NONBLOCK);
struct libevdev *dev = NULL;
rc = libevdev_new_from_fd(fd, &dev);
if (rc < 0) {
printf("couldn't open device\n");
exit(1);
}
int sw_value = libevdev_get_event_value(dev, EV_SW, SW_RFKILL_ALL);
printf("real device switch value is %d\n", sw_value);
struct libevdev_uinput *uinput_dev = NULL;
rc = libevdev_uinput_create_from_device(dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uinput_dev);
if (rc < 0) {
printf("couldn't create uinput");
libevdev_free(dev);
exit(1);
}
int uinput_sw_value = libevdev_get_event_value(uinput_dev, EV_SW, SW_RFKILL_ALL);
printf("uinput device switch value is %d\n", uinput_sw_value);
libevdev_set_event_value(uinput_dev, EV_SW, SW_RFKILL_ALL, 1);
uinput_sw_value = libevdev_get_event_value(uinput_dev, EV_SW, SW_RFKILL_ALL);
printf("uinput device switch value after setting value to 1 is %d\n", uinput_sw_value);
libevdev_free(dev);
libevdev_uinput_destroy(uinput_dev);
}
When compiled and run, this prints:
real device switch value is 1
uinput device switch value is 0
uinput device switch value after setting value to 1 is 0
The docs say:
The uinput device will be an exact copy of the libevdev device, minus the bits that uinput doesn't allow to be set.
Is the state of the SW_RFKILL_ALL
switch one of these bits that can't be set on uinput devices?
Would I maybe be better off constructing the uinput device manually, e.g. with libevdev_enable_event_code
, enumerating each event code, and skipping the EV_SW
events entirely?
Thank you, and sorry if this ends up being more of a support request than a proper bug.