* [PATCH 11/12] rfkill: do not allow userspace to override ALL RADIOS OFF
2008-06-04 3:10 [GIT PATCH] rkfill improvements for -next Henrique de Moraes Holschuh
@ 2008-06-04 3:10 ` Henrique de Moraes Holschuh
0 siblings, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-04 3:10 UTC (permalink / raw)
To: John W. Linville
Cc: Ivo van Doorn, linux-wireless, Henrique de Moraes Holschuh,
Dmitry Torokhov
SW_RFKILL_ALL is the "emergency power-off all radios" input event. It must
be handled, and must always do the same thing as far as the rfkill system
is concerned: all transmitters are to go *immediately* offline.
For safety, do NOT allow userspace to override EV_SW SW_RFKILL_ALL OFF. As
long as rfkill-input is loaded, that event will *always* be processed, and
it will *always* force all rfkill switches to disable all wireless
transmitters, regardless of user_claim attribute or anything else.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
Cc: Dmitry Torokhov <dtor@mail.ru>
---
net/rfkill/rfkill-input.c | 29 ++++++++++++++---------------
net/rfkill/rfkill-input.h | 1 +
net/rfkill/rfkill.c | 18 ++++++++++++++++++
3 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c
index 29c13d3..0fadeed 100644
--- a/net/rfkill/rfkill-input.c
+++ b/net/rfkill/rfkill-input.c
@@ -127,21 +127,20 @@ static void rfkill_event(struct input_handle *handle, unsigned int type,
switch (code) {
case SW_RFKILL_ALL:
/* EVERY radio type. data != 0 means radios ON */
- rfkill_schedule_set(&rfkill_wwan,
- (data)? RFKILL_STATE_ON:
- RFKILL_STATE_OFF);
- rfkill_schedule_set(&rfkill_wimax,
- (data)? RFKILL_STATE_ON:
- RFKILL_STATE_OFF);
- rfkill_schedule_set(&rfkill_uwb,
- (data)? RFKILL_STATE_ON:
- RFKILL_STATE_OFF);
- rfkill_schedule_set(&rfkill_bt,
- (data)? RFKILL_STATE_ON:
- RFKILL_STATE_OFF);
- rfkill_schedule_set(&rfkill_wlan,
- (data)? RFKILL_STATE_ON:
- RFKILL_STATE_OFF);
+ /* handle EPO (emergency power off) through shortcut */
+ if (data) {
+ rfkill_schedule_set(&rfkill_wwan,
+ RFKILL_STATE_ON);
+ rfkill_schedule_set(&rfkill_wimax,
+ RFKILL_STATE_ON);
+ rfkill_schedule_set(&rfkill_uwb,
+ RFKILL_STATE_ON);
+ rfkill_schedule_set(&rfkill_bt,
+ RFKILL_STATE_ON);
+ rfkill_schedule_set(&rfkill_wlan,
+ RFKILL_STATE_ON);
+ } else
+ rfkill_epo();
break;
default:
break;
diff --git a/net/rfkill/rfkill-input.h b/net/rfkill/rfkill-input.h
index 4dae500..f63d050 100644
--- a/net/rfkill/rfkill-input.h
+++ b/net/rfkill/rfkill-input.h
@@ -12,5 +12,6 @@
#define __RFKILL_INPUT_H
void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state);
+void rfkill_epo(void);
#endif /* __RFKILL_INPUT_H */
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 8d24c3b..bd418db 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -182,6 +182,24 @@ void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state)
EXPORT_SYMBOL(rfkill_switch_all);
/**
+ * rfkill_epo - emergency power off all transmitters
+ *
+ * This kicks all rfkill devices to RFKILL_STATE_OFF, ignoring
+ * everything in its path but rfkill_mutex.
+ */
+void rfkill_epo(void)
+{
+ struct rfkill *rfkill;
+
+ mutex_lock(&rfkill_mutex);
+ list_for_each_entry(rfkill, &rfkill_list, node) {
+ rfkill_toggle_radio(rfkill, RFKILL_STATE_OFF, 1);
+ }
+ mutex_unlock(&rfkill_mutex);
+}
+EXPORT_SYMBOL_GPL(rfkill_epo);
+
+/**
* rfkill_force_state - Force the internal rfkill radio state
* @rfkill: pointer to the rfkill class to modify.
* @state: the current radio state the class should be forced to.
--
1.5.5.3
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PATCH] rfkill rework for 2.6.27 (v2)
@ 2008-06-22 15:38 Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 01/12] rfkill: clarify meaning of rfkill states Henrique de Moraes Holschuh
` (11 more replies)
0 siblings, 12 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-22 15:38 UTC (permalink / raw)
To: John Linville
Cc: linux-wireless, Ivo van Doorn, Matthew Garrett, Dan Williams,
Thomas Renninger
Hello John,
Here is the revised patchset to bring rfkill up to shape enough that it
becomes useable for platform drivers like thinkpad-acpi.
There are some very minor changes:
* Added a check for illegal states on rfkill_force_state() since
it is an exported function and someone might call it with wrong
parameters;
* Fix use of %u instead of %d on uevent generation for RFKILL_STATE
to match the type for enum rfkill_state;
* Minor documentation wording changes;
All the patches in this patchset have been ACKed by Ivo, the rfkill
maintainer. They're based on wireless-testing master branch, but they
apply cleanly on top of 2.6.26-rc7 as well.
No real problem was found on any of the patches in the thread they
generated last time I posted, AFAIK all doubts regarding these patches
have been explained to the satisfaction of everyone involved, and they
dealt far more with the rfkill subsystem itself than with anything any
of the patches was doing.
True, there are still shortcomings in the rfkill subsystem even after
this patchset, but that's not a problem with the patches but rather
missing features and changes that should be done on further patches.
Some of these patches are ready (e.g. extra documentation) and others (a
new hardlocked rfkill state for rfkill-state) are being tested, and will
be send to linux-wireless soon.
Please merge this patchset on wireless-testing to get it on its way to
linux-next, so that it can go to 2.6.27 when the merge window opens.
This patchset is extremely important for my thinkpad-acpi work, and for
other drivers like hp-wmi.
Note that these patches are backwards-compatible in API and ABI. No
in-tree drivers are broken by it, but it doesn't magically fixes their
rfkill support either. It just makes it possible to write drivers using
rfkill that actually work properly.
These patches went through a lot of discursion already, available at
http://thread.gmane.org/gmane.linux.kernel/664500 and a more recent
thread at http://thread.gmane.org/gmane.linux.kernel/682233 and
http://thread.gmane.org/gmane.linux.kernel.wireless.general/15677.
This series is available as a git branch at:
git://repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git for-upstream/rfkill
Shortlog:
Henrique de Moraes Holschuh (12):
rfkill: clarify meaning of rfkill states
rfkill: fix minor typo in kernel doc
rfkill: handle SW_RFKILL_ALL events
rfkill: add parameter to disable radios by default
rfkill: add read-write rfkill switch support
rfkill: add the WWAN radio type
rfkill: rework suspend and resume handlers
rfkill: add notifier chains support
rfkill: add type string helper
rfkill: add uevent notifications
rfkill: do not allow userspace to override ALL RADIOS OFF
rfkill: document rw rfkill switches and clarify input subsystem interactions
Thank you.
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 01/12] rfkill: clarify meaning of rfkill states
2008-06-22 15:38 [GIT PATCH] rfkill rework for 2.6.27 (v2) Henrique de Moraes Holschuh
@ 2008-06-22 15:38 ` Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 02/12] rfkill: fix minor typo in kernel doc Henrique de Moraes Holschuh
` (10 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-22 15:38 UTC (permalink / raw)
To: John Linville
Cc: linux-wireless, Ivo van Doorn, Matthew Garrett, Dan Williams,
Thomas Renninger, Henrique de Moraes Holschuh, John W. Linville,
Dmitry Torokhov
rfkill really should have been named rfswitch. As it is, one can get
confused whether RFKILL_STATE_ON means the KILL switch is on (and
therefore, the radio is being *blocked* from operating), or whether it
means the RADIO rf output is on.
Clearly state that RFKILL_STATE_ON means the radio is *unblocked* from
operating (i.e. there is no rf killing going on).
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
Cc: John W. Linville <linville@tuxdriver.com>
Cc: Dmitry Torokhov <dtor@mail.ru>
---
Documentation/rfkill.txt | 7 +++++++
include/linux/rfkill.h | 6 +++---
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt
index a83ff23..ec75d6d 100644
--- a/Documentation/rfkill.txt
+++ b/Documentation/rfkill.txt
@@ -8,6 +8,13 @@ rfkill - RF switch subsystem support
===============================================================================
1: Implementation details
+The rfkill switch subsystem exists to add a generic interface to circuitry that
+can enable or disable the RF output of a radio *transmitter* of any type.
+
+When a rfkill switch is in the RFKILL_STATE_ON, the radio transmitter is
+*enabled*. When the rfkill switch is in the RFKILL_STATE_OFF, the radio
+transmitter is *disabled*.
+
The rfkill switch subsystem offers support for keys often found on laptops
to enable wireless devices like WiFi and Bluetooth.
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index e3ab21d..ca89ae1 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -44,8 +44,8 @@ enum rfkill_type {
};
enum rfkill_state {
- RFKILL_STATE_OFF = 0,
- RFKILL_STATE_ON = 1,
+ RFKILL_STATE_OFF = 0, /* Radio output blocked */
+ RFKILL_STATE_ON = 1, /* Radio output active */
};
/**
@@ -53,7 +53,7 @@ enum rfkill_state {
* @name: Name of the switch.
* @type: Radio type which the button controls, the value stored
* here should be a value from enum rfkill_type.
- * @state: State of the switch (on/off).
+ * @state: State of the switch, "ON" means radio can operate.
* @user_claim_unsupported: Whether the hardware supports exclusive
* RF-kill control by userspace. Set this before registering.
* @user_claim: Set when the switch is controlled exlusively by userspace.
--
1.5.5.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 02/12] rfkill: fix minor typo in kernel doc
2008-06-22 15:38 [GIT PATCH] rfkill rework for 2.6.27 (v2) Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 01/12] rfkill: clarify meaning of rfkill states Henrique de Moraes Holschuh
@ 2008-06-22 15:38 ` Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 03/12] rfkill: handle SW_RFKILL_ALL events Henrique de Moraes Holschuh
` (9 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-22 15:38 UTC (permalink / raw)
To: John Linville
Cc: linux-wireless, Ivo van Doorn, Matthew Garrett, Dan Williams,
Thomas Renninger, Henrique de Moraes Holschuh, John W. Linville,
Dmitry Torokhov
Fix a minor typo in an exported function documentation
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
Cc: John W. Linville <linville@tuxdriver.com>
Cc: Dmitry Torokhov <dtor@mail.ru>
---
net/rfkill/rfkill.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 4e10a95..f95081a 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -412,7 +412,7 @@ int rfkill_register(struct rfkill *rfkill)
EXPORT_SYMBOL(rfkill_register);
/**
- * rfkill_unregister - Uegister a rfkill structure.
+ * rfkill_unregister - Unregister a rfkill structure.
* @rfkill: rfkill structure to be unregistered
*
* This function should be called by the network driver during device
--
1.5.5.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 03/12] rfkill: handle SW_RFKILL_ALL events
2008-06-22 15:38 [GIT PATCH] rfkill rework for 2.6.27 (v2) Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 01/12] rfkill: clarify meaning of rfkill states Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 02/12] rfkill: fix minor typo in kernel doc Henrique de Moraes Holschuh
@ 2008-06-22 15:38 ` Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 04/12] rfkill: add parameter to disable radios by default Henrique de Moraes Holschuh
` (8 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-22 15:38 UTC (permalink / raw)
To: John Linville
Cc: linux-wireless, Ivo van Doorn, Matthew Garrett, Dan Williams,
Thomas Renninger, Henrique de Moraes Holschuh, Dmitry Torokhov
Teach rfkill-input how to handle SW_RFKILL_ALL events (new name for the
SW_RADIO event).
SW_RFKILL_ALL is an absolute enable-or-disable command that is tied to all
radios in a system.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
Cc: Dmitry Torokhov <dtor@mail.ru>
---
net/rfkill/rfkill-input.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c
index e4b051d..9d6c925 100644
--- a/net/rfkill/rfkill-input.c
+++ b/net/rfkill/rfkill-input.c
@@ -55,6 +55,22 @@ static void rfkill_task_handler(struct work_struct *work)
mutex_unlock(&task->mutex);
}
+static void rfkill_schedule_set(struct rfkill_task *task,
+ enum rfkill_state desired_state)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&task->lock, flags);
+
+ if (time_after(jiffies, task->last + msecs_to_jiffies(200))) {
+ task->desired_state = desired_state;
+ task->last = jiffies;
+ schedule_work(&task->work);
+ }
+
+ spin_unlock_irqrestore(&task->lock, flags);
+}
+
static void rfkill_schedule_toggle(struct rfkill_task *task)
{
unsigned long flags;
@@ -87,9 +103,9 @@ static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB);
static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX);
static void rfkill_event(struct input_handle *handle, unsigned int type,
- unsigned int code, int down)
+ unsigned int code, int data)
{
- if (type == EV_KEY && down == 1) {
+ if (type == EV_KEY && data == 1) {
switch (code) {
case KEY_WLAN:
rfkill_schedule_toggle(&rfkill_wlan);
@@ -106,6 +122,26 @@ static void rfkill_event(struct input_handle *handle, unsigned int type,
default:
break;
}
+ } else if (type == EV_SW) {
+ switch (code) {
+ case SW_RFKILL_ALL:
+ /* EVERY radio type. data != 0 means radios ON */
+ rfkill_schedule_set(&rfkill_wimax,
+ (data)? RFKILL_STATE_ON:
+ RFKILL_STATE_OFF);
+ rfkill_schedule_set(&rfkill_uwb,
+ (data)? RFKILL_STATE_ON:
+ RFKILL_STATE_OFF);
+ rfkill_schedule_set(&rfkill_bt,
+ (data)? RFKILL_STATE_ON:
+ RFKILL_STATE_OFF);
+ rfkill_schedule_set(&rfkill_wlan,
+ (data)? RFKILL_STATE_ON:
+ RFKILL_STATE_OFF);
+ break;
+ default:
+ break;
+ }
}
}
@@ -168,6 +204,11 @@ static const struct input_device_id rfkill_ids[] = {
.evbit = { BIT_MASK(EV_KEY) },
.keybit = { [BIT_WORD(KEY_WIMAX)] = BIT_MASK(KEY_WIMAX) },
},
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_SWBIT,
+ .evbit = { BIT(EV_SW) },
+ .swbit = { [BIT_WORD(SW_RFKILL_ALL)] = BIT_MASK(SW_RFKILL_ALL) },
+ },
{ }
};
--
1.5.5.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 04/12] rfkill: add parameter to disable radios by default
2008-06-22 15:38 [GIT PATCH] rfkill rework for 2.6.27 (v2) Henrique de Moraes Holschuh
` (2 preceding siblings ...)
2008-06-22 15:38 ` [PATCH 03/12] rfkill: handle SW_RFKILL_ALL events Henrique de Moraes Holschuh
@ 2008-06-22 15:38 ` Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 05/12] rfkill: add read-write rfkill switch support Henrique de Moraes Holschuh
` (7 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-22 15:38 UTC (permalink / raw)
To: John Linville
Cc: linux-wireless, Ivo van Doorn, Matthew Garrett, Dan Williams,
Thomas Renninger, Henrique de Moraes Holschuh
Currently, radios are always enabled when their rfkill interface is
registered. This is not optimal, the safest state for a radio is to be
offline unless the user turns it on.
Add a module parameter that causes all radios to be disabled when their
rfkill interface is registered. The module default is not changed so
unless the parameter is used, radios will still be forced to their enabled
state when they are registered.
The new rfkill module parameter is called "default_state".
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
---
net/rfkill/rfkill.c | 11 ++++++++++-
1 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index f95081a..3edc585 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -39,6 +39,11 @@ MODULE_LICENSE("GPL");
static LIST_HEAD(rfkill_list); /* list of registered rf switches */
static DEFINE_MUTEX(rfkill_mutex);
+static unsigned int rfkill_default_state = RFKILL_STATE_ON;
+module_param_named(default_state, rfkill_default_state, uint, 0444);
+MODULE_PARM_DESC(default_state,
+ "Default initial state for all radio types, 0 = radio off");
+
static enum rfkill_state rfkill_states[RFKILL_TYPE_MAX];
@@ -436,8 +441,12 @@ static int __init rfkill_init(void)
int error;
int i;
+ if (rfkill_default_state != RFKILL_STATE_OFF &&
+ rfkill_default_state != RFKILL_STATE_ON)
+ return -EINVAL;
+
for (i = 0; i < ARRAY_SIZE(rfkill_states); i++)
- rfkill_states[i] = RFKILL_STATE_ON;
+ rfkill_states[i] = rfkill_default_state;
error = class_register(&rfkill_class);
if (error) {
--
1.5.5.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 05/12] rfkill: add read-write rfkill switch support
2008-06-22 15:38 [GIT PATCH] rfkill rework for 2.6.27 (v2) Henrique de Moraes Holschuh
` (3 preceding siblings ...)
2008-06-22 15:38 ` [PATCH 04/12] rfkill: add parameter to disable radios by default Henrique de Moraes Holschuh
@ 2008-06-22 15:38 ` Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 06/12] rfkill: add the WWAN radio type Henrique de Moraes Holschuh
` (6 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-22 15:38 UTC (permalink / raw)
To: John Linville
Cc: linux-wireless, Ivo van Doorn, Matthew Garrett, Dan Williams,
Thomas Renninger, Henrique de Moraes Holschuh, Dmitry Torokhov
Currently, rfkill support for read/write rfkill switches is hacked through
a round-trip over the input layer and rfkill-input to let a driver sync
rfkill->state to hardware changes.
This is buggy and sub-optimal. It causes real problems. It is best to
think of the rfkill class as supporting only write-only switches at the
moment.
In order to implement the read/write functionality properly:
Add a get_state() hook that is called by the class every time it needs to
fetch the current state of the switch. Add a call to this hook every time
the *current* state of the radio plays a role in a decision.
Also add a force_state() method that can be used to forcefully syncronize
the class' idea of the current state of the switch. This allows for a
faster implementation of the read/write functionality, as a driver which
get events on switch changes can avoid the need for a get_state() hook.
If the get_state() hook is left as NULL, current behaviour is maintained,
so this change is fully backwards compatible with the current rfkill
drivers.
For hardware that issues events when the rfkill state changes, leave
get_state() NULL in the rfkill struct, set the initial state properly
before registering with the rfkill class, and use the force_state() method
in the driver to keep the rfkill interface up-to-date.
get_state() can be called by the class from atomic context. It must not
sleep.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
Cc: Dmitry Torokhov <dtor@mail.ru>
---
include/linux/rfkill.h | 5 ++++
net/rfkill/rfkill.c | 53 +++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 55 insertions(+), 3 deletions(-)
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index ca89ae1..844e961 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -61,6 +61,8 @@ enum rfkill_state {
* @data: Pointer to the RF button drivers private data which will be
* passed along when toggling radio state.
* @toggle_radio(): Mandatory handler to control state of the radio.
+ * @get_state(): handler to read current radio state from hardware,
+ * may be called from atomic context, should return 0 on success.
* @led_trigger: A LED trigger for this button's LED.
* @dev: Device structure integrating the switch into device tree.
* @node: Used to place switch into list of all switches known to the
@@ -80,6 +82,7 @@ struct rfkill {
void *data;
int (*toggle_radio)(void *data, enum rfkill_state state);
+ int (*get_state)(void *data, enum rfkill_state *state);
#ifdef CONFIG_RFKILL_LEDS
struct led_trigger led_trigger;
@@ -95,6 +98,8 @@ void rfkill_free(struct rfkill *rfkill);
int rfkill_register(struct rfkill *rfkill);
void rfkill_unregister(struct rfkill *rfkill);
+int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state);
+
/**
* rfkill_get_led_name - Get the LED trigger name for the button's LED.
* This function might return a NULL pointer if registering of the
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 3edc585..4ae4486 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -62,19 +62,39 @@ static void rfkill_led_trigger(struct rfkill *rfkill,
#endif /* CONFIG_RFKILL_LEDS */
}
+static void update_rfkill_state(struct rfkill *rfkill)
+{
+ enum rfkill_state newstate;
+
+ if (rfkill->get_state) {
+ mutex_lock(&rfkill->mutex);
+ if (!rfkill->get_state(rfkill->data, &newstate))
+ rfkill->state = newstate;
+ mutex_unlock(&rfkill->mutex);
+ }
+}
+
static int rfkill_toggle_radio(struct rfkill *rfkill,
enum rfkill_state state)
{
int retval = 0;
+ enum rfkill_state oldstate, newstate;
+
+ oldstate = rfkill->state;
+
+ if (rfkill->get_state &&
+ !rfkill->get_state(rfkill->data, &newstate))
+ rfkill->state = newstate;
if (state != rfkill->state) {
retval = rfkill->toggle_radio(rfkill->data, state);
- if (!retval) {
+ if (!retval)
rfkill->state = state;
- rfkill_led_trigger(rfkill, state);
- }
}
+ if (rfkill->state != oldstate)
+ rfkill_led_trigger(rfkill, rfkill->state);
+
return retval;
}
@@ -105,6 +125,32 @@ void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state)
}
EXPORT_SYMBOL(rfkill_switch_all);
+/**
+ * rfkill_force_state - Force the internal rfkill radio state
+ * @rfkill: pointer to the rfkill class to modify.
+ * @state: the current radio state the class should be forced to.
+ *
+ * This function updates the internal state of the radio cached
+ * by the rfkill class. It should be used when the driver gets
+ * a notification by the firmware/hardware of the current *real*
+ * state of the radio rfkill switch.
+ *
+ * It may not be called from an atomic context.
+ */
+int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state)
+{
+ if (state != RFKILL_STATE_OFF &&
+ state != RFKILL_STATE_ON)
+ return -EINVAL;
+
+ mutex_lock(&rfkill->mutex);
+ rfkill->state = state;
+ mutex_unlock(&rfkill->mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(rfkill_force_state);
+
static ssize_t rfkill_name_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -147,6 +193,7 @@ static ssize_t rfkill_state_show(struct device *dev,
{
struct rfkill *rfkill = to_rfkill(dev);
+ update_rfkill_state(rfkill);
return sprintf(buf, "%d\n", rfkill->state);
}
--
1.5.5.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 06/12] rfkill: add the WWAN radio type
2008-06-22 15:38 [GIT PATCH] rfkill rework for 2.6.27 (v2) Henrique de Moraes Holschuh
` (4 preceding siblings ...)
2008-06-22 15:38 ` [PATCH 05/12] rfkill: add read-write rfkill switch support Henrique de Moraes Holschuh
@ 2008-06-22 15:38 ` Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 07/12] rfkill: rework suspend and resume handlers Henrique de Moraes Holschuh
` (5 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-22 15:38 UTC (permalink / raw)
To: John Linville
Cc: linux-wireless, Ivo van Doorn, Matthew Garrett, Dan Williams,
Thomas Renninger, Henrique de Moraes Holschuh,
Iñaky Pérez-González, John W. Linville,
David S. Miller
Unfortunately, instead of adding a generic Wireless WAN type, a technol=
ogy-
specific type (WiMAX) was added. That's useless for other WWAN devices=
,
such as EDGE, UMTS, X-RTT and other such radios.
Add a WWAN rfkill type for generic wireless WAN devices. No keys are a=
dded
as most devices really want to use KEY_WLAN for WWAN control (in a cycl=
e of
none, WLAN, WWAN, WLAN+WWAN) and need no specific keycode added.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
Cc: I=C3=B1aky P=C3=A9rez-Gonz=C3=A1lez <inaky.perez-gonzalez@intel.com=
>
Cc: John W. Linville <linville@tuxdriver.com>
Cc: David S. Miller <davem@davemloft.net>
---
include/linux/rfkill.h | 2 ++
net/rfkill/rfkill-input.c | 4 ++++
net/rfkill/rfkill.c | 3 +++
3 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index 844e961..c0cab7d 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -34,12 +34,14 @@
* RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device.
* RFKILL_TYPE_UWB: switch is on a ultra wideband device.
* RFKILL_TYPE_WIMAX: switch is on a WiMAX device.
+ * RFKILL_TYPE_WWAN: switch is on a wireless WAN device.
*/
enum rfkill_type {
RFKILL_TYPE_WLAN ,
RFKILL_TYPE_BLUETOOTH,
RFKILL_TYPE_UWB,
RFKILL_TYPE_WIMAX,
+ RFKILL_TYPE_WWAN,
RFKILL_TYPE_MAX,
};
=20
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c
index 9d6c925..29c13d3 100644
--- a/net/rfkill/rfkill-input.c
+++ b/net/rfkill/rfkill-input.c
@@ -101,6 +101,7 @@ static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_=
WLAN);
static DEFINE_RFKILL_TASK(rfkill_bt, RFKILL_TYPE_BLUETOOTH);
static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB);
static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX);
+static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN);
=20
static void rfkill_event(struct input_handle *handle, unsigned int typ=
e,
unsigned int code, int data)
@@ -126,6 +127,9 @@ static void rfkill_event(struct input_handle *handl=
e, unsigned int type,
switch (code) {
case SW_RFKILL_ALL:
/* EVERY radio type. data !=3D 0 means radios ON */
+ rfkill_schedule_set(&rfkill_wwan,
+ (data)? RFKILL_STATE_ON:
+ RFKILL_STATE_OFF);
rfkill_schedule_set(&rfkill_wimax,
(data)? RFKILL_STATE_ON:
RFKILL_STATE_OFF);
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 4ae4486..79f3bbb 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -180,6 +180,9 @@ static ssize_t rfkill_type_show(struct device *dev,
case RFKILL_TYPE_WIMAX:
type =3D "wimax";
break;
+ case RFKILL_TYPE_WWAN:
+ type =3D "wwan";
+ break;
default:
BUG();
}
--=20
1.5.5.4
--
To unsubscribe from this list: send the line "unsubscribe linux-wireles=
s" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 07/12] rfkill: rework suspend and resume handlers
2008-06-22 15:38 [GIT PATCH] rfkill rework for 2.6.27 (v2) Henrique de Moraes Holschuh
` (5 preceding siblings ...)
2008-06-22 15:38 ` [PATCH 06/12] rfkill: add the WWAN radio type Henrique de Moraes Holschuh
@ 2008-06-22 15:38 ` Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 08/12] rfkill: add notifier chains support Henrique de Moraes Holschuh
` (4 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-22 15:38 UTC (permalink / raw)
To: John Linville
Cc: linux-wireless, Ivo van Doorn, Matthew Garrett, Dan Williams,
Thomas Renninger, Henrique de Moraes Holschuh
The resume handler should reset the wireless transmitter rfkill
state to exactly what it was when the system was suspended. Do it,
and do it using the normal routines for state change while at it.
The suspend handler should force-switch the transmitter to blocked
state, ignoring caches. Do it.
Also take an opportunity shot to rfkill_remove_switch() and also
force the transmitter to blocked state there, bypassing caches.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
---
net/rfkill/rfkill.c | 35 ++++++++++++++++++-----------------
1 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 79f3bbb..fb56690 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -75,24 +75,25 @@ static void update_rfkill_state(struct rfkill *rfkill)
}
static int rfkill_toggle_radio(struct rfkill *rfkill,
- enum rfkill_state state)
+ enum rfkill_state state,
+ int force)
{
int retval = 0;
enum rfkill_state oldstate, newstate;
oldstate = rfkill->state;
- if (rfkill->get_state &&
+ if (rfkill->get_state && !force &&
!rfkill->get_state(rfkill->data, &newstate))
rfkill->state = newstate;
- if (state != rfkill->state) {
+ if (force || state != rfkill->state) {
retval = rfkill->toggle_radio(rfkill->data, state);
if (!retval)
rfkill->state = state;
}
- if (rfkill->state != oldstate)
+ if (force || rfkill->state != oldstate)
rfkill_led_trigger(rfkill, rfkill->state);
return retval;
@@ -107,7 +108,6 @@ static int rfkill_toggle_radio(struct rfkill *rfkill,
* a specific switch is claimed by userspace in which case it is
* left alone.
*/
-
void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state)
{
struct rfkill *rfkill;
@@ -118,7 +118,7 @@ void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state)
list_for_each_entry(rfkill, &rfkill_list, node) {
if ((!rfkill->user_claim) && (rfkill->type == type))
- rfkill_toggle_radio(rfkill, state);
+ rfkill_toggle_radio(rfkill, state, 0);
}
mutex_unlock(&rfkill_mutex);
@@ -214,7 +214,8 @@ static ssize_t rfkill_state_store(struct device *dev,
if (mutex_lock_interruptible(&rfkill->mutex))
return -ERESTARTSYS;
error = rfkill_toggle_radio(rfkill,
- state ? RFKILL_STATE_ON : RFKILL_STATE_OFF);
+ state ? RFKILL_STATE_ON : RFKILL_STATE_OFF,
+ 0);
mutex_unlock(&rfkill->mutex);
return error ? error : count;
@@ -255,7 +256,8 @@ static ssize_t rfkill_claim_store(struct device *dev,
if (rfkill->user_claim != claim) {
if (!claim)
rfkill_toggle_radio(rfkill,
- rfkill_states[rfkill->type]);
+ rfkill_states[rfkill->type],
+ 0);
rfkill->user_claim = claim;
}
@@ -288,12 +290,11 @@ static int rfkill_suspend(struct device *dev, pm_message_t state)
if (dev->power.power_state.event != state.event) {
if (state.event & PM_EVENT_SLEEP) {
- mutex_lock(&rfkill->mutex);
-
- if (rfkill->state == RFKILL_STATE_ON)
- rfkill->toggle_radio(rfkill->data,
- RFKILL_STATE_OFF);
+ /* Stop transmitter, keep state, no notifies */
+ update_rfkill_state(rfkill);
+ mutex_lock(&rfkill->mutex);
+ rfkill->toggle_radio(rfkill->data, RFKILL_STATE_OFF);
mutex_unlock(&rfkill->mutex);
}
@@ -310,8 +311,8 @@ static int rfkill_resume(struct device *dev)
if (dev->power.power_state.event != PM_EVENT_ON) {
mutex_lock(&rfkill->mutex);
- if (rfkill->state == RFKILL_STATE_ON)
- rfkill->toggle_radio(rfkill->data, RFKILL_STATE_ON);
+ /* restore radio state AND notify everybody */
+ rfkill_toggle_radio(rfkill, rfkill->state, 1);
mutex_unlock(&rfkill->mutex);
}
@@ -338,7 +339,7 @@ static int rfkill_add_switch(struct rfkill *rfkill)
mutex_lock(&rfkill_mutex);
- error = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type]);
+ error = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type], 0);
if (!error)
list_add_tail(&rfkill->node, &rfkill_list);
@@ -351,7 +352,7 @@ static void rfkill_remove_switch(struct rfkill *rfkill)
{
mutex_lock(&rfkill_mutex);
list_del_init(&rfkill->node);
- rfkill_toggle_radio(rfkill, RFKILL_STATE_OFF);
+ rfkill_toggle_radio(rfkill, RFKILL_STATE_OFF, 1);
mutex_unlock(&rfkill_mutex);
}
--
1.5.5.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 08/12] rfkill: add notifier chains support
2008-06-22 15:38 [GIT PATCH] rfkill rework for 2.6.27 (v2) Henrique de Moraes Holschuh
` (6 preceding siblings ...)
2008-06-22 15:38 ` [PATCH 07/12] rfkill: rework suspend and resume handlers Henrique de Moraes Holschuh
@ 2008-06-22 15:38 ` Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 09/12] rfkill: add type string helper Henrique de Moraes Holschuh
` (3 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-22 15:38 UTC (permalink / raw)
To: John Linville
Cc: linux-wireless, Ivo van Doorn, Matthew Garrett, Dan Williams,
Thomas Renninger, Henrique de Moraes Holschuh
Add a notifier chain for use by the rfkill class. This notifier chain
signals the following events (more to be added when needed):
1. rfkill: rfkill device state has changed
A pointer to the rfkill struct will be passed as a parameter.
The notifier message types have been added to include/linux/rfkill.h
instead of to include/linux/notifier.h in order to avoid the madness of
modifying a header used globally (and that triggers an almost full tree
rebuild every time it is touched) with information that is of interest only
to code that includes the rfkill.h header.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
---
include/linux/rfkill.h | 7 +++++
net/rfkill/rfkill.c | 70 +++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 74 insertions(+), 3 deletions(-)
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index c0cab7d..98667be 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -117,4 +117,11 @@ static inline char *rfkill_get_led_name(struct rfkill *rfkill)
#endif
}
+/* rfkill notification chain */
+#define RFKILL_STATE_CHANGED 0x0001 /* state of a normal rfkill
+ switch has changed */
+
+int register_rfkill_notifier(struct notifier_block *nb);
+int unregister_rfkill_notifier(struct notifier_block *nb);
+
#endif /* RFKILL_H */
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index fb56690..a561e35 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -46,6 +46,49 @@ MODULE_PARM_DESC(default_state,
static enum rfkill_state rfkill_states[RFKILL_TYPE_MAX];
+static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list);
+
+
+/**
+ * register_rfkill_notifier - Add notifier to rfkill notifier chain
+ * @nb: pointer to the new entry to add to the chain
+ *
+ * See blocking_notifier_chain_register() for return value and further
+ * observations.
+ *
+ * Adds a notifier to the rfkill notifier chain. The chain will be
+ * called with a pointer to the relevant rfkill structure as a parameter,
+ * refer to include/linux/rfkill.h for the possible events.
+ *
+ * Notifiers added to this chain are to always return NOTIFY_DONE. This
+ * chain is a blocking notifier chain: notifiers can sleep.
+ *
+ * Calls to this chain may have been done through a workqueue. One must
+ * assume unordered asynchronous behaviour, there is no way to know if
+ * actions related to the event that generated the notification have been
+ * carried out already.
+ */
+int register_rfkill_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&rfkill_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(register_rfkill_notifier);
+
+/**
+ * unregister_rfkill_notifier - remove notifier from rfkill notifier chain
+ * @nb: pointer to the entry to remove from the chain
+ *
+ * See blocking_notifier_chain_unregister() for return value and further
+ * observations.
+ *
+ * Removes a notifier from the rfkill notifier chain.
+ */
+int unregister_rfkill_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&rfkill_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_rfkill_notifier);
+
static void rfkill_led_trigger(struct rfkill *rfkill,
enum rfkill_state state)
@@ -62,14 +105,25 @@ static void rfkill_led_trigger(struct rfkill *rfkill,
#endif /* CONFIG_RFKILL_LEDS */
}
+static void notify_rfkill_state_change(struct rfkill *rfkill)
+{
+ blocking_notifier_call_chain(&rfkill_notifier_list,
+ RFKILL_STATE_CHANGED,
+ rfkill);
+}
+
static void update_rfkill_state(struct rfkill *rfkill)
{
- enum rfkill_state newstate;
+ enum rfkill_state newstate, oldstate;
if (rfkill->get_state) {
mutex_lock(&rfkill->mutex);
- if (!rfkill->get_state(rfkill->data, &newstate))
+ if (!rfkill->get_state(rfkill->data, &newstate)) {
+ oldstate = rfkill->state;
rfkill->state = newstate;
+ if (oldstate != newstate)
+ notify_rfkill_state_change(rfkill);
+ }
mutex_unlock(&rfkill->mutex);
}
}
@@ -93,8 +147,10 @@ static int rfkill_toggle_radio(struct rfkill *rfkill,
rfkill->state = state;
}
- if (force || rfkill->state != oldstate)
+ if (force || rfkill->state != oldstate) {
rfkill_led_trigger(rfkill, rfkill->state);
+ notify_rfkill_state_change(rfkill);
+ }
return retval;
}
@@ -139,12 +195,20 @@ EXPORT_SYMBOL(rfkill_switch_all);
*/
int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state)
{
+ enum rfkill_state oldstate;
+
if (state != RFKILL_STATE_OFF &&
state != RFKILL_STATE_ON)
return -EINVAL;
mutex_lock(&rfkill->mutex);
+
+ oldstate = rfkill->state;
rfkill->state = state;
+
+ if (state != oldstate)
+ notify_rfkill_state_change(rfkill);
+
mutex_unlock(&rfkill->mutex);
return 0;
--
1.5.5.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 09/12] rfkill: add type string helper
2008-06-22 15:38 [GIT PATCH] rfkill rework for 2.6.27 (v2) Henrique de Moraes Holschuh
` (7 preceding siblings ...)
2008-06-22 15:38 ` [PATCH 08/12] rfkill: add notifier chains support Henrique de Moraes Holschuh
@ 2008-06-22 15:38 ` Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 10/12] rfkill: add uevent notifications Henrique de Moraes Holschuh
` (2 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-22 15:38 UTC (permalink / raw)
To: John Linville
Cc: linux-wireless, Ivo van Doorn, Matthew Garrett, Dan Williams,
Thomas Renninger, Henrique de Moraes Holschuh
We will need access to the rfkill switch type in string format for more
than just sysfs. Therefore, move it to a generic helper.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
---
net/rfkill/rfkill.c | 33 +++++++++++++++------------------
1 files changed, 15 insertions(+), 18 deletions(-)
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index a561e35..3c77734 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -224,34 +224,31 @@ static ssize_t rfkill_name_show(struct device *dev,
return sprintf(buf, "%s\n", rfkill->name);
}
-static ssize_t rfkill_type_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static const char *rfkill_get_type_str(enum rfkill_type type)
{
- struct rfkill *rfkill = to_rfkill(dev);
- const char *type;
-
- switch (rfkill->type) {
+ switch (type) {
case RFKILL_TYPE_WLAN:
- type = "wlan";
- break;
+ return "wlan";
case RFKILL_TYPE_BLUETOOTH:
- type = "bluetooth";
- break;
+ return "bluetooth";
case RFKILL_TYPE_UWB:
- type = "ultrawideband";
- break;
+ return "ultrawideband";
case RFKILL_TYPE_WIMAX:
- type = "wimax";
- break;
+ return "wimax";
case RFKILL_TYPE_WWAN:
- type = "wwan";
- break;
+ return "wwan";
default:
BUG();
}
+}
+
+static ssize_t rfkill_type_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct rfkill *rfkill = to_rfkill(dev);
- return sprintf(buf, "%s\n", type);
+ return sprintf(buf, "%s\n", rfkill_get_type_str(rfkill->type));
}
static ssize_t rfkill_state_show(struct device *dev,
--
1.5.5.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 10/12] rfkill: add uevent notifications
2008-06-22 15:38 [GIT PATCH] rfkill rework for 2.6.27 (v2) Henrique de Moraes Holschuh
` (8 preceding siblings ...)
2008-06-22 15:38 ` [PATCH 09/12] rfkill: add type string helper Henrique de Moraes Holschuh
@ 2008-06-22 15:38 ` Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 11/12] rfkill: do not allow userspace to override ALL RADIOS OFF Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 12/12] rfkill: document rw rfkill switches and clarify input subsystem interactions Henrique de Moraes Holschuh
11 siblings, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-22 15:38 UTC (permalink / raw)
To: John Linville
Cc: linux-wireless, Ivo van Doorn, Matthew Garrett, Dan Williams,
Thomas Renninger, Henrique de Moraes Holschuh, Dmitry Torokhov
Use the notification chains to also send uevents, so that userspace can be
notified of state changes of every rfkill switch.
Userspace should use these events for OSD/status report applications and
rfkill GUI frontends. HAL might want to broadcast them over DBUS, for
example. It might be also useful for userspace implementations of
rfkill-input, or to use HAL as the platform driver which promotes rfkill
switch change events into input events (to synchronize all other switches)
when necessary for platforms that lack a convenient platform-specific
kernel module to do it.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
Cc: Dmitry Torokhov <dtor@mail.ru>
---
net/rfkill/rfkill.c | 42 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 42 insertions(+), 0 deletions(-)
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 3c77734..dd1c3f1 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -386,12 +386,51 @@ static int rfkill_resume(struct device *dev)
#define rfkill_resume NULL
#endif
+static int rfkill_blocking_uevent_notifier(struct notifier_block *nb,
+ unsigned long eventid,
+ void *data)
+{
+ struct rfkill *rfkill = (struct rfkill *)data;
+
+ switch (eventid) {
+ case RFKILL_STATE_CHANGED:
+ kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE);
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block rfkill_blocking_uevent_nb = {
+ .notifier_call = rfkill_blocking_uevent_notifier,
+ .priority = 0,
+};
+
+static int rfkill_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ struct rfkill *rfkill = to_rfkill(dev);
+ int error;
+
+ error = add_uevent_var(env, "RFKILL_NAME=%s", rfkill->name);
+ if (error)
+ return error;
+ error = add_uevent_var(env, "RFKILL_TYPE=%s",
+ rfkill_get_type_str(rfkill->type));
+ if (error)
+ return error;
+ error = add_uevent_var(env, "RFKILL_STATE=%d", rfkill->state);
+ return error;
+}
+
static struct class rfkill_class = {
.name = "rfkill",
.dev_release = rfkill_release,
.dev_attrs = rfkill_dev_attrs,
.suspend = rfkill_suspend,
.resume = rfkill_resume,
+ .dev_uevent = rfkill_dev_uevent,
};
static int rfkill_add_switch(struct rfkill *rfkill)
@@ -566,11 +605,14 @@ static int __init rfkill_init(void)
return error;
}
+ register_rfkill_notifier(&rfkill_blocking_uevent_nb);
+
return 0;
}
static void __exit rfkill_exit(void)
{
+ unregister_rfkill_notifier(&rfkill_blocking_uevent_nb);
class_unregister(&rfkill_class);
}
--
1.5.5.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 11/12] rfkill: do not allow userspace to override ALL RADIOS OFF
2008-06-22 15:38 [GIT PATCH] rfkill rework for 2.6.27 (v2) Henrique de Moraes Holschuh
` (9 preceding siblings ...)
2008-06-22 15:38 ` [PATCH 10/12] rfkill: add uevent notifications Henrique de Moraes Holschuh
@ 2008-06-22 15:38 ` Henrique de Moraes Holschuh
2008-06-22 19:39 ` Fabien Crespel
2008-06-23 2:17 ` Dmitry Torokhov
2008-06-22 15:38 ` [PATCH 12/12] rfkill: document rw rfkill switches and clarify input subsystem interactions Henrique de Moraes Holschuh
11 siblings, 2 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-22 15:38 UTC (permalink / raw)
To: John Linville
Cc: linux-wireless, Ivo van Doorn, Matthew Garrett, Dan Williams,
Thomas Renninger, Henrique de Moraes Holschuh, Dmitry Torokhov
SW_RFKILL_ALL is the "emergency power-off all radios" input event. It must
be handled, and must always do the same thing as far as the rfkill system
is concerned: all transmitters are to go *immediately* offline.
For safety, do NOT allow userspace to override EV_SW SW_RFKILL_ALL OFF. As
long as rfkill-input is loaded, that event will *always* be processed, and
it will *always* force all rfkill switches to disable all wireless
transmitters, regardless of user_claim attribute or anything else.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
Cc: Dmitry Torokhov <dtor@mail.ru>
---
net/rfkill/rfkill-input.c | 29 ++++++++++++++---------------
net/rfkill/rfkill-input.h | 1 +
net/rfkill/rfkill.c | 18 ++++++++++++++++++
3 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c
index 29c13d3..0fadeed 100644
--- a/net/rfkill/rfkill-input.c
+++ b/net/rfkill/rfkill-input.c
@@ -127,21 +127,20 @@ static void rfkill_event(struct input_handle *handle, unsigned int type,
switch (code) {
case SW_RFKILL_ALL:
/* EVERY radio type. data != 0 means radios ON */
- rfkill_schedule_set(&rfkill_wwan,
- (data)? RFKILL_STATE_ON:
- RFKILL_STATE_OFF);
- rfkill_schedule_set(&rfkill_wimax,
- (data)? RFKILL_STATE_ON:
- RFKILL_STATE_OFF);
- rfkill_schedule_set(&rfkill_uwb,
- (data)? RFKILL_STATE_ON:
- RFKILL_STATE_OFF);
- rfkill_schedule_set(&rfkill_bt,
- (data)? RFKILL_STATE_ON:
- RFKILL_STATE_OFF);
- rfkill_schedule_set(&rfkill_wlan,
- (data)? RFKILL_STATE_ON:
- RFKILL_STATE_OFF);
+ /* handle EPO (emergency power off) through shortcut */
+ if (data) {
+ rfkill_schedule_set(&rfkill_wwan,
+ RFKILL_STATE_ON);
+ rfkill_schedule_set(&rfkill_wimax,
+ RFKILL_STATE_ON);
+ rfkill_schedule_set(&rfkill_uwb,
+ RFKILL_STATE_ON);
+ rfkill_schedule_set(&rfkill_bt,
+ RFKILL_STATE_ON);
+ rfkill_schedule_set(&rfkill_wlan,
+ RFKILL_STATE_ON);
+ } else
+ rfkill_epo();
break;
default:
break;
diff --git a/net/rfkill/rfkill-input.h b/net/rfkill/rfkill-input.h
index 4dae500..f63d050 100644
--- a/net/rfkill/rfkill-input.h
+++ b/net/rfkill/rfkill-input.h
@@ -12,5 +12,6 @@
#define __RFKILL_INPUT_H
void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state);
+void rfkill_epo(void);
#endif /* __RFKILL_INPUT_H */
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index dd1c3f1..7d07175 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -182,6 +182,24 @@ void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state)
EXPORT_SYMBOL(rfkill_switch_all);
/**
+ * rfkill_epo - emergency power off all transmitters
+ *
+ * This kicks all rfkill devices to RFKILL_STATE_OFF, ignoring
+ * everything in its path but rfkill_mutex.
+ */
+void rfkill_epo(void)
+{
+ struct rfkill *rfkill;
+
+ mutex_lock(&rfkill_mutex);
+ list_for_each_entry(rfkill, &rfkill_list, node) {
+ rfkill_toggle_radio(rfkill, RFKILL_STATE_OFF, 1);
+ }
+ mutex_unlock(&rfkill_mutex);
+}
+EXPORT_SYMBOL_GPL(rfkill_epo);
+
+/**
* rfkill_force_state - Force the internal rfkill radio state
* @rfkill: pointer to the rfkill class to modify.
* @state: the current radio state the class should be forced to.
--
1.5.5.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 12/12] rfkill: document rw rfkill switches and clarify input subsystem interactions
2008-06-22 15:38 [GIT PATCH] rfkill rework for 2.6.27 (v2) Henrique de Moraes Holschuh
` (10 preceding siblings ...)
2008-06-22 15:38 ` [PATCH 11/12] rfkill: do not allow userspace to override ALL RADIOS OFF Henrique de Moraes Holschuh
@ 2008-06-22 15:38 ` Henrique de Moraes Holschuh
2008-06-23 2:24 ` Dmitry Torokhov
11 siblings, 1 reply; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-22 15:38 UTC (permalink / raw)
To: John Linville
Cc: linux-wireless, Ivo van Doorn, Matthew Garrett, Dan Williams,
Thomas Renninger, Henrique de Moraes Holschuh, Dmitry Torokhov
Rework the documentation so as to make sure driver writers understand
exactly where the boundaries are for input drivers related to rfkill
switches, buttons and keys, and rfkill class drivers.
Also fix a small error in the documentation: setting the state of a normal
instance of the rfkill class does not affect the state of any other devices
(unless they are tied by firmware/hardware somehow).
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
Cc: Dmitry Torokhov <dtor@mail.ru>
---
Documentation/rfkill.txt | 362 +++++++++++++++++++++++++++++++++++++++-------
1 files changed, 307 insertions(+), 55 deletions(-)
diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt
index ec75d6d..e08a79e 100644
--- a/Documentation/rfkill.txt
+++ b/Documentation/rfkill.txt
@@ -1,83 +1,327 @@
rfkill - RF switch subsystem support
====================================
-1 Implementation details
-2 Driver support
-3 Userspace support
+1 Introduction
+2 Implementation details
+3 Kernel driver guidelines
+4 Kernel API
+5 Userspace support
-===============================================================================
-1: Implementation details
+
+1. Introduction:
The rfkill switch subsystem exists to add a generic interface to circuitry that
-can enable or disable the RF output of a radio *transmitter* of any type.
+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.
-When a rfkill switch is in the RFKILL_STATE_ON, the radio transmitter is
-*enabled*. When the rfkill switch is in the RFKILL_STATE_OFF, the radio
-transmitter is *disabled*.
+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 rfkill switch subsystem offers support for keys often found on laptops
-to enable wireless devices like WiFi and Bluetooth.
+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).
-This is done by providing the user 3 possibilities:
- 1 - The rfkill system handles all events; userspace is not aware of events.
- 2 - The rfkill system handles all events; userspace is informed about the events.
- 3 - The rfkill system does not handle events; userspace handles all events.
+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.
-The buttons to enable and disable the wireless radios are important in
-situations where the user is for example using his laptop on a location where
-wireless radios _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 still 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. This is optional, and can also be done in
+userspace.
+
+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 the input device. It also creates several
-sysfs entries which can be used by userspace. See section "Userspace support".
+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.
-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 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:
====================================
-2: Driver support
-To build a driver with rfkill subsystem support, the driver should
-depend on the Kconfig symbol RFKILL; it should _not_ depend on
-RKFILL_INPUT.
+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.
-Unless key events trigger an interrupt to which the driver listens, polling
-will be required to determine the key state changes. For this the input
-layer providers the input-polldev handler.
+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).
-A driver should implement a few steps to correctly make use of the
-rfkill subsystem. First for non-polling drivers:
+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.
- - rfkill_allocate()
- - input_allocate_device()
- - rfkill_register()
- - input_register_device()
+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.
-For polling drivers:
+There is no provision for a statically-allocated rfkill struct. You must
+use rfkill_allocate() to allocate one.
+You should:
- rfkill_allocate()
- - input_allocate_polled_device()
+ - modify rfkill fields (flags, name)
+ - modify state to the current hardware state (THIS IS THE ONLY TIME
+ YOU CAN ACCESS state DIRECTLY)
- rfkill_register()
- - input_register_polled_device()
-When a key event has been detected, the correct event should be
-sent over the input device which has been registered by the driver.
+Please refer to the source for more documentation.
-====================================
-3: Userspace support
+===============================================================================
+5: Userspace support
+
+rfkill devices issue uevents (with an action of "change"), with the following
+environment variables set:
+
+RFKILL_NAME
+RFKILL_STATE
+RFKILL_TYPE
-For each key an input device will be created which will send out the correct
-key event when the rfkill key has been pressed.
+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:
@@ -87,10 +331,18 @@ The following sysfs entries will be created:
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 all radios, not yet in the requested
-state, will be will be toggled accordingly.
+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.
+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.
--
1.5.5.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH 11/12] rfkill: do not allow userspace to override ALL RADIOS OFF
2008-06-22 15:38 ` [PATCH 11/12] rfkill: do not allow userspace to override ALL RADIOS OFF Henrique de Moraes Holschuh
@ 2008-06-22 19:39 ` Fabien Crespel
2008-06-23 5:22 ` Henrique de Moraes Holschuh
2008-06-23 16:24 ` Henrique de Moraes Holschuh
2008-06-23 2:17 ` Dmitry Torokhov
1 sibling, 2 replies; 22+ messages in thread
From: Fabien Crespel @ 2008-06-22 19:39 UTC (permalink / raw)
To: Henrique de Moraes Holschuh
Cc: John Linville, public-linux-wireless-u79uwXL29TY76Z2rM5mHXA,
Ivo van Doorn, Matthew Garrett, Dan Williams, Thomas Renninger,
Dmitry Torokhov
Hello there,
I've been testing this series of patch today for a new version of asus-laptop,
and this patch ("rfkill: do not allow userspace to override ALL RADIOS OFF")
introduces a bug in rfkill-input.
rfkill_epo() doesn't change the current_state of the tasks, and the various calls
to rfkill_schedule_set(..., RFKILL_STATE_ON) don't work if the last current_state
stored was already RFKILL_STATE_ON.
Anyway, the whole current_state thing seems completely useless and a source of
problems in rfkill-input, since state comparison is already done in rfkill, and
rfkill-input is more than likely to become out of sync with the real state.
Therefore I propose this additional patch to remove current_state completely from
rfkill-input.
- Fabien.
---
--- a/net/rfkill/rfkill-input.c 2008-06-22 21:16:15.000000000 +0200
+++ b/net/rfkill/rfkill-input.c 2008-06-22 21:20:01.000000000 +0200
@@ -30,27 +30,15 @@
spinlock_t lock; /* for accessing last and desired state */
unsigned long last; /* last schedule */
enum rfkill_state desired_state; /* on/off */
- enum rfkill_state current_state; /* on/off */
};
static void rfkill_task_handler(struct work_struct *work)
{
struct rfkill_task *task = container_of(work, struct rfkill_task, work);
- enum rfkill_state state;
mutex_lock(&task->mutex);
- /*
- * Use temp variable to fetch desired state to keep it
- * consistent even if rfkill_schedule_toggle() runs in
- * another thread or interrupts us.
- */
- state = task->desired_state;
-
- if (state != task->current_state) {
- rfkill_switch_all(task->type, state);
- task->current_state = state;
- }
+ rfkill_switch_all(task->type, task->desired_state);
mutex_unlock(&task->mutex);
}
@@ -94,7 +82,6 @@
.mutex = __MUTEX_INITIALIZER(n.mutex), \
.lock = __SPIN_LOCK_UNLOCKED(n.lock), \
.desired_state = RFKILL_STATE_ON, \
- .current_state = RFKILL_STATE_ON, \
}
static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN);
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 11/12] rfkill: do not allow userspace to override ALL RADIOS OFF
2008-06-22 15:38 ` [PATCH 11/12] rfkill: do not allow userspace to override ALL RADIOS OFF Henrique de Moraes Holschuh
2008-06-22 19:39 ` Fabien Crespel
@ 2008-06-23 2:17 ` Dmitry Torokhov
2008-06-23 5:14 ` Henrique de Moraes Holschuh
1 sibling, 1 reply; 22+ messages in thread
From: Dmitry Torokhov @ 2008-06-23 2:17 UTC (permalink / raw)
To: Henrique de Moraes Holschuh
Cc: John Linville, linux-wireless, Ivo van Doorn, Matthew Garrett,
Dan Williams, Thomas Renninger
Hi Henrique,
On Sun, Jun 22, 2008 at 12:38:47PM -0300, Henrique de Moraes Holschuh wrote:
> SW_RFKILL_ALL is the "emergency power-off all radios" input event. It must
> be handled, and must always do the same thing as far as the rfkill system
> is concerned: all transmitters are to go *immediately* offline.
>
> For safety, do NOT allow userspace to override EV_SW SW_RFKILL_ALL OFF. As
> long as rfkill-input is loaded, that event will *always* be processed, and
> it will *always* force all rfkill switches to disable all wireless
> transmitters, regardless of user_claim attribute or anything else.
>
> Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
> Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
> Cc: Dmitry Torokhov <dtor@mail.ru>
rfkill_event() is called with handle->dev.event_lock spinlock held and
therefore can not sleep. rfkill_epo() takes rfkill mutex and may sleep
so it can't be used in the interrupt context. That is the reason why
we had tasks for switching rf switches in the first place.
--
Dmitry
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 12/12] rfkill: document rw rfkill switches and clarify input subsystem interactions
2008-06-22 15:38 ` [PATCH 12/12] rfkill: document rw rfkill switches and clarify input subsystem interactions Henrique de Moraes Holschuh
@ 2008-06-23 2:24 ` Dmitry Torokhov
2008-06-23 5:09 ` Henrique de Moraes Holschuh
0 siblings, 1 reply; 22+ messages in thread
From: Dmitry Torokhov @ 2008-06-23 2:24 UTC (permalink / raw)
To: Henrique de Moraes Holschuh
Cc: John Linville, linux-wireless, Ivo van Doorn, Matthew Garrett,
Dan Williams, Thomas Renninger
Hi Henrique,
On Sun, Jun 22, 2008 at 12:38:48PM -0300, Henrique de Moraes Holschuh wrote:
> +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. This is optional, and can also be done in
> +userspace.
> +
> +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.
> +
I think I would like to see the statement that rfkill-input is an
in-kernel implementation of default policy of reacting to Wifi-related
(in wide sense) button presses and neither mandatory nor required for
wireless drivers to operate.
--
Dmitry
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 12/12] rfkill: document rw rfkill switches and clarify input subsystem interactions
2008-06-23 2:24 ` Dmitry Torokhov
@ 2008-06-23 5:09 ` Henrique de Moraes Holschuh
0 siblings, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-23 5:09 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: John Linville, linux-wireless, Ivo van Doorn, Matthew Garrett,
Dan Williams, Thomas Renninger
On Sun, 22 Jun 2008, Dmitry Torokhov wrote:
> Hi Henrique,
Hi Dmitry,
Thanks for looking into these in detail.
> > +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. This is optional, and can also be done in
> > +userspace.
> > +
> > +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.
> > +
>
> I think I would like to see the statement that rfkill-input is an
> in-kernel implementation of default policy of reacting to Wifi-related
> (in wide sense) button presses and neither mandatory nor required for
> wireless drivers to operate.
Agreed, will add it. I already wrote it somewhere, I think, but it is
always good to repeat that information in any place it would be useful to
drive the point home.
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 11/12] rfkill: do not allow userspace to override ALL RADIOS OFF
2008-06-23 2:17 ` Dmitry Torokhov
@ 2008-06-23 5:14 ` Henrique de Moraes Holschuh
0 siblings, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-23 5:14 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: John Linville, linux-wireless, Ivo van Doorn, Matthew Garrett,
Dan Williams, Thomas Renninger
On Sun, 22 Jun 2008, Dmitry Torokhov wrote:
> On Sun, Jun 22, 2008 at 12:38:47PM -0300, Henrique de Moraes Holschuh wrote:
> > SW_RFKILL_ALL is the "emergency power-off all radios" input event. It must
> > be handled, and must always do the same thing as far as the rfkill system
> > is concerned: all transmitters are to go *immediately* offline.
> >
> > For safety, do NOT allow userspace to override EV_SW SW_RFKILL_ALL OFF. As
> > long as rfkill-input is loaded, that event will *always* be processed, and
> > it will *always* force all rfkill switches to disable all wireless
> > transmitters, regardless of user_claim attribute or anything else.
> >
> > Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
> > Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
> > Cc: Dmitry Torokhov <dtor@mail.ru>
>
> rfkill_event() is called with handle->dev.event_lock spinlock held and
> therefore can not sleep. rfkill_epo() takes rfkill mutex and may sleep
> so it can't be used in the interrupt context. That is the reason why
> we had tasks for switching rf switches in the first place.
Will fix to schedule an immediate call to _epo in task context, that
should fix the locking issue. Thanks for noticing that one!
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 11/12] rfkill: do not allow userspace to override ALL RADIOS OFF
2008-06-22 19:39 ` Fabien Crespel
@ 2008-06-23 5:22 ` Henrique de Moraes Holschuh
[not found] ` <20080623095053.ZZRA012@mailhub.coreip.homeip.net>
2008-06-23 16:24 ` Henrique de Moraes Holschuh
1 sibling, 1 reply; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-23 5:22 UTC (permalink / raw)
To: Fabien Crespel
Cc: John Linville, public-linux-wireless-u79uwXL29TY76Z2rM5mHXA,
Ivo van Doorn, Matthew Garrett, Dan Williams, Thomas Renninger,
Dmitry Torokhov
On Sun, 22 Jun 2008, Fabien Crespel wrote:
> I've been testing this series of patch today for a new version of
> asus-laptop, and this patch ("rfkill: do not allow userspace to override
> ALL RADIOS OFF") introduces a bug in rfkill-input.
More than one, apparently. Dmitry pointed out that _epo needs to be called
in task context, which rfkill-input was failing to do.
> rfkill_epo() doesn't change the current_state of the tasks, and the
> various calls to rfkill_schedule_set(..., RFKILL_STATE_ON) don't work if
> the last current_state stored was already RFKILL_STATE_ON.
>
> Anyway, the whole current_state thing seems completely useless and a
> source of problems in rfkill-input, since state comparison is already
> done in rfkill, and rfkill-input is more than likely to become out of
> sync with the real state.
>
> Therefore I propose this additional patch to remove current_state
> completely from rfkill-input.
I would like to get rid of it, but I need some sleep before I can think
clearly about this issue.
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 11/12] rfkill: do not allow userspace to override ALL RADIOS OFF
2008-06-22 19:39 ` Fabien Crespel
2008-06-23 5:22 ` Henrique de Moraes Holschuh
@ 2008-06-23 16:24 ` Henrique de Moraes Holschuh
1 sibling, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-23 16:24 UTC (permalink / raw)
To: Fabien Crespel
Cc: linux-wireless, Ivo van Doorn, Matthew Garrett, Dan Williams,
Thomas Renninger, Dmitry Torokhov, John Linville
On Sun, 22 Jun 2008, Fabien Crespel wrote:
> Anyway, the whole current_state thing seems completely useless and a
> source of problems in rfkill-input, since state comparison is already
> done in rfkill, and rfkill-input is more than likely to become out of
> sync with the real state.
>
> Therefore I propose this additional patch to remove current_state
> completely from rfkill-input.
It would work fine from what I see. And it will even be beneficial in the
long run, as it will cause rfkill-input to reapply a global state, fixing
any switches that diverged from it (and are lot BLOCKED, or "claimed", etc).
Right now, this is not very useful, but when we add a sysfs interface to
interact with the global states directly, it will be.
Please send me your signed-off line, I will respin the patch to fit exactly
before the EPO patch into the patchset (so that we don't have breakage in
any intermediate step of the patchset), and send it as a block.
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 11/12] rfkill: do not allow userspace to override ALL RADIOS OFF
[not found] ` <20080623095053.ZZRA012@mailhub.coreip.homeip.net>
@ 2008-06-23 18:10 ` Henrique de Moraes Holschuh
0 siblings, 0 replies; 22+ messages in thread
From: Henrique de Moraes Holschuh @ 2008-06-23 18:10 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Fabien Crespel, John Linville,
public-linux-wireless-u79uwXL29TY76Z2rM5mHXA, Ivo van Doorn,
Matthew Garrett, Dan Williams, Thomas Renninger, Dmitry Torokhov
On Mon, 23 Jun 2008, Dmitry Torokhov wrote:
> On Mon, Jun 23, 2008 at 02:22:07AM -0300, Henrique de Moraes Holschuh wrote:
> > On Sun, 22 Jun 2008, Fabien Crespel wrote:
> > > rfkill_epo() doesn't change the current_state of the tasks, and the
> > > various calls to rfkill_schedule_set(..., RFKILL_STATE_ON) don't work if
> > > the last current_state stored was already RFKILL_STATE_ON.
> > >
> > > Anyway, the whole current_state thing seems completely useless and a
> > > source of problems in rfkill-input, since state comparison is already
> > > done in rfkill, and rfkill-input is more than likely to become out of
> > > sync with the real state.
>
> Real state of what? The state of rfkill-input represents desired
> (target) state of a group of RF switches of certain type (all WIFI or
> all Bluetooth, etc) and may indeed be different from the state of
> individual transmitter.
Indeed. rfkill-input takes care of what I call "global state (per rfkill
type)". We don't export that to userspace yet, the only way to interact
with them is through input events right now. This will change, eventually.
That said, there is no need to try to avoid extra calls to
rfkill_switch_all, which AFAIK is all current_state is good for.
I tested Fabien's patch here, and it does seem to work well. I added some
guards to EPO so that it just ignores any attempts to queue
rfkill_switch_all calls while a rfkill_epo call is queued, as well.
> > > Therefore I propose this additional patch to remove current_state
> > > completely from rfkill-input.
> >
> > I would like to get rid of it, but I need some sleep before I can think
> > clearly about this issue.
>
> I think the best solution for now would be to add 'force' argument to
> rfkill_switch_all that would override rfkill->user_claim.
No, rfkill-input is not to override rfkill->user_claim except for EPO. Even
if we added a force parameter to rfkill_switch_all, rfkill-input wouldn't be
able to use it (except in the EPO path, that has a better helper to use
anyway: rfkill_epo()).
I fixed the whole EPO issue already, btw. I tried with Fabien's patch, and
on top of it I applied a modified version of the EPO patch that calls
rfkill_epo through the generic work queue and ignores other attempts to
queue rfkill_switch_all while rfkill_epo hasn't run yet (on the grounds that
rfkill_epo would override them anyway, and that when in doubt of what should
be happening because we got a bunch of confusing events all piled up, we
want EPO to win).
I am just waiting for Fabien's signed-off-by line, so that I can push v3 of
the patchset with the bug fixes.
I am also looking at a way to make rfkill-input restore the previous global
states when it receives an SW_RFKILL_ALL ON sometime after an EPO. That's
how I'd prefer it to act (so I will make it selectable, and you guys tell me
what the default should be).
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2008-06-23 18:10 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-22 15:38 [GIT PATCH] rfkill rework for 2.6.27 (v2) Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 01/12] rfkill: clarify meaning of rfkill states Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 02/12] rfkill: fix minor typo in kernel doc Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 03/12] rfkill: handle SW_RFKILL_ALL events Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 04/12] rfkill: add parameter to disable radios by default Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 05/12] rfkill: add read-write rfkill switch support Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 06/12] rfkill: add the WWAN radio type Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 07/12] rfkill: rework suspend and resume handlers Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 08/12] rfkill: add notifier chains support Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 09/12] rfkill: add type string helper Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 10/12] rfkill: add uevent notifications Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 11/12] rfkill: do not allow userspace to override ALL RADIOS OFF Henrique de Moraes Holschuh
2008-06-22 19:39 ` Fabien Crespel
2008-06-23 5:22 ` Henrique de Moraes Holschuh
[not found] ` <20080623095053.ZZRA012@mailhub.coreip.homeip.net>
2008-06-23 18:10 ` Henrique de Moraes Holschuh
2008-06-23 16:24 ` Henrique de Moraes Holschuh
2008-06-23 2:17 ` Dmitry Torokhov
2008-06-23 5:14 ` Henrique de Moraes Holschuh
2008-06-22 15:38 ` [PATCH 12/12] rfkill: document rw rfkill switches and clarify input subsystem interactions Henrique de Moraes Holschuh
2008-06-23 2:24 ` Dmitry Torokhov
2008-06-23 5:09 ` Henrique de Moraes Holschuh
-- strict thread matches above, loose matches on Subject: below --
2008-06-04 3:10 [GIT PATCH] rkfill improvements for -next Henrique de Moraes Holschuh
2008-06-04 3:10 ` [PATCH 11/12] rfkill: do not allow userspace to override ALL RADIOS OFF Henrique de Moraes Holschuh
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.