Commit 6e28fbef0f330d7c1cade345eeae003d4e5d6070

Authored by Henrique de Moraes Holschuh
Committed by John W. Linville
1 parent f860ee26db

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>

Showing 1 changed file with 39 additions and 15 deletions Side-by-side Diff

net/rfkill/rfkill-input.c
... ... @@ -109,6 +109,25 @@
109 109 static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX);
110 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 131 static void rfkill_event(struct input_handle *handle, unsigned int type,
113 132 unsigned int code, int data)
114 133 {
... ... @@ -132,21 +151,7 @@
132 151 } else if (type == EV_SW) {
133 152 switch (code) {
134 153 case SW_RFKILL_ALL:
135   - /* EVERY radio type. data != 0 means radios ON */
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();
  154 + rfkill_schedule_evsw_rfkillall(data);
150 155 break;
151 156 default:
152 157 break;
... ... @@ -168,6 +173,7 @@
168 173 handle->handler = handler;
169 174 handle->name = "rfkill";
170 175  
  176 + /* causes rfkill_start() to be called */
171 177 error = input_register_handle(handle);
172 178 if (error)
173 179 goto err_free_handle;
... ... @@ -185,6 +191,23 @@
185 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 211 static void rfkill_disconnect(struct input_handle *handle)
189 212 {
190 213 input_close_device(handle);
... ... @@ -225,6 +248,7 @@
225 248 .event = rfkill_event,
226 249 .connect = rfkill_connect,
227 250 .disconnect = rfkill_disconnect,
  251 + .start = rfkill_start,
228 252 .name = "rfkill",
229 253 .id_table = rfkill_ids,
230 254 };