123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- rfkill - RF switch subsystem support
- ====================================
- 1 Introduction
- 2 Implementation details
- 3 Kernel driver guidelines
- 4 Kernel API
- 5 Userspace support
- 1. Introduction:
- The rfkill switch subsystem exists to add a generic interface to circuitry that
- 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.
- 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.
- 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).
- 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.
- ===============================================================================
- 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.
- The system inside the kernel has been split into 2 separate sections:
- 1 - RFKILL
- 2 - RFKILL_INPUT
- 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.
- When a rfkill switch is in the RFKILL_STATE_ON, the wireless transmitter (radio
- TX circuit for example) is *enabled*. When the rfkill switch is in the
- RFKILL_STATE_OFF, the wireless transmitter is to be *blocked* from operating.
- 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
- overrides and local state cache and forces all transmitters to
- the OFF state (including those which are already supposed to be
- OFF). Note that the opposite event (power on all transmitters)
- is handled normally.
- 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.
- 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.
- Corner cases and examples:
- ====================================
- 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.
- 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).
- 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.
- 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.
- There is no provision for a statically-allocated rfkill struct. You must
- use rfkill_allocate() to allocate one.
- You should:
- - rfkill_allocate()
- - modify rfkill fields (flags, name)
- - modify state to the current hardware state (THIS IS THE ONLY TIME
- YOU CAN ACCESS state DIRECTLY)
- - rfkill_register()
- Please refer to the source for more documentation.
- ===============================================================================
- 5: Userspace support
- rfkill devices issue uevents (with an action of "change"), with the following
- environment variables set:
- RFKILL_NAME
- RFKILL_STATE
- RFKILL_TYPE
- 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
- OFF state, no questions asked.
- 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).
- state: Current state of the key. 1: On, 0: Off.
- claim: 1: Userspace handles events, 0: Kernel handles events
- Both the "state" and "claim" entries are also writable. For the "state" entry
- 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.
- 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
- 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.
|