diff options
author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2016-07-13 18:06:01 +0200 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2016-08-05 13:39:16 +0200 |
commit | e6f2813a6d3fd924a399f8b19bcd8b11487155bc (patch) | |
tree | 38e49d6df64ecdfc907a2d2baf605788f51cdbd7 /drivers/hid/wacom_wac.c | |
parent | a50aac7193f18a5a997588556f1212b0d1ba029b (diff) |
HID: wacom: EKR: add a worker to add/remove resources on addition/removal
wacom_remote_status_irq() sends information of addition/removal of EKR.
We want to allocate one input node per remote, so better having this
in a separate worker, not handled in the IRQ directly.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Acked-by: Ping Cheng <pingc@wacom.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/wacom_wac.c')
-rw-r--r-- | drivers/hid/wacom_wac.c | 53 |
1 files changed, 21 insertions, 32 deletions
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 932d3eec933b..d54992967391 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -823,52 +823,40 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) return 1; } -static int wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) +static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) { struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); unsigned char *data = wacom_wac->data; - int i; + struct wacom_remote_data remote_data; + unsigned long flags; + int i, ret; if (data[0] != WACOM_REPORT_DEVICE_LIST) - return 0; + return; + + memset(&remote_data, 0, sizeof(struct wacom_remote_data)); for (i = 0; i < WACOM_MAX_REMOTES; i++) { int j = i * 6; int serial = (data[j+6] << 16) + (data[j+5] << 8) + data[j+4]; bool connected = data[j+2]; - if (connected) { - int k; - - if (wacom_wac->serial[i] == serial) - continue; - - if (wacom_wac->serial[i]) { - wacom_remote_destroy_attr_group(wacom, - wacom_wac->serial[i]); - } - - /* A remote can pair more than once with an EKR, - * check to make sure this serial isn't already paired. - */ - for (k = 0; k < WACOM_MAX_REMOTES; k++) { - if (wacom_wac->serial[k] == serial) - break; - } + remote_data.remote[i].serial = serial; + remote_data.remote[i].connected = connected; + } - if (k < WACOM_MAX_REMOTES) { - wacom_wac->serial[i] = serial; - continue; - } - wacom_remote_create_attr_group(wacom, serial, i); + spin_lock_irqsave(&wacom->remote_lock, flags); - } else if (wacom_wac->serial[i]) { - wacom_remote_destroy_attr_group(wacom, - wacom_wac->serial[i]); - } + ret = kfifo_in(&wacom->remote_fifo, &remote_data, sizeof(remote_data)); + if (ret != sizeof(remote_data)) { + spin_unlock_irqrestore(&wacom->remote_lock, flags); + hid_err(wacom->hdev, "Can't queue Remote status event.\n"); + return; } - return 0; + spin_unlock_irqrestore(&wacom->remote_lock, flags); + + wacom_schedule_work(wacom_wac, WACOM_WORKER_REMOTE); } static int wacom_intuos_general(struct wacom_wac *wacom) @@ -2310,8 +2298,9 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) break; case REMOTE: + sync = false; if (wacom_wac->data[0] == WACOM_REPORT_DEVICE_LIST) - sync = wacom_remote_status_irq(wacom_wac, len); + wacom_remote_status_irq(wacom_wac, len); else sync = wacom_remote_irq(wacom_wac, len); break; |