cregit-Linux how code gets into the kernel

Release 4.11 net/rfkill/core.c

Directory: net/rfkill
/*
 * 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

PersonTokensPropCommitsCommitProp
Michael Büsch3768.52%150.00%
Johannes Berg1731.48%150.00%
Total54100.00%2100.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

PersonTokensPropCommitsCommitProp
Dmitry Baryshkov3085.71%150.00%
Johannes Berg514.29%150.00%
Total35100.00%2100.00%


const char *rfkill_get_led_trigger_name(struct rfkill *rfkill) { return rfkill->led_trigger.name; }

Contributors

PersonTokensPropCommitsCommitProp
AceLan Kao19100.00%1100.00%
Total19100.00%1100.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

PersonTokensPropCommitsCommitProp
AceLan Kao27100.00%1100.00%
Total27100.00%1100.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

PersonTokensPropCommitsCommitProp
Johannes Berg2553.19%150.00%
Henrique de Moraes Holschuh2246.81%150.00%
Total47100.00%2100.00%


static void rfkill_led_trigger_unregister(struct rfkill *rfkill) { led_trigger_unregister(&rfkill->led_trigger); }

Contributors

PersonTokensPropCommitsCommitProp
Johannes Berg1578.95%150.00%
Henrique de Moraes Holschuh421.05%150.00%
Total19100.00%2100.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

PersonTokensPropCommitsCommitProp
Michał Kępień70100.00%1100.00%
Total70100.00%1100.00%


static void rfkill_any_led_trigger_event(void) { schedule_work(&rfkill_any_work); }

Contributors

PersonTokensPropCommitsCommitProp
Michał Kępień14100.00%1100.00%
Total14100.00%1100.00%


static void rfkill_any_led_trigger_activate(struct led_classdev *led_cdev) { rfkill_any_led_trigger_event(); }

Contributors

PersonTokensPropCommitsCommitProp
Michał Kępień14100.00%1100.00%
Total14100.00%1100.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

PersonTokensPropCommitsCommitProp
Michał Kępień35100.00%1100.00%
Total35100.00%1100.00%


static void rfkill_any_led_trigger_unregister(void) { led_trigger_unregister(&rfkill_any_led_trigger); cancel_work_sync(&rfkill_any_work); }

Contributors

PersonTokensPropCommitsCommitProp
Michał Kępień20100.00%1100.00%
Total20100.00%1100.00%

#else
static void rfkill_led_trigger_event(struct rfkill *rfkill) { }

Contributors

PersonTokensPropCommitsCommitProp
Johannes Berg990.00%150.00%
Henrique de Moraes Holschuh110.00%150.00%
Total10100.00%2100.00%


static inline int rfkill_led_trigger_register(struct rfkill *rfkill) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Johannes Berg15100.00%1100.00%
Total15100.00%1100.00%


static inline void rfkill_led_trigger_unregister(struct rfkill *rfkill) { }

Contributors

PersonTokensPropCommitsCommitProp
Johannes Berg11100.00%1100.00%
Total11100.00%1100.00%


static void rfkill_any_led_trigger_event(void) { }

Contributors

PersonTokensPropCommitsCommitProp
Michał Kępień7100.00%1100.00%
Total7100.00%1100.00%


static int rfkill_any_led_trigger_register(void) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Michał Kępień11100.00%1100.00%
Total11100.00%1100.00%


static void rfkill_any_led_trigger_unregister(void) { }

Contributors

PersonTokensPropCommitsCommitProp
Michał Kępień7100.00%1100.00%
Total7100.00%1100.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

PersonTokensPropCommitsCommitProp
Johannes Berg98100.00%1100.00%
Total98100.00%1100.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

PersonTokensPropCommitsCommitProp
Johannes Berg103100.00%1100.00%
Total103100.00%1100.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

PersonTokensPropCommitsCommitProp
Johannes Berg3179.49%266.67%
Henrique de Moraes Holschuh820.51%133.33%
Total39100.00%3100.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

PersonTokensPropCommitsCommitProp
Johannes Berg11447.30%214.29%
Henrique de Moraes Holschuh4317.84%535.71%
Ivo van Doorn2912.03%17.14%
Vitaly Wool2711.20%17.14%
Alan Jenkins187.47%17.14%
Larry Finger52.07%17.14%
Michał Kępień31.24%17.14%
João Paulo Rechi Vita20.83%214.29%
Total241100.00%14100.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

PersonTokensPropCommitsCommitProp
João Paulo Rechi Vita4478.57%240.00%
Ivo van Doorn916.07%120.00%
Johannes Berg23.57%120.00%
Henrique de Moraes Holschuh11.79%120.00%
Total56100.00%5100.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

PersonTokensPropCommitsCommitProp
João Paulo Rechi Vita2239.29%233.33%
Ivo van Doorn1425.00%116.67%
Johannes Berg1221.43%116.67%
Carlos Corbacho47.14%116.67%
Alex Hung47.14%116.67%
Total56100.00%6100.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

PersonTokensPropCommitsCommitProp
Johannes Berg3271.11%240.00%
Henrique de Moraes Holschuh1022.22%240.00%
Ivo van Doorn36.67%120.00%
Total45100.00%5100.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

PersonTokensPropCommitsCommitProp
Johannes Berg8288.17%233.33%
Larry Finger55.38%116.67%
Henrique de Moraes Holschuh55.38%233.33%
Alan Jenkins11.08%116.67%
Total93100.00%6100.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

PersonTokensPropCommitsCommitProp
Johannes Berg3761.67%228.57%
Henrique de Moraes Holschuh1626.67%342.86%
Ivo van Doorn610.00%114.29%
Alan Jenkins11.67%114.29%
Total60100.00%7100.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

PersonTokensPropCommitsCommitProp
Johannes Berg2990.62%266.67%
Ivo van Doorn39.38%133.33%
Total32100.00%3100.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

PersonTokensPropCommitsCommitProp
Johannes Berg990.00%150.00%
Henrique de Moraes Holschuh110.00%150.00%
Total10100.00%2100.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

PersonTokensPropCommitsCommitProp
Johannes Berg1794.44%150.00%
Henrique de Moraes Holschuh15.56%150.00%
Total18100.00%2100.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

PersonTokensPropCommitsCommitProp
João Paulo Rechi Vita7260.50%120.00%
Johannes Berg3025.21%240.00%
Henrique de Moraes Holschuh1411.76%120.00%
Michał Kępień32.52%120.00%
Total119100.00%5100.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

PersonTokensPropCommitsCommitProp
Johannes Berg4692.00%150.00%
Henrique de Moraes Holschuh48.00%150.00%
Total50100.00%2100.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

PersonTokensPropCommitsCommitProp
Johannes Berg9879.67%120.00%
Henrique de Moraes Holschuh1915.45%240.00%
Michał Kępień32.44%120.00%
Alan Jenkins32.44%120.00%
Total123100.00%5100.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

PersonTokensPropCommitsCommitProp
Alan Jenkins63100.00%1100.00%
Total63100.00%1100.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

PersonTokensPropCommitsCommitProp
Johannes Berg6746.21%112.50%
Henrique de Moraes Holschuh4128.28%337.50%
Alan Jenkins2920.00%225.00%
Larry Finger53.45%112.50%
Michał Kępień32.07%112.50%
Total145100.00%8100.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

PersonTokensPropCommitsCommitProp
Heikki Krogerus6296.88%133.33%
Larry Finger11.56%133.33%
Alan Jenkins11.56%133.33%
Total64100.00%3100.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

PersonTokensPropCommitsCommitProp
Ivo van Doorn4197.62%150.00%
Greg Kroah-Hartman12.38%150.00%
Total42100.00%2100.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

PersonTokensPropCommitsCommitProp
Henrique de Moraes Holschuh3168.89%125.00%
Ivo van Doorn1022.22%125.00%
Heikki Krogerus36.67%125.00%
Greg Kroah-Hartman12.22%125.00%
Total45100.00%4100.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

PersonTokensPropCommitsCommitProp
Johannes Berg4197.62%150.00%
Greg Kroah-Hartman12.38%150.00%
Total42100.00%2100.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

PersonTokensPropCommitsCommitProp
Alan Jenkins4197.62%150.00%
Greg Kroah-Hartman12.38%150.00%
Total42100.00%2100.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

PersonTokensPropCommitsCommitProp
Florian Mickler4998.00%266.67%
Greg Kroah-Hartman12.00%133.33%
Total50100.00%3100.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

PersonTokensPropCommitsCommitProp
Florian Mickler4998.00%266.67%
Greg Kroah-Hartman12.00%133.33%
Total50100.00%3100.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

PersonTokensPropCommitsCommitProp
Florian Mickler10298.08%133.33%
Julia Lawall10.96%133.33%
Greg Kroah-Hartman10.96%133.33%
Total104100.00%3100.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

PersonTokensPropCommitsCommitProp
Johannes Berg2374.19%150.00%
Ivo van Doorn825.81%150.00%
Total31100.00%2100.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

PersonTokensPropCommitsCommitProp
Ivo van Doorn2351.11%125.00%
Johannes Berg1942.22%125.00%
Florian Mickler24.44%125.00%
Greg Kroah-Hartman12.22%125.00%
Total45100.00%4100.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

PersonTokensPropCommitsCommitProp
Johannes Berg10595.45%240.00%
Ivo van Doorn32.73%120.00%
Julia Lawall10.91%120.00%
Greg Kroah-Hartman10.91%120.00%
Total110100.00%5100.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

PersonTokensPropCommitsCommitProp
Ivo van Doorn26100.00%1100.00%
Total26100.00%1100.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"