aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/rfkill.txt56
-rw-r--r--include/linux/rfkill.h32
-rw-r--r--net/rfkill/rfkill-input.c29
-rw-r--r--net/rfkill/rfkill.c75
4 files changed, 152 insertions, 40 deletions
diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt
index cf230c1ad9ef..5316cea95ce0 100644
--- a/Documentation/rfkill.txt
+++ b/Documentation/rfkill.txt
@@ -60,9 +60,20 @@ The second option provides an rfkill input handler. This handler will listen to
60all rfkill key events and will toggle the radio accordingly. With this option 60all rfkill key events and will toggle the radio accordingly. With this option
61enabled userspace could either do nothing or simply perform monitoring tasks. 61enabled userspace could either do nothing or simply perform monitoring tasks.
62 62
63When a rfkill switch is in the RFKILL_STATE_ON, the wireless transmitter (radio 63When a rfkill switch is in the RFKILL_STATE_UNBLOCKED, the wireless transmitter
64TX circuit for example) is *enabled*. When the rfkill switch is in the 64(radio TX circuit for example) is *enabled*. When the rfkill switch is in the
65RFKILL_STATE_OFF, the wireless transmitter is to be *blocked* from operating. 65RFKILL_STATE_SOFT_BLOCKED or RFKILL_STATE_HARD_BLOCKED, the wireless
66transmitter is to be *blocked* from operating.
67
68RFKILL_STATE_SOFT_BLOCKED indicates that a call to toggle_radio() can change
69that state. RFKILL_STATE_HARD_BLOCKED indicates that a call to toggle_radio()
70will not be able to change the state and will return with a suitable error if
71attempts are made to set the state to RFKILL_STATE_UNBLOCKED.
72
73RFKILL_STATE_HARD_BLOCKED is used by drivers to signal that the device is
74locked in the BLOCKED state by a hardwire rfkill line (typically an input pin
75that, when active, forces the transmitter to be disabled) which the driver
76CANNOT override.
66 77
67Full rfkill functionality requires two different subsystems to cooperate: the 78Full rfkill functionality requires two different subsystems to cooperate: the
68input layer and the rfkill class. The input layer issues *commands* to the 79input layer and the rfkill class. The input layer issues *commands* to the
@@ -122,10 +133,10 @@ Userspace input handlers (uevents) or kernel input handlers (rfkill-input):
122 action). 133 action).
123 * rfkill-input implements EPO by handling EV_SW SW_RFKILL_ALL 0 134 * rfkill-input implements EPO by handling EV_SW SW_RFKILL_ALL 0
124 (power off all transmitters) in a special way: it ignores any 135 (power off all transmitters) in a special way: it ignores any
125 overrides and local state cache and forces all transmitters to 136 overrides and local state cache and forces all transmitters to the
126 the OFF state (including those which are already supposed to be 137 RFKILL_STATE_SOFT_BLOCKED state (including those which are already
127 OFF). Note that the opposite event (power on all transmitters) 138 supposed to be BLOCKED). Note that the opposite event (power on all
128 is handled normally. 139 transmitters) is handled normally.
129 140
130Userspace uevent handler or kernel platform-specific drivers hooked to the 141Userspace uevent handler or kernel platform-specific drivers hooked to the
131rfkill notifier chain: 142rfkill notifier chain:
@@ -284,6 +295,19 @@ You should:
284 YOU CAN ACCESS state DIRECTLY) 295 YOU CAN ACCESS state DIRECTLY)
285 - rfkill_register() 296 - rfkill_register()
286 297
298The only way to set a device to the RFKILL_STATE_HARD_BLOCKED state is through
299a suitable return of get_state() or through rfkill_force_state().
300
301When a device is in the RFKILL_STATE_HARD_BLOCKED state, the only way to switch
302it to a different state is through a suitable return of get_state() or through
303rfkill_force_state().
304
305If toggle_radio() is called to set a device to state RFKILL_STATE_SOFT_BLOCKED
306when that device is already at the RFKILL_STATE_HARD_BLOCKED state, it should
307not return an error. Instead, it should try to double-block the transmitter,
308so that its state will change from RFKILL_STATE_HARD_BLOCKED to
309RFKILL_STATE_SOFT_BLOCKED should the hardware blocking cease.
310
287Please refer to the source for more documentation. 311Please refer to the source for more documentation.
288 312
289=============================================================================== 313===============================================================================
@@ -322,13 +346,27 @@ change by writing to the "state" attribute in order for anything to happen.
322 346
323Take particular care to implement EV_SW SW_RFKILL_ALL properly. When that 347Take particular care to implement EV_SW SW_RFKILL_ALL properly. When that
324switch is set to OFF, *every* rfkill device *MUST* be immediately put into the 348switch is set to OFF, *every* rfkill device *MUST* be immediately put into the
325OFF state, no questions asked. 349RFKILL_STATE_SOFT_BLOCKED state, no questions asked.
326 350
327The following sysfs entries will be created: 351The following sysfs entries will be created:
328 352
329 name: Name assigned by driver to this key (interface or driver name). 353 name: Name assigned by driver to this key (interface or driver name).
330 type: Name of the key type ("wlan", "bluetooth", etc). 354 type: Name of the key type ("wlan", "bluetooth", etc).
331 state: Current state of the key. 1: On, 0: Off. 355 state: Current state of the transmitter
356 0: RFKILL_STATE_SOFT_BLOCKED
357 transmitter is forced off, but you can override it
358 by a write to the state attribute, or through input
359 events (if rfkill-input is loaded).
360 1: RFKILL_STATE_UNBLOCKED
361 transmiter is NOT forced off, and may operate if
362 all other conditions for such operation are met
363 (such as interface is up and configured, etc).
364 2: RFKILL_STATE_HARD_BLOCKED
365 transmitter is forced off by something outside of
366 the driver's control.
367
368 You cannot set a device to this state through
369 writes to the state attribute.
332 claim: 1: Userspace handles events, 0: Kernel handles events 370 claim: 1: Userspace handles events, 0: Kernel handles events
333 371
334Both the "state" and "claim" entries are also writable. For the "state" entry 372Both the "state" and "claim" entries are also writable. For the "state" entry
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index 98667becdee4..c5f6e54ec6ae 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -46,16 +46,25 @@ enum rfkill_type {
46}; 46};
47 47
48enum rfkill_state { 48enum rfkill_state {
49 RFKILL_STATE_OFF = 0, /* Radio output blocked */ 49 RFKILL_STATE_SOFT_BLOCKED = 0, /* Radio output blocked */
50 RFKILL_STATE_ON = 1, /* Radio output active */ 50 RFKILL_STATE_UNBLOCKED = 1, /* Radio output allowed */
51 RFKILL_STATE_HARD_BLOCKED = 2, /* Output blocked, non-overrideable */
51}; 52};
52 53
54/*
55 * These are DEPRECATED, drivers using them should be verified to
56 * comply with the rfkill usage guidelines in Documentation/rfkill.txt
57 * and then converted to use the new names for rfkill_state
58 */
59#define RFKILL_STATE_OFF RFKILL_STATE_SOFT_BLOCKED
60#define RFKILL_STATE_ON RFKILL_STATE_UNBLOCKED
61
53/** 62/**
54 * struct rfkill - rfkill control structure. 63 * struct rfkill - rfkill control structure.
55 * @name: Name of the switch. 64 * @name: Name of the switch.
56 * @type: Radio type which the button controls, the value stored 65 * @type: Radio type which the button controls, the value stored
57 * here should be a value from enum rfkill_type. 66 * here should be a value from enum rfkill_type.
58 * @state: State of the switch, "ON" means radio can operate. 67 * @state: State of the switch, "UNBLOCKED" means radio can operate.
59 * @user_claim_unsupported: Whether the hardware supports exclusive 68 * @user_claim_unsupported: Whether the hardware supports exclusive
60 * RF-kill control by userspace. Set this before registering. 69 * RF-kill control by userspace. Set this before registering.
61 * @user_claim: Set when the switch is controlled exlusively by userspace. 70 * @user_claim: Set when the switch is controlled exlusively by userspace.
@@ -63,8 +72,12 @@ enum rfkill_state {
63 * @data: Pointer to the RF button drivers private data which will be 72 * @data: Pointer to the RF button drivers private data which will be
64 * passed along when toggling radio state. 73 * passed along when toggling radio state.
65 * @toggle_radio(): Mandatory handler to control state of the radio. 74 * @toggle_radio(): Mandatory handler to control state of the radio.
75 * only RFKILL_STATE_SOFT_BLOCKED and RFKILL_STATE_UNBLOCKED are
76 * valid parameters.
66 * @get_state(): handler to read current radio state from hardware, 77 * @get_state(): handler to read current radio state from hardware,
67 * may be called from atomic context, should return 0 on success. 78 * may be called from atomic context, should return 0 on success.
79 * Either this handler OR judicious use of rfkill_force_state() is
80 * MANDATORY for any driver capable of RFKILL_STATE_HARD_BLOCKED.
68 * @led_trigger: A LED trigger for this button's LED. 81 * @led_trigger: A LED trigger for this button's LED.
69 * @dev: Device structure integrating the switch into device tree. 82 * @dev: Device structure integrating the switch into device tree.
70 * @node: Used to place switch into list of all switches known to the 83 * @node: Used to place switch into list of all switches known to the
@@ -103,6 +116,19 @@ void rfkill_unregister(struct rfkill *rfkill);
103int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state); 116int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state);
104 117
105/** 118/**
119 * rfkill_state_complement - return complementar state
120 * @state: state to return the complement of
121 *
122 * Returns RFKILL_STATE_SOFT_BLOCKED if @state is RFKILL_STATE_UNBLOCKED,
123 * returns RFKILL_STATE_UNBLOCKED otherwise.
124 */
125static inline enum rfkill_state rfkill_state_complement(enum rfkill_state state)
126{
127 return (state == RFKILL_STATE_UNBLOCKED) ?
128 RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED;
129}
130
131/**
106 * rfkill_get_led_name - Get the LED trigger name for the button's LED. 132 * rfkill_get_led_name - Get the LED trigger name for the button's LED.
107 * This function might return a NULL pointer if registering of the 133 * This function might return a NULL pointer if registering of the
108 * LED trigger failed. 134 * LED trigger failed.
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c
index 5d4c8b2446f7..8aa822730145 100644
--- a/net/rfkill/rfkill-input.c
+++ b/net/rfkill/rfkill-input.c
@@ -84,7 +84,8 @@ static void rfkill_schedule_toggle(struct rfkill_task *task)
84 spin_lock_irqsave(&task->lock, flags); 84 spin_lock_irqsave(&task->lock, flags);
85 85
86 if (time_after(jiffies, task->last + msecs_to_jiffies(200))) { 86 if (time_after(jiffies, task->last + msecs_to_jiffies(200))) {
87 task->desired_state = !task->desired_state; 87 task->desired_state =
88 rfkill_state_complement(task->desired_state);
88 task->last = jiffies; 89 task->last = jiffies;
89 schedule_work(&task->work); 90 schedule_work(&task->work);
90 } 91 }
@@ -92,14 +93,14 @@ static void rfkill_schedule_toggle(struct rfkill_task *task)
92 spin_unlock_irqrestore(&task->lock, flags); 93 spin_unlock_irqrestore(&task->lock, flags);
93} 94}
94 95
95#define DEFINE_RFKILL_TASK(n, t) \ 96#define DEFINE_RFKILL_TASK(n, t) \
96 struct rfkill_task n = { \ 97 struct rfkill_task n = { \
97 .work = __WORK_INITIALIZER(n.work, \ 98 .work = __WORK_INITIALIZER(n.work, \
98 rfkill_task_handler), \ 99 rfkill_task_handler), \
99 .type = t, \ 100 .type = t, \
100 .mutex = __MUTEX_INITIALIZER(n.mutex), \ 101 .mutex = __MUTEX_INITIALIZER(n.mutex), \
101 .lock = __SPIN_LOCK_UNLOCKED(n.lock), \ 102 .lock = __SPIN_LOCK_UNLOCKED(n.lock), \
102 .desired_state = RFKILL_STATE_ON, \ 103 .desired_state = RFKILL_STATE_UNBLOCKED, \
103 } 104 }
104 105
105static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN); 106static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN);
@@ -135,15 +136,15 @@ static void rfkill_event(struct input_handle *handle, unsigned int type,
135 /* handle EPO (emergency power off) through shortcut */ 136 /* handle EPO (emergency power off) through shortcut */
136 if (data) { 137 if (data) {
137 rfkill_schedule_set(&rfkill_wwan, 138 rfkill_schedule_set(&rfkill_wwan,
138 RFKILL_STATE_ON); 139 RFKILL_STATE_UNBLOCKED);
139 rfkill_schedule_set(&rfkill_wimax, 140 rfkill_schedule_set(&rfkill_wimax,
140 RFKILL_STATE_ON); 141 RFKILL_STATE_UNBLOCKED);
141 rfkill_schedule_set(&rfkill_uwb, 142 rfkill_schedule_set(&rfkill_uwb,
142 RFKILL_STATE_ON); 143 RFKILL_STATE_UNBLOCKED);
143 rfkill_schedule_set(&rfkill_bt, 144 rfkill_schedule_set(&rfkill_bt,
144 RFKILL_STATE_ON); 145 RFKILL_STATE_UNBLOCKED);
145 rfkill_schedule_set(&rfkill_wlan, 146 rfkill_schedule_set(&rfkill_wlan,
146 RFKILL_STATE_ON); 147 RFKILL_STATE_UNBLOCKED);
147 } else 148 } else
148 rfkill_schedule_epo(); 149 rfkill_schedule_epo();
149 break; 150 break;
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 7d07175c407f..ce0e23148cdd 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -39,7 +39,7 @@ MODULE_LICENSE("GPL");
39static LIST_HEAD(rfkill_list); /* list of registered rf switches */ 39static LIST_HEAD(rfkill_list); /* list of registered rf switches */
40static DEFINE_MUTEX(rfkill_mutex); 40static DEFINE_MUTEX(rfkill_mutex);
41 41
42static unsigned int rfkill_default_state = RFKILL_STATE_ON; 42static unsigned int rfkill_default_state = RFKILL_STATE_UNBLOCKED;
43module_param_named(default_state, rfkill_default_state, uint, 0444); 43module_param_named(default_state, rfkill_default_state, uint, 0444);
44MODULE_PARM_DESC(default_state, 44MODULE_PARM_DESC(default_state,
45 "Default initial state for all radio types, 0 = radio off"); 45 "Default initial state for all radio types, 0 = radio off");
@@ -98,7 +98,7 @@ static void rfkill_led_trigger(struct rfkill *rfkill,
98 98
99 if (!led->name) 99 if (!led->name)
100 return; 100 return;
101 if (state == RFKILL_STATE_OFF) 101 if (state != RFKILL_STATE_UNBLOCKED)
102 led_trigger_event(led, LED_OFF); 102 led_trigger_event(led, LED_OFF);
103 else 103 else
104 led_trigger_event(led, LED_FULL); 104 led_trigger_event(led, LED_FULL);
@@ -128,6 +128,28 @@ static void update_rfkill_state(struct rfkill *rfkill)
128 } 128 }
129} 129}
130 130
131/**
132 * rfkill_toggle_radio - wrapper for toggle_radio hook
133 * calls toggle_radio taking into account a lot of "small"
134 * details.
135 * @rfkill: the rfkill struct to use
136 * @force: calls toggle_radio even if cache says it is not needed,
137 * and also makes sure notifications of the state will be
138 * sent even if it didn't change
139 * @state: the new state to call toggle_radio() with
140 *
141 * This wrappen protects and enforces the API for toggle_radio
142 * calls. Note that @force cannot override a (possibly cached)
143 * state of RFKILL_STATE_HARD_BLOCKED. Any device making use of
144 * RFKILL_STATE_HARD_BLOCKED implements either get_state() or
145 * rfkill_force_state(), so the cache either is bypassed or valid.
146 *
147 * Note that we do call toggle_radio for RFKILL_STATE_SOFT_BLOCKED
148 * even if the radio is in RFKILL_STATE_HARD_BLOCKED state, so as to
149 * give the driver a hint that it should double-BLOCK the transmitter.
150 *
151 * Caller must have aquired rfkill_mutex.
152 */
131static int rfkill_toggle_radio(struct rfkill *rfkill, 153static int rfkill_toggle_radio(struct rfkill *rfkill,
132 enum rfkill_state state, 154 enum rfkill_state state,
133 int force) 155 int force)
@@ -141,9 +163,28 @@ static int rfkill_toggle_radio(struct rfkill *rfkill,
141 !rfkill->get_state(rfkill->data, &newstate)) 163 !rfkill->get_state(rfkill->data, &newstate))
142 rfkill->state = newstate; 164 rfkill->state = newstate;
143 165
166 switch (state) {
167 case RFKILL_STATE_HARD_BLOCKED:
168 /* typically happens when refreshing hardware state,
169 * such as on resume */
170 state = RFKILL_STATE_SOFT_BLOCKED;
171 break;
172 case RFKILL_STATE_UNBLOCKED:
173 /* force can't override this, only rfkill_force_state() can */
174 if (rfkill->state == RFKILL_STATE_HARD_BLOCKED)
175 return -EPERM;
176 break;
177 case RFKILL_STATE_SOFT_BLOCKED:
178 /* nothing to do, we want to give drivers the hint to double
179 * BLOCK even a transmitter that is already in state
180 * RFKILL_STATE_HARD_BLOCKED */
181 break;
182 }
183
144 if (force || state != rfkill->state) { 184 if (force || state != rfkill->state) {
145 retval = rfkill->toggle_radio(rfkill->data, state); 185 retval = rfkill->toggle_radio(rfkill->data, state);
146 if (!retval) 186 /* never allow a HARD->SOFT downgrade! */
187 if (!retval && rfkill->state != RFKILL_STATE_HARD_BLOCKED)
147 rfkill->state = state; 188 rfkill->state = state;
148 } 189 }
149 190
@@ -184,7 +225,7 @@ EXPORT_SYMBOL(rfkill_switch_all);
184/** 225/**
185 * rfkill_epo - emergency power off all transmitters 226 * rfkill_epo - emergency power off all transmitters
186 * 227 *
187 * This kicks all rfkill devices to RFKILL_STATE_OFF, ignoring 228 * This kicks all rfkill devices to RFKILL_STATE_SOFT_BLOCKED, ignoring
188 * everything in its path but rfkill_mutex. 229 * everything in its path but rfkill_mutex.
189 */ 230 */
190void rfkill_epo(void) 231void rfkill_epo(void)
@@ -193,7 +234,7 @@ void rfkill_epo(void)
193 234
194 mutex_lock(&rfkill_mutex); 235 mutex_lock(&rfkill_mutex);
195 list_for_each_entry(rfkill, &rfkill_list, node) { 236 list_for_each_entry(rfkill, &rfkill_list, node) {
196 rfkill_toggle_radio(rfkill, RFKILL_STATE_OFF, 1); 237 rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1);
197 } 238 }
198 mutex_unlock(&rfkill_mutex); 239 mutex_unlock(&rfkill_mutex);
199} 240}
@@ -215,8 +256,9 @@ int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state)
215{ 256{
216 enum rfkill_state oldstate; 257 enum rfkill_state oldstate;
217 258
218 if (state != RFKILL_STATE_OFF && 259 if (state != RFKILL_STATE_SOFT_BLOCKED &&
219 state != RFKILL_STATE_ON) 260 state != RFKILL_STATE_UNBLOCKED &&
261 state != RFKILL_STATE_HARD_BLOCKED)
220 return -EINVAL; 262 return -EINVAL;
221 263
222 mutex_lock(&rfkill->mutex); 264 mutex_lock(&rfkill->mutex);
@@ -290,11 +332,14 @@ static ssize_t rfkill_state_store(struct device *dev,
290 if (!capable(CAP_NET_ADMIN)) 332 if (!capable(CAP_NET_ADMIN))
291 return -EPERM; 333 return -EPERM;
292 334
335 /* RFKILL_STATE_HARD_BLOCKED is illegal here... */
336 if (state != RFKILL_STATE_UNBLOCKED &&
337 state != RFKILL_STATE_SOFT_BLOCKED)
338 return -EINVAL;
339
293 if (mutex_lock_interruptible(&rfkill->mutex)) 340 if (mutex_lock_interruptible(&rfkill->mutex))
294 return -ERESTARTSYS; 341 return -ERESTARTSYS;
295 error = rfkill_toggle_radio(rfkill, 342 error = rfkill_toggle_radio(rfkill, state, 0);
296 state ? RFKILL_STATE_ON : RFKILL_STATE_OFF,
297 0);
298 mutex_unlock(&rfkill->mutex); 343 mutex_unlock(&rfkill->mutex);
299 344
300 return error ? error : count; 345 return error ? error : count;
@@ -373,7 +418,8 @@ static int rfkill_suspend(struct device *dev, pm_message_t state)
373 update_rfkill_state(rfkill); 418 update_rfkill_state(rfkill);
374 419
375 mutex_lock(&rfkill->mutex); 420 mutex_lock(&rfkill->mutex);
376 rfkill->toggle_radio(rfkill->data, RFKILL_STATE_OFF); 421 rfkill->toggle_radio(rfkill->data,
422 RFKILL_STATE_SOFT_BLOCKED);
377 mutex_unlock(&rfkill->mutex); 423 mutex_unlock(&rfkill->mutex);
378 } 424 }
379 425
@@ -470,7 +516,7 @@ static void rfkill_remove_switch(struct rfkill *rfkill)
470{ 516{
471 mutex_lock(&rfkill_mutex); 517 mutex_lock(&rfkill_mutex);
472 list_del_init(&rfkill->node); 518 list_del_init(&rfkill->node);
473 rfkill_toggle_radio(rfkill, RFKILL_STATE_OFF, 1); 519 rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1);
474 mutex_unlock(&rfkill_mutex); 520 mutex_unlock(&rfkill_mutex);
475} 521}
476 522
@@ -610,8 +656,9 @@ static int __init rfkill_init(void)
610 int error; 656 int error;
611 int i; 657 int i;
612 658
613 if (rfkill_default_state != RFKILL_STATE_OFF && 659 /* RFKILL_STATE_HARD_BLOCKED is illegal here... */
614 rfkill_default_state != RFKILL_STATE_ON) 660 if (rfkill_default_state != RFKILL_STATE_SOFT_BLOCKED &&
661 rfkill_default_state != RFKILL_STATE_UNBLOCKED)
615 return -EINVAL; 662 return -EINVAL;
616 663
617 for (i = 0; i < ARRAY_SIZE(rfkill_states); i++) 664 for (i = 0; i < ARRAY_SIZE(rfkill_states); i++)