Commit 6e28fbef authored by Henrique de Moraes Holschuh's avatar Henrique de Moraes Holschuh Committed by John W. Linville

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: default avatarHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: default avatarIvo van Doorn <IvDoorn@gmail.com>
Cc: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent f860ee26
...@@ -109,6 +109,25 @@ static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB); ...@@ -109,6 +109,25 @@ static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB);
static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX); static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX);
static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN); static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN);
static void rfkill_schedule_evsw_rfkillall(int state)
{
/* EVERY radio type. state != 0 means radios ON */
/* handle EPO (emergency power off) through shortcut */
if (state) {
rfkill_schedule_set(&rfkill_wwan,
RFKILL_STATE_UNBLOCKED);
rfkill_schedule_set(&rfkill_wimax,
RFKILL_STATE_UNBLOCKED);
rfkill_schedule_set(&rfkill_uwb,
RFKILL_STATE_UNBLOCKED);
rfkill_schedule_set(&rfkill_bt,
RFKILL_STATE_UNBLOCKED);
rfkill_schedule_set(&rfkill_wlan,
RFKILL_STATE_UNBLOCKED);
} else
rfkill_schedule_epo();
}
static void rfkill_event(struct input_handle *handle, unsigned int type, static void rfkill_event(struct input_handle *handle, unsigned int type,
unsigned int code, int data) unsigned int code, int data)
{ {
...@@ -132,21 +151,7 @@ static void rfkill_event(struct input_handle *handle, unsigned int type, ...@@ -132,21 +151,7 @@ static void rfkill_event(struct input_handle *handle, unsigned int type,
} else if (type == EV_SW) { } else if (type == EV_SW) {
switch (code) { switch (code) {
case SW_RFKILL_ALL: case SW_RFKILL_ALL:
/* EVERY radio type. data != 0 means radios ON */ rfkill_schedule_evsw_rfkillall(data);
/* handle EPO (emergency power off) through shortcut */
if (data) {
rfkill_schedule_set(&rfkill_wwan,
RFKILL_STATE_UNBLOCKED);
rfkill_schedule_set(&rfkill_wimax,
RFKILL_STATE_UNBLOCKED);
rfkill_schedule_set(&rfkill_uwb,
RFKILL_STATE_UNBLOCKED);
rfkill_schedule_set(&rfkill_bt,
RFKILL_STATE_UNBLOCKED);
rfkill_schedule_set(&rfkill_wlan,
RFKILL_STATE_UNBLOCKED);
} else
rfkill_schedule_epo();
break; break;
default: default:
break; break;
...@@ -168,6 +173,7 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -168,6 +173,7 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev,
handle->handler = handler; handle->handler = handler;
handle->name = "rfkill"; handle->name = "rfkill";
/* causes rfkill_start() to be called */
error = input_register_handle(handle); error = input_register_handle(handle);
if (error) if (error)
goto err_free_handle; goto err_free_handle;
...@@ -185,6 +191,23 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -185,6 +191,23 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev,
return error; return error;
} }
static void rfkill_start(struct input_handle *handle)
{
/* Take event_lock to guard against configuration changes, we
* should be able to deal with concurrency with rfkill_event()
* just fine (which event_lock will also avoid). */
spin_lock_irq(&handle->dev->event_lock);
if (test_bit(EV_SW, handle->dev->evbit)) {
if (test_bit(SW_RFKILL_ALL, handle->dev->swbit))
rfkill_schedule_evsw_rfkillall(test_bit(SW_RFKILL_ALL,
handle->dev->sw));
/* add resync for further EV_SW events here */
}
spin_unlock_irq(&handle->dev->event_lock);
}
static void rfkill_disconnect(struct input_handle *handle) static void rfkill_disconnect(struct input_handle *handle)
{ {
input_close_device(handle); input_close_device(handle);
...@@ -225,6 +248,7 @@ static struct input_handler rfkill_handler = { ...@@ -225,6 +248,7 @@ static struct input_handler rfkill_handler = {
.event = rfkill_event, .event = rfkill_event,
.connect = rfkill_connect, .connect = rfkill_connect,
.disconnect = rfkill_disconnect, .disconnect = rfkill_disconnect,
.start = rfkill_start,
.name = "rfkill", .name = "rfkill",
.id_table = rfkill_ids, .id_table = rfkill_ids,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment