rfkill: improve docs
Now that the dust has settled a bit, improve the docs on rfkill and include more information about /dev/rfkill. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
committed by
John W. Linville
parent
7e9debe978
commit
ce0879e324
@@ -3,9 +3,8 @@ rfkill - RF kill switch support
|
|||||||
|
|
||||||
1. Introduction
|
1. Introduction
|
||||||
2. Implementation details
|
2. Implementation details
|
||||||
3. Kernel driver guidelines
|
3. Kernel API
|
||||||
4. Kernel API
|
4. Userspace support
|
||||||
5. Userspace support
|
|
||||||
|
|
||||||
|
|
||||||
1. Introduction
|
1. Introduction
|
||||||
@@ -19,82 +18,62 @@ disable all transmitters of a certain type (or all). This is intended for
|
|||||||
situations where transmitters need to be turned off, for example on
|
situations where transmitters need to be turned off, for example on
|
||||||
aircraft.
|
aircraft.
|
||||||
|
|
||||||
|
The rfkill subsystem has a concept of "hard" and "soft" block, which
|
||||||
|
differ little in their meaning (block == transmitters off) but rather in
|
||||||
|
whether they can be changed or not:
|
||||||
|
- hard block: read-only radio block that cannot be overriden by software
|
||||||
|
- soft block: writable radio block (need not be readable) that is set by
|
||||||
|
the system software.
|
||||||
|
|
||||||
|
|
||||||
2. Implementation details
|
2. Implementation details
|
||||||
|
|
||||||
The rfkill subsystem is composed of various components: the rfkill class, the
|
The rfkill subsystem is composed of three main components:
|
||||||
rfkill-input module (an input layer handler), and some specific input layer
|
* the rfkill core,
|
||||||
events.
|
* the deprecated rfkill-input module (an input layer handler, being
|
||||||
|
replaced by userspace policy code) and
|
||||||
|
* the rfkill drivers.
|
||||||
|
|
||||||
The rfkill class is provided for kernel drivers to register their radio
|
The rfkill core provides API for kernel drivers to register their radio
|
||||||
transmitter with the kernel, provide methods for turning it on and off and,
|
transmitter with the kernel, methods for turning it on and off and, letting
|
||||||
optionally, letting the system know about hardware-disabled states that may
|
the system know about hardware-disabled states that may be implemented on
|
||||||
be implemented on the device. This code is enabled with the CONFIG_RFKILL
|
the device.
|
||||||
Kconfig option, which drivers can "select".
|
|
||||||
|
|
||||||
The rfkill class code also notifies userspace of state changes, this is
|
The rfkill core code also notifies userspace of state changes, and provides
|
||||||
achieved via uevents. It also provides some sysfs files for userspace to
|
ways for userspace to query the current states. See the "Userspace support"
|
||||||
check the status of radio transmitters. See the "Userspace support" section
|
section below.
|
||||||
below.
|
|
||||||
|
|
||||||
|
|
||||||
The rfkill-input code implements a basic response to rfkill buttons -- it
|
|
||||||
implements turning on/off all devices of a certain class (or all).
|
|
||||||
|
|
||||||
When the device is hard-blocked (either by a call to rfkill_set_hw_state()
|
When the device is hard-blocked (either by a call to rfkill_set_hw_state()
|
||||||
or from query_hw_block) set_block() will be invoked but drivers can well
|
or from query_hw_block) set_block() will be invoked for additional software
|
||||||
ignore the method call since they can use the return value of the function
|
block, but drivers can ignore the method call since they can use the return
|
||||||
rfkill_set_hw_state() to sync the software state instead of keeping track
|
value of the function rfkill_set_hw_state() to sync the software state
|
||||||
of calls to set_block().
|
instead of keeping track of calls to set_block(). In fact, drivers should
|
||||||
|
use the return value of rfkill_set_hw_state() unless the hardware actually
|
||||||
|
keeps track of soft and hard block separately.
|
||||||
|
|
||||||
|
|
||||||
The entire functionality is spread over more than one subsystem:
|
3. Kernel API
|
||||||
|
|
||||||
* The kernel input layer generates KEY_WWAN, KEY_WLAN etc. and
|
|
||||||
SW_RFKILL_ALL -- when the user presses a button. Drivers for radio
|
|
||||||
transmitters generally do not register to the input layer, unless the
|
|
||||||
device really provides an input device (i.e. a button that has no
|
|
||||||
effect other than generating a button press event)
|
|
||||||
|
|
||||||
* The rfkill-input code hooks up to these events and switches the soft-block
|
|
||||||
of the various radio transmitters, depending on the button type.
|
|
||||||
|
|
||||||
* The rfkill drivers turn off/on their transmitters as requested.
|
|
||||||
|
|
||||||
* The rfkill class will generate userspace notifications (uevents) to tell
|
|
||||||
userspace what the current state is.
|
|
||||||
|
|
||||||
|
|
||||||
|
Drivers for radio transmitters normally implement an rfkill driver.
|
||||||
3. Kernel driver guidelines
|
|
||||||
|
|
||||||
|
|
||||||
Drivers for radio transmitters normally implement only the rfkill class.
|
|
||||||
These drivers may not unblock the transmitter based on own decisions, they
|
|
||||||
should act on information provided by the rfkill class only.
|
|
||||||
|
|
||||||
Platform drivers might implement input devices if the rfkill button is just
|
Platform drivers might implement input devices if the rfkill button is just
|
||||||
that, a button. If that button influences the hardware then you need to
|
that, a button. If that button influences the hardware then you need to
|
||||||
implement an rfkill class instead. This also applies if the platform provides
|
implement an rfkill driver instead. This also applies if the platform provides
|
||||||
a way to turn on/off the transmitter(s).
|
a way to turn on/off the transmitter(s).
|
||||||
|
|
||||||
During suspend/hibernation, transmitters should only be left enabled when
|
For some platforms, it is possible that the hardware state changes during
|
||||||
wake-on wlan or similar functionality requires it and the device wasn't
|
suspend/hibernation, in which case it will be necessary to update the rfkill
|
||||||
blocked before suspend/hibernate. Note that it may be necessary to update
|
core with the current state is at resume time.
|
||||||
the rfkill subsystem's idea of what the current state is at resume time if
|
|
||||||
the state may have changed over suspend.
|
|
||||||
|
|
||||||
|
To create an rfkill driver, driver's Kconfig needs to have
|
||||||
|
|
||||||
|
depends on RFKILL || !RFKILL
|
||||||
|
|
||||||
4. Kernel API
|
to ensure the driver cannot be built-in when rfkill is modular. The !RFKILL
|
||||||
|
case allows the driver to be built when rfkill is not configured, which which
|
||||||
To build a driver with rfkill subsystem support, the driver should depend on
|
case all rfkill API can still be used but will be provided by static inlines
|
||||||
(or select) the Kconfig symbol RFKILL.
|
which compile to almost nothing.
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
Calling rfkill_set_hw_state() when a state change happens is required from
|
Calling rfkill_set_hw_state() when a state change happens is required from
|
||||||
rfkill drivers that control devices that can be hard-blocked unless they also
|
rfkill drivers that control devices that can be hard-blocked unless they also
|
||||||
@@ -105,10 +84,33 @@ device). Don't do this unless you cannot get the event in any other way.
|
|||||||
|
|
||||||
5. Userspace support
|
5. Userspace support
|
||||||
|
|
||||||
The following sysfs entries exist for every rfkill device:
|
The recommended userspace interface to use is /dev/rfkill, which is a misc
|
||||||
|
character device that allows userspace to obtain and set the state of rfkill
|
||||||
|
devices and sets of devices. It also notifies userspace about device addition
|
||||||
|
and removal. The API is a simple read/write API that is defined in
|
||||||
|
linux/rfkill.h, with one ioctl that allows turning off the deprecated input
|
||||||
|
handler in the kernel for the transition period.
|
||||||
|
|
||||||
|
Except for the one ioctl, communication with the kernel is done via read()
|
||||||
|
and write() of instances of 'struct rfkill_event'. In this structure, the
|
||||||
|
soft and hard block are properly separated (unlike sysfs, see below) and
|
||||||
|
userspace is able to get a consistent snapshot of all rfkill devices in the
|
||||||
|
system. Also, it is possible to switch all rfkill drivers (or all drivers of
|
||||||
|
a specified type) into a state which also updates the default state for
|
||||||
|
hotplugged devices.
|
||||||
|
|
||||||
|
After an application opens /dev/rfkill, it can read the current state of
|
||||||
|
all devices, and afterwards can poll the descriptor for hotplug or state
|
||||||
|
change events.
|
||||||
|
|
||||||
|
Applications must ignore operations (the "op" field) they do not handle,
|
||||||
|
this allows the API to be extended in the future.
|
||||||
|
|
||||||
|
Additionally, each rfkill device is registered in sysfs and there has the
|
||||||
|
following attributes:
|
||||||
|
|
||||||
name: Name assigned by driver to this key (interface or driver name).
|
name: Name assigned by driver to this key (interface or driver name).
|
||||||
type: Name of the key type ("wlan", "bluetooth", etc).
|
type: Driver type string ("wlan", "bluetooth", etc).
|
||||||
state: Current state of the transmitter
|
state: Current state of the transmitter
|
||||||
0: RFKILL_STATE_SOFT_BLOCKED
|
0: RFKILL_STATE_SOFT_BLOCKED
|
||||||
transmitter is turned off by software
|
transmitter is turned off by software
|
||||||
@@ -117,7 +119,12 @@ The following sysfs entries exist for every rfkill device:
|
|||||||
2: RFKILL_STATE_HARD_BLOCKED
|
2: RFKILL_STATE_HARD_BLOCKED
|
||||||
transmitter is forced off by something outside of
|
transmitter is forced off by something outside of
|
||||||
the driver's control.
|
the driver's control.
|
||||||
claim: 0: Kernel handles events (currently always reads that value)
|
This file is deprecated because it can only properly show
|
||||||
|
three of the four possible states, soft-and-hard-blocked is
|
||||||
|
missing.
|
||||||
|
claim: 0: Kernel handles events
|
||||||
|
This file is deprecated because there no longer is a way to
|
||||||
|
claim just control over a single rfkill instance.
|
||||||
|
|
||||||
rfkill devices also issue uevents (with an action of "change"), with the
|
rfkill devices also issue uevents (with an action of "change"), with the
|
||||||
following environment variables set:
|
following environment variables set:
|
||||||
@@ -128,9 +135,3 @@ RFKILL_TYPE
|
|||||||
|
|
||||||
The contents of these variables corresponds to the "name", "state" and
|
The contents of these variables corresponds to the "name", "state" and
|
||||||
"type" sysfs files explained above.
|
"type" sysfs files explained above.
|
||||||
|
|
||||||
An alternative userspace interface exists as a misc device /dev/rfkill,
|
|
||||||
which allows userspace to obtain and set the state of rfkill devices and
|
|
||||||
sets of devices. It also notifies userspace about device addition and
|
|
||||||
removal. The API is a simple read/write API that is defined in
|
|
||||||
linux/rfkill.h.
|
|
||||||
|
Reference in New Issue
Block a user