diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2009-01-03 21:56:02 +0300 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-01-29 23:59:47 +0300 |
commit | cca3e99861e883358ceb39ad17c9eaee082138a5 (patch) | |
tree | 7876976ddc1e60e510fdf905ac9fd3fca939d1d7 | |
parent | c97c92d92715ea4ea2d7cf00957e8a014439bdd8 (diff) | |
download | linux-cca3e99861e883358ceb39ad17c9eaee082138a5.tar.xz |
rt2x00: Replace RFKILL with INPUT
As discussed on linux-wireless rt2x00 does not offer a true RFKILL key,
for that reason RFKILL support should be entirely removed.
The key which is attached to the hardware should be treated as normal
input device instead. Implement input_poll_dev support to poll the device
frequently. When the key status has changed report it as a SW event.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/rt2x00/Kconfig | 7 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00lib.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00rfkill.c | 122 |
4 files changed, 46 insertions, 90 deletions
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 178b313293b4..bfc5d9cf716e 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -97,10 +97,11 @@ config RT2X00_LIB_CRYPTO config RT2X00_LIB_RFKILL boolean - default y if (RT2X00_LIB=y && RFKILL=y) || (RT2X00_LIB=m && RFKILL!=n) + default y if (RT2X00_LIB=y && INPUT=y) || (RT2X00_LIB=m && INPUT!=n) + select INPUT_POLLDEV -comment "rt2x00 rfkill support disabled due to modularized RFKILL and built-in rt2x00" - depends on RT2X00_LIB=y && RFKILL=m +comment "rt2x00 rfkill support disabled due to modularized INPUT and built-in rt2x00" + depends on RT2X00_LIB=y && INPUT=m config RT2X00_LIB_LEDS boolean diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 890c7216cf38..27c0f335f403 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -33,6 +33,7 @@ #include <linux/leds.h> #include <linux/mutex.h> #include <linux/etherdevice.h> +#include <linux/input-polldev.h> #include <net/mac80211.h> @@ -638,8 +639,8 @@ struct rt2x00_dev { unsigned long rfkill_state; #define RFKILL_STATE_ALLOCATED 1 #define RFKILL_STATE_REGISTERED 2 - struct rfkill *rfkill; - struct delayed_work rfkill_work; +#define RFKILL_STATE_BLOCKED 3 + struct input_polled_dev *rfkill_poll_dev; #endif /* CONFIG_RT2X00_LIB_RFKILL */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 5e8df250e50d..92918f315ee5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -33,7 +33,7 @@ * Both the link tuner as the rfkill will be called once per second. */ #define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) ) -#define RFKILL_POLL_INTERVAL ( round_jiffies_relative(HZ) ) +#define RFKILL_POLL_INTERVAL ( 1000 ) /* * rt2x00_rate: Per rate device information diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 3298cae1e12d..595efd05ce44 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c @@ -25,73 +25,30 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/rfkill.h> #include "rt2x00.h" #include "rt2x00lib.h" -static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state) +static void rt2x00rfkill_poll(struct input_polled_dev *poll_dev) { - struct rt2x00_dev *rt2x00dev = data; - int retval = 0; - - if (unlikely(!rt2x00dev)) - return 0; - - /* - * Only continue if there are enabled interfaces. - */ - if (!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) - return 0; - - if (state == RFKILL_STATE_UNBLOCKED) { - INFO(rt2x00dev, "RFKILL event: enabling radio.\n"); - clear_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags); - retval = rt2x00lib_enable_radio(rt2x00dev); - } else if (state == RFKILL_STATE_SOFT_BLOCKED) { - INFO(rt2x00dev, "RFKILL event: disabling radio.\n"); - set_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags); - rt2x00lib_disable_radio(rt2x00dev); - } else { - WARNING(rt2x00dev, "RFKILL event: unknown state %d.\n", state); - } - - return retval; -} - -static int rt2x00rfkill_get_state(void *data, enum rfkill_state *state) -{ - struct rt2x00_dev *rt2x00dev = data; - - /* - * rfkill_poll reports 1 when the key has been pressed and the - * radio should be blocked. - */ - *state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ? - RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED; - - return 0; -} - -static void rt2x00rfkill_poll(struct work_struct *work) -{ - struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, rfkill_work.work); - enum rfkill_state state; + struct rt2x00_dev *rt2x00dev = poll_dev->private; + int state, old_state; if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state) || !test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) return; /* - * Poll latest state and report it to rfkill who should sort - * out if the state should be toggled or not. + * Poll latest state, if the state is different then the previous state, + * we should generate an input event. */ - if (!rt2x00rfkill_get_state(rt2x00dev, &state)) - rfkill_force_state(rt2x00dev->rfkill, state); + state = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev); + old_state = !!test_bit(RFKILL_STATE_BLOCKED, &rt2x00dev->rfkill_state); - queue_delayed_work(rt2x00dev->hw->workqueue, - &rt2x00dev->rfkill_work, RFKILL_POLL_INTERVAL); + if (old_state != state) { + input_report_switch(poll_dev->input, SW_RFKILL_ALL, state); + change_bit(RFKILL_STATE_BLOCKED, &rt2x00dev->rfkill_state); + } } void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) @@ -100,8 +57,8 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) return; - if (rfkill_register(rt2x00dev->rfkill)) { - ERROR(rt2x00dev, "Failed to register rfkill handler.\n"); + if (input_register_polled_device(rt2x00dev->rfkill_poll_dev)) { + ERROR(rt2x00dev, "Failed to register polled device.\n"); return; } @@ -109,10 +66,10 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) /* * Force initial poll which will detect the initial device state, - * and correctly sends the signal to the rfkill layer about this + * and correctly sends the signal to the input layer about this * state. */ - rt2x00rfkill_poll(&rt2x00dev->rfkill_work.work); + rt2x00rfkill_poll(rt2x00dev->rfkill_poll_dev); } void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) @@ -121,52 +78,49 @@ void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) return; - cancel_delayed_work_sync(&rt2x00dev->rfkill_work); - - rfkill_unregister(rt2x00dev->rfkill); + input_unregister_polled_device(rt2x00dev->rfkill_poll_dev); __clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state); } void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) { - struct device *dev = wiphy_dev(rt2x00dev->hw->wiphy); + struct input_polled_dev *poll_dev; if (test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) return; - rt2x00dev->rfkill = rfkill_allocate(dev, RFKILL_TYPE_WLAN); - if (!rt2x00dev->rfkill) { - ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n"); + poll_dev = input_allocate_polled_device(); + if (!poll_dev) { + ERROR(rt2x00dev, "Failed to allocate polled device.\n"); return; } - __set_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state); + poll_dev->private = rt2x00dev; + poll_dev->poll = rt2x00rfkill_poll; + poll_dev->poll_interval = RFKILL_POLL_INTERVAL; - rt2x00dev->rfkill->name = rt2x00dev->ops->name; - rt2x00dev->rfkill->data = rt2x00dev; - rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio; - if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) { - rt2x00dev->rfkill->get_state = rt2x00rfkill_get_state; - rt2x00dev->rfkill->state = - rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ? - RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED; - } else { - rt2x00dev->rfkill->state = RFKILL_STATE_UNBLOCKED; - } + poll_dev->input->name = rt2x00dev->ops->name; + poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy); + poll_dev->input->id.bustype = BUS_HOST; + poll_dev->input->id.vendor = 0x1814; + poll_dev->input->id.product = rt2x00dev->chip.rt; + poll_dev->input->id.version = rt2x00dev->chip.rev; + poll_dev->input->dev.parent = wiphy_dev(rt2x00dev->hw->wiphy); + poll_dev->input->evbit[0] = BIT(EV_SW); + poll_dev->input->swbit[0] = BIT(SW_RFKILL_ALL); - INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00rfkill_poll); + rt2x00dev->rfkill_poll_dev = poll_dev; - return; + __set_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state); } void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) { - if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) + if (!__test_and_clear_bit(RFKILL_STATE_ALLOCATED, + &rt2x00dev->rfkill_state)) return; - cancel_delayed_work_sync(&rt2x00dev->rfkill_work); - - rfkill_free(rt2x00dev->rfkill); - rt2x00dev->rfkill = NULL; + input_free_polled_device(rt2x00dev->rfkill_poll_dev); + rt2x00dev->rfkill_poll_dev = NULL; } |