Release 4.11 net/rfkill/core.c
/*
* Copyright (C) 2006 - 2007 Ivo van Doorn
* Copyright (C) 2007 Dmitry Torokhov
* Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/workqueue.h>
#include <linux/capability.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/rfkill.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include "rfkill.h"
#define POLL_INTERVAL (5 * HZ)
#define RFKILL_BLOCK_HW BIT(0)
#define RFKILL_BLOCK_SW BIT(1)
#define RFKILL_BLOCK_SW_PREV BIT(2)
#define RFKILL_BLOCK_ANY (RFKILL_BLOCK_HW |\
RFKILL_BLOCK_SW |\
RFKILL_BLOCK_SW_PREV)
#define RFKILL_BLOCK_SW_SETCALL BIT(31)
struct rfkill {
spinlock_t lock;
enum rfkill_type type;
unsigned long state;
u32 idx;
bool registered;
bool persistent;
bool polling_paused;
bool suspended;
const struct rfkill_ops *ops;
void *data;
#ifdef CONFIG_RFKILL_LEDS
struct led_trigger led_trigger;
const char *ledtrigname;
#endif
struct device dev;
struct list_head node;
struct delayed_work poll_work;
struct work_struct uevent_work;
struct work_struct sync_work;
char name[];
};
#define to_rfkill(d) container_of(d, struct rfkill, dev)
struct rfkill_int_event {
struct list_head list;
struct rfkill_event ev;
};
struct rfkill_data {
struct list_head list;
struct list_head events;
struct mutex mtx;
wait_queue_head_t read_wait;
bool input_handler;
};
MODULE_AUTHOR("Ivo van Doorn <IvDoorn@gmail.com>");
MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
MODULE_DESCRIPTION("RF switch support");
MODULE_LICENSE("GPL");
/*
* The locking here should be made much smarter, we currently have
* a bit of a stupid situation because drivers might want to register
* the rfkill struct under their own lock, and take this lock during
* rfkill method calls -- which will cause an AB-BA deadlock situation.
*
* To fix that, we need to rework this code here to be mostly lock-free
* and only use the mutex for list manipulations, not to protect the
* various other global variables. Then we can avoid holding the mutex
* around driver operations, and all is happy.
*/
static LIST_HEAD(rfkill_list); /* list of registered rf switches */
static DEFINE_MUTEX(rfkill_global_mutex);
static LIST_HEAD(rfkill_fds); /* list of open fds of /dev/rfkill */
static unsigned int rfkill_default_state = 1;
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 struct {
bool cur, sav;
}
rfkill_global_states[NUM_RFKILL_TYPES];
static bool rfkill_epo_lock_active;
#ifdef CONFIG_RFKILL_LEDS
static void rfkill_led_trigger_event(struct rfkill *rfkill)
{
struct led_trigger *trigger;
if (!rfkill->registered)
return;
trigger = &rfkill->led_trigger;
if (rfkill->state & RFKILL_BLOCK_ANY)
led_trigger_event(trigger, LED_OFF);
else
led_trigger_event(trigger, LED_FULL);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Michael Büsch | 37 | 68.52% | 1 | 50.00% |
Johannes Berg | 17 | 31.48% | 1 | 50.00% |
Total | 54 | 100.00% | 2 | 100.00% |
static void rfkill_led_trigger_activate(struct led_classdev *led)
{
struct rfkill *rfkill;
rfkill = container_of(led->trigger, struct rfkill, led_trigger);
rfkill_led_trigger_event(rfkill);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Baryshkov | 30 | 85.71% | 1 | 50.00% |
Johannes Berg | 5 | 14.29% | 1 | 50.00% |
Total | 35 | 100.00% | 2 | 100.00% |
const char *rfkill_get_led_trigger_name(struct rfkill *rfkill)
{
return rfkill->led_trigger.name;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
AceLan Kao | 19 | 100.00% | 1 | 100.00% |
Total | 19 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL(rfkill_get_led_trigger_name);
void rfkill_set_led_trigger_name(struct rfkill *rfkill, const char *name)
{
BUG_ON(!rfkill);
rfkill->ledtrigname = name;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
AceLan Kao | 27 | 100.00% | 1 | 100.00% |
Total | 27 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL(rfkill_set_led_trigger_name);
static int rfkill_led_trigger_register(struct rfkill *rfkill)
{
rfkill->led_trigger.name = rfkill->ledtrigname
? : dev_name(&rfkill->dev);
rfkill->led_trigger.activate = rfkill_led_trigger_activate;
return led_trigger_register(&rfkill->led_trigger);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 25 | 53.19% | 1 | 50.00% |
Henrique de Moraes Holschuh | 22 | 46.81% | 1 | 50.00% |
Total | 47 | 100.00% | 2 | 100.00% |
static void rfkill_led_trigger_unregister(struct rfkill *rfkill)
{
led_trigger_unregister(&rfkill->led_trigger);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 15 | 78.95% | 1 | 50.00% |
Henrique de Moraes Holschuh | 4 | 21.05% | 1 | 50.00% |
Total | 19 | 100.00% | 2 | 100.00% |
static struct led_trigger rfkill_any_led_trigger;
static struct work_struct rfkill_any_work;
static void rfkill_any_led_trigger_worker(struct work_struct *work)
{
enum led_brightness brightness = LED_OFF;
struct rfkill *rfkill;
mutex_lock(&rfkill_global_mutex);
list_for_each_entry(rfkill, &rfkill_list, node) {
if (!(rfkill->state & RFKILL_BLOCK_ANY)) {
brightness = LED_FULL;
break;
}
}
mutex_unlock(&rfkill_global_mutex);
led_trigger_event(&rfkill_any_led_trigger, brightness);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Michał Kępień | 70 | 100.00% | 1 | 100.00% |
Total | 70 | 100.00% | 1 | 100.00% |
static void rfkill_any_led_trigger_event(void)
{
schedule_work(&rfkill_any_work);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Michał Kępień | 14 | 100.00% | 1 | 100.00% |
Total | 14 | 100.00% | 1 | 100.00% |
static void rfkill_any_led_trigger_activate(struct led_classdev *led_cdev)
{
rfkill_any_led_trigger_event();
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Michał Kępień | 14 | 100.00% | 1 | 100.00% |
Total | 14 | 100.00% | 1 | 100.00% |
static int rfkill_any_led_trigger_register(void)
{
INIT_WORK(&rfkill_any_work, rfkill_any_led_trigger_worker);
rfkill_any_led_trigger.name = "rfkill-any";
rfkill_any_led_trigger.activate = rfkill_any_led_trigger_activate;
return led_trigger_register(&rfkill_any_led_trigger);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Michał Kępień | 35 | 100.00% | 1 | 100.00% |
Total | 35 | 100.00% | 1 | 100.00% |
static void rfkill_any_led_trigger_unregister(void)
{
led_trigger_unregister(&rfkill_any_led_trigger);
cancel_work_sync(&rfkill_any_work);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Michał Kępień | 20 | 100.00% | 1 | 100.00% |
Total | 20 | 100.00% | 1 | 100.00% |
#else
static void rfkill_led_trigger_event(struct rfkill *rfkill)
{
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 9 | 90.00% | 1 | 50.00% |
Henrique de Moraes Holschuh | 1 | 10.00% | 1 | 50.00% |
Total | 10 | 100.00% | 2 | 100.00% |
static inline int rfkill_led_trigger_register(struct rfkill *rfkill)
{
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 15 | 100.00% | 1 | 100.00% |
Total | 15 | 100.00% | 1 | 100.00% |
static inline void rfkill_led_trigger_unregister(struct rfkill *rfkill)
{
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 11 | 100.00% | 1 | 100.00% |
Total | 11 | 100.00% | 1 | 100.00% |
static void rfkill_any_led_trigger_event(void)
{
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Michał Kępień | 7 | 100.00% | 1 | 100.00% |
Total | 7 | 100.00% | 1 | 100.00% |
static int rfkill_any_led_trigger_register(void)
{
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Michał Kępień | 11 | 100.00% | 1 | 100.00% |
Total | 11 | 100.00% | 1 | 100.00% |
static void rfkill_any_led_trigger_unregister(void)
{
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Michał Kępień | 7 | 100.00% | 1 | 100.00% |
Total | 7 | 100.00% | 1 | 100.00% |
#endif /* CONFIG_RFKILL_LEDS */
static void rfkill_fill_event(struct rfkill_event *ev, struct rfkill *rfkill,
enum rfkill_operation op)
{
unsigned long flags;
ev->idx = rfkill->idx;
ev->type = rfkill->type;
ev->op = op;
spin_lock_irqsave(&rfkill->lock, flags);
ev->hard = !!(rfkill->state & RFKILL_BLOCK_HW);
ev->soft = !!(rfkill->state & (RFKILL_BLOCK_SW |
RFKILL_BLOCK_SW_PREV));
spin_unlock_irqrestore(&rfkill->lock, flags);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 98 | 100.00% | 1 | 100.00% |
Total | 98 | 100.00% | 1 | 100.00% |
static void rfkill_send_events(struct rfkill *rfkill, enum rfkill_operation op)
{
struct rfkill_data *data;
struct rfkill_int_event *ev;
list_for_each_entry(data, &rfkill_fds, list) {
ev = kzalloc(sizeof(*ev), GFP_KERNEL);
if (!ev)
continue;
rfkill_fill_event(&ev->ev, rfkill, op);
mutex_lock(&data->mtx);
list_add_tail(&ev->list, &data->events);
mutex_unlock(&data->mtx);
wake_up_interruptible(&data->read_wait);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 103 | 100.00% | 1 | 100.00% |
Total | 103 | 100.00% | 1 | 100.00% |
static void rfkill_event(struct rfkill *rfkill)
{
if (!rfkill->registered)
return;
kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE);
/* also send event to /dev/rfkill */
rfkill_send_events(rfkill, RFKILL_OP_CHANGE);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 31 | 79.49% | 2 | 66.67% |
Henrique de Moraes Holschuh | 8 | 20.51% | 1 | 33.33% |
Total | 39 | 100.00% | 3 | 100.00% |
/**
* rfkill_set_block - wrapper for set_block method
*
* @rfkill: the rfkill struct to use
* @blocked: the new software state
*
* Calls the set_block method (when applicable) and handles notifications
* etc. as well.
*/
static void rfkill_set_block(struct rfkill *rfkill, bool blocked)
{
unsigned long flags;
bool prev, curr;
int err;
if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP))
return;
/*
* Some platforms (...!) generate input events which affect the
* _hard_ kill state -- whenever something tries to change the
* current software state query the hardware state too.
*/
if (rfkill->ops->query)
rfkill->ops->query(rfkill, rfkill->data);
spin_lock_irqsave(&rfkill->lock, flags);
prev = rfkill->state & RFKILL_BLOCK_SW;
if (prev)
rfkill->state |= RFKILL_BLOCK_SW_PREV;
else
rfkill->state &= ~RFKILL_BLOCK_SW_PREV;
if (blocked)
rfkill->state |= RFKILL_BLOCK_SW;
else
rfkill->state &= ~RFKILL_BLOCK_SW;
rfkill->state |= RFKILL_BLOCK_SW_SETCALL;
spin_unlock_irqrestore(&rfkill->lock, flags);
err = rfkill->ops->set_block(rfkill->data, blocked);
spin_lock_irqsave(&rfkill->lock, flags);
if (err) {
/*
* Failed -- reset status to _PREV, which may be different
* from what we have set _PREV to earlier in this function
* if rfkill_set_sw_state was invoked.
*/
if (rfkill->state & RFKILL_BLOCK_SW_PREV)
rfkill->state |= RFKILL_BLOCK_SW;
else
rfkill->state &= ~RFKILL_BLOCK_SW;
}
rfkill->state &= ~RFKILL_BLOCK_SW_SETCALL;
rfkill->state &= ~RFKILL_BLOCK_SW_PREV;
curr = rfkill->state & RFKILL_BLOCK_SW;
spin_unlock_irqrestore(&rfkill->lock, flags);
rfkill_led_trigger_event(rfkill);
rfkill_any_led_trigger_event();
if (prev != curr)
rfkill_event(rfkill);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 114 | 47.30% | 2 | 14.29% |
Henrique de Moraes Holschuh | 43 | 17.84% | 5 | 35.71% |
Ivo van Doorn | 29 | 12.03% | 1 | 7.14% |
Vitaly Wool | 27 | 11.20% | 1 | 7.14% |
Alan Jenkins | 18 | 7.47% | 1 | 7.14% |
Larry Finger | 5 | 2.07% | 1 | 7.14% |
Michał Kępień | 3 | 1.24% | 1 | 7.14% |
João Paulo Rechi Vita | 2 | 0.83% | 2 | 14.29% |
Total | 241 | 100.00% | 14 | 100.00% |
static void rfkill_update_global_state(enum rfkill_type type, bool blocked)
{
int i;
if (type != RFKILL_TYPE_ALL) {
rfkill_global_states[type].cur = blocked;
return;
}
for (i = 0; i < NUM_RFKILL_TYPES; i++)
rfkill_global_states[i].cur = blocked;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
João Paulo Rechi Vita | 44 | 78.57% | 2 | 40.00% |
Ivo van Doorn | 9 | 16.07% | 1 | 20.00% |
Johannes Berg | 2 | 3.57% | 1 | 20.00% |
Henrique de Moraes Holschuh | 1 | 1.79% | 1 | 20.00% |
Total | 56 | 100.00% | 5 | 100.00% |
#ifdef CONFIG_RFKILL_INPUT
static atomic_t rfkill_input_disabled = ATOMIC_INIT(0);
/**
* __rfkill_switch_all - Toggle state of all switches of given type
* @type: type of interfaces to be affected
* @blocked: the new state
*
* This function sets the state of all switches of given type,
* unless a specific switch is suspended.
*
* Caller must have acquired rfkill_global_mutex.
*/
static void __rfkill_switch_all(const enum rfkill_type type, bool blocked)
{
struct rfkill *rfkill;
rfkill_update_global_state(type, blocked);
list_for_each_entry(rfkill, &rfkill_list, node) {
if (rfkill->type != type && type != RFKILL_TYPE_ALL)
continue;
rfkill_set_block(rfkill, blocked);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
João Paulo Rechi Vita | 22 | 39.29% | 2 | 33.33% |
Ivo van Doorn | 14 | 25.00% | 1 | 16.67% |
Johannes Berg | 12 | 21.43% | 1 | 16.67% |
Carlos Corbacho | 4 | 7.14% | 1 | 16.67% |
Alex Hung | 4 | 7.14% | 1 | 16.67% |
Total | 56 | 100.00% | 6 | 100.00% |
/**
* rfkill_switch_all - Toggle state of all switches of given type
* @type: type of interfaces to be affected
* @blocked: the new state
*
* Acquires rfkill_global_mutex and calls __rfkill_switch_all(@type, @state).
* Please refer to __rfkill_switch_all() for details.
*
* Does nothing if the EPO lock is active.
*/
void rfkill_switch_all(enum rfkill_type type, bool blocked)
{
if (atomic_read(&rfkill_input_disabled))
return;
mutex_lock(&rfkill_global_mutex);
if (!rfkill_epo_lock_active)
__rfkill_switch_all(type, blocked);
mutex_unlock(&rfkill_global_mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 32 | 71.11% | 2 | 40.00% |
Henrique de Moraes Holschuh | 10 | 22.22% | 2 | 40.00% |
Ivo van Doorn | 3 | 6.67% | 1 | 20.00% |
Total | 45 | 100.00% | 5 | 100.00% |
/**
* rfkill_epo - emergency power off all transmitters
*
* This kicks all non-suspended rfkill devices to RFKILL_STATE_SOFT_BLOCKED,
* ignoring everything in its path but rfkill_global_mutex and rfkill->mutex.
*
* The global state before the EPO is saved and can be restored later
* using rfkill_restore_states().
*/
void rfkill_epo(void)
{
struct rfkill *rfkill;
int i;
if (atomic_read(&rfkill_input_disabled))
return;
mutex_lock(&rfkill_global_mutex);
rfkill_epo_lock_active = true;
list_for_each_entry(rfkill, &rfkill_list, node)
rfkill_set_block(rfkill, true);
for (i = 0; i < NUM_RFKILL_TYPES; i++) {
rfkill_global_states[i].sav = rfkill_global_states[i].cur;
rfkill_global_states[i].cur = true;
}
mutex_unlock(&rfkill_global_mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 82 | 88.17% | 2 | 33.33% |
Larry Finger | 5 | 5.38% | 1 | 16.67% |
Henrique de Moraes Holschuh | 5 | 5.38% | 2 | 33.33% |
Alan Jenkins | 1 | 1.08% | 1 | 16.67% |
Total | 93 | 100.00% | 6 | 100.00% |
/**
* rfkill_restore_states - restore global states
*
* Restore (and sync switches to) the global state from the
* states in rfkill_default_states. This can undo the effects of
* a call to rfkill_epo().
*/
void rfkill_restore_states(void)
{
int i;
if (atomic_read(&rfkill_input_disabled))
return;
mutex_lock(&rfkill_global_mutex);
rfkill_epo_lock_active = false;
for (i = 0; i < NUM_RFKILL_TYPES; i++)
__rfkill_switch_all(i, rfkill_global_states[i].sav);
mutex_unlock(&rfkill_global_mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 37 | 61.67% | 2 | 28.57% |
Henrique de Moraes Holschuh | 16 | 26.67% | 3 | 42.86% |
Ivo van Doorn | 6 | 10.00% | 1 | 14.29% |
Alan Jenkins | 1 | 1.67% | 1 | 14.29% |
Total | 60 | 100.00% | 7 | 100.00% |
/**
* rfkill_remove_epo_lock - unlock state changes
*
* Used by rfkill-input manually unlock state changes, when
* the EPO switch is deactivated.
*/
void rfkill_remove_epo_lock(void)
{
if (atomic_read(&rfkill_input_disabled))
return;
mutex_lock(&rfkill_global_mutex);
rfkill_epo_lock_active = false;
mutex_unlock(&rfkill_global_mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 29 | 90.62% | 2 | 66.67% |
Ivo van Doorn | 3 | 9.38% | 1 | 33.33% |
Total | 32 | 100.00% | 3 | 100.00% |
/**
* rfkill_is_epo_lock_active - returns true EPO is active
*
* Returns 0 (false) if there is NOT an active EPO contidion,
* and 1 (true) if there is an active EPO contition, which
* locks all radios in one of the BLOCKED states.
*
* Can be called in atomic context.
*/
bool rfkill_is_epo_lock_active(void)
{
return rfkill_epo_lock_active;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 9 | 90.00% | 1 | 50.00% |
Henrique de Moraes Holschuh | 1 | 10.00% | 1 | 50.00% |
Total | 10 | 100.00% | 2 | 100.00% |
/**
* rfkill_get_global_sw_state - returns global state for a type
* @type: the type to get the global state of
*
* Returns the current global state for a given wireless
* device type.
*/
bool rfkill_get_global_sw_state(const enum rfkill_type type)
{
return rfkill_global_states[type].cur;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 17 | 94.44% | 1 | 50.00% |
Henrique de Moraes Holschuh | 1 | 5.56% | 1 | 50.00% |
Total | 18 | 100.00% | 2 | 100.00% |
#endif
bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked)
{
unsigned long flags;
bool ret, prev;
BUG_ON(!rfkill);
spin_lock_irqsave(&rfkill->lock, flags);
prev = !!(rfkill->state & RFKILL_BLOCK_HW);
if (blocked)
rfkill->state |= RFKILL_BLOCK_HW;
else
rfkill->state &= ~RFKILL_BLOCK_HW;
ret = !!(rfkill->state & RFKILL_BLOCK_ANY);
spin_unlock_irqrestore(&rfkill->lock, flags);
rfkill_led_trigger_event(rfkill);
rfkill_any_led_trigger_event();
if (rfkill->registered && prev != blocked)
schedule_work(&rfkill->uevent_work);
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
João Paulo Rechi Vita | 72 | 60.50% | 1 | 20.00% |
Johannes Berg | 30 | 25.21% | 2 | 40.00% |
Henrique de Moraes Holschuh | 14 | 11.76% | 1 | 20.00% |
Michał Kępień | 3 | 2.52% | 1 | 20.00% |
Total | 119 | 100.00% | 5 | 100.00% |
EXPORT_SYMBOL(rfkill_set_hw_state);
static void __rfkill_set_sw_state(struct rfkill *rfkill, bool blocked)
{
u32 bit = RFKILL_BLOCK_SW;
/* if in a ops->set_block right now, use other bit */
if (rfkill->state & RFKILL_BLOCK_SW_SETCALL)
bit = RFKILL_BLOCK_SW_PREV;
if (blocked)
rfkill->state |= bit;
else
rfkill->state &= ~bit;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 46 | 92.00% | 1 | 50.00% |
Henrique de Moraes Holschuh | 4 | 8.00% | 1 | 50.00% |
Total | 50 | 100.00% | 2 | 100.00% |
bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked)
{
unsigned long flags;
bool prev, hwblock;
BUG_ON(!rfkill);
spin_lock_irqsave(&rfkill->lock, flags);
prev = !!(rfkill->state & RFKILL_BLOCK_SW);
__rfkill_set_sw_state(rfkill, blocked);
hwblock = !!(rfkill->state & RFKILL_BLOCK_HW);
blocked = blocked || hwblock;
spin_unlock_irqrestore(&rfkill->lock, flags);
if (!rfkill->registered)
return blocked;
if (prev != blocked && !hwblock)
schedule_work(&rfkill->uevent_work);
rfkill_led_trigger_event(rfkill);
rfkill_any_led_trigger_event();
return blocked;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 98 | 79.67% | 1 | 20.00% |
Henrique de Moraes Holschuh | 19 | 15.45% | 2 | 40.00% |
Michał Kępień | 3 | 2.44% | 1 | 20.00% |
Alan Jenkins | 3 | 2.44% | 1 | 20.00% |
Total | 123 | 100.00% | 5 | 100.00% |
EXPORT_SYMBOL(rfkill_set_sw_state);
void rfkill_init_sw_state(struct rfkill *rfkill, bool blocked)
{
unsigned long flags;
BUG_ON(!rfkill);
BUG_ON(rfkill->registered);
spin_lock_irqsave(&rfkill->lock, flags);
__rfkill_set_sw_state(rfkill, blocked);
rfkill->persistent = true;
spin_unlock_irqrestore(&rfkill->lock, flags);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Alan Jenkins | 63 | 100.00% | 1 | 100.00% |
Total | 63 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL(rfkill_init_sw_state);
void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw)
{
unsigned long flags;
bool swprev, hwprev;
BUG_ON(!rfkill);
spin_lock_irqsave(&rfkill->lock, flags);
/*
* No need to care about prev/setblock ... this is for uevent only
* and that will get triggered by rfkill_set_block anyway.
*/
swprev = !!(rfkill->state & RFKILL_BLOCK_SW);
hwprev = !!(rfkill->state & RFKILL_BLOCK_HW);
__rfkill_set_sw_state(rfkill, sw);
if (hw)
rfkill->state |= RFKILL_BLOCK_HW;
else
rfkill->state &= ~RFKILL_BLOCK_HW;
spin_unlock_irqrestore(&rfkill->lock, flags);
if (!rfkill->registered) {
rfkill->persistent = true;
} else {
if (swprev != sw || hwprev != hw)
schedule_work(&rfkill->uevent_work);
rfkill_led_trigger_event(rfkill);
rfkill_any_led_trigger_event();
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 67 | 46.21% | 1 | 12.50% |
Henrique de Moraes Holschuh | 41 | 28.28% | 3 | 37.50% |
Alan Jenkins | 29 | 20.00% | 2 | 25.00% |
Larry Finger | 5 | 3.45% | 1 | 12.50% |
Michał Kępień | 3 | 2.07% | 1 | 12.50% |
Total | 145 | 100.00% | 8 | 100.00% |
EXPORT_SYMBOL(rfkill_set_states);
static const char * const rfkill_types[] = {
NULL, /* RFKILL_TYPE_ALL */
"wlan",
"bluetooth",
"ultrawideband",
"wimax",
"wwan",
"gps",
"fm",
"nfc",
};
enum rfkill_type rfkill_find_type(const char *name)
{
int i;
BUILD_BUG_ON(ARRAY_SIZE(rfkill_types) != NUM_RFKILL_TYPES);
if (!name)
return RFKILL_TYPE_ALL;
for (i = 1; i < NUM_RFKILL_TYPES; i++)
if (!strcmp(name, rfkill_types[i]))
return i;
return RFKILL_TYPE_ALL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Heikki Krogerus | 62 | 96.88% | 1 | 33.33% |
Larry Finger | 1 | 1.56% | 1 | 33.33% |
Alan Jenkins | 1 | 1.56% | 1 | 33.33% |
Total | 64 | 100.00% | 3 | 100.00% |
EXPORT_SYMBOL(rfkill_find_type);
static ssize_t name_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct rfkill *rfkill = to_rfkill(dev);
return sprintf(buf, "%s\n", rfkill->name);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Ivo van Doorn | 41 | 97.62% | 1 | 50.00% |
Greg Kroah-Hartman | 1 | 2.38% | 1 | 50.00% |
Total | 42 | 100.00% | 2 | 100.00% |
static DEVICE_ATTR_RO(name);
static ssize_t type_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct rfkill *rfkill = to_rfkill(dev);
return sprintf(buf, "%s\n", rfkill_types[rfkill->type]);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Henrique de Moraes Holschuh | 31 | 68.89% | 1 | 25.00% |
Ivo van Doorn | 10 | 22.22% | 1 | 25.00% |
Heikki Krogerus | 3 | 6.67% | 1 | 25.00% |
Greg Kroah-Hartman | 1 | 2.22% | 1 | 25.00% |
Total | 45 | 100.00% | 4 | 100.00% |
static DEVICE_ATTR_RO(type);
static ssize_t index_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct rfkill *rfkill = to_rfkill(dev);
return sprintf(buf, "%d\n", rfkill->idx);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 41 | 97.62% | 1 | 50.00% |
Greg Kroah-Hartman | 1 | 2.38% | 1 | 50.00% |
Total | 42 | 100.00% | 2 | 100.00% |
static DEVICE_ATTR_RO(index);
static ssize_t persistent_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct rfkill *rfkill = to_rfkill(dev);
return sprintf(buf, "%d\n", rfkill->persistent);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Alan Jenkins | 41 | 97.62% | 1 | 50.00% |
Greg Kroah-Hartman | 1 | 2.38% | 1 | 50.00% |
Total | 42 | 100.00% | 2 | 100.00% |
static DEVICE_ATTR_RO(persistent);
static ssize_t hard_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct rfkill *rfkill = to_rfkill(dev);
return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_HW) ? 1 : 0 );
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Florian Mickler | 49 | 98.00% | 2 | 66.67% |
Greg Kroah-Hartman | 1 | 2.00% | 1 | 33.33% |
Total | 50 | 100.00% | 3 | 100.00% |
static DEVICE_ATTR_RO(hard);
static ssize_t soft_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct rfkill *rfkill = to_rfkill(dev);
return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0 );
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Florian Mickler | 49 | 98.00% | 2 | 66.67% |
Greg Kroah-Hartman | 1 | 2.00% | 1 | 33.33% |
Total | 50 | 100.00% | 3 | 100.00% |
static ssize_t soft_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct rfkill *rfkill = to_rfkill(dev);
unsigned long state;
int err;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
err = kstrtoul(buf, 0, &state);
if (err)
return err;
if (state > 1 )
return -EINVAL;
mutex_lock(&rfkill_global_mutex);
rfkill_set_block(rfkill, state);
mutex_unlock(&rfkill_global_mutex);
return count;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Florian Mickler | 102 | 98.08% | 1 | 33.33% |
Julia Lawall | 1 | 0.96% | 1 | 33.33% |
Greg Kroah-Hartman | 1 | 0.96% | 1 | 33.33% |
Total | 104 | 100.00% | 3 | 100.00% |
static DEVICE_ATTR_RW(soft);
static u8 user_state_from_blocked(unsigned long state)
{
if (state & RFKILL_BLOCK_HW)
return RFKILL_USER_STATE_HARD_BLOCKED;
if (state & RFKILL_BLOCK_SW)
return RFKILL_USER_STATE_SOFT_BLOCKED;
return RFKILL_USER_STATE_UNBLOCKED;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 23 | 74.19% | 1 | 50.00% |
Ivo van Doorn | 8 | 25.81% | 1 | 50.00% |
Total | 31 | 100.00% | 2 | 100.00% |
static ssize_t state_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct rfkill *rfkill = to_rfkill(dev);
return sprintf(buf, "%d\n", user_state_from_blocked(rfkill->state));
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Ivo van Doorn | 23 | 51.11% | 1 | 25.00% |
Johannes Berg | 19 | 42.22% | 1 | 25.00% |
Florian Mickler | 2 | 4.44% | 1 | 25.00% |
Greg Kroah-Hartman | 1 | 2.22% | 1 | 25.00% |
Total | 45 | 100.00% | 4 | 100.00% |
static ssize_t state_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct rfkill *rfkill = to_rfkill(dev);
unsigned long state;
int err;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
err = kstrtoul(buf, 0, &state);
if (err)
return err;
if (state != RFKILL_USER_STATE_SOFT_BLOCKED &&
state != RFKILL_USER_STATE_UNBLOCKED)
return -EINVAL;
mutex_lock(&rfkill_global_mutex);
rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED);
mutex_unlock(&rfkill_global_mutex);
return count;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johannes Berg | 105 | 95.45% | 2 | 40.00% |
Ivo van Doorn | 3 | 2.73% | 1 | 20.00% |
Julia Lawall | 1 | 0.91% | 1 | 20.00% |
Greg Kroah-Hartman | 1 | 0.91% | 1 | 20.00% |
Total | 110 | 100.00% | 5 | 100.00% |
static DEVICE_ATTR_RW(state);
static struct attribute *rfkill_dev_attrs[] = {
&dev_attr_name.attr,
&dev_attr_type.attr,
&dev_attr_index.attr,
&dev_attr_persistent.attr,
&dev_attr_state.attr,
&dev_attr_soft.attr,
&dev_attr_hard.attr,
NULL,
};
ATTRIBUTE_GROUPS(rfkill_dev);
static void rfkill_release(struct device *dev)
{
struct rfkill *rfkill = to_rfkill(dev);
kfree(rfkill);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Ivo van Doorn | 26 | 100.00% | 1 | 100.00% |
Total | 26 | 100.00% | 1 | 100.00% |
static int rfkill_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct rfkill *rfkill = to_rfkill(dev);
unsigned long flags;
u32 state;
int error;
error = add_uevent_var(env, "RFKILL_NAME=%s", rfkill->name);
if (error)
return error;
error = add_uevent_var(env, "RFKILL_TYPE=%s"