diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00rfkill.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00rfkill.c | 127 |
1 files changed, 41 insertions, 86 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 3298cae1e12d..b6d4c6700bf3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2008 rt2x00 SourceForge Project | 2 | Copyright (C) 2004 - 2009 rt2x00 SourceForge Project |
3 | <http://rt2x00.serialmonkey.com> | 3 | <http://rt2x00.serialmonkey.com> |
4 | 4 | ||
5 | This program is free software; you can redistribute it and/or modify | 5 | This program is free software; you can redistribute it and/or modify |
@@ -25,73 +25,30 @@ | |||
25 | 25 | ||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/rfkill.h> | ||
29 | 28 | ||
30 | #include "rt2x00.h" | 29 | #include "rt2x00.h" |
31 | #include "rt2x00lib.h" | 30 | #include "rt2x00lib.h" |
32 | 31 | ||
33 | static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state) | 32 | static void rt2x00rfkill_poll(struct input_polled_dev *poll_dev) |
34 | { | 33 | { |
35 | struct rt2x00_dev *rt2x00dev = data; | 34 | struct rt2x00_dev *rt2x00dev = poll_dev->private; |
36 | int retval = 0; | 35 | int state, old_state; |
37 | |||
38 | if (unlikely(!rt2x00dev)) | ||
39 | return 0; | ||
40 | |||
41 | /* | ||
42 | * Only continue if there are enabled interfaces. | ||
43 | */ | ||
44 | if (!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) | ||
45 | return 0; | ||
46 | |||
47 | if (state == RFKILL_STATE_UNBLOCKED) { | ||
48 | INFO(rt2x00dev, "RFKILL event: enabling radio.\n"); | ||
49 | clear_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags); | ||
50 | retval = rt2x00lib_enable_radio(rt2x00dev); | ||
51 | } else if (state == RFKILL_STATE_SOFT_BLOCKED) { | ||
52 | INFO(rt2x00dev, "RFKILL event: disabling radio.\n"); | ||
53 | set_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags); | ||
54 | rt2x00lib_disable_radio(rt2x00dev); | ||
55 | } else { | ||
56 | WARNING(rt2x00dev, "RFKILL event: unknown state %d.\n", state); | ||
57 | } | ||
58 | |||
59 | return retval; | ||
60 | } | ||
61 | |||
62 | static int rt2x00rfkill_get_state(void *data, enum rfkill_state *state) | ||
63 | { | ||
64 | struct rt2x00_dev *rt2x00dev = data; | ||
65 | |||
66 | /* | ||
67 | * rfkill_poll reports 1 when the key has been pressed and the | ||
68 | * radio should be blocked. | ||
69 | */ | ||
70 | *state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ? | ||
71 | RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED; | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static void rt2x00rfkill_poll(struct work_struct *work) | ||
77 | { | ||
78 | struct rt2x00_dev *rt2x00dev = | ||
79 | container_of(work, struct rt2x00_dev, rfkill_work.work); | ||
80 | enum rfkill_state state; | ||
81 | 36 | ||
82 | if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state) || | 37 | if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state) || |
83 | !test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) | 38 | !test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) |
84 | return; | 39 | return; |
85 | 40 | ||
86 | /* | 41 | /* |
87 | * Poll latest state and report it to rfkill who should sort | 42 | * Poll latest state, if the state is different then the previous state, |
88 | * out if the state should be toggled or not. | 43 | * we should generate an input event. |
89 | */ | 44 | */ |
90 | if (!rt2x00rfkill_get_state(rt2x00dev, &state)) | 45 | state = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev); |
91 | rfkill_force_state(rt2x00dev->rfkill, state); | 46 | old_state = !!test_bit(RFKILL_STATE_BLOCKED, &rt2x00dev->rfkill_state); |
92 | 47 | ||
93 | queue_delayed_work(rt2x00dev->hw->workqueue, | 48 | if (old_state != state) { |
94 | &rt2x00dev->rfkill_work, RFKILL_POLL_INTERVAL); | 49 | input_report_switch(poll_dev->input, SW_RFKILL_ALL, state); |
50 | change_bit(RFKILL_STATE_BLOCKED, &rt2x00dev->rfkill_state); | ||
51 | } | ||
95 | } | 52 | } |
96 | 53 | ||
97 | void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) | 54 | void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) |
@@ -100,8 +57,8 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) | |||
100 | test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) | 57 | test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) |
101 | return; | 58 | return; |
102 | 59 | ||
103 | if (rfkill_register(rt2x00dev->rfkill)) { | 60 | if (input_register_polled_device(rt2x00dev->rfkill_poll_dev)) { |
104 | ERROR(rt2x00dev, "Failed to register rfkill handler.\n"); | 61 | ERROR(rt2x00dev, "Failed to register polled device.\n"); |
105 | return; | 62 | return; |
106 | } | 63 | } |
107 | 64 | ||
@@ -109,10 +66,10 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) | |||
109 | 66 | ||
110 | /* | 67 | /* |
111 | * Force initial poll which will detect the initial device state, | 68 | * Force initial poll which will detect the initial device state, |
112 | * and correctly sends the signal to the rfkill layer about this | 69 | * and correctly sends the signal to the input layer about this |
113 | * state. | 70 | * state. |
114 | */ | 71 | */ |
115 | rt2x00rfkill_poll(&rt2x00dev->rfkill_work.work); | 72 | rt2x00rfkill_poll(rt2x00dev->rfkill_poll_dev); |
116 | } | 73 | } |
117 | 74 | ||
118 | void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) | 75 | void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) |
@@ -121,52 +78,50 @@ void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) | |||
121 | !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) | 78 | !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) |
122 | return; | 79 | return; |
123 | 80 | ||
124 | cancel_delayed_work_sync(&rt2x00dev->rfkill_work); | 81 | input_unregister_polled_device(rt2x00dev->rfkill_poll_dev); |
125 | |||
126 | rfkill_unregister(rt2x00dev->rfkill); | ||
127 | 82 | ||
128 | __clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state); | 83 | __clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state); |
129 | } | 84 | } |
130 | 85 | ||
131 | void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) | 86 | void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) |
132 | { | 87 | { |
133 | struct device *dev = wiphy_dev(rt2x00dev->hw->wiphy); | 88 | struct input_polled_dev *poll_dev; |
134 | 89 | ||
135 | if (test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) | 90 | if (test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state) || |
91 | !test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) | ||
136 | return; | 92 | return; |
137 | 93 | ||
138 | rt2x00dev->rfkill = rfkill_allocate(dev, RFKILL_TYPE_WLAN); | 94 | poll_dev = input_allocate_polled_device(); |
139 | if (!rt2x00dev->rfkill) { | 95 | if (!poll_dev) { |
140 | ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n"); | 96 | ERROR(rt2x00dev, "Failed to allocate polled device.\n"); |
141 | return; | 97 | return; |
142 | } | 98 | } |
143 | 99 | ||
144 | __set_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state); | 100 | poll_dev->private = rt2x00dev; |
101 | poll_dev->poll = rt2x00rfkill_poll; | ||
102 | poll_dev->poll_interval = RFKILL_POLL_INTERVAL; | ||
145 | 103 | ||
146 | rt2x00dev->rfkill->name = rt2x00dev->ops->name; | 104 | poll_dev->input->name = rt2x00dev->ops->name; |
147 | rt2x00dev->rfkill->data = rt2x00dev; | 105 | poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy); |
148 | rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio; | 106 | poll_dev->input->id.bustype = BUS_HOST; |
149 | if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) { | 107 | poll_dev->input->id.vendor = 0x1814; |
150 | rt2x00dev->rfkill->get_state = rt2x00rfkill_get_state; | 108 | poll_dev->input->id.product = rt2x00dev->chip.rt; |
151 | rt2x00dev->rfkill->state = | 109 | poll_dev->input->id.version = rt2x00dev->chip.rev; |
152 | rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ? | 110 | poll_dev->input->dev.parent = wiphy_dev(rt2x00dev->hw->wiphy); |
153 | RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED; | 111 | poll_dev->input->evbit[0] = BIT(EV_SW); |
154 | } else { | 112 | poll_dev->input->swbit[0] = BIT(SW_RFKILL_ALL); |
155 | rt2x00dev->rfkill->state = RFKILL_STATE_UNBLOCKED; | ||
156 | } | ||
157 | 113 | ||
158 | INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00rfkill_poll); | 114 | rt2x00dev->rfkill_poll_dev = poll_dev; |
159 | 115 | ||
160 | return; | 116 | __set_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state); |
161 | } | 117 | } |
162 | 118 | ||
163 | void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) | 119 | void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) |
164 | { | 120 | { |
165 | if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) | 121 | if (!__test_and_clear_bit(RFKILL_STATE_ALLOCATED, |
122 | &rt2x00dev->rfkill_state)) | ||
166 | return; | 123 | return; |
167 | 124 | ||
168 | cancel_delayed_work_sync(&rt2x00dev->rfkill_work); | 125 | input_free_polled_device(rt2x00dev->rfkill_poll_dev); |
169 | 126 | rt2x00dev->rfkill_poll_dev = NULL; | |
170 | rfkill_free(rt2x00dev->rfkill); | ||
171 | rt2x00dev->rfkill = NULL; | ||
172 | } | 127 | } |