mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 11:46:19 +00:00
rfkill: rename the rfkill_state states and add block-locked state
The current naming of rfkill_state causes a lot of confusion: not only the "kill" in rfkill suggests negative logic, but also the fact that rfkill cannot turn anything on (it can just force something off or stop forcing something off) is often forgotten. Rename RFKILL_STATE_OFF to RFKILL_STATE_SOFT_BLOCKED (transmitter is blocked and will not operate; state can be changed by a toggle_radio request), and RFKILL_STATE_ON to RFKILL_STATE_UNBLOCKED (transmitter is not blocked, and may operate). Also, add a new third state, RFKILL_STATE_HARD_BLOCKED (transmitter is blocked and will not operate; state cannot be changed through a toggle_radio request), which is used by drivers to indicate a wireless transmiter was blocked by a hardware rfkill line that accepts no overrides. Keep the old names as #defines, but document them as deprecated. This way, drivers can be converted to the new names *and* verified to actually use rfkill correctly one by one. Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Acked-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
dc288520a2
commit
5005657cbd
4 changed files with 152 additions and 40 deletions
|
@ -60,9 +60,20 @@ 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
|
all rfkill key events and will toggle the radio accordingly. With this option
|
||||||
enabled userspace could either do nothing or simply perform monitoring tasks.
|
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
|
When a rfkill switch is in the RFKILL_STATE_UNBLOCKED, the wireless transmitter
|
||||||
TX circuit for example) is *enabled*. When the rfkill switch is in the
|
(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.
|
RFKILL_STATE_SOFT_BLOCKED or RFKILL_STATE_HARD_BLOCKED, the wireless
|
||||||
|
transmitter is to be *blocked* from operating.
|
||||||
|
|
||||||
|
RFKILL_STATE_SOFT_BLOCKED indicates that a call to toggle_radio() can change
|
||||||
|
that state. RFKILL_STATE_HARD_BLOCKED indicates that a call to toggle_radio()
|
||||||
|
will not be able to change the state and will return with a suitable error if
|
||||||
|
attempts are made to set the state to RFKILL_STATE_UNBLOCKED.
|
||||||
|
|
||||||
|
RFKILL_STATE_HARD_BLOCKED is used by drivers to signal that the device is
|
||||||
|
locked in the BLOCKED state by a hardwire rfkill line (typically an input pin
|
||||||
|
that, when active, forces the transmitter to be disabled) which the driver
|
||||||
|
CANNOT override.
|
||||||
|
|
||||||
Full rfkill functionality requires two different subsystems to cooperate: the
|
Full rfkill functionality requires two different subsystems to cooperate: the
|
||||||
input layer and the rfkill class. The input layer issues *commands* to the
|
input 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):
|
||||||
action).
|
action).
|
||||||
* rfkill-input implements EPO by handling EV_SW SW_RFKILL_ALL 0
|
* rfkill-input implements EPO by handling EV_SW SW_RFKILL_ALL 0
|
||||||
(power off all transmitters) in a special way: it ignores any
|
(power off all transmitters) in a special way: it ignores any
|
||||||
overrides and local state cache and forces all transmitters to
|
overrides and local state cache and forces all transmitters to the
|
||||||
the OFF state (including those which are already supposed to be
|
RFKILL_STATE_SOFT_BLOCKED state (including those which are already
|
||||||
OFF). Note that the opposite event (power on all transmitters)
|
supposed to be BLOCKED). Note that the opposite event (power on all
|
||||||
is handled normally.
|
transmitters) is handled normally.
|
||||||
|
|
||||||
Userspace uevent handler or kernel platform-specific drivers hooked to the
|
Userspace uevent handler or kernel platform-specific drivers hooked to the
|
||||||
rfkill notifier chain:
|
rfkill notifier chain:
|
||||||
|
@ -284,6 +295,19 @@ You should:
|
||||||
YOU CAN ACCESS state DIRECTLY)
|
YOU CAN ACCESS state DIRECTLY)
|
||||||
- rfkill_register()
|
- rfkill_register()
|
||||||
|
|
||||||
|
The only way to set a device to the RFKILL_STATE_HARD_BLOCKED state is through
|
||||||
|
a suitable return of get_state() or through rfkill_force_state().
|
||||||
|
|
||||||
|
When a device is in the RFKILL_STATE_HARD_BLOCKED state, the only way to switch
|
||||||
|
it to a different state is through a suitable return of get_state() or through
|
||||||
|
rfkill_force_state().
|
||||||
|
|
||||||
|
If toggle_radio() is called to set a device to state RFKILL_STATE_SOFT_BLOCKED
|
||||||
|
when that device is already at the RFKILL_STATE_HARD_BLOCKED state, it should
|
||||||
|
not return an error. Instead, it should try to double-block the transmitter,
|
||||||
|
so that its state will change from RFKILL_STATE_HARD_BLOCKED to
|
||||||
|
RFKILL_STATE_SOFT_BLOCKED should the hardware blocking cease.
|
||||||
|
|
||||||
Please refer to the source for more documentation.
|
Please refer to the source for more documentation.
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
@ -322,13 +346,27 @@ 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
|
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
|
switch is set to OFF, *every* rfkill device *MUST* be immediately put into the
|
||||||
OFF state, no questions asked.
|
RFKILL_STATE_SOFT_BLOCKED state, no questions asked.
|
||||||
|
|
||||||
The following sysfs entries will be created:
|
The following sysfs entries will be created:
|
||||||
|
|
||||||
name: Name assigned by driver to this key (interface or driver name).
|
name: Name assigned by driver to this key (interface or driver name).
|
||||||
type: Name of the key type ("wlan", "bluetooth", etc).
|
type: Name of the key type ("wlan", "bluetooth", etc).
|
||||||
state: Current state of the key. 1: On, 0: Off.
|
state: Current state of the transmitter
|
||||||
|
0: RFKILL_STATE_SOFT_BLOCKED
|
||||||
|
transmitter is forced off, but you can override it
|
||||||
|
by a write to the state attribute, or through input
|
||||||
|
events (if rfkill-input is loaded).
|
||||||
|
1: RFKILL_STATE_UNBLOCKED
|
||||||
|
transmiter is NOT forced off, and may operate if
|
||||||
|
all other conditions for such operation are met
|
||||||
|
(such as interface is up and configured, etc).
|
||||||
|
2: RFKILL_STATE_HARD_BLOCKED
|
||||||
|
transmitter is forced off by something outside of
|
||||||
|
the driver's control.
|
||||||
|
|
||||||
|
You cannot set a device to this state through
|
||||||
|
writes to the state attribute.
|
||||||
claim: 1: Userspace handles events, 0: Kernel handles events
|
claim: 1: Userspace handles events, 0: Kernel handles events
|
||||||
|
|
||||||
Both the "state" and "claim" entries are also writable. For the "state" entry
|
Both the "state" and "claim" entries are also writable. For the "state" entry
|
||||||
|
|
|
@ -46,16 +46,25 @@ enum rfkill_type {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum rfkill_state {
|
enum rfkill_state {
|
||||||
RFKILL_STATE_OFF = 0, /* Radio output blocked */
|
RFKILL_STATE_SOFT_BLOCKED = 0, /* Radio output blocked */
|
||||||
RFKILL_STATE_ON = 1, /* Radio output active */
|
RFKILL_STATE_UNBLOCKED = 1, /* Radio output allowed */
|
||||||
|
RFKILL_STATE_HARD_BLOCKED = 2, /* Output blocked, non-overrideable */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are DEPRECATED, drivers using them should be verified to
|
||||||
|
* comply with the rfkill usage guidelines in Documentation/rfkill.txt
|
||||||
|
* and then converted to use the new names for rfkill_state
|
||||||
|
*/
|
||||||
|
#define RFKILL_STATE_OFF RFKILL_STATE_SOFT_BLOCKED
|
||||||
|
#define RFKILL_STATE_ON RFKILL_STATE_UNBLOCKED
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct rfkill - rfkill control structure.
|
* struct rfkill - rfkill control structure.
|
||||||
* @name: Name of the switch.
|
* @name: Name of the switch.
|
||||||
* @type: Radio type which the button controls, the value stored
|
* @type: Radio type which the button controls, the value stored
|
||||||
* here should be a value from enum rfkill_type.
|
* here should be a value from enum rfkill_type.
|
||||||
* @state: State of the switch, "ON" means radio can operate.
|
* @state: State of the switch, "UNBLOCKED" means radio can operate.
|
||||||
* @user_claim_unsupported: Whether the hardware supports exclusive
|
* @user_claim_unsupported: Whether the hardware supports exclusive
|
||||||
* RF-kill control by userspace. Set this before registering.
|
* RF-kill control by userspace. Set this before registering.
|
||||||
* @user_claim: Set when the switch is controlled exlusively by userspace.
|
* @user_claim: Set when the switch is controlled exlusively by userspace.
|
||||||
|
@ -63,8 +72,12 @@ enum rfkill_state {
|
||||||
* @data: Pointer to the RF button drivers private data which will be
|
* @data: Pointer to the RF button drivers private data which will be
|
||||||
* passed along when toggling radio state.
|
* passed along when toggling radio state.
|
||||||
* @toggle_radio(): Mandatory handler to control state of the radio.
|
* @toggle_radio(): Mandatory handler to control state of the radio.
|
||||||
|
* only RFKILL_STATE_SOFT_BLOCKED and RFKILL_STATE_UNBLOCKED are
|
||||||
|
* valid parameters.
|
||||||
* @get_state(): handler to read current radio state from hardware,
|
* @get_state(): handler to read current radio state from hardware,
|
||||||
* may be called from atomic context, should return 0 on success.
|
* may be called from atomic context, should return 0 on success.
|
||||||
|
* Either this handler OR judicious use of rfkill_force_state() is
|
||||||
|
* MANDATORY for any driver capable of RFKILL_STATE_HARD_BLOCKED.
|
||||||
* @led_trigger: A LED trigger for this button's LED.
|
* @led_trigger: A LED trigger for this button's LED.
|
||||||
* @dev: Device structure integrating the switch into device tree.
|
* @dev: Device structure integrating the switch into device tree.
|
||||||
* @node: Used to place switch into list of all switches known to the
|
* @node: Used to place switch into list of all switches known to the
|
||||||
|
@ -102,6 +115,19 @@ void rfkill_unregister(struct rfkill *rfkill);
|
||||||
|
|
||||||
int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state);
|
int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rfkill_state_complement - return complementar state
|
||||||
|
* @state: state to return the complement of
|
||||||
|
*
|
||||||
|
* Returns RFKILL_STATE_SOFT_BLOCKED if @state is RFKILL_STATE_UNBLOCKED,
|
||||||
|
* returns RFKILL_STATE_UNBLOCKED otherwise.
|
||||||
|
*/
|
||||||
|
static inline enum rfkill_state rfkill_state_complement(enum rfkill_state state)
|
||||||
|
{
|
||||||
|
return (state == RFKILL_STATE_UNBLOCKED) ?
|
||||||
|
RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rfkill_get_led_name - Get the LED trigger name for the button's LED.
|
* 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
|
* This function might return a NULL pointer if registering of the
|
||||||
|
|
|
@ -84,7 +84,8 @@ static void rfkill_schedule_toggle(struct rfkill_task *task)
|
||||||
spin_lock_irqsave(&task->lock, flags);
|
spin_lock_irqsave(&task->lock, flags);
|
||||||
|
|
||||||
if (time_after(jiffies, task->last + msecs_to_jiffies(200))) {
|
if (time_after(jiffies, task->last + msecs_to_jiffies(200))) {
|
||||||
task->desired_state = !task->desired_state;
|
task->desired_state =
|
||||||
|
rfkill_state_complement(task->desired_state);
|
||||||
task->last = jiffies;
|
task->last = jiffies;
|
||||||
schedule_work(&task->work);
|
schedule_work(&task->work);
|
||||||
}
|
}
|
||||||
|
@ -92,14 +93,14 @@ static void rfkill_schedule_toggle(struct rfkill_task *task)
|
||||||
spin_unlock_irqrestore(&task->lock, flags);
|
spin_unlock_irqrestore(&task->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEFINE_RFKILL_TASK(n, t) \
|
#define DEFINE_RFKILL_TASK(n, t) \
|
||||||
struct rfkill_task n = { \
|
struct rfkill_task n = { \
|
||||||
.work = __WORK_INITIALIZER(n.work, \
|
.work = __WORK_INITIALIZER(n.work, \
|
||||||
rfkill_task_handler), \
|
rfkill_task_handler), \
|
||||||
.type = t, \
|
.type = t, \
|
||||||
.mutex = __MUTEX_INITIALIZER(n.mutex), \
|
.mutex = __MUTEX_INITIALIZER(n.mutex), \
|
||||||
.lock = __SPIN_LOCK_UNLOCKED(n.lock), \
|
.lock = __SPIN_LOCK_UNLOCKED(n.lock), \
|
||||||
.desired_state = RFKILL_STATE_ON, \
|
.desired_state = RFKILL_STATE_UNBLOCKED, \
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN);
|
static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN);
|
||||||
|
@ -135,15 +136,15 @@ static void rfkill_event(struct input_handle *handle, unsigned int type,
|
||||||
/* handle EPO (emergency power off) through shortcut */
|
/* handle EPO (emergency power off) through shortcut */
|
||||||
if (data) {
|
if (data) {
|
||||||
rfkill_schedule_set(&rfkill_wwan,
|
rfkill_schedule_set(&rfkill_wwan,
|
||||||
RFKILL_STATE_ON);
|
RFKILL_STATE_UNBLOCKED);
|
||||||
rfkill_schedule_set(&rfkill_wimax,
|
rfkill_schedule_set(&rfkill_wimax,
|
||||||
RFKILL_STATE_ON);
|
RFKILL_STATE_UNBLOCKED);
|
||||||
rfkill_schedule_set(&rfkill_uwb,
|
rfkill_schedule_set(&rfkill_uwb,
|
||||||
RFKILL_STATE_ON);
|
RFKILL_STATE_UNBLOCKED);
|
||||||
rfkill_schedule_set(&rfkill_bt,
|
rfkill_schedule_set(&rfkill_bt,
|
||||||
RFKILL_STATE_ON);
|
RFKILL_STATE_UNBLOCKED);
|
||||||
rfkill_schedule_set(&rfkill_wlan,
|
rfkill_schedule_set(&rfkill_wlan,
|
||||||
RFKILL_STATE_ON);
|
RFKILL_STATE_UNBLOCKED);
|
||||||
} else
|
} else
|
||||||
rfkill_schedule_epo();
|
rfkill_schedule_epo();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -39,7 +39,7 @@ MODULE_LICENSE("GPL");
|
||||||
static LIST_HEAD(rfkill_list); /* list of registered rf switches */
|
static LIST_HEAD(rfkill_list); /* list of registered rf switches */
|
||||||
static DEFINE_MUTEX(rfkill_mutex);
|
static DEFINE_MUTEX(rfkill_mutex);
|
||||||
|
|
||||||
static unsigned int rfkill_default_state = RFKILL_STATE_ON;
|
static unsigned int rfkill_default_state = RFKILL_STATE_UNBLOCKED;
|
||||||
module_param_named(default_state, rfkill_default_state, uint, 0444);
|
module_param_named(default_state, rfkill_default_state, uint, 0444);
|
||||||
MODULE_PARM_DESC(default_state,
|
MODULE_PARM_DESC(default_state,
|
||||||
"Default initial state for all radio types, 0 = radio off");
|
"Default initial state for all radio types, 0 = radio off");
|
||||||
|
@ -98,7 +98,7 @@ static void rfkill_led_trigger(struct rfkill *rfkill,
|
||||||
|
|
||||||
if (!led->name)
|
if (!led->name)
|
||||||
return;
|
return;
|
||||||
if (state == RFKILL_STATE_OFF)
|
if (state != RFKILL_STATE_UNBLOCKED)
|
||||||
led_trigger_event(led, LED_OFF);
|
led_trigger_event(led, LED_OFF);
|
||||||
else
|
else
|
||||||
led_trigger_event(led, LED_FULL);
|
led_trigger_event(led, LED_FULL);
|
||||||
|
@ -128,6 +128,28 @@ static void update_rfkill_state(struct rfkill *rfkill)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rfkill_toggle_radio - wrapper for toggle_radio hook
|
||||||
|
* calls toggle_radio taking into account a lot of "small"
|
||||||
|
* details.
|
||||||
|
* @rfkill: the rfkill struct to use
|
||||||
|
* @force: calls toggle_radio even if cache says it is not needed,
|
||||||
|
* and also makes sure notifications of the state will be
|
||||||
|
* sent even if it didn't change
|
||||||
|
* @state: the new state to call toggle_radio() with
|
||||||
|
*
|
||||||
|
* This wrappen protects and enforces the API for toggle_radio
|
||||||
|
* calls. Note that @force cannot override a (possibly cached)
|
||||||
|
* state of RFKILL_STATE_HARD_BLOCKED. Any device making use of
|
||||||
|
* RFKILL_STATE_HARD_BLOCKED implements either get_state() or
|
||||||
|
* rfkill_force_state(), so the cache either is bypassed or valid.
|
||||||
|
*
|
||||||
|
* Note that we do call toggle_radio for RFKILL_STATE_SOFT_BLOCKED
|
||||||
|
* even if the radio is in RFKILL_STATE_HARD_BLOCKED state, so as to
|
||||||
|
* give the driver a hint that it should double-BLOCK the transmitter.
|
||||||
|
*
|
||||||
|
* Caller must have aquired rfkill_mutex.
|
||||||
|
*/
|
||||||
static int rfkill_toggle_radio(struct rfkill *rfkill,
|
static int rfkill_toggle_radio(struct rfkill *rfkill,
|
||||||
enum rfkill_state state,
|
enum rfkill_state state,
|
||||||
int force)
|
int force)
|
||||||
|
@ -141,9 +163,28 @@ static int rfkill_toggle_radio(struct rfkill *rfkill,
|
||||||
!rfkill->get_state(rfkill->data, &newstate))
|
!rfkill->get_state(rfkill->data, &newstate))
|
||||||
rfkill->state = newstate;
|
rfkill->state = newstate;
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case RFKILL_STATE_HARD_BLOCKED:
|
||||||
|
/* typically happens when refreshing hardware state,
|
||||||
|
* such as on resume */
|
||||||
|
state = RFKILL_STATE_SOFT_BLOCKED;
|
||||||
|
break;
|
||||||
|
case RFKILL_STATE_UNBLOCKED:
|
||||||
|
/* force can't override this, only rfkill_force_state() can */
|
||||||
|
if (rfkill->state == RFKILL_STATE_HARD_BLOCKED)
|
||||||
|
return -EPERM;
|
||||||
|
break;
|
||||||
|
case RFKILL_STATE_SOFT_BLOCKED:
|
||||||
|
/* nothing to do, we want to give drivers the hint to double
|
||||||
|
* BLOCK even a transmitter that is already in state
|
||||||
|
* RFKILL_STATE_HARD_BLOCKED */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (force || state != rfkill->state) {
|
if (force || state != rfkill->state) {
|
||||||
retval = rfkill->toggle_radio(rfkill->data, state);
|
retval = rfkill->toggle_radio(rfkill->data, state);
|
||||||
if (!retval)
|
/* never allow a HARD->SOFT downgrade! */
|
||||||
|
if (!retval && rfkill->state != RFKILL_STATE_HARD_BLOCKED)
|
||||||
rfkill->state = state;
|
rfkill->state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +225,7 @@ EXPORT_SYMBOL(rfkill_switch_all);
|
||||||
/**
|
/**
|
||||||
* rfkill_epo - emergency power off all transmitters
|
* rfkill_epo - emergency power off all transmitters
|
||||||
*
|
*
|
||||||
* This kicks all rfkill devices to RFKILL_STATE_OFF, ignoring
|
* This kicks all rfkill devices to RFKILL_STATE_SOFT_BLOCKED, ignoring
|
||||||
* everything in its path but rfkill_mutex.
|
* everything in its path but rfkill_mutex.
|
||||||
*/
|
*/
|
||||||
void rfkill_epo(void)
|
void rfkill_epo(void)
|
||||||
|
@ -193,7 +234,7 @@ void rfkill_epo(void)
|
||||||
|
|
||||||
mutex_lock(&rfkill_mutex);
|
mutex_lock(&rfkill_mutex);
|
||||||
list_for_each_entry(rfkill, &rfkill_list, node) {
|
list_for_each_entry(rfkill, &rfkill_list, node) {
|
||||||
rfkill_toggle_radio(rfkill, RFKILL_STATE_OFF, 1);
|
rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1);
|
||||||
}
|
}
|
||||||
mutex_unlock(&rfkill_mutex);
|
mutex_unlock(&rfkill_mutex);
|
||||||
}
|
}
|
||||||
|
@ -215,8 +256,9 @@ int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state)
|
||||||
{
|
{
|
||||||
enum rfkill_state oldstate;
|
enum rfkill_state oldstate;
|
||||||
|
|
||||||
if (state != RFKILL_STATE_OFF &&
|
if (state != RFKILL_STATE_SOFT_BLOCKED &&
|
||||||
state != RFKILL_STATE_ON)
|
state != RFKILL_STATE_UNBLOCKED &&
|
||||||
|
state != RFKILL_STATE_HARD_BLOCKED)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&rfkill->mutex);
|
mutex_lock(&rfkill->mutex);
|
||||||
|
@ -290,11 +332,14 @@ static ssize_t rfkill_state_store(struct device *dev,
|
||||||
if (!capable(CAP_NET_ADMIN))
|
if (!capable(CAP_NET_ADMIN))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
|
/* RFKILL_STATE_HARD_BLOCKED is illegal here... */
|
||||||
|
if (state != RFKILL_STATE_UNBLOCKED &&
|
||||||
|
state != RFKILL_STATE_SOFT_BLOCKED)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if (mutex_lock_interruptible(&rfkill->mutex))
|
if (mutex_lock_interruptible(&rfkill->mutex))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
error = rfkill_toggle_radio(rfkill,
|
error = rfkill_toggle_radio(rfkill, state, 0);
|
||||||
state ? RFKILL_STATE_ON : RFKILL_STATE_OFF,
|
|
||||||
0);
|
|
||||||
mutex_unlock(&rfkill->mutex);
|
mutex_unlock(&rfkill->mutex);
|
||||||
|
|
||||||
return error ? error : count;
|
return error ? error : count;
|
||||||
|
@ -373,7 +418,8 @@ static int rfkill_suspend(struct device *dev, pm_message_t state)
|
||||||
update_rfkill_state(rfkill);
|
update_rfkill_state(rfkill);
|
||||||
|
|
||||||
mutex_lock(&rfkill->mutex);
|
mutex_lock(&rfkill->mutex);
|
||||||
rfkill->toggle_radio(rfkill->data, RFKILL_STATE_OFF);
|
rfkill->toggle_radio(rfkill->data,
|
||||||
|
RFKILL_STATE_SOFT_BLOCKED);
|
||||||
mutex_unlock(&rfkill->mutex);
|
mutex_unlock(&rfkill->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,7 +516,7 @@ static void rfkill_remove_switch(struct rfkill *rfkill)
|
||||||
{
|
{
|
||||||
mutex_lock(&rfkill_mutex);
|
mutex_lock(&rfkill_mutex);
|
||||||
list_del_init(&rfkill->node);
|
list_del_init(&rfkill->node);
|
||||||
rfkill_toggle_radio(rfkill, RFKILL_STATE_OFF, 1);
|
rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1);
|
||||||
mutex_unlock(&rfkill_mutex);
|
mutex_unlock(&rfkill_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,8 +656,9 @@ static int __init rfkill_init(void)
|
||||||
int error;
|
int error;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (rfkill_default_state != RFKILL_STATE_OFF &&
|
/* RFKILL_STATE_HARD_BLOCKED is illegal here... */
|
||||||
rfkill_default_state != RFKILL_STATE_ON)
|
if (rfkill_default_state != RFKILL_STATE_SOFT_BLOCKED &&
|
||||||
|
rfkill_default_state != RFKILL_STATE_UNBLOCKED)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(rfkill_states); i++)
|
for (i = 0; i < ARRAY_SIZE(rfkill_states); i++)
|
||||||
|
|
Loading…
Reference in a new issue