Commit c64fb016 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

rfkill: create useful userspace interface

The new code added by this patch will make rfkill create
a misc character device /dev/rfkill that userspace can use
to control rfkill soft blocks and get status of devices as
well as events when the status changes.

Using it is very simple -- when you open it you can read
a number of times to get the initial state, and every
further read blocks (you can poll) on getting the next
event from the kernel. The same structure you read is
also used when writing to it to change the soft block of
a given device, all devices of a given type, or all
devices.

This also makes CONFIG_RFKILL_INPUT selectable again in
order to be able to test without it present since its
functionality can now be replaced by userspace entirely
and distros and users may not want the input part of
rfkill interfering with their userspace code. We will
also write a userspace daemon to handle all that and
consequently add the input code to the feature removal
schedule.

In order to have rfkilld support both kernels with and
without CONFIG_RFKILL_INPUT (or new kernels after its
eventual removal) we also add an ioctl (that only exists
if rfkill-input is present) to disable rfkill-input.
It is not very efficient, but at least gives the correct
behaviour in all cases.
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Acked-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 19d337df
...@@ -437,3 +437,10 @@ Why: Superseded by tdfxfb. I2C/DDC support used to live in a separate ...@@ -437,3 +437,10 @@ Why: Superseded by tdfxfb. I2C/DDC support used to live in a separate
driver but this caused driver conflicts. driver but this caused driver conflicts.
Who: Jean Delvare <khali@linux-fr.org> Who: Jean Delvare <khali@linux-fr.org>
Krzysztof Helt <krzysztof.h1@wp.pl> Krzysztof Helt <krzysztof.h1@wp.pl>
---------------------------
What: CONFIG_RFKILL_INPUT
When: 2.6.33
Why: Should be implemented in userspace, policy daemon.
Who: Johannes Berg <johannes@sipsolutions.net>
...@@ -22,34 +22,17 @@ ...@@ -22,34 +22,17 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include <linux/types.h>
/* define userspace visible states */ /* define userspace visible states */
#define RFKILL_STATE_SOFT_BLOCKED 0 #define RFKILL_STATE_SOFT_BLOCKED 0
#define RFKILL_STATE_UNBLOCKED 1 #define RFKILL_STATE_UNBLOCKED 1
#define RFKILL_STATE_HARD_BLOCKED 2 #define RFKILL_STATE_HARD_BLOCKED 2
/* and that's all userspace gets */
#ifdef __KERNEL__
/* don't allow anyone to use these in the kernel */
enum rfkill_user_states {
RFKILL_USER_STATE_SOFT_BLOCKED = RFKILL_STATE_SOFT_BLOCKED,
RFKILL_USER_STATE_UNBLOCKED = RFKILL_STATE_UNBLOCKED,
RFKILL_USER_STATE_HARD_BLOCKED = RFKILL_STATE_HARD_BLOCKED,
};
#undef RFKILL_STATE_SOFT_BLOCKED
#undef RFKILL_STATE_UNBLOCKED
#undef RFKILL_STATE_HARD_BLOCKED
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/leds.h>
/** /**
* enum rfkill_type - type of rfkill switch. * enum rfkill_type - type of rfkill switch.
* *
* @RFKILL_TYPE_ALL: toggles all switches (userspace only)
* @RFKILL_TYPE_WLAN: switch is on a 802.11 wireless network device. * @RFKILL_TYPE_WLAN: switch is on a 802.11 wireless network device.
* @RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device. * @RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device.
* @RFKILL_TYPE_UWB: switch is on a ultra wideband device. * @RFKILL_TYPE_UWB: switch is on a ultra wideband device.
...@@ -58,6 +41,7 @@ enum rfkill_user_states { ...@@ -58,6 +41,7 @@ enum rfkill_user_states {
* @NUM_RFKILL_TYPES: number of defined rfkill types * @NUM_RFKILL_TYPES: number of defined rfkill types
*/ */
enum rfkill_type { enum rfkill_type {
RFKILL_TYPE_ALL = 0,
RFKILL_TYPE_WLAN, RFKILL_TYPE_WLAN,
RFKILL_TYPE_BLUETOOTH, RFKILL_TYPE_BLUETOOTH,
RFKILL_TYPE_UWB, RFKILL_TYPE_UWB,
...@@ -66,6 +50,62 @@ enum rfkill_type { ...@@ -66,6 +50,62 @@ enum rfkill_type {
NUM_RFKILL_TYPES, NUM_RFKILL_TYPES,
}; };
/**
* enum rfkill_operation - operation types
* @RFKILL_OP_ADD: a device was added
* @RFKILL_OP_DEL: a device was removed
* @RFKILL_OP_CHANGE: a device's state changed -- userspace changes one device
* @RFKILL_OP_CHANGE_ALL: userspace changes all devices (of a type, or all)
*/
enum rfkill_operation {
RFKILL_OP_ADD = 0,
RFKILL_OP_DEL,
RFKILL_OP_CHANGE,
RFKILL_OP_CHANGE_ALL,
};
/**
* struct rfkill_event - events for userspace on /dev/rfkill
* @idx: index of dev rfkill
* @type: type of the rfkill struct
* @op: operation code
* @hard: hard state (0/1)
* @soft: soft state (0/1)
*
* Structure used for userspace communication on /dev/rfkill,
* used for events from the kernel and control to the kernel.
*/
struct rfkill_event {
__u32 idx;
__u8 type;
__u8 op;
__u8 soft, hard;
} __packed;
/* ioctl for turning off rfkill-input (if present) */
#define RFKILL_IOC_MAGIC 'R'
#define RFKILL_IOC_NOINPUT 1
#define RFKILL_IOCTL_NOINPUT _IO(RFKILL_IOC_MAGIC, RFKILL_IOC_NOINPUT)
/* and that's all userspace gets */
#ifdef __KERNEL__
/* don't allow anyone to use these in the kernel */
enum rfkill_user_states {
RFKILL_USER_STATE_SOFT_BLOCKED = RFKILL_STATE_SOFT_BLOCKED,
RFKILL_USER_STATE_UNBLOCKED = RFKILL_STATE_UNBLOCKED,
RFKILL_USER_STATE_HARD_BLOCKED = RFKILL_STATE_HARD_BLOCKED,
};
#undef RFKILL_STATE_SOFT_BLOCKED
#undef RFKILL_STATE_UNBLOCKED
#undef RFKILL_STATE_HARD_BLOCKED
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/leds.h>
/* this is opaque */ /* this is opaque */
struct rfkill; struct rfkill;
...@@ -84,11 +124,7 @@ struct rfkill; ...@@ -84,11 +124,7 @@ struct rfkill;
* the rfkill core query your driver before setting a requested * the rfkill core query your driver before setting a requested
* block. * block.
* @set_block: turn the transmitter on (blocked == false) or off * @set_block: turn the transmitter on (blocked == false) or off
* (blocked == true) -- this is called only while the transmitter * (blocked == true) -- ignore and return 0 when hard blocked.
* is not hard-blocked, but note that the core's view of whether
* the transmitter is hard-blocked might differ from your driver's
* view due to race conditions, so it is possible that it is still
* called at the same time as you are calling rfkill_set_hw_state().
* This callback must be assigned. * This callback must be assigned.
*/ */
struct rfkill_ops { struct rfkill_ops {
......
...@@ -18,7 +18,7 @@ config RFKILL_LEDS ...@@ -18,7 +18,7 @@ config RFKILL_LEDS
default y default y
config RFKILL_INPUT config RFKILL_INPUT
bool bool "RF switch input support"
depends on RFKILL depends on RFKILL
depends on INPUT = y || RFKILL = INPUT depends on INPUT = y || RFKILL = INPUT
default y default y if !EMBEDDED
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment