oblitum / caps2esc

Transforming the most useless key ever in the most useful one
GNU General Public License v3.0
166 stars 37 forks source link

caps2esc causes wifi to be softblocked on suspend #2

Closed auscompgeek closed 7 years ago

auscompgeek commented 7 years ago

In what is possibly the most bizarre bug I've ever encountered, it seems caps2esc causes my HP Spectre x360's wifi to be soft rfkilled whenever I suspend my laptop. (The issue disappears when caps2esc is not running when suspending.)

oblitum commented 7 years ago

Thanks for the report. I will soon be doing a lot of refactoring to caps2esc, in truth I'm working on a more general tool where caps2esc will be a special case. So, I invite you to take a look when those changes come.

In case you figure out specifically what's the actual issue in detail, feel free to report all you got here. I have no issues with suspending and attaching new devices, but I found interesting behaviour in another unrelated code that creates uinput devices set to respond too many events. When enabling all those events I've seen plane mode being enabled in my notebook, which was quite strange.

auscompgeek commented 7 years ago

I suspect that it might have something to do with the fact that my laptop likes to send XF86WLAN key events sometimes. I still haven't worked out when exactly it does this, but it is quite infuriating…

oblitum commented 7 years ago

If your wifi device reports that it sends CAPSLOCK or ESC events, it will be grabbed, you may check whether that is happening, if so, you should exclude it by name or something in the should_grab function.

auscompgeek commented 7 years ago

Something gives me the feeling that doing so would render caps2esc dead on arrival…

$ libinput-debug-events --device /dev/input/event4
-event4     DEVICE_ADDED     AT Translated Set 2 keyboard      seat0 default group1 cap:k
 event4     KEYBOARD_KEY     +13.01s    KEY_SPACE (57) pressed
 event4     KEYBOARD_KEY     +13.14s    KEY_SPACE (57) released
 event4     KEYBOARD_KEY     +17.93s    KEY_WLAN (238) pressed
 event4     KEYBOARD_KEY     +17.94s    KEY_WLAN (238) released
 event4     KEYBOARD_KEY     +17.96s    KEY_WLAN (238) pressed
 event4     KEYBOARD_KEY     +17.96s    KEY_WLAN (238) released
 event4     KEYBOARD_KEY     +17.98s    KEY_WLAN (238) pressed
 event4     KEYBOARD_KEY     +17.98s    KEY_WLAN (238) released
 event4     KEYBOARD_KEY     +19.46s    KEY_WLAN (238) pressed
 event4     KEYBOARD_KEY     +19.46s    KEY_WLAN (238) released
 event4     KEYBOARD_KEY     +19.48s    KEY_WLAN (238) pressed
 event4     KEYBOARD_KEY     +19.48s    KEY_WLAN (238) released
 event4     KEYBOARD_KEY     +19.50s    KEY_WLAN (238) pressed
 event4     KEYBOARD_KEY     +19.50s    KEY_WLAN (238) released
 event4     KEYBOARD_KEY     +20.98s    KEY_WLAN (238) pressed
 event4     KEYBOARD_KEY     +20.99s    KEY_WLAN (238) released
 event4     KEYBOARD_KEY     +21.00s    KEY_WLAN (238) pressed
 event4     KEYBOARD_KEY     +21.01s    KEY_WLAN (238) released
 event4     KEYBOARD_KEY     +21.02s    KEY_WLAN (238) pressed
 event4     KEYBOARD_KEY     +21.03s    KEY_WLAN (238) released
 event4     KEYBOARD_KEY     +30.59s    KEY_ENTER (28) pressed
 event4     KEYBOARD_KEY     +30.64s    KEY_ENTER (28) released
 event4     KEYBOARD_KEY     +58.49s    KEY_LEFTCTRL (29) pressed
 event4     KEYBOARD_KEY     +58.70s    KEY_C (46) pressed

(This is my actual keyboard, without caps2esc running.)

In further investigation, I found that the kernel rfkill module directly handles KEY_WLAN. Fun times.

My laptop does have "Intel Virtual Button driver", "HP WMI hotkeys", and "HP Wireless hotkeys" keyboards, none of which are grabbed by caps2esc, nor do they send KEY_WLAN themselves.

oblitum commented 7 years ago

caps2esc will work like this: It will create a virtual device and simply map all events that come from the grabbed device to this virtual device, except for CAPSLOCK and ESC, which it tweaks to provide its main functionality.

I have no idea how KEY_WLAN is handled by the system, or how it should be... one tentative direction could be to not replicate this event at all through the virtual device. You may try changing the eventmap function to detect that key and return 0.

oblitum commented 7 years ago

I'm interested if you are able to tweak it with success. Given that your keyboard device has that KEY_WLAN and that is causing problems, the first solution I can think of is trying to not touch that event. There are two ways that this can be accomplished:

  1. When such event arrives from the grabbed device, don't reproduce it on the virtual udev device.
  2. Don't create an udev device with such event enabled.

1 is easy, as I said before, you just change the eventmap function to return 0 when the event is KEY_WLAN. 2 is also easy, currently the udev device is being created as a clone of the real device through libevdev_uinput_create_from_device, so, just before the call to this function you should call libevdev_disable_event_code on the original device to disable KEY_WLAN before creating the udev clone. Disabling the code on the original device won't modify the original device in truth, it will just change the device appearance for the program.

oblitum commented 7 years ago

If this doesn't solve it, I have no more ideas. If it does solve it, I'll incorporate the fix.

oblitum commented 7 years ago

Actually, libevdev_disable_event_code docs tells that after disabling a given event code, even though the device may produce such event, it won't come up to the application because it will be filtered by the libevdev API, so merely disabling it seems sufficient, no need to change the eventmap function. Please check whether applying the following is of any help:

@@ -113,6 +113,8 @@ int eventmap_loop(const char *devnode) {
         goto teardown_grab;
     if (libevdev_enable_event_code(dev, EV_KEY, KEY_LEFTCTRL, NULL) < 0)
         goto teardown_grab;
+    if (libevdev_disable_event_code(dev, EV_KEY, KEY_WLAN) < 0)
+        goto teardown_grab;

     struct libevdev_uinput *udev;
     if (libevdev_uinput_create_from_device(dev, LIBEVDEV_UINPUT_OPEN_MANAGED,
oblitum commented 7 years ago

You may still check it in the eventmap function just to be sure, but I think it won't show up there anymore.

oblitum commented 7 years ago

Hi, please let me know about results if you tried the provided potential solution. Otherwise I will have to close for inactivity.

auscompgeek commented 7 years ago

Sorry, uni finals are annoying.

Seems to work, although I'm concerned about the possible consequences for those who actually have a WLAN key.

oblitum commented 7 years ago

I think the WLAN key will be handled kernel level, so when it reaches caps2esc it will have nothing to do with it? If that's how it's handled, I guess there's no problem incorporating this patch.

auscompgeek commented 7 years ago

Turns out this is a udev hwdb bug anyway.