diff options
author | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2008-07-31 09:53:57 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-08-01 15:31:32 -0400 |
commit | 6e28fbef0f330d7c1cade345eeae003d4e5d6070 (patch) | |
tree | 69d5f4e32a6ed95eb2bdc89678ca87d60274d2fb | |
parent | f860ee26db51c478fd70039bd4902912a8d93993 (diff) |
rfkill: query EV_SW states when rfkill-input (re)?connects to a input device
Every time a new input device that is capable of one of the
rfkill EV_SW events (currently only SW_RFKILL_ALL) is connected to
rfkill-input, we must check the states of the input EV_SW switches
and take action. Otherwise, we will ignore the initial switch state.
We also need to re-check the states of the EV_SW switches after
a device that was under an exclusive grab is released back to us,
since we got no input events from that device while it was grabbed.
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>
-rw-r--r-- | net/rfkill/rfkill-input.c | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c index 8aa822730145..e5b69556bb5b 100644 --- a/net/rfkill/rfkill-input.c +++ b/net/rfkill/rfkill-input.c | |||
@@ -109,6 +109,25 @@ static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB); | |||
109 | static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX); | 109 | static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX); |
110 | static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN); | 110 | static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN); |
111 | 111 | ||
112 | static void rfkill_schedule_evsw_rfkillall(int state) | ||
113 | { | ||
114 | /* EVERY radio type. state != 0 means radios ON */ | ||
115 | /* handle EPO (emergency power off) through shortcut */ | ||
116 | if (state) { | ||
117 | rfkill_schedule_set(&rfkill_wwan, | ||
118 | RFKILL_STATE_UNBLOCKED); | ||
119 | rfkill_schedule_set(&rfkill_wimax, | ||
120 | RFKILL_STATE_UNBLOCKED); | ||
121 | rfkill_schedule_set(&rfkill_uwb, | ||
122 | RFKILL_STATE_UNBLOCKED); | ||
123 | rfkill_schedule_set(&rfkill_bt, | ||
124 | RFKILL_STATE_UNBLOCKED); | ||
125 | rfkill_schedule_set(&rfkill_wlan, | ||
126 | RFKILL_STATE_UNBLOCKED); | ||
127 | } else | ||
128 | rfkill_schedule_epo(); | ||
129 | } | ||
130 | |||
112 | static void rfkill_event(struct input_handle *handle, unsigned int type, | 131 | static void rfkill_event(struct input_handle *handle, unsigned int type, |
113 | unsigned int code, int data) | 132 | unsigned int code, int data) |
114 | { | 133 | { |
@@ -132,21 +151,7 @@ static void rfkill_event(struct input_handle *handle, unsigned int type, | |||
132 | } else if (type == EV_SW) { | 151 | } else if (type == EV_SW) { |
133 | switch (code) { | 152 | switch (code) { |
134 | case SW_RFKILL_ALL: | 153 | case SW_RFKILL_ALL: |
135 | /* EVERY radio type. data != 0 means radios ON */ | 154 | rfkill_schedule_evsw_rfkillall(data); |
136 | /* handle EPO (emergency power off) through shortcut */ | ||
137 | if (data) { | ||
138 | rfkill_schedule_set(&rfkill_wwan, | ||
139 | RFKILL_STATE_UNBLOCKED); | ||
140 | rfkill_schedule_set(&rfkill_wimax, | ||
141 | RFKILL_STATE_UNBLOCKED); | ||
142 | rfkill_schedule_set(&rfkill_uwb, | ||
143 | RFKILL_STATE_UNBLOCKED); | ||
144 | rfkill_schedule_set(&rfkill_bt, | ||
145 | RFKILL_STATE_UNBLOCKED); | ||
146 | rfkill_schedule_set(&rfkill_wlan, | ||
147 | RFKILL_STATE_UNBLOCKED); | ||
148 | } else | ||
149 | rfkill_schedule_epo(); | ||
150 | break; | 155 | break; |
151 | default: | 156 | default: |
152 | break; | 157 | break; |
@@ -168,6 +173,7 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev, | |||
168 | handle->handler = handler; | 173 | handle->handler = handler; |
169 | handle->name = "rfkill"; | 174 | handle->name = "rfkill"; |
170 | 175 | ||
176 | /* causes rfkill_start() to be called */ | ||
171 | error = input_register_handle(handle); | 177 | error = input_register_handle(handle); |
172 | if (error) | 178 | if (error) |
173 | goto err_free_handle; | 179 | goto err_free_handle; |
@@ -185,6 +191,23 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev, | |||
185 | return error; | 191 | return error; |
186 | } | 192 | } |
187 | 193 | ||
194 | static void rfkill_start(struct input_handle *handle) | ||
195 | { | ||
196 | /* Take event_lock to guard against configuration changes, we | ||
197 | * should be able to deal with concurrency with rfkill_event() | ||
198 | * just fine (which event_lock will also avoid). */ | ||
199 | spin_lock_irq(&handle->dev->event_lock); | ||
200 | |||
201 | if (test_bit(EV_SW, handle->dev->evbit)) { | ||
202 | if (test_bit(SW_RFKILL_ALL, handle->dev->swbit)) | ||
203 | rfkill_schedule_evsw_rfkillall(test_bit(SW_RFKILL_ALL, | ||
204 | handle->dev->sw)); | ||
205 | /* add resync for further EV_SW events here */ | ||
206 | } | ||
207 | |||
208 | spin_unlock_irq(&handle->dev->event_lock); | ||
209 | } | ||
210 | |||
188 | static void rfkill_disconnect(struct input_handle *handle) | 211 | static void rfkill_disconnect(struct input_handle *handle) |
189 | { | 212 | { |
190 | input_close_device(handle); | 213 | input_close_device(handle); |
@@ -225,6 +248,7 @@ static struct input_handler rfkill_handler = { | |||
225 | .event = rfkill_event, | 248 | .event = rfkill_event, |
226 | .connect = rfkill_connect, | 249 | .connect = rfkill_connect, |
227 | .disconnect = rfkill_disconnect, | 250 | .disconnect = rfkill_disconnect, |
251 | .start = rfkill_start, | ||
228 | .name = "rfkill", | 252 | .name = "rfkill", |
229 | .id_table = rfkill_ids, | 253 | .id_table = rfkill_ids, |
230 | }; | 254 | }; |