diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index 6b8df67b3653..393b5af871d9 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h @@ -123,6 +123,8 @@ struct wacom_remote { struct { struct attribute_group group; u32 serial; + struct input_dev *input; + bool registered; } remotes[WACOM_MAX_REMOTES]; }; diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index c3b269237af5..f2f5b4b248cb 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1905,6 +1905,11 @@ static void wacom_remote_destroy_one(struct wacom *wacom, unsigned int index) struct wacom_remote *remote = wacom->remote; u32 serial = remote->remotes[index].serial; int i; + unsigned long flags; + + spin_lock_irqsave(&remote->remote_lock, flags); + remote->remotes[index].registered = false; + spin_unlock_irqrestore(&remote->remote_lock, flags); if (remote->remotes[index].group.name) devres_release_group(&wacom->hdev->dev, @@ -1914,6 +1919,7 @@ static void wacom_remote_destroy_one(struct wacom *wacom, unsigned int index) if (remote->remotes[i].serial == serial) { remote->remotes[i].serial = 0; remote->remotes[i].group.name = NULL; + remote->remotes[i].registered = false; wacom->led.groups[i].select = WACOM_STATUS_UNKNOWN; } } @@ -1946,8 +1952,32 @@ static int wacom_remote_create_one(struct wacom *wacom, u32 serial, if (error) goto fail; + remote->remotes[index].input = wacom_allocate_input(wacom); + if (!remote->remotes[index].input) { + error = -ENOMEM; + goto fail; + } + remote->remotes[index].input->uniq = remote->remotes[index].group.name; + remote->remotes[index].input->name = wacom->wacom_wac.pad_name; + + if (!remote->remotes[index].input->name) { + error = -EINVAL; + goto fail; + } + + error = wacom_setup_pad_input_capabilities(remote->remotes[index].input, + &wacom->wacom_wac); + if (error) + goto fail; + remote->remotes[index].serial = serial; + error = input_register_device(remote->remotes[index].input); + if (error) + goto fail; + + remote->remotes[index].registered = true; + devres_close_group(dev, &remote->remotes[index]); return 0; diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index aee07613040d..99d688a3ee71 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -751,23 +751,38 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) { unsigned char *data = wacom_wac->data; - struct input_dev *input = wacom_wac->pad_input; + struct input_dev *input; struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); struct wacom_remote *remote = wacom->remote; struct wacom_features *features = &wacom_wac->features; int bat_charging, bat_percent, touch_ring_mode; __u32 serial; - int i; + int i, index = -1; + unsigned long flags; if (data[0] != WACOM_REPORT_REMOTE) { - dev_dbg(input->dev.parent, - "%s: received unknown report #%d", __func__, data[0]); + hid_dbg(wacom->hdev, "%s: received unknown report #%d", + __func__, data[0]); return 0; } serial = data[3] + (data[4] << 8) + (data[5] << 16); wacom_wac->id[0] = PAD_DEVICE_ID; + spin_lock_irqsave(&remote->remote_lock, flags); + + for (i = 0; i < WACOM_MAX_REMOTES; i++) { + if (remote->remotes[i].serial == serial) { + index = i; + break; + } + } + + if (index < 0 || !remote->remotes[index].registered) + goto out; + + input = remote->remotes[index].input; + input_report_key(input, BTN_0, (data[9] & 0x01)); input_report_key(input, BTN_1, (data[9] & 0x02)); input_report_key(input, BTN_2, (data[9] & 0x04)); @@ -804,6 +819,8 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) input_event(input, EV_MSC, MSC_SERIAL, serial); + input_sync(input); + /*Which mode select (LED light) is currently on?*/ touch_ring_mode = (data[11] & 0xC0) >> 6; @@ -821,7 +838,9 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) wacom_notify_battery(wacom_wac, bat_percent, bat_charging, 1, bat_charging); - return 1; +out: + spin_unlock_irqrestore(&remote->remote_lock, flags); + return 0; } static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) @@ -2458,6 +2477,9 @@ void wacom_setup_device_quirks(struct wacom *wacom) features->quirks |= WACOM_QUIRK_BATTERY; } } + + if (features->type == REMOTE) + features->device_type |= WACOM_DEVICETYPE_WL_MONITOR; } int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, @@ -2762,6 +2784,9 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, if (!(features->device_type & WACOM_DEVICETYPE_PAD)) return -ENODEV; + if (features->type == REMOTE && input_dev == wacom_wac->pad_input) + return -ENODEV; + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); /* kept for making legacy xf86-input-wacom working with the wheels */