HID: wacom: EKR: allocate one input node per remote
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>
Wed, 13 Jul 2016 16:06:07 +0000 (18:06 +0200)
committerJiri Kosina <jkosina@suse.cz>
Fri, 5 Aug 2016 11:39:18 +0000 (13:39 +0200)
Thanks to devres, we can now afford to create more than one input node
without having to overload the remove/failure paths. Having one input
node per remote is something which should have been implemented from start
but the probability of having users with several remotes is quite low.
Anyway, still, better looking at the future and implement things properly.

Remote input nodes will be freed/unregistered magically as they are
created in the devres group &remote->remotes[index].

We need to open the hid node now that the remotes are dynamically
allocated.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Acked-by: Ping Cheng <pingc@wacom.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
drivers/hid/wacom.h
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c

index 6b8df67b3653b397d7cd258687130ae1aad16037..393b5af871d9ab6e5a629ba8c31b36b5cb8cac68 100644 (file)
@@ -123,6 +123,8 @@ struct wacom_remote {
        struct {
                struct attribute_group group;
                u32 serial;
+               struct input_dev *input;
+               bool registered;
        } remotes[WACOM_MAX_REMOTES];
 };
 
index c3b269237af5dd026173f94cfed7f9467b5313d8..f2f5b4b248cb1f504655f053f0b9a0276188d28d 100644 (file)
@@ -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;
 
index aee07613040d1a7c7fe835ec6426cbf613bd88c6..99d688a3ee71d99f14b61b166cc804ce420f86b0 100644 (file)
@@ -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 */