2007-09-13 01:22:55 -06:00
|
|
|
rfkill - RF switch subsystem support
|
|
|
|
====================================
|
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
1 Introduction
|
|
|
|
2 Implementation details
|
|
|
|
3 Kernel driver guidelines
|
|
|
|
4 Kernel API
|
|
|
|
5 Userspace support
|
2007-09-13 01:22:55 -06:00
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
|
|
|
|
1. Introduction:
|
2007-09-13 01:22:55 -06:00
|
|
|
|
2008-06-23 14:22:56 -06:00
|
|
|
The rfkill switch subsystem exists to add a generic interface to circuitry that
|
2008-06-23 14:23:08 -06:00
|
|
|
can enable or disable the signal output of a wireless *transmitter* of any
|
|
|
|
type. By far, the most common use is to disable radio-frequency transmitters.
|
2008-06-23 14:22:56 -06:00
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
The rfkill switch subsystem offers support for keys and switches often found on
|
|
|
|
laptops to enable wireless devices like WiFi and Bluetooth to actually perform
|
|
|
|
an action.
|
2008-06-23 14:22:56 -06:00
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
The buttons to enable and disable the wireless transmitters are important in
|
|
|
|
situations where the user is for example using his laptop on a location where
|
|
|
|
radio-frequency transmitters _must_ be disabled (e.g. airplanes).
|
2007-09-13 01:22:55 -06:00
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
Because of this requirement, userspace support for the keys should not be made
|
|
|
|
mandatory. Because userspace might want to perform some additional smarter
|
|
|
|
tasks when the key is pressed, rfkill provides userspace the possibility to
|
|
|
|
take over the task to handle the key events.
|
2007-09-13 01:22:55 -06:00
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
===============================================================================
|
|
|
|
2: Implementation details
|
|
|
|
|
|
|
|
The rfkill class provides kernel drivers with an interface that allows them to
|
|
|
|
know when they should enable or disable a wireless network device transmitter.
|
|
|
|
|
|
|
|
The rfkill-input module provides the kernel with the ability to implement a
|
|
|
|
basic response when the user presses a key or button (or toggles a switch)
|
|
|
|
related to rfkill functionality. It is an in-kernel implementation of default
|
|
|
|
policy of reacting to rfkill-related input events and neither mandatory nor
|
|
|
|
required for wireless drivers to operate.
|
|
|
|
|
|
|
|
The rfkill-input module also provides EPO (emergency power-off) functionality
|
|
|
|
for all wireless transmitters. This function cannot be overriden, and it is
|
|
|
|
always active. rfkill EPO is related to *_RFKILL_ALL input events.
|
|
|
|
|
|
|
|
All state changes on rfkill devices are propagated by the rfkill class to a
|
|
|
|
notification chain and also to userspace through uevents.
|
2007-09-13 01:22:55 -06:00
|
|
|
|
|
|
|
The system inside the kernel has been split into 2 separate sections:
|
|
|
|
1 - RFKILL
|
|
|
|
2 - RFKILL_INPUT
|
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
The first option enables rfkill support and will make sure userspace will be
|
|
|
|
notified of any events through uevents. It provides a notification chain for
|
|
|
|
interested parties in the kernel to also get notified of rfkill state changes
|
|
|
|
in other drivers. It creates several sysfs entries which can be used by
|
|
|
|
userspace. See section "Userspace support".
|
|
|
|
|
|
|
|
The second option provides an rfkill input handler. This handler will listen to
|
|
|
|
all rfkill key events and will toggle the radio accordingly. With this option
|
|
|
|
enabled userspace could either do nothing or simply perform monitoring tasks.
|
|
|
|
|
2008-06-23 14:46:42 -06:00
|
|
|
When a rfkill switch is in the RFKILL_STATE_UNBLOCKED, the wireless transmitter
|
|
|
|
(radio TX circuit for example) is *enabled*. When the rfkill switch is in the
|
|
|
|
RFKILL_STATE_SOFT_BLOCKED or RFKILL_STATE_HARD_BLOCKED, the wireless
|
|
|
|
transmitter is to be *blocked* from operating.
|
|
|
|
|
|
|
|
RFKILL_STATE_SOFT_BLOCKED indicates that a call to toggle_radio() can change
|
|
|
|
that state. RFKILL_STATE_HARD_BLOCKED indicates that a call to toggle_radio()
|
|
|
|
will not be able to change the state and will return with a suitable error if
|
|
|
|
attempts are made to set the state to RFKILL_STATE_UNBLOCKED.
|
|
|
|
|
|
|
|
RFKILL_STATE_HARD_BLOCKED is used by drivers to signal that the device is
|
|
|
|
locked in the BLOCKED state by a hardwire rfkill line (typically an input pin
|
|
|
|
that, when active, forces the transmitter to be disabled) which the driver
|
|
|
|
CANNOT override.
|
2008-06-23 14:23:08 -06:00
|
|
|
|
|
|
|
Full rfkill functionality requires two different subsystems to cooperate: the
|
|
|
|
input layer and the rfkill class. The input layer issues *commands* to the
|
|
|
|
entire system requesting that devices registered to the rfkill class change
|
|
|
|
state. The way this interaction happens is not complex, but it is not obvious
|
|
|
|
either:
|
|
|
|
|
|
|
|
Kernel Input layer:
|
|
|
|
|
|
|
|
* Generates KEY_WWAN, KEY_WLAN, KEY_BLUETOOTH, SW_RFKILL_ALL, and
|
|
|
|
other such events when the user presses certain keys, buttons, or
|
|
|
|
toggles certain physical switches.
|
|
|
|
|
|
|
|
THE INPUT LAYER IS NEVER USED TO PROPAGATE STATUS, NOTIFICATIONS OR THE
|
|
|
|
KIND OF STUFF AN ON-SCREEN-DISPLAY APPLICATION WOULD REPORT. It is
|
|
|
|
used to issue *commands* for the system to change behaviour, and these
|
|
|
|
commands may or may not be carried out by some kernel driver or
|
|
|
|
userspace application. It follows that doing user feedback based only
|
|
|
|
on input events is broken, there is no guarantee that an input event
|
|
|
|
will be acted upon.
|
|
|
|
|
|
|
|
Most wireless communication device drivers implementing rfkill
|
|
|
|
functionality MUST NOT generate these events, and have no reason to
|
|
|
|
register themselves with the input layer. This is a common
|
|
|
|
misconception. There is an API to propagate rfkill status change
|
|
|
|
information, and it is NOT the input layer.
|
|
|
|
|
|
|
|
rfkill class:
|
|
|
|
|
|
|
|
* Calls a hook in a driver to effectively change the wireless
|
|
|
|
transmitter state;
|
|
|
|
* Keeps track of the wireless transmitter state (with help from
|
|
|
|
the driver);
|
|
|
|
* Generates userspace notifications (uevents) and a call to a
|
|
|
|
notification chain (kernel) when there is a wireless transmitter
|
|
|
|
state change;
|
|
|
|
* Connects a wireless communications driver with the common rfkill
|
|
|
|
control system, which, for example, allows actions such as
|
|
|
|
"switch all bluetooth devices offline" to be carried out by
|
|
|
|
userspace or by rfkill-input.
|
|
|
|
|
|
|
|
THE RFKILL CLASS NEVER ISSUES INPUT EVENTS. THE RFKILL CLASS DOES
|
|
|
|
NOT LISTEN TO INPUT EVENTS. NO DRIVER USING THE RFKILL CLASS SHALL
|
|
|
|
EVER LISTEN TO, OR ACT ON RFKILL INPUT EVENTS.
|
|
|
|
|
|
|
|
Most wireless data communication drivers in the kernel have just to
|
|
|
|
implement the rfkill class API to work properly. Interfacing to the
|
|
|
|
input layer is not often required (and is very often a *bug*).
|
|
|
|
|
|
|
|
Userspace input handlers (uevents) or kernel input handlers (rfkill-input):
|
|
|
|
|
|
|
|
* Implements the policy of what should happen when one of the input
|
|
|
|
layer events related to rfkill operation is received.
|
|
|
|
* Uses the sysfs interface (userspace) or private rfkill API calls
|
|
|
|
to tell the devices registered with the rfkill class to change
|
|
|
|
their state (i.e. translates the input layer event into real
|
|
|
|
action).
|
|
|
|
* rfkill-input implements EPO by handling EV_SW SW_RFKILL_ALL 0
|
|
|
|
(power off all transmitters) in a special way: it ignores any
|
2008-06-23 14:46:42 -06:00
|
|
|
overrides and local state cache and forces all transmitters to the
|
|
|
|
RFKILL_STATE_SOFT_BLOCKED state (including those which are already
|
|
|
|
supposed to be BLOCKED). Note that the opposite event (power on all
|
|
|
|
transmitters) is handled normally.
|
2008-06-23 14:23:08 -06:00
|
|
|
|
|
|
|
Userspace uevent handler or kernel platform-specific drivers hooked to the
|
|
|
|
rfkill notifier chain:
|
|
|
|
|
|
|
|
* Taps into the rfkill notifier chain or to KOBJ_CHANGE uevents,
|
|
|
|
in order to know when a device that is registered with the rfkill
|
|
|
|
class changes state;
|
|
|
|
* Issues feedback notifications to the user;
|
|
|
|
* In the rare platforms where this is required, synthesizes an input
|
|
|
|
event to command all *OTHER* rfkill devices to also change their
|
|
|
|
statues when a specific rfkill device changes state.
|
|
|
|
|
|
|
|
|
|
|
|
===============================================================================
|
|
|
|
3: Kernel driver guidelines
|
|
|
|
|
|
|
|
The first thing one needs to know is whether his driver should be talking to
|
|
|
|
the rfkill class or to the input layer.
|
|
|
|
|
|
|
|
Do not mistake input devices for rfkill devices. The only type of "rfkill
|
|
|
|
switch" device that is to be registered with the rfkill class are those
|
|
|
|
directly controlling the circuits that cause a wireless transmitter to stop
|
|
|
|
working (or the software equivalent of them). Every other kind of "rfkill
|
|
|
|
switch" is just an input device and MUST NOT be registered with the rfkill
|
|
|
|
class.
|
|
|
|
|
|
|
|
A driver should register a device with the rfkill class when ALL of the
|
|
|
|
following conditions are met:
|
|
|
|
|
|
|
|
1. The device is/controls a data communications wireless transmitter;
|
|
|
|
|
|
|
|
2. The kernel can interact with the hardware/firmware to CHANGE the wireless
|
|
|
|
transmitter state (block/unblock TX operation);
|
|
|
|
|
|
|
|
A driver should register a device with the input subsystem to issue
|
|
|
|
rfkill-related events (KEY_WLAN, KEY_BLUETOOTH, KEY_WWAN, KEY_WIMAX,
|
|
|
|
SW_RFKILL_ALL, etc) when ALL of the folowing conditions are met:
|
|
|
|
|
|
|
|
1. It is directly related to some physical device the user interacts with, to
|
|
|
|
command the O.S./firmware/hardware to enable/disable a data communications
|
|
|
|
wireless transmitter.
|
|
|
|
|
|
|
|
Examples of the physical device are: buttons, keys and switches the user
|
|
|
|
will press/touch/slide/switch to enable or disable the wireless
|
|
|
|
communication device.
|
|
|
|
|
|
|
|
2. It is NOT slaved to another device, i.e. there is no other device that
|
|
|
|
issues rfkill-related input events in preference to this one.
|
|
|
|
|
|
|
|
Typically, the ACPI "radio kill" switch of a laptop is the master input
|
|
|
|
device to issue rfkill events, and, e.g., the WLAN card is just a slave
|
|
|
|
device that gets disabled by its hardware radio-kill input pin.
|
2007-09-13 01:22:55 -06:00
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
When in doubt, do not issue input events. For drivers that should generate
|
|
|
|
input events in some platforms, but not in others (e.g. b43), the best solution
|
|
|
|
is to NEVER generate input events in the first place. That work should be
|
|
|
|
deferred to a platform-specific kernel module (which will know when to generate
|
|
|
|
events through the rfkill notifier chain) or to userspace. This avoids the
|
|
|
|
usual maintenance problems with DMI whitelisting.
|
2007-09-13 01:22:55 -06:00
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
|
|
|
|
Corner cases and examples:
|
2007-09-13 01:22:55 -06:00
|
|
|
====================================
|
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
1. If the device is an input device that, because of hardware or firmware,
|
|
|
|
causes wireless transmitters to be blocked regardless of the kernel's will, it
|
|
|
|
is still just an input device, and NOT to be registered with the rfkill class.
|
2007-09-13 01:22:55 -06:00
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
2. If the wireless transmitter switch control is read-only, it is an input
|
|
|
|
device and not to be registered with the rfkill class (and maybe not to be made
|
|
|
|
an input layer event source either, see below).
|
2007-09-13 01:22:55 -06:00
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
3. If there is some other device driver *closer* to the actual hardware the
|
|
|
|
user interacted with (the button/switch/key) to issue an input event, THAT is
|
|
|
|
the device driver that should be issuing input events.
|
2007-09-13 01:22:55 -06:00
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
E.g:
|
|
|
|
[RFKILL slider switch] -- [GPIO hardware] -- [WLAN card rf-kill input]
|
|
|
|
(platform driver) (wireless card driver)
|
|
|
|
|
|
|
|
The user is closer to the RFKILL slide switch plaform driver, so the driver
|
|
|
|
which must issue input events is the platform driver looking at the GPIO
|
|
|
|
hardware, and NEVER the wireless card driver (which is just a slave). It is
|
|
|
|
very likely that there are other leaves than just the WLAN card rf-kill input
|
|
|
|
(e.g. a bluetooth card, etc)...
|
|
|
|
|
|
|
|
On the other hand, some embedded devices do this:
|
|
|
|
|
|
|
|
[RFKILL slider switch] -- [WLAN card rf-kill input]
|
|
|
|
(wireless card driver)
|
|
|
|
|
|
|
|
In this situation, the wireless card driver *could* register itself as an input
|
|
|
|
device and issue rf-kill related input events... but in order to AVOID the need
|
|
|
|
for DMI whitelisting, the wireless card driver does NOT do it. Userspace (HAL)
|
|
|
|
or a platform driver (that exists only on these embedded devices) will do the
|
|
|
|
dirty job of issuing the input events.
|
|
|
|
|
|
|
|
|
|
|
|
COMMON MISTAKES in kernel drivers, related to rfkill:
|
|
|
|
====================================
|
|
|
|
|
|
|
|
1. NEVER confuse input device keys and buttons with input device switches.
|
|
|
|
|
|
|
|
1a. Switches are always set or reset. They report the current state
|
|
|
|
(on position or off position).
|
|
|
|
|
|
|
|
1b. Keys and buttons are either in the pressed or not-pressed state, and
|
|
|
|
that's it. A "button" that latches down when you press it, and
|
|
|
|
unlatches when you press it again is in fact a switch as far as input
|
|
|
|
devices go.
|
|
|
|
|
|
|
|
Add the SW_* events you need for switches, do NOT try to emulate a button using
|
|
|
|
KEY_* events just because there is no such SW_* event yet. Do NOT try to use,
|
|
|
|
for example, KEY_BLUETOOTH when you should be using SW_BLUETOOTH instead.
|
|
|
|
|
|
|
|
2. Input device switches (sources of EV_SW events) DO store their current
|
|
|
|
state, and that state CAN be queried from userspace through IOCTLs. There is
|
|
|
|
no sysfs interface for this, but that doesn't mean you should break things
|
|
|
|
trying to hook it to the rfkill class to get a sysfs interface :-)
|
|
|
|
|
|
|
|
3. Do not issue *_RFKILL_ALL events, unless you are sure it is the correct
|
|
|
|
event for your switch/button. These events are emergency power-off events when
|
|
|
|
they are trying to turn the transmitters off. An example of an input device
|
|
|
|
which SHOULD generate *_RFKILL_ALL events is the wireless-kill switch in a
|
|
|
|
laptop which is NOT a hotkey, but a real switch that kills radios in hardware,
|
|
|
|
even if the O.S. has gone to lunch. An example of an input device which SHOULD
|
|
|
|
NOT generate *_RFKILL_ALL events is any sort of hot key that does nothing by
|
|
|
|
itself, as well as any hot key that is type-specific (e.g. the one for WLAN).
|
|
|
|
|
|
|
|
|
|
|
|
===============================================================================
|
|
|
|
4: Kernel API
|
|
|
|
|
|
|
|
To build a driver with rfkill subsystem support, the driver should depend on
|
|
|
|
the Kconfig symbol RFKILL; it should _not_ depend on RKFILL_INPUT.
|
|
|
|
|
|
|
|
The hardware the driver talks to may be write-only (where the current state
|
|
|
|
of the hardware is unknown), or read-write (where the hardware can be queried
|
|
|
|
about its current state).
|
|
|
|
|
|
|
|
The rfkill class will call the get_state hook of a device every time it needs
|
|
|
|
to know the *real* current state of the hardware. This can happen often.
|
|
|
|
|
|
|
|
Some hardware provides events when its status changes. In these cases, it is
|
|
|
|
best for the driver to not provide a get_state hook, and instead register the
|
|
|
|
rfkill class *already* with the correct status, and keep it updated using
|
|
|
|
rfkill_force_state() when it gets an event from the hardware.
|
2007-09-13 01:22:55 -06:00
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
There is no provision for a statically-allocated rfkill struct. You must
|
|
|
|
use rfkill_allocate() to allocate one.
|
2007-09-13 01:22:55 -06:00
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
You should:
|
2007-09-13 01:22:55 -06:00
|
|
|
- rfkill_allocate()
|
2008-06-23 14:23:08 -06:00
|
|
|
- modify rfkill fields (flags, name)
|
|
|
|
- modify state to the current hardware state (THIS IS THE ONLY TIME
|
|
|
|
YOU CAN ACCESS state DIRECTLY)
|
2007-09-13 01:22:55 -06:00
|
|
|
- rfkill_register()
|
|
|
|
|
2008-06-23 14:46:42 -06:00
|
|
|
The only way to set a device to the RFKILL_STATE_HARD_BLOCKED state is through
|
|
|
|
a suitable return of get_state() or through rfkill_force_state().
|
|
|
|
|
|
|
|
When a device is in the RFKILL_STATE_HARD_BLOCKED state, the only way to switch
|
|
|
|
it to a different state is through a suitable return of get_state() or through
|
|
|
|
rfkill_force_state().
|
|
|
|
|
|
|
|
If toggle_radio() is called to set a device to state RFKILL_STATE_SOFT_BLOCKED
|
|
|
|
when that device is already at the RFKILL_STATE_HARD_BLOCKED state, it should
|
|
|
|
not return an error. Instead, it should try to double-block the transmitter,
|
|
|
|
so that its state will change from RFKILL_STATE_HARD_BLOCKED to
|
|
|
|
RFKILL_STATE_SOFT_BLOCKED should the hardware blocking cease.
|
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
Please refer to the source for more documentation.
|
2007-09-13 01:22:55 -06:00
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
===============================================================================
|
|
|
|
5: Userspace support
|
|
|
|
|
|
|
|
rfkill devices issue uevents (with an action of "change"), with the following
|
|
|
|
environment variables set:
|
|
|
|
|
|
|
|
RFKILL_NAME
|
|
|
|
RFKILL_STATE
|
|
|
|
RFKILL_TYPE
|
2007-09-13 01:22:55 -06:00
|
|
|
|
2008-06-23 14:23:08 -06:00
|
|
|
The ABI for these variables is defined by the sysfs attributes. It is best
|
|
|
|
to take a quick look at the source to make sure of the possible values.
|
|
|
|
|
|
|
|
It is expected that HAL will trap those, and bridge them to DBUS, etc. These
|
|
|
|
events CAN and SHOULD be used to give feedback to the user about the rfkill
|
|
|
|
status of the system.
|
|
|
|
|
|
|
|
Input devices may issue events that are related to rfkill. These are the
|
|
|
|
various KEY_* events and SW_* events supported by rfkill-input.c.
|
|
|
|
|
|
|
|
******IMPORTANT******
|
|
|
|
When rfkill-input is ACTIVE, userspace is NOT TO CHANGE THE STATE OF AN RFKILL
|
|
|
|
SWITCH IN RESPONSE TO AN INPUT EVENT also handled by rfkill-input, unless it
|
|
|
|
has set to true the user_claim attribute for that particular switch. This rule
|
|
|
|
is *absolute*; do NOT violate it.
|
|
|
|
******IMPORTANT******
|
|
|
|
|
|
|
|
Userspace must not assume it is the only source of control for rfkill switches.
|
|
|
|
Their state CAN and WILL change on its own, due to firmware actions, direct
|
|
|
|
user actions, and the rfkill-input EPO override for *_RFKILL_ALL.
|
|
|
|
|
|
|
|
When rfkill-input is not active, userspace must initiate an rfkill status
|
|
|
|
change by writing to the "state" attribute in order for anything to happen.
|
|
|
|
|
|
|
|
Take particular care to implement EV_SW SW_RFKILL_ALL properly. When that
|
|
|
|
switch is set to OFF, *every* rfkill device *MUST* be immediately put into the
|
2008-06-23 14:46:42 -06:00
|
|
|
RFKILL_STATE_SOFT_BLOCKED state, no questions asked.
|
2007-09-13 01:22:55 -06:00
|
|
|
|
|
|
|
The following sysfs entries will be created:
|
|
|
|
|
|
|
|
name: Name assigned by driver to this key (interface or driver name).
|
|
|
|
type: Name of the key type ("wlan", "bluetooth", etc).
|
2008-06-23 14:46:42 -06:00
|
|
|
state: Current state of the transmitter
|
|
|
|
0: RFKILL_STATE_SOFT_BLOCKED
|
|
|
|
transmitter is forced off, but you can override it
|
|
|
|
by a write to the state attribute, or through input
|
|
|
|
events (if rfkill-input is loaded).
|
|
|
|
1: RFKILL_STATE_UNBLOCKED
|
|
|
|
transmiter is NOT forced off, and may operate if
|
|
|
|
all other conditions for such operation are met
|
|
|
|
(such as interface is up and configured, etc).
|
|
|
|
2: RFKILL_STATE_HARD_BLOCKED
|
|
|
|
transmitter is forced off by something outside of
|
|
|
|
the driver's control.
|
|
|
|
|
|
|
|
You cannot set a device to this state through
|
|
|
|
writes to the state attribute.
|
2007-09-13 01:22:55 -06:00
|
|
|
claim: 1: Userspace handles events, 0: Kernel handles events
|
|
|
|
|
|
|
|
Both the "state" and "claim" entries are also writable. For the "state" entry
|
2008-06-23 14:23:08 -06:00
|
|
|
this means that when 1 or 0 is written, the device rfkill state (if not yet in
|
|
|
|
the requested state), will be will be toggled accordingly.
|
|
|
|
|
2007-09-13 01:22:55 -06:00
|
|
|
For the "claim" entry writing 1 to it means that the kernel no longer handles
|
|
|
|
key events even though RFKILL_INPUT input was enabled. When "claim" has been
|
|
|
|
set to 0, userspace should make sure that it listens for the input events or
|
2008-06-23 14:23:08 -06:00
|
|
|
check the sysfs "state" entry regularly to correctly perform the required tasks
|
|
|
|
when the rkfill key is pressed.
|
|
|
|
|
|
|
|
A note about input devices and EV_SW events:
|
|
|
|
|
|
|
|
In order to know the current state of an input device switch (like
|
|
|
|
SW_RFKILL_ALL), you will need to use an IOCTL. That information is not
|
|
|
|
available through sysfs in a generic way at this time, and it is not available
|
|
|
|
through the rfkill class AT ALL.
|