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 /net/rfkill | |
| 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>
Diffstat (limited to 'net/rfkill')
| -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 | }; |
