![Henrique de Moraes Holschuh](/assets/img/avatar_default.png)
Currently, rfkill support for read/write rfkill switches is hacked through a round-trip over the input layer and rfkill-input to let a driver sync rfkill->state to hardware changes. This is buggy and sub-optimal. It causes real problems. It is best to think of the rfkill class as supporting only write-only switches at the moment. In order to implement the read/write functionality properly: Add a get_state() hook that is called by the class every time it needs to fetch the current state of the switch. Add a call to this hook every time the *current* state of the radio plays a role in a decision. Also add a force_state() method that can be used to forcefully syncronize the class' idea of the current state of the switch. This allows for a faster implementation of the read/write functionality, as a driver which get events on switch changes can avoid the need for a get_state() hook. If the get_state() hook is left as NULL, current behaviour is maintained, so this change is fully backwards compatible with the current rfkill drivers. For hardware that issues events when the rfkill state changes, leave get_state() NULL in the rfkill struct, set the initial state properly before registering with the rfkill class, and use the force_state() method in the driver to keep the rfkill interface up-to-date. get_state() can be called by the class from atomic context. It must not sleep. Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Acked-by: Ivo van Doorn <IvDoorn@gmail.com> Cc: Dmitry Torokhov <dtor@mail.ru> Signed-off-by: John W. Linville <linville@tuxdriver.com>
119 lines
3.7 KiB
C
119 lines
3.7 KiB
C
#ifndef __RFKILL_H
|
|
#define __RFKILL_H
|
|
|
|
/*
|
|
* Copyright (C) 2006 - 2007 Ivo van Doorn
|
|
* Copyright (C) 2007 Dmitry Torokhov
|
|
*
|
|
* 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, write to the
|
|
* Free Software Foundation, Inc.,
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/list.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/device.h>
|
|
#include <linux/leds.h>
|
|
|
|
/**
|
|
* enum rfkill_type - type of rfkill switch.
|
|
* RFKILL_TYPE_WLAN: switch is on a 802.11 wireless network device.
|
|
* RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device.
|
|
* RFKILL_TYPE_UWB: switch is on a ultra wideband device.
|
|
* RFKILL_TYPE_WIMAX: switch is on a WiMAX device.
|
|
*/
|
|
enum rfkill_type {
|
|
RFKILL_TYPE_WLAN ,
|
|
RFKILL_TYPE_BLUETOOTH,
|
|
RFKILL_TYPE_UWB,
|
|
RFKILL_TYPE_WIMAX,
|
|
RFKILL_TYPE_MAX,
|
|
};
|
|
|
|
enum rfkill_state {
|
|
RFKILL_STATE_OFF = 0, /* Radio output blocked */
|
|
RFKILL_STATE_ON = 1, /* Radio output active */
|
|
};
|
|
|
|
/**
|
|
* struct rfkill - rfkill control structure.
|
|
* @name: Name of the switch.
|
|
* @type: Radio type which the button controls, the value stored
|
|
* here should be a value from enum rfkill_type.
|
|
* @state: State of the switch, "ON" means radio can operate.
|
|
* @user_claim_unsupported: Whether the hardware supports exclusive
|
|
* RF-kill control by userspace. Set this before registering.
|
|
* @user_claim: Set when the switch is controlled exlusively by userspace.
|
|
* @mutex: Guards switch state transitions
|
|
* @data: Pointer to the RF button drivers private data which will be
|
|
* passed along when toggling radio state.
|
|
* @toggle_radio(): Mandatory handler to control state of the radio.
|
|
* @get_state(): handler to read current radio state from hardware,
|
|
* may be called from atomic context, should return 0 on success.
|
|
* @led_trigger: A LED trigger for this button's LED.
|
|
* @dev: Device structure integrating the switch into device tree.
|
|
* @node: Used to place switch into list of all switches known to the
|
|
* the system.
|
|
*
|
|
* This structure represents a RF switch located on a network device.
|
|
*/
|
|
struct rfkill {
|
|
const char *name;
|
|
enum rfkill_type type;
|
|
|
|
enum rfkill_state state;
|
|
bool user_claim_unsupported;
|
|
bool user_claim;
|
|
|
|
struct mutex mutex;
|
|
|
|
void *data;
|
|
int (*toggle_radio)(void *data, enum rfkill_state state);
|
|
int (*get_state)(void *data, enum rfkill_state *state);
|
|
|
|
#ifdef CONFIG_RFKILL_LEDS
|
|
struct led_trigger led_trigger;
|
|
#endif
|
|
|
|
struct device dev;
|
|
struct list_head node;
|
|
};
|
|
#define to_rfkill(d) container_of(d, struct rfkill, dev)
|
|
|
|
struct rfkill *rfkill_allocate(struct device *parent, enum rfkill_type type);
|
|
void rfkill_free(struct rfkill *rfkill);
|
|
int rfkill_register(struct rfkill *rfkill);
|
|
void rfkill_unregister(struct rfkill *rfkill);
|
|
|
|
int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state);
|
|
|
|
/**
|
|
* rfkill_get_led_name - Get the LED trigger name for the button's LED.
|
|
* This function might return a NULL pointer if registering of the
|
|
* LED trigger failed.
|
|
* Use this as "default_trigger" for the LED.
|
|
*/
|
|
static inline char *rfkill_get_led_name(struct rfkill *rfkill)
|
|
{
|
|
#ifdef CONFIG_RFKILL_LEDS
|
|
return (char *)(rfkill->led_trigger.name);
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
#endif /* RFKILL_H */
|