aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2008-07-31 09:53:57 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-01 15:31:32 -0400
commit6e28fbef0f330d7c1cade345eeae003d4e5d6070 (patch)
tree69d5f4e32a6ed95eb2bdc89678ca87d60274d2fb
parentf860ee26db51c478fd70039bd4902912a8d93993 (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.c54
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);
109static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX); 109static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX);
110static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN); 110static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN);
111 111
112static 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
112static void rfkill_event(struct input_handle *handle, unsigned int type, 131static 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
194static 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
188static void rfkill_disconnect(struct input_handle *handle) 211static 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};