Skip to content

Commit

Permalink
[fix] stop rfkill from blocking all radio devices
Browse files Browse the repository at this point in the history
This fixes a bug introduced in af0115e.

After creating a uinput device with switches support, all radio devices were
blocked. This was due to rfkill reacting to the uinput creation.

We disable rfkill-input (the module reacting to new device creation) to avoid
blocking all radio devices. When a new device (virtual or physical) with the
SW_RFKILL_ALL switch capability bit set appears, rfkill reacts immediately
depending on the value bit. This value bit defaults to unset, which causes
rfkill to use its default eop mode (emergency power off). The uinput API does
not give any way to set the corresponding value bit before creating the device,
and we have no way to avoid rfkill acting upon the device creation or to change
its default mode. Thus, we disable rfkill-input temporarily, hopefully fast
enough that it won't impact anyone. rfkill-input gets enabled automatically
after uinput device creation (actually, when the file gets closed).
  • Loading branch information
ajanon committed Dec 17, 2022
1 parent a315c78 commit 0af3d0d
Showing 1 changed file with 20 additions and 0 deletions.
20 changes: 20 additions & 0 deletions swhkd/src/uinput.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ use evdev::{
AttributeSet, Key, RelativeAxisType, SwitchType,
};

use nix::ioctl_none;
use std::fs::File;
use std::os::unix::io::AsRawFd;

ioctl_none!(rfkill_noinput, b'R', 1);

pub fn create_uinput_device() -> Result<VirtualDevice, Box<dyn std::error::Error>> {
let mut keys = AttributeSet::<Key>::new();
for key in get_all_keys() {
Expand All @@ -29,6 +35,20 @@ pub fn create_uinput_switches_device() -> Result<VirtualDevice, Box<dyn std::err
switches.insert(switch);
}

// We have to disable rfkill-input to avoid blocking all radio devices. When
// a new device (virtual or physical) with the SW_RFKILL_ALL capability bit
// set appears, rfkill reacts immediately depending on the value bit. This
// value bit defaults to unset, which causes rfkill to use its default mode
// (which is eop - emergency power off). The uinput API does not give any
// way to set the corresponding value bit before creating the device, and we
// have no way to avoid rfkill acting upon the device creation or to change
// its default mode. Thus, we disable rfkill-input temporarily, hopefully
// fast enough that it won't impact anyone. rfkill-input will be enabled
// again when the file gets closed.
let rfkill_file = File::open("/dev/rfkill")?;
unsafe {
rfkill_noinput(rfkill_file.as_raw_fd())?;
}
let device = VirtualDeviceBuilder::new()?
.name("swhkd switches virtual output")
.with_switches(&switches)?
Expand Down

0 comments on commit 0af3d0d

Please sign in to comment.