From 3cb83157e83bf82883e136240c7e059b7d9e29d1 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 12:47:47 -0700 Subject: [PATCH 01/37] Input: Revert "wacom - testing result shows get_report is unnecessary." This reverts commit 1b2faaf7e219fc2905d75afcd4c815e5d39eda80. The Intuos4 series presents a bug in which it hangs if it receives a set feature command while switching to the enhanced mode. This bug is triggered when plugging an Intuos 4 while having a gnome user session up and running. Signed-off-by: Benjamin Tissoires Signed-off-by: Aristeu Rozanski Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 2c613cd41dd6..72b1724ac7d0 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -536,6 +536,9 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, report_id, rep_data, length, 1); + if (error >= 0) + error = wacom_get_report(intf, WAC_HID_FEATURE_REPORT, + report_id, rep_data, length, 1); } while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES); kfree(rep_data); From 7097d4cb597d1d9fe5296082cc3f191db44ab349 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 12:48:06 -0700 Subject: [PATCH 02/37] Input: wacom - assign phys field from struct wacom into input_dev This field was not used for 9 years, it is time to assign it. Signed-off-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 72b1724ac7d0..7cd0886cddd2 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -1127,6 +1127,7 @@ static int wacom_register_input(struct wacom *wacom) } input_dev->name = wacom_wac->name; + input_dev->phys = wacom->phys; input_dev->dev.parent = &intf->dev; input_dev->open = wacom_open; input_dev->close = wacom_close; From d2d13f18aaa51af070c7b6f20606d5cfdb7e87c1 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 12:48:28 -0700 Subject: [PATCH 03/37] Input: wacom - create a separate input device for pads Currently, the pad events are sent through the stylus input device for the Intuos/Cintiqs, and through the touch input device for the Bamboos. To differentiate the buttons pressed on the pad from the ones pressed on the stylus, the Intuos/Cintiq uses MISC_SERIAL and ABS_MISC. This lead to a multiplexing of the events into one device, which are then splitted out in xf86-input-wacom. Bamboos are not using MISC events because the pad is attached to the touch interface, and only BTN_TOUCH is used for the finger (and DOUBLE_TAP, etc...). However, the user space driver still splits out the pad from the touch interface in the same way it does for the pro line devices. The other problem we can see with this fact is that some of the Intuos and Cintiq have a wheel, and the effective range of the reported values is [0..71]. Unfortunately, the airbrush stylus also sends wheel events (there is a small wheel on it), but in the range [0..1023]. From the user space point of view it is kind of difficult to understand that because the wheel on the pad are quite common, while the airbrush tool is not. A solution to fix all of these problems is to split out the pad device from the stylus/touch. This decision makes more sense because the pad is not linked to the absolute position of the finger or pen, and usually, the events from the pad are filtered out by the compositor, which then convert them into actions or keyboard shortcuts. For backward compatibility with current xf86-input-wacom, the pad devices still present the ABS_X, ABS_Y and ABS_MISC events, but they can be completely ignored in the new implementation. Signed-off-by: Benjamin Tissoires Reviewed-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom.h | 2 + drivers/input/tablet/wacom_sys.c | 63 ++++++++++++++++++++++++++++---- drivers/input/tablet/wacom_wac.c | 27 +++++++++++++- drivers/input/tablet/wacom_wac.h | 2 + 4 files changed, 85 insertions(+), 9 deletions(-) diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 9ebf0ed3b3b3..caa59cab2c5f 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h @@ -136,4 +136,6 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); void wacom_setup_device_quirks(struct wacom_features *features); int wacom_setup_input_capabilities(struct input_dev *input_dev, struct wacom_wac *wacom_wac); +int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, + struct wacom_wac *wacom_wac); #endif diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 7cd0886cddd2..b25848581fc1 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -135,6 +135,9 @@ static int wacom_open(struct input_dev *dev) mutex_lock(&wacom->lock); + if (wacom->open) + goto out; + if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { retval = -EIO; goto out; @@ -157,9 +160,14 @@ static void wacom_close(struct input_dev *dev) autopm_error = usb_autopm_get_interface(wacom->intf); mutex_lock(&wacom->lock); + if (!wacom->open) + goto out; + usb_kill_urb(wacom->irq); wacom->open = false; wacom->intf->needs_remote_wakeup = 0; + +out: mutex_unlock(&wacom->lock); if (!autopm_error) @@ -1112,19 +1120,16 @@ static void wacom_destroy_battery(struct wacom *wacom) } } -static int wacom_register_input(struct wacom *wacom) +static struct input_dev *wacom_allocate_input(struct wacom *wacom) { struct input_dev *input_dev; struct usb_interface *intf = wacom->intf; struct usb_device *dev = interface_to_usbdev(intf); struct wacom_wac *wacom_wac = &(wacom->wacom_wac); - int error; input_dev = input_allocate_device(); - if (!input_dev) { - error = -ENOMEM; - goto fail1; - } + if (!input_dev) + return NULL; input_dev->name = wacom_wac->name; input_dev->phys = wacom->phys; @@ -1134,21 +1139,59 @@ static int wacom_register_input(struct wacom *wacom) usb_to_input_id(dev, &input_dev->id); input_set_drvdata(input_dev, wacom); + return input_dev; +} + +static int wacom_register_input(struct wacom *wacom) +{ + struct input_dev *input_dev, *pad_input_dev; + struct wacom_wac *wacom_wac = &(wacom->wacom_wac); + int error; + + input_dev = wacom_allocate_input(wacom); + pad_input_dev = wacom_allocate_input(wacom); + if (!input_dev || !pad_input_dev) { + error = -ENOMEM; + goto fail1; + } + wacom_wac->input = input_dev; + wacom_wac->pad_input = pad_input_dev; + wacom_wac->pad_input->name = wacom_wac->pad_name; + error = wacom_setup_input_capabilities(input_dev, wacom_wac); if (error) - goto fail1; + goto fail2; error = input_register_device(input_dev); if (error) goto fail2; + error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac); + if (error) { + /* no pad in use on this interface */ + input_free_device(pad_input_dev); + wacom_wac->pad_input = NULL; + pad_input_dev = NULL; + } else { + error = input_register_device(pad_input_dev); + if (error) + goto fail3; + } + return 0; +fail3: + input_unregister_device(input_dev); + input_dev = NULL; fail2: - input_free_device(input_dev); wacom_wac->input = NULL; + wacom_wac->pad_input = NULL; fail1: + if (input_dev) + input_free_device(input_dev); + if (pad_input_dev) + input_free_device(pad_input_dev); return error; } @@ -1367,6 +1410,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i wacom_calculate_res(features); strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); + snprintf(wacom_wac->pad_name, sizeof(wacom_wac->pad_name), + "%s Pad", features->name); if (features->quirks & WACOM_QUIRK_MULTI_INPUT) { struct usb_device *other_dev; @@ -1441,6 +1486,8 @@ static void wacom_disconnect(struct usb_interface *intf) cancel_work_sync(&wacom->work); if (wacom->wacom_wac.input) input_unregister_device(wacom->wacom_wac.input); + if (wacom->wacom_wac.pad_input) + input_unregister_device(wacom->wacom_wac.pad_input); wacom_destroy_battery(wacom); wacom_destroy_leds(wacom); usb_free_urb(wacom->irq); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 977d05cd9e2e..4b16a34c95fb 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1489,8 +1489,11 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) break; } - if (sync) + if (sync) { input_sync(wacom_wac->input); + if (wacom_wac->pad_input) + input_sync(wacom_wac->pad_input); + } } static void wacom_setup_cintiq(struct wacom_wac *wacom_wac) @@ -1939,6 +1942,28 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, return 0; } +int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, + struct wacom_wac *wacom_wac) +{ + struct wacom_features *features = &wacom_wac->features; + + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + + /* kept for making legacy xf86-input-wacom working with the wheels */ + __set_bit(ABS_MISC, input_dev->absbit); + + /* kept for making legacy xf86-input-wacom accepting the pad */ + input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0); + input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0); + + switch (features->type) { + default: + /* no pad supported */ + return 1; + } + return 0; +} + static const struct wacom_features wacom_features_0x00 = { "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255, 0, PENPARTNER, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES }; diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index b2c9a9c1b551..f48164c780f4 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -150,6 +150,7 @@ struct wacom_shared { struct wacom_wac { char name[WACOM_NAME_MAX]; + char pad_name[WACOM_NAME_MAX]; unsigned char *data; int tool[2]; int id[2]; @@ -157,6 +158,7 @@ struct wacom_wac { struct wacom_features features; struct wacom_shared *shared; struct input_dev *input; + struct input_dev *pad_input; int pid; int battery_capacity; int num_contacts_left; From 10059cdc0ad0be9dc8f7df2fbf2e21b406a94539 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 12:49:08 -0700 Subject: [PATCH 04/37] Input: wacom - split out the pad device for Intuos/Cintiq MSC_SERIAL can be safely dropped for pad input devices. Signed-off-by: Benjamin Tissoires Reviewed-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 208 ++++++++++++++++++------------- 1 file changed, 122 insertions(+), 86 deletions(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 4b16a34c95fb..8807ab511974 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -584,6 +584,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) /* pad packets. Works as a second tool and is always in prox */ if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD) { + input = wacom->pad_input; if (features->type >= INTUOS4S && features->type <= INTUOS4L) { input_report_key(input, BTN_0, (data[2] & 0x01)); input_report_key(input, BTN_1, (data[3] & 0x01)); @@ -773,7 +774,6 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) input_report_abs(input, ABS_MISC, 0); } } - input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff); return 1; } @@ -1656,61 +1656,20 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, break; case WACOM_24HD: - __set_bit(BTN_A, input_dev->keybit); - __set_bit(BTN_B, input_dev->keybit); - __set_bit(BTN_C, input_dev->keybit); - __set_bit(BTN_X, input_dev->keybit); - __set_bit(BTN_Y, input_dev->keybit); - __set_bit(BTN_Z, input_dev->keybit); - - for (i = 6; i < 10; i++) - __set_bit(BTN_0 + i, input_dev->keybit); - - __set_bit(KEY_PROG1, input_dev->keybit); - __set_bit(KEY_PROG2, input_dev->keybit); - __set_bit(KEY_PROG3, input_dev->keybit); - input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0); /* fall through */ case DTK: - for (i = 0; i < 6; i++) - __set_bit(BTN_0 + i, input_dev->keybit); - __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); wacom_setup_cintiq(wacom_wac); break; case WACOM_22HD: - __set_bit(KEY_PROG1, input_dev->keybit); - __set_bit(KEY_PROG2, input_dev->keybit); - __set_bit(KEY_PROG3, input_dev->keybit); - /* fall through */ - case WACOM_21UX2: - __set_bit(BTN_A, input_dev->keybit); - __set_bit(BTN_B, input_dev->keybit); - __set_bit(BTN_C, input_dev->keybit); - __set_bit(BTN_X, input_dev->keybit); - __set_bit(BTN_Y, input_dev->keybit); - __set_bit(BTN_Z, input_dev->keybit); - __set_bit(BTN_BASE, input_dev->keybit); - __set_bit(BTN_BASE2, input_dev->keybit); - /* fall through */ - case WACOM_BEE: - __set_bit(BTN_8, input_dev->keybit); - __set_bit(BTN_9, input_dev->keybit); - /* fall through */ - case CINTIQ: - for (i = 0; i < 8; i++) - __set_bit(BTN_0 + i, input_dev->keybit); - - input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); - input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); @@ -1719,9 +1678,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, break; case WACOM_13HD: - for (i = 0; i < 9; i++) - __set_bit(BTN_0 + i, input_dev->keybit); - input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); wacom_setup_cintiq(wacom_wac); @@ -1729,21 +1685,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case INTUOS3: case INTUOS3L: - __set_bit(BTN_4, input_dev->keybit); - __set_bit(BTN_5, input_dev->keybit); - __set_bit(BTN_6, input_dev->keybit); - __set_bit(BTN_7, input_dev->keybit); - - input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); - /* fall through */ - case INTUOS3S: - __set_bit(BTN_0, input_dev->keybit); - __set_bit(BTN_1, input_dev->keybit); - __set_bit(BTN_2, input_dev->keybit); - __set_bit(BTN_3, input_dev->keybit); - - input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); /* fall through */ @@ -1757,20 +1699,11 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case INTUOS5L: case INTUOSPM: case INTUOSPL: - if (features->device_type == BTN_TOOL_PEN) { - __set_bit(BTN_7, input_dev->keybit); - __set_bit(BTN_8, input_dev->keybit); - } - /* fall through */ - case INTUOS5S: case INTUOSPS: __set_bit(INPUT_PROP_POINTER, input_dev->propbit); if (features->device_type == BTN_TOOL_PEN) { - for (i = 0; i < 7; i++) - __set_bit(BTN_0 + i, input_dev->keybit); - input_set_abs_params(input_dev, ABS_DISTANCE, 0, features->distance_max, 0, 0); @@ -1791,14 +1724,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case INTUOS4: case INTUOS4L: - __set_bit(BTN_7, input_dev->keybit); - __set_bit(BTN_8, input_dev->keybit); - /* fall through */ - case INTUOS4S: - for (i = 0; i < 7; i++) - __set_bit(BTN_0 + i, input_dev->keybit); - input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); wacom_setup_intuos(wacom_wac); @@ -1922,17 +1848,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, break; case CINTIQ_HYBRID: - __set_bit(BTN_1, input_dev->keybit); - __set_bit(BTN_2, input_dev->keybit); - __set_bit(BTN_3, input_dev->keybit); - __set_bit(BTN_4, input_dev->keybit); - - __set_bit(BTN_5, input_dev->keybit); - __set_bit(BTN_6, input_dev->keybit); - __set_bit(BTN_7, input_dev->keybit); - __set_bit(BTN_8, input_dev->keybit); - __set_bit(BTN_0, input_dev->keybit); - input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); @@ -1946,6 +1861,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { struct wacom_features *features = &wacom_wac->features; + int i; input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); @@ -1957,6 +1873,126 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0); switch (features->type) { + case WACOM_24HD: + __set_bit(BTN_A, input_dev->keybit); + __set_bit(BTN_B, input_dev->keybit); + __set_bit(BTN_C, input_dev->keybit); + __set_bit(BTN_X, input_dev->keybit); + __set_bit(BTN_Y, input_dev->keybit); + __set_bit(BTN_Z, input_dev->keybit); + + for (i = 0; i < 10; i++) + __set_bit(BTN_0 + i, input_dev->keybit); + + __set_bit(KEY_PROG1, input_dev->keybit); + __set_bit(KEY_PROG2, input_dev->keybit); + __set_bit(KEY_PROG3, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); + input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0); + break; + + case DTK: + for (i = 0; i < 6; i++) + __set_bit(BTN_0 + i, input_dev->keybit); + + break; + + case WACOM_22HD: + __set_bit(KEY_PROG1, input_dev->keybit); + __set_bit(KEY_PROG2, input_dev->keybit); + __set_bit(KEY_PROG3, input_dev->keybit); + /* fall through */ + + case WACOM_21UX2: + __set_bit(BTN_A, input_dev->keybit); + __set_bit(BTN_B, input_dev->keybit); + __set_bit(BTN_C, input_dev->keybit); + __set_bit(BTN_X, input_dev->keybit); + __set_bit(BTN_Y, input_dev->keybit); + __set_bit(BTN_Z, input_dev->keybit); + __set_bit(BTN_BASE, input_dev->keybit); + __set_bit(BTN_BASE2, input_dev->keybit); + /* fall through */ + + case WACOM_BEE: + __set_bit(BTN_8, input_dev->keybit); + __set_bit(BTN_9, input_dev->keybit); + /* fall through */ + + case CINTIQ: + for (i = 0; i < 8; i++) + __set_bit(BTN_0 + i, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); + input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); + break; + + case WACOM_13HD: + for (i = 0; i < 9; i++) + __set_bit(BTN_0 + i, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); + break; + + case INTUOS3: + case INTUOS3L: + __set_bit(BTN_4, input_dev->keybit); + __set_bit(BTN_5, input_dev->keybit); + __set_bit(BTN_6, input_dev->keybit); + __set_bit(BTN_7, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); + /* fall through */ + + case INTUOS3S: + __set_bit(BTN_0, input_dev->keybit); + __set_bit(BTN_1, input_dev->keybit); + __set_bit(BTN_2, input_dev->keybit); + __set_bit(BTN_3, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); + break; + + case INTUOS5: + case INTUOS5L: + case INTUOSPM: + case INTUOSPL: + __set_bit(BTN_7, input_dev->keybit); + __set_bit(BTN_8, input_dev->keybit); + /* fall through */ + + case INTUOS5S: + case INTUOSPS: + /* touch interface does not have the pad device */ + if (features->device_type != BTN_TOOL_PEN) + return 1; + + for (i = 0; i < 7; i++) + __set_bit(BTN_0 + i, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); + break; + + case INTUOS4: + case INTUOS4L: + __set_bit(BTN_7, input_dev->keybit); + __set_bit(BTN_8, input_dev->keybit); + /* fall through */ + + case INTUOS4S: + for (i = 0; i < 7; i++) + __set_bit(BTN_0 + i, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); + break; + + case CINTIQ_HYBRID: + for (i = 0; i < 9; i++) + __set_bit(BTN_0 + i, input_dev->keybit); + + break; + default: /* no pad supported */ return 1; From 3116871f427386933a1fcd87e831ea664cbd0bf2 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 12:50:10 -0700 Subject: [PATCH 05/37] Input: wacom - split out the pad device for Bamboos We rely on the return code of wacom_bpt*() to do the input_sync(). wacom_wac_irq() then properly sync the input devices. Signed-off-by: Benjamin Tissoires Reviewed-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 39 +++++++++++++++++++------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 8807ab511974..5aaa3d2e9afc 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1143,6 +1143,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; struct input_dev *input = wacom->input; + struct input_dev *pad_input = wacom->pad_input; unsigned char *data = wacom->data; int i; @@ -1177,14 +1178,12 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) input_mt_report_pointer_emulation(input, true); - input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); - input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0); - input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0); - input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0); + input_report_key(pad_input, BTN_LEFT, (data[1] & 0x08) != 0); + input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0); + input_report_key(pad_input, BTN_BACK, (data[1] & 0x02) != 0); + input_report_key(pad_input, BTN_RIGHT, (data[1] & 0x01) != 0); - input_sync(input); - - return 0; + return 1; } static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) @@ -1232,7 +1231,7 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data) { - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->pad_input; struct wacom_features *features = &wacom->features; if (features->type == INTUOSHT) { @@ -1269,9 +1268,7 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom) } input_mt_report_pointer_emulation(input, true); - input_sync(input); - - return 0; + return 1; } static int wacom_bpt_pen(struct wacom_wac *wacom) @@ -1806,11 +1803,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, if (features->device_type == BTN_TOOL_FINGER) { - __set_bit(BTN_LEFT, input_dev->keybit); - __set_bit(BTN_FORWARD, input_dev->keybit); - __set_bit(BTN_BACK, input_dev->keybit); - __set_bit(BTN_RIGHT, input_dev->keybit); - if (features->touch_max) { /* touch interface */ unsigned int flags = INPUT_MT_POINTER; @@ -1993,6 +1985,21 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, break; + case INTUOSHT: + case BAMBOO_PT: + /* pad device is on the touch interface */ + if (features->device_type != BTN_TOOL_FINGER) + return 1; + + __clear_bit(ABS_MISC, input_dev->absbit); + + __set_bit(BTN_LEFT, input_dev->keybit); + __set_bit(BTN_FORWARD, input_dev->keybit); + __set_bit(BTN_BACK, input_dev->keybit); + __set_bit(BTN_RIGHT, input_dev->keybit); + + break; + default: /* no pad supported */ return 1; From 422b0314b9f29a2c61d426fdaf1864556809ac1c Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 12:50:39 -0700 Subject: [PATCH 06/37] Input: wacom - split out the pad device for DTUS MSC_SERIAL can be safely removed from the pad device. Signed-off-by: Benjamin Tissoires Reviewed-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 5aaa3d2e9afc..d3aef3af1921 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -217,17 +217,13 @@ static int wacom_dtus_irq(struct wacom_wac *wacom) "%s: received unknown report #%d", __func__, data[0]); return 0; } else if (data[0] == WACOM_REPORT_DTUSPAD) { + input = wacom->pad_input; input_report_key(input, BTN_0, (data[1] & 0x01)); input_report_key(input, BTN_1, (data[1] & 0x02)); input_report_key(input, BTN_2, (data[1] & 0x04)); input_report_key(input, BTN_3, (data[1] & 0x08)); input_report_abs(input, ABS_MISC, data[1] & 0x0f ? PAD_DEVICE_ID : 0); - /* - * Serial number is required when expresskeys are - * reported through pen interface. - */ - input_event(input, EV_MSC, MSC_SERIAL, 0xf0); return 1; } else { prox = data[1] & 0x80; @@ -257,7 +253,6 @@ static int wacom_dtus_irq(struct wacom_wac *wacom) wacom->id[0] = 0; input_report_key(input, wacom->tool[0], prox); input_report_abs(input, ABS_MISC, wacom->id[0]); - input_event(input, EV_MSC, MSC_SERIAL, 1); return 1; } } @@ -1615,7 +1610,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { struct wacom_features *features = &wacom_wac->features; - int i; input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); @@ -1765,11 +1759,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case DTUS: case PL: case DTU: - if (features->type == DTUS) { - input_set_capability(input_dev, EV_MSC, MSC_SERIAL); - for (i = 0; i < 4; i++) - __set_bit(BTN_0 + i, input_dev->keybit); - } __set_bit(BTN_TOOL_PEN, input_dev->keybit); __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); __set_bit(BTN_STYLUS, input_dev->keybit); @@ -1985,6 +1974,11 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, break; + case DTUS: + for (i = 0; i < 4; i++) + __set_bit(BTN_0 + i, input_dev->keybit); + break; + case INTUOSHT: case BAMBOO_PT: /* pad device is on the touch interface */ From 3813810c7103f90eb2a0ec43fbd637265360c618 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 12:51:03 -0700 Subject: [PATCH 07/37] Input: wacom - split out the pad device for Graphire G4 and MO MSC_SERIAL can be safely removed from pad devices. If it is not here, xf86-input-wacom correctly generates ones for its internal use. Signed-off-by: Benjamin Tissoires Reviewed-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 44 ++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index d3aef3af1921..f170277b6f28 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -262,6 +262,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; struct input_dev *input = wacom->input; + struct input_dev *pad_input = wacom->pad_input; int prox; int rw = 0; int retval = 0; @@ -322,7 +323,6 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) wacom->id[0] = 0; input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */ input_report_key(input, wacom->tool[0], prox); - input_event(input, EV_MSC, MSC_SERIAL, 1); input_sync(input); /* sync last event */ } @@ -332,14 +332,13 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) prox = data[7] & 0xf8; if (prox || wacom->id[1]) { wacom->id[1] = PAD_DEVICE_ID; - input_report_key(input, BTN_BACK, (data[7] & 0x40)); - input_report_key(input, BTN_FORWARD, (data[7] & 0x80)); + input_report_key(pad_input, BTN_BACK, (data[7] & 0x40)); + input_report_key(pad_input, BTN_FORWARD, (data[7] & 0x80)); rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); - input_report_rel(input, REL_WHEEL, rw); + input_report_rel(pad_input, REL_WHEEL, rw); if (!prox) wacom->id[1] = 0; - input_report_abs(input, ABS_MISC, wacom->id[1]); - input_event(input, EV_MSC, MSC_SERIAL, 0xf0); + input_report_abs(pad_input, ABS_MISC, wacom->id[1]); retval = 1; } break; @@ -348,15 +347,14 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) prox = (data[7] & 0xf8) || data[8]; if (prox || wacom->id[1]) { wacom->id[1] = PAD_DEVICE_ID; - input_report_key(input, BTN_BACK, (data[7] & 0x08)); - input_report_key(input, BTN_LEFT, (data[7] & 0x20)); - input_report_key(input, BTN_FORWARD, (data[7] & 0x10)); - input_report_key(input, BTN_RIGHT, (data[7] & 0x40)); - input_report_abs(input, ABS_WHEEL, (data[8] & 0x7f)); + input_report_key(pad_input, BTN_BACK, (data[7] & 0x08)); + input_report_key(pad_input, BTN_LEFT, (data[7] & 0x20)); + input_report_key(pad_input, BTN_FORWARD, (data[7] & 0x10)); + input_report_key(pad_input, BTN_RIGHT, (data[7] & 0x40)); + input_report_abs(pad_input, ABS_WHEEL, (data[8] & 0x7f)); if (!prox) wacom->id[1] = 0; - input_report_abs(input, ABS_MISC, wacom->id[1]); - input_event(input, EV_MSC, MSC_SERIAL, 0xf0); + input_report_abs(pad_input, ABS_MISC, wacom->id[1]); retval = 1; } break; @@ -1624,10 +1622,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, /* fall through */ case WACOM_G4: - input_set_capability(input_dev, EV_MSC, MSC_SERIAL); - - __set_bit(BTN_BACK, input_dev->keybit); - __set_bit(BTN_FORWARD, input_dev->keybit); /* fall through */ case GRAPHIRE: @@ -1854,6 +1848,22 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0); switch (features->type) { + case WACOM_MO: + __set_bit(BTN_BACK, input_dev->keybit); + __set_bit(BTN_LEFT, input_dev->keybit); + __set_bit(BTN_FORWARD, input_dev->keybit); + __set_bit(BTN_RIGHT, input_dev->keybit); + input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); + break; + + case WACOM_G4: + __set_bit(BTN_BACK, input_dev->keybit); + __set_bit(BTN_LEFT, input_dev->keybit); + __set_bit(BTN_FORWARD, input_dev->keybit); + __set_bit(BTN_RIGHT, input_dev->keybit); + input_set_capability(input_dev, EV_REL, REL_WHEEL); + break; + case WACOM_24HD: __set_bit(BTN_A, input_dev->keybit); __set_bit(BTN_B, input_dev->keybit); From 008f4d9e3cd666c1c4f97b53c102a868a6041f64 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 12:51:26 -0700 Subject: [PATCH 08/37] Input: wacom - split out the pad device for the wireless receiver The Wireless Receiver should also behave in the same way than regular USB devices. To simplify the unregistering of the different devices, wacom_unregister_inputs() is introduced. For consistency, the function wacom_register_input() is renamed into wacom_register_inputs(). Signed-off-by: Benjamin Tissoires Reviewed-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 46 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index b25848581fc1..dd0dbc250c94 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -1142,7 +1142,17 @@ static struct input_dev *wacom_allocate_input(struct wacom *wacom) return input_dev; } -static int wacom_register_input(struct wacom *wacom) +static void wacom_unregister_inputs(struct wacom *wacom) +{ + if (wacom->wacom_wac.input) + input_unregister_device(wacom->wacom_wac.input); + if (wacom->wacom_wac.pad_input) + input_unregister_device(wacom->wacom_wac.pad_input); + wacom->wacom_wac.input = NULL; + wacom->wacom_wac.pad_input = NULL; +} + +static int wacom_register_inputs(struct wacom *wacom) { struct input_dev *input_dev, *pad_input_dev; struct wacom_wac *wacom_wac = &(wacom->wacom_wac); @@ -1214,16 +1224,12 @@ static void wacom_wireless_work(struct work_struct *work) /* Stylus interface */ wacom1 = usb_get_intfdata(usbdev->config->interface[1]); wacom_wac1 = &(wacom1->wacom_wac); - if (wacom_wac1->input) - input_unregister_device(wacom_wac1->input); - wacom_wac1->input = NULL; + wacom_unregister_inputs(wacom1); /* Touch interface */ wacom2 = usb_get_intfdata(usbdev->config->interface[2]); wacom_wac2 = &(wacom2->wacom_wac); - if (wacom_wac2->input) - input_unregister_device(wacom_wac2->input); - wacom_wac2->input = NULL; + wacom_unregister_inputs(wacom2); if (wacom_wac->pid == 0) { dev_info(&wacom->intf->dev, "wireless tablet disconnected\n"); @@ -1253,9 +1259,11 @@ static void wacom_wireless_work(struct work_struct *work) wacom_wac1->features.device_type = BTN_TOOL_PEN; snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen", wacom_wac1->features.name); + snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad", + wacom_wac1->features.name); wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max; wacom_wac1->shared->type = wacom_wac1->features.type; - error = wacom_register_input(wacom1); + error = wacom_register_inputs(wacom1); if (error) goto fail; @@ -1273,7 +1281,9 @@ static void wacom_wireless_work(struct work_struct *work) else snprintf(wacom_wac2->name, WACOM_NAME_MAX, "%s (WL) Pad",wacom_wac2->features.name); - error = wacom_register_input(wacom2); + snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX, + "%s (WL) Pad", wacom_wac2->features.name); + error = wacom_register_inputs(wacom2); if (error) goto fail; @@ -1290,15 +1300,8 @@ static void wacom_wireless_work(struct work_struct *work) return; fail: - if (wacom_wac2->input) { - input_unregister_device(wacom_wac2->input); - wacom_wac2->input = NULL; - } - - if (wacom_wac1->input) { - input_unregister_device(wacom_wac1->input); - wacom_wac1->input = NULL; - } + wacom_unregister_inputs(wacom1); + wacom_unregister_inputs(wacom2); return; } @@ -1444,7 +1447,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i goto fail4; if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) { - error = wacom_register_input(wacom); + error = wacom_register_inputs(wacom); if (error) goto fail5; } @@ -1484,10 +1487,7 @@ static void wacom_disconnect(struct usb_interface *intf) usb_kill_urb(wacom->irq); cancel_work_sync(&wacom->work); - if (wacom->wacom_wac.input) - input_unregister_device(wacom->wacom_wac.input); - if (wacom->wacom_wac.pad_input) - input_unregister_device(wacom->wacom_wac.pad_input); + wacom_unregister_inputs(wacom); wacom_destroy_battery(wacom); wacom_destroy_leds(wacom); usb_free_urb(wacom->irq); From f54bc61cf7236db84939ca8827ac89737d79ef24 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 12:52:00 -0700 Subject: [PATCH 09/37] Input: wacom - include and use linux/hid.h The current wacom code redefines constants that are already in linux/hid.h This patch includes the official implementation and use it accross the code. There is a conflict with HID_USAGE and others at the same level: - in the wacom.ko implementation, those are the #define regarding the value of the field in the report descriptor - in the hid.h, those are bitmask So add HDESC_ in their current definition. Also, the struct hid_descriptor slightly differs from the linux/hid.h point of view, so mark it as custom for this driver. Signed-off-by: Benjamin Tissoires Reviewed-by: Jason Gerecke Tested-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 51 +++++++++++++------------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index dd0dbc250c94..c34791e7f0b9 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -13,28 +13,19 @@ #include "wacom_wac.h" #include "wacom.h" +#include /* defines to get HID report descriptor */ #define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01) #define HID_DEVICET_REPORT (USB_TYPE_CLASS | 0x02) -#define HID_USAGE_UNDEFINED 0x00 -#define HID_USAGE_PAGE 0x05 -#define HID_USAGE_PAGE_DIGITIZER 0x0d -#define HID_USAGE_PAGE_DESKTOP 0x01 -#define HID_USAGE 0x09 -#define HID_USAGE_X ((HID_USAGE_PAGE_DESKTOP << 16) | 0x30) -#define HID_USAGE_Y ((HID_USAGE_PAGE_DESKTOP << 16) | 0x31) -#define HID_USAGE_PRESSURE ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x30) -#define HID_USAGE_X_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3d) -#define HID_USAGE_Y_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3e) -#define HID_USAGE_FINGER ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x22) -#define HID_USAGE_STYLUS ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x20) -#define HID_USAGE_CONTACTMAX ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x55) -#define HID_COLLECTION 0xa1 -#define HID_COLLECTION_LOGICAL 0x02 -#define HID_COLLECTION_END 0xc0 +#define HID_HDESC_USAGE_UNDEFINED 0x00 +#define HID_HDESC_USAGE_PAGE 0x05 +#define HID_HDESC_USAGE 0x09 +#define HID_HDESC_COLLECTION 0xa1 +#define HID_HDESC_COLLECTION_LOGICAL 0x02 +#define HID_HDESC_COLLECTION_END 0xc0 -struct hid_descriptor { +struct wac_hid_descriptor { struct usb_descriptor_header header; __le16 bcdHID; u8 bCountryCode; @@ -301,7 +292,7 @@ static void wacom_retrieve_report_data(struct usb_interface *intf, * this after returning from this function. */ static int wacom_parse_hid(struct usb_interface *intf, - struct hid_descriptor *hid_desc, + struct wac_hid_descriptor *hid_desc, struct wacom_features *features) { struct usb_device *dev = interface_to_usbdev(intf); @@ -334,14 +325,14 @@ static int wacom_parse_hid(struct usb_interface *intf, for (i = 0; i < hid_desc->wDescriptorLength; i++) { switch (report[i]) { - case HID_USAGE_PAGE: + case HID_HDESC_USAGE_PAGE: page = report[i + 1]; i++; break; - case HID_USAGE: + case HID_HDESC_USAGE: switch (page << 16 | report[i + 1]) { - case HID_USAGE_X: + case HID_GD_X: if (finger) { features->device_type = BTN_TOOL_FINGER; /* touch device at least supports one touch point */ @@ -420,7 +411,7 @@ static int wacom_parse_hid(struct usb_interface *intf, } break; - case HID_USAGE_Y: + case HID_GD_Y: if (finger) { switch (features->type) { case TABLETPC2FG: @@ -472,7 +463,7 @@ static int wacom_parse_hid(struct usb_interface *intf, } break; - case HID_USAGE_FINGER: + case HID_DG_FINGER: finger = 1; i++; break; @@ -482,19 +473,19 @@ static int wacom_parse_hid(struct usb_interface *intf, * X/Y values and some cases of invalid Digitizer X/Y * values commonly reported. */ - case HID_USAGE_STYLUS: + case HID_DG_STYLUS: pen = 1; i++; break; - case HID_USAGE_CONTACTMAX: + case HID_DG_CONTACTMAX: /* leave touch_max as is if predefined */ if (!features->touch_max) wacom_retrieve_report_data(intf, features); i++; break; - case HID_USAGE_PRESSURE: + case HID_DG_TIPPRESSURE: if (pen) { features->pressure_max = get_unaligned_le16(&report[i + 3]); @@ -504,15 +495,15 @@ static int wacom_parse_hid(struct usb_interface *intf, } break; - case HID_COLLECTION_END: + case HID_HDESC_COLLECTION_END: /* reset UsagePage and Finger */ finger = page = 0; break; - case HID_COLLECTION: + case HID_HDESC_COLLECTION: i++; switch (report[i]) { - case HID_COLLECTION_LOGICAL: + case HID_HDESC_COLLECTION_LOGICAL: i += wacom_parse_logical_collection(&report[i], features); break; @@ -585,7 +576,7 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, { int error = 0; struct usb_host_interface *interface = intf->cur_altsetting; - struct hid_descriptor *hid_desc; + struct wac_hid_descriptor *hid_desc; /* default features */ features->device_type = BTN_TOOL_PEN; From 29b4739134c73a2873adec93346f09bb76d6a794 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 12:52:23 -0700 Subject: [PATCH 10/37] Input: wacom - switch from an USB driver to a HID driver All USB Wacom tablets are actually HID devices. For historical reasons, they are handled as plain USB devices. The current code makes more and more reference to the HID subsystem like implementing its own HID report descriptor parser to handle new devices. From the user point of view, we can transparently switch from this state to a driver handled in the HID subsystem and clean up a lot of USB specific code in the wacom.ko driver. The other benefit once the USB dependecies have been removed is that we can use a tool like uhid to make regression tests and allow further cleanup or new implementations without risking breaking current behaviors. To match the current handling of devices in wacom_wac.c, we rely on the hid_type set by usbhid. usbhid sets the hid_type to HID_TYPE_USBMOUSE when it sees a USB boot mouse protocol declared and HID_TYPE_USBNONE when the device is plain HID. There is thus a one to one matching between the list of supported devices before and after the switch from USB to HID. Signed-off-by: Benjamin Tissoires Reviewed-by: Jason Gerecke Tested-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/hid/hid-core.c | 10 +- drivers/hid/hid-wacom.c | 2 +- drivers/input/tablet/wacom.h | 6 +- drivers/input/tablet/wacom_sys.c | 232 ++++++++++++------------------- drivers/input/tablet/wacom_wac.c | 80 +++++------ drivers/input/tablet/wacom_wac.h | 4 +- include/linux/hid.h | 5 + 7 files changed, 146 insertions(+), 193 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 8ed66fd1ea87..1ce751db5a7a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -787,6 +787,15 @@ static int hid_scan_report(struct hid_device *hid) /* hid-rmi should take care of them, not hid-generic */ hid->group = HID_GROUP_RMI; + /* + * Vendor specific handlings + */ + switch (hid->vendor) { + case USB_VENDOR_ID_WACOM: + hid->group = HID_GROUP_WACOM; + break; + } + vfree(parser); return 0; } @@ -2339,7 +2348,6 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) }, { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WACOM, HID_ANY_ID) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT) }, diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 902013ec041b..4874f4ec43f5 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -960,7 +960,7 @@ static const struct hid_device_id wacom_devices[] = { MODULE_DEVICE_TABLE(hid, wacom_devices); static struct hid_driver wacom_driver = { - .name = "wacom", + .name = "hid-wacom", .id_table = wacom_devices, .probe = wacom_probe, .remove = wacom_remove, diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index caa59cab2c5f..b9212390db71 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h @@ -106,14 +106,12 @@ MODULE_LICENSE(DRIVER_LICENSE); #define USB_VENDOR_ID_LENOVO 0x17ef struct wacom { - dma_addr_t data_dma; struct usb_device *usbdev; struct usb_interface *intf; - struct urb *irq; struct wacom_wac wacom_wac; + struct hid_device *hdev; struct mutex lock; struct work_struct work; - bool open; char phys[32]; struct wacom_led { u8 select[2]; /* status led selector (0..3) */ @@ -130,7 +128,7 @@ static inline void wacom_schedule_work(struct wacom_wac *wacom_wac) schedule_work(&wacom->work); } -extern const struct usb_device_id wacom_ids[]; +extern const struct hid_device_id wacom_ids[]; void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); void wacom_setup_device_quirks(struct wacom_features *features); diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index c34791e7f0b9..5ceeab6e95f1 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -83,86 +83,40 @@ static int wacom_set_report(struct usb_interface *intf, u8 type, u8 id, return retval; } -static void wacom_sys_irq(struct urb *urb) +static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, + u8 *raw_data, int size) { - struct wacom *wacom = urb->context; - struct device *dev = &wacom->intf->dev; - int retval; + struct wacom *wacom = hid_get_drvdata(hdev); - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dev_dbg(dev, "%s - urb shutting down with status: %d\n", - __func__, urb->status); - return; - default: - dev_dbg(dev, "%s - nonzero urb status received: %d\n", - __func__, urb->status); - goto exit; - } + if (size > WACOM_PKGLEN_MAX) + return 1; - wacom_wac_irq(&wacom->wacom_wac, urb->actual_length); + memcpy(wacom->wacom_wac.data, raw_data, size); - exit: - usb_mark_last_busy(wacom->usbdev); - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "%s - usb_submit_urb failed with result %d\n", - __func__, retval); + wacom_wac_irq(&wacom->wacom_wac, size); + + return 0; } static int wacom_open(struct input_dev *dev) { struct wacom *wacom = input_get_drvdata(dev); - int retval = 0; - - if (usb_autopm_get_interface(wacom->intf) < 0) - return -EIO; + int retval; mutex_lock(&wacom->lock); - - if (wacom->open) - goto out; - - if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { - retval = -EIO; - goto out; - } - - wacom->open = true; - wacom->intf->needs_remote_wakeup = 1; - -out: + retval = hid_hw_open(wacom->hdev); mutex_unlock(&wacom->lock); - usb_autopm_put_interface(wacom->intf); + return retval; } static void wacom_close(struct input_dev *dev) { struct wacom *wacom = input_get_drvdata(dev); - int autopm_error; - - autopm_error = usb_autopm_get_interface(wacom->intf); mutex_lock(&wacom->lock); - if (!wacom->open) - goto out; - - usb_kill_urb(wacom->irq); - wacom->open = false; - wacom->intf->needs_remote_wakeup = 0; - -out: + hid_hw_close(wacom->hdev); mutex_unlock(&wacom->lock); - - if (!autopm_error) - usb_autopm_put_interface(wacom->intf); } /* @@ -807,7 +761,8 @@ out: static ssize_t wacom_led_select_store(struct device *dev, int set_id, const char *buf, size_t count) { - struct wacom *wacom = dev_get_drvdata(dev); + struct hid_device *hdev = dev_get_drvdata(dev); + struct wacom *wacom = hid_get_drvdata(hdev); unsigned int id; int err; @@ -834,7 +789,8 @@ static ssize_t wacom_led##SET_ID##_select_store(struct device *dev, \ static ssize_t wacom_led##SET_ID##_select_show(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ - struct wacom *wacom = dev_get_drvdata(dev); \ + struct hid_device *hdev = dev_get_drvdata(dev); \ + struct wacom *wacom = hid_get_drvdata(hdev); \ return snprintf(buf, 2, "%d\n", wacom->led.select[SET_ID]); \ } \ static DEVICE_ATTR(status_led##SET_ID##_select, S_IWUSR | S_IRUSR, \ @@ -868,7 +824,8 @@ static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest, static ssize_t wacom_##name##_luminance_store(struct device *dev, \ struct device_attribute *attr, const char *buf, size_t count) \ { \ - struct wacom *wacom = dev_get_drvdata(dev); \ + struct hid_device *hdev = dev_get_drvdata(dev); \ + struct wacom *wacom = hid_get_drvdata(hdev); \ \ return wacom_luminance_store(wacom, &wacom->led.field, \ buf, count); \ @@ -883,7 +840,8 @@ DEVICE_LUMINANCE_ATTR(buttons, img_lum); static ssize_t wacom_button_image_store(struct device *dev, int button_id, const char *buf, size_t count) { - struct wacom *wacom = dev_get_drvdata(dev); + struct hid_device *hdev = dev_get_drvdata(dev); + struct wacom *wacom = hid_get_drvdata(hdev); int err; if (count != 1024) @@ -1201,6 +1159,7 @@ static void wacom_wireless_work(struct work_struct *work) struct wacom *wacom = container_of(work, struct wacom, work); struct usb_device *usbdev = wacom->usbdev; struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct hid_device *hdev1, *hdev2; struct wacom *wacom1, *wacom2; struct wacom_wac *wacom_wac1, *wacom_wac2; int error; @@ -1213,32 +1172,34 @@ static void wacom_wireless_work(struct work_struct *work) wacom_destroy_battery(wacom); /* Stylus interface */ - wacom1 = usb_get_intfdata(usbdev->config->interface[1]); + hdev1 = usb_get_intfdata(usbdev->config->interface[1]); + wacom1 = hid_get_drvdata(hdev1); wacom_wac1 = &(wacom1->wacom_wac); wacom_unregister_inputs(wacom1); /* Touch interface */ - wacom2 = usb_get_intfdata(usbdev->config->interface[2]); + hdev2 = usb_get_intfdata(usbdev->config->interface[2]); + wacom2 = hid_get_drvdata(hdev2); wacom_wac2 = &(wacom2->wacom_wac); wacom_unregister_inputs(wacom2); if (wacom_wac->pid == 0) { dev_info(&wacom->intf->dev, "wireless tablet disconnected\n"); } else { - const struct usb_device_id *id = wacom_ids; + const struct hid_device_id *id = wacom_ids; dev_info(&wacom->intf->dev, "wireless tablet connected with PID %x\n", wacom_wac->pid); - while (id->match_flags) { - if (id->idVendor == USB_VENDOR_ID_WACOM && - id->idProduct == wacom_wac->pid) + while (id->bus) { + if (id->vendor == USB_VENDOR_ID_WACOM && + id->product == wacom_wac->pid) break; id++; } - if (!id->match_flags) { + if (!id->bus) { dev_info(&wacom->intf->dev, "ignoring unknown PID.\n"); return; @@ -1246,7 +1207,7 @@ static void wacom_wireless_work(struct work_struct *work) /* Stylus interface */ wacom_wac1->features = - *((struct wacom_features *)id->driver_info); + *((struct wacom_features *)id->driver_data); wacom_wac1->features.device_type = BTN_TOOL_PEN; snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen", wacom_wac1->features.name); @@ -1262,7 +1223,7 @@ static void wacom_wireless_work(struct work_struct *work) if (wacom_wac1->features.touch_max || wacom_wac1->features.type == INTUOSHT) { wacom_wac2->features = - *((struct wacom_features *)id->driver_info); + *((struct wacom_features *)id->driver_data); wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; wacom_wac2->features.device_type = BTN_TOOL_FINGER; wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096; @@ -1323,8 +1284,10 @@ static void wacom_calculate_res(struct wacom_features *features) features->unitExpo); } -static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) +static int wacom_probe(struct hid_device *hdev, + const struct hid_device_id *id) { + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); struct usb_device *dev = interface_to_usbdev(intf); struct usb_endpoint_descriptor *endpoint; struct wacom *wacom; @@ -1332,34 +1295,29 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i struct wacom_features *features; int error; - if (!id->driver_info) + if (!id->driver_data) return -EINVAL; wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); if (!wacom) return -ENOMEM; + hid_set_drvdata(hdev, wacom); + wacom->hdev = hdev; + wacom_wac = &wacom->wacom_wac; - wacom_wac->features = *((struct wacom_features *)id->driver_info); + wacom_wac->features = *((struct wacom_features *)id->driver_data); features = &wacom_wac->features; if (features->pktlen > WACOM_PKGLEN_MAX) { error = -EINVAL; goto fail1; } - wacom_wac->data = usb_alloc_coherent(dev, WACOM_PKGLEN_MAX, - GFP_KERNEL, &wacom->data_dma); - if (!wacom_wac->data) { - error = -ENOMEM; + if (features->check_for_hid_type && features->hid_type != hdev->type) { + error = -ENODEV; goto fail1; } - wacom->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!wacom->irq) { - error = -ENOMEM; - goto fail2; - } - wacom->usbdev = dev; wacom->intf = intf; mutex_init(&wacom->lock); @@ -1375,7 +1333,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i /* Retrieve the physical and logical size for touch devices */ error = wacom_retrieve_hid_descriptor(intf, features); if (error) - goto fail3; + goto fail1; /* * Intuos5 has no useful data about its touch interface in its @@ -1423,38 +1381,38 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i other_dev = dev; error = wacom_add_shared_data(wacom_wac, other_dev); if (error) - goto fail3; + goto fail1; } - usb_fill_int_urb(wacom->irq, dev, - usb_rcvintpipe(dev, endpoint->bEndpointAddress), - wacom_wac->data, features->pktlen, - wacom_sys_irq, wacom, endpoint->bInterval); - wacom->irq->transfer_dma = wacom->data_dma; - wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - error = wacom_initialize_leds(wacom); if (error) - goto fail4; + goto fail2; if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) { error = wacom_register_inputs(wacom); if (error) - goto fail5; + goto fail3; } /* Note that if query fails it is not a hard failure */ wacom_query_tablet_data(intf, features); - usb_set_intfdata(intf, wacom); - - if (features->quirks & WACOM_QUIRK_MONITOR) { - if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { - error = -EIO; - goto fail5; - } + /* Regular HID work starts now */ + error = hid_parse(hdev); + if (error) { + hid_err(hdev, "parse failed\n"); + goto fail4; } + error = hid_hw_start(hdev, HID_CONNECT_HIDRAW); + if (error) { + hid_err(hdev, "hw start failed\n"); + goto fail4; + } + + if (features->quirks & WACOM_QUIRK_MONITOR) + error = hid_hw_open(hdev); + if (wacom_wac->features.type == INTUOSHT && wacom_wac->features.touch_max) { if (wacom_wac->features.device_type == BTN_TOOL_FINGER) wacom_wac->shared->touch_input = wacom_wac->input; @@ -1462,78 +1420,60 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i return 0; - fail5: wacom_destroy_leds(wacom); - fail4: wacom_remove_shared_data(wacom_wac); - fail3: usb_free_urb(wacom->irq); - fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); + fail4: wacom_unregister_inputs(wacom); + fail3: wacom_destroy_leds(wacom); + fail2: wacom_remove_shared_data(wacom_wac); fail1: kfree(wacom); + hid_set_drvdata(hdev, NULL); return error; } -static void wacom_disconnect(struct usb_interface *intf) +static void wacom_remove(struct hid_device *hdev) { - struct wacom *wacom = usb_get_intfdata(intf); + struct wacom *wacom = hid_get_drvdata(hdev); - usb_set_intfdata(intf, NULL); + hid_hw_stop(hdev); - usb_kill_urb(wacom->irq); cancel_work_sync(&wacom->work); wacom_unregister_inputs(wacom); wacom_destroy_battery(wacom); wacom_destroy_leds(wacom); - usb_free_urb(wacom->irq); - usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, - wacom->wacom_wac.data, wacom->data_dma); wacom_remove_shared_data(&wacom->wacom_wac); + + hid_set_drvdata(hdev, NULL); kfree(wacom); } -static int wacom_suspend(struct usb_interface *intf, pm_message_t message) +static int wacom_resume(struct hid_device *hdev) { - struct wacom *wacom = usb_get_intfdata(intf); + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_features *features = &wacom->wacom_wac.features; mutex_lock(&wacom->lock); - usb_kill_urb(wacom->irq); + + /* switch to wacom mode first */ + wacom_query_tablet_data(wacom->intf, features); + wacom_led_control(wacom); + mutex_unlock(&wacom->lock); return 0; } -static int wacom_resume(struct usb_interface *intf) +static int wacom_reset_resume(struct hid_device *hdev) { - struct wacom *wacom = usb_get_intfdata(intf); - struct wacom_features *features = &wacom->wacom_wac.features; - int rv = 0; - - mutex_lock(&wacom->lock); - - /* switch to wacom mode first */ - wacom_query_tablet_data(intf, features); - wacom_led_control(wacom); - - if ((wacom->open || (features->quirks & WACOM_QUIRK_MONITOR)) && - usb_submit_urb(wacom->irq, GFP_NOIO) < 0) - rv = -EIO; - - mutex_unlock(&wacom->lock); - - return rv; + return wacom_resume(hdev); } -static int wacom_reset_resume(struct usb_interface *intf) -{ - return wacom_resume(intf); -} - -static struct usb_driver wacom_driver = { +static struct hid_driver wacom_driver = { .name = "wacom", .id_table = wacom_ids, .probe = wacom_probe, - .disconnect = wacom_disconnect, - .suspend = wacom_suspend, + .remove = wacom_remove, +#ifdef CONFIG_PM .resume = wacom_resume, .reset_resume = wacom_reset_resume, - .supports_autosuspend = 1, +#endif + .raw_event = wacom_raw_event, }; - -module_usb_driver(wacom_driver); +module_hid_driver(wacom_driver); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index f170277b6f28..1c95ce78d749 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -2197,15 +2197,18 @@ static const struct wacom_features wacom_features_0x2A = static const struct wacom_features wacom_features_0x314 = { "Wacom Intuos Pro S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, 63, INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, - .touch_max = 16 }; + .touch_max = 16, + .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x315 = { "Wacom Intuos Pro M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, - .touch_max = 16 }; + .touch_max = 16, + .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x317 = { "Wacom Intuos Pro L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, 63, INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, - .touch_max = 16 }; + .touch_max = 16, + .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0xF4 = { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104280, 65400, 2047, 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; @@ -2215,7 +2218,8 @@ static const struct wacom_features wacom_features_0xF8 = .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 }; static const struct wacom_features wacom_features_0xF6 = { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ - .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10 }; + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10, + .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x3F = { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; @@ -2233,7 +2237,8 @@ static const struct wacom_features wacom_features_0xC7 = 0, PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xCE = { "Wacom DTU2231", WACOM_PKGLEN_GRAPHIRE, 47864, 27011, 511, - 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + .check_for_hid_type = true, .hid_type = HID_TYPE_USBMOUSE }; static const struct wacom_features wacom_features_0xF0 = { "Wacom DTU1631", WACOM_PKGLEN_GRAPHIRE, 34623, 19553, 511, 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -2249,7 +2254,8 @@ static const struct wacom_features wacom_features_0x59 = /* Pen */ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D }; static const struct wacom_features wacom_features_0x5D = /* Touch */ { "Wacom DTH2242", .type = WACOM_24HDT, - .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10 }; + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10, + .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0xCC = { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87000, 65400, 2047, 63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; @@ -2262,7 +2268,8 @@ static const struct wacom_features wacom_features_0x5B = .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e }; static const struct wacom_features wacom_features_0x5E = { "Wacom Cintiq 22HDT", .type = WACOM_24HDT, - .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5b, .touch_max = 10 }; + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5b, .touch_max = 10, + .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x90 = { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -2400,14 +2407,17 @@ static const struct wacom_features wacom_features_0x301 = static const struct wacom_features wacom_features_0x302 = { "Wacom Intuos PT S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023, 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 16 }; + .touch_max = 16, + .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x303 = { "Wacom Intuos PT M", WACOM_PKGLEN_BBPEN, 21600, 13500, 1023, 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 16 }; + .touch_max = 16, + .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x30E = { "Wacom Intuos S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023, - 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x6004 = { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -2417,22 +2427,18 @@ static const struct wacom_features wacom_features_0x0307 = .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 }; static const struct wacom_features wacom_features_0x0309 = { "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */ - .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10 }; + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10, + .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; -#define USB_DEVICE_WACOM(prod) \ - USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ - .driver_info = (kernel_ulong_t)&wacom_features_##prod - -#define USB_DEVICE_DETAILED(prod, class, sub, proto) \ - USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_WACOM, prod, class, \ - sub, proto), \ - .driver_info = (kernel_ulong_t)&wacom_features_##prod +#define USB_DEVICE_WACOM(prod) \ + HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\ + .driver_data = (kernel_ulong_t)&wacom_features_##prod #define USB_DEVICE_LENOVO(prod) \ - USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \ - .driver_info = (kernel_ulong_t)&wacom_features_##prod + HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \ + .driver_data = (kernel_ulong_t)&wacom_features_##prod -const struct usb_device_id wacom_ids[] = { +const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x00) }, { USB_DEVICE_WACOM(0x10) }, { USB_DEVICE_WACOM(0x11) }, @@ -2478,9 +2484,9 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x45) }, { USB_DEVICE_WACOM(0x57) }, { USB_DEVICE_WACOM(0x59) }, - { USB_DEVICE_DETAILED(0x5D, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_WACOM(0x5D) }, { USB_DEVICE_WACOM(0x5B) }, - { USB_DEVICE_DETAILED(0x5E, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_WACOM(0x5E) }, { USB_DEVICE_WACOM(0xB0) }, { USB_DEVICE_WACOM(0xB1) }, { USB_DEVICE_WACOM(0xB2) }, @@ -2502,13 +2508,7 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xC5) }, { USB_DEVICE_WACOM(0xC6) }, { USB_DEVICE_WACOM(0xC7) }, - /* - * DTU-2231 has two interfaces on the same configuration, - * only one is used. - */ - { USB_DEVICE_DETAILED(0xCE, USB_CLASS_HID, - USB_INTERFACE_SUBCLASS_BOOT, - USB_INTERFACE_PROTOCOL_MOUSE) }, + { USB_DEVICE_WACOM(0xCE) }, { USB_DEVICE_WACOM(0x84) }, { USB_DEVICE_WACOM(0xD0) }, { USB_DEVICE_WACOM(0xD1) }, @@ -2546,13 +2546,13 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x116) }, { USB_DEVICE_WACOM(0x300) }, { USB_DEVICE_WACOM(0x301) }, - { USB_DEVICE_DETAILED(0x302, USB_CLASS_HID, 0, 0) }, - { USB_DEVICE_DETAILED(0x303, USB_CLASS_HID, 0, 0) }, - { USB_DEVICE_DETAILED(0x30E, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_WACOM(0x302) }, + { USB_DEVICE_WACOM(0x303) }, + { USB_DEVICE_WACOM(0x30E) }, { USB_DEVICE_WACOM(0x304) }, - { USB_DEVICE_DETAILED(0x314, USB_CLASS_HID, 0, 0) }, - { USB_DEVICE_DETAILED(0x315, USB_CLASS_HID, 0, 0) }, - { USB_DEVICE_DETAILED(0x317, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_WACOM(0x314) }, + { USB_DEVICE_WACOM(0x315) }, + { USB_DEVICE_WACOM(0x317) }, { USB_DEVICE_WACOM(0x4001) }, { USB_DEVICE_WACOM(0x4004) }, { USB_DEVICE_WACOM(0x5000) }, @@ -2560,12 +2560,12 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0xF4) }, { USB_DEVICE_WACOM(0xF8) }, - { USB_DEVICE_DETAILED(0xF6, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_WACOM(0xF6) }, { USB_DEVICE_WACOM(0xFA) }, { USB_DEVICE_WACOM(0xFB) }, { USB_DEVICE_WACOM(0x0307) }, - { USB_DEVICE_DETAILED(0x0309, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_WACOM(0x0309) }, { USB_DEVICE_LENOVO(0x6004) }, { } }; -MODULE_DEVICE_TABLE(usb, wacom_ids); +MODULE_DEVICE_TABLE(hid, wacom_ids); diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index f48164c780f4..8821a518abf6 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -137,6 +137,8 @@ struct wacom_features { unsigned touch_max; int oVid; int oPid; + bool check_for_hid_type; + int hid_type; }; struct wacom_shared { @@ -151,7 +153,7 @@ struct wacom_shared { struct wacom_wac { char name[WACOM_NAME_MAX]; char pad_name[WACOM_NAME_MAX]; - unsigned char *data; + unsigned char data[WACOM_PKGLEN_MAX]; int tool[2]; int id[2]; __u32 serial[2]; diff --git a/include/linux/hid.h b/include/linux/hid.h index 77632cf159c0..07fa80671db0 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -310,6 +310,11 @@ struct hid_item { */ #define HID_GROUP_RMI 0x0100 +/* + * Vendor specific HID device groups + */ +#define HID_GROUP_WACOM 0x0101 + /* * This is the global environment of the parser. This information is * persistent for main-items. The global environment can be saved and From 27b20a9dec0cb1a4cc0517b94302875800191e34 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 12:56:22 -0700 Subject: [PATCH 11/37] Input: wacom - use hid communication instead of plain usb Wacom.ko was a plain USB driver for a HID device. The communications from/to the devices can actually be replaced with the HID API. At the USB level, the reports are exactly the same. This will allow to use uhid virtual devices instead of true USB devices. This step is necessary to implement regression tests. Signed-off-by: Benjamin Tissoires Reviewed-by: Jason Gerecke Tested-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 81 ++++++++++++++------------------ 1 file changed, 36 insertions(+), 45 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 5ceeab6e95f1..120ab1b5df3c 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -34,11 +34,6 @@ struct wac_hid_descriptor { __le16 wDescriptorLength; } __attribute__ ((packed)); -/* defines to get/set USB message */ -#define USB_REQ_GET_REPORT 0x01 -#define USB_REQ_SET_REPORT 0x09 - -#define WAC_HID_FEATURE_REPORT 0x03 #define WAC_MSG_RETRIES 5 #define WAC_CMD_LED_CONTROL 0x20 @@ -46,38 +41,27 @@ struct wac_hid_descriptor { #define WAC_CMD_ICON_XFER 0x23 #define WAC_CMD_RETRIES 10 -static int wacom_get_report(struct usb_interface *intf, u8 type, u8 id, +static int wacom_get_report(struct hid_device *hdev, u8 type, u8 id, void *buf, size_t size, unsigned int retries) { - struct usb_device *dev = interface_to_usbdev(intf); int retval; do { - retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_REPORT, - USB_DIR_IN | USB_TYPE_CLASS | - USB_RECIP_INTERFACE, - (type << 8) + id, - intf->altsetting[0].desc.bInterfaceNumber, - buf, size, 100); + retval = hid_hw_raw_request(hdev, id, buf, size, type, + HID_REQ_GET_REPORT); } while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries); return retval; } -static int wacom_set_report(struct usb_interface *intf, u8 type, u8 id, +static int wacom_set_report(struct hid_device *hdev, u8 type, u8 id, void *buf, size_t size, unsigned int retries) { - struct usb_device *dev = interface_to_usbdev(intf); int retval; do { - retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_REPORT, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, - (type << 8) + id, - intf->altsetting[0].desc.bInterfaceNumber, - buf, size, 1000); + retval = hid_hw_raw_request(hdev, id, buf, size, type, + HID_REQ_SET_REPORT); } while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries); return retval; @@ -188,7 +172,7 @@ static int wacom_parse_logical_collection(unsigned char *report, return length; } -static void wacom_retrieve_report_data(struct usb_interface *intf, +static void wacom_retrieve_report_data(struct hid_device *hdev, struct wacom_features *features) { int result = 0; @@ -198,7 +182,7 @@ static void wacom_retrieve_report_data(struct usb_interface *intf, if (rep_data) { rep_data[0] = 12; - result = wacom_get_report(intf, WAC_HID_FEATURE_REPORT, + result = wacom_get_report(hdev, HID_FEATURE_REPORT, rep_data[0], rep_data, 2, WAC_MSG_RETRIES); @@ -245,10 +229,12 @@ static void wacom_retrieve_report_data(struct usb_interface *intf, * Intuos5 touch interface does not contain useful data. We deal with * this after returning from this function. */ -static int wacom_parse_hid(struct usb_interface *intf, +static int wacom_parse_hid(struct hid_device *hdev, struct wac_hid_descriptor *hid_desc, struct wacom_features *features) { + struct wacom *wacom = hid_get_drvdata(hdev); + struct usb_interface *intf = wacom->intf; struct usb_device *dev = interface_to_usbdev(intf); char limit = 0; /* result has to be defined as int for some devices */ @@ -435,7 +421,7 @@ static int wacom_parse_hid(struct usb_interface *intf, case HID_DG_CONTACTMAX: /* leave touch_max as is if predefined */ if (!features->touch_max) - wacom_retrieve_report_data(intf, features); + wacom_retrieve_report_data(hdev, features); i++; break; @@ -474,7 +460,8 @@ static int wacom_parse_hid(struct usb_interface *intf, return result; } -static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int length, int mode) +static int wacom_set_device_mode(struct hid_device *hdev, int report_id, + int length, int mode) { unsigned char *rep_data; int error = -ENOMEM, limit = 0; @@ -487,10 +474,10 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int rep_data[0] = report_id; rep_data[1] = mode; - error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, + error = wacom_set_report(hdev, HID_FEATURE_REPORT, report_id, rep_data, length, 1); if (error >= 0) - error = wacom_get_report(intf, WAC_HID_FEATURE_REPORT, + error = wacom_get_report(hdev, HID_FEATURE_REPORT, report_id, rep_data, length, 1); } while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES); @@ -506,29 +493,32 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int * from the tablet, it is necessary to switch the tablet out of this * mode and into one which sends the full range of tablet data. */ -static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features) +static int wacom_query_tablet_data(struct hid_device *hdev, + struct wacom_features *features) { if (features->device_type == BTN_TOOL_FINGER) { if (features->type > TABLETPC) { /* MT Tablet PC touch */ - return wacom_set_device_mode(intf, 3, 4, 4); + return wacom_set_device_mode(hdev, 3, 4, 4); } else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) { - return wacom_set_device_mode(intf, 18, 3, 2); + return wacom_set_device_mode(hdev, 18, 3, 2); } } else if (features->device_type == BTN_TOOL_PEN) { if (features->type <= BAMBOO_PT && features->type != WIRELESS) { - return wacom_set_device_mode(intf, 2, 2, 2); + return wacom_set_device_mode(hdev, 2, 2, 2); } } return 0; } -static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, +static int wacom_retrieve_hid_descriptor(struct hid_device *hdev, struct wacom_features *features) { int error = 0; + struct wacom *wacom = hid_get_drvdata(hdev); + struct usb_interface *intf = wacom->intf; struct usb_host_interface *interface = intf->cur_altsetting; struct wac_hid_descriptor *hid_desc; @@ -564,12 +554,12 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, error = usb_get_extra_descriptor(&interface->endpoint[0], HID_DEVICET_REPORT, &hid_desc); if (error) { - dev_err(&intf->dev, + hid_err(hdev, "can not retrieve extra class descriptor\n"); goto out; } } - error = wacom_parse_hid(intf, hid_desc, features); + error = wacom_parse_hid(hdev, hid_desc, features); out: return error; @@ -711,8 +701,8 @@ static int wacom_led_control(struct wacom *wacom) buf[4] = wacom->led.img_lum; } - retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL, - buf, 9, WAC_CMD_RETRIES); + retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, + WAC_CMD_LED_CONTROL, buf, 9, WAC_CMD_RETRIES); kfree(buf); return retval; @@ -730,8 +720,8 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *im /* Send 'start' command */ buf[0] = WAC_CMD_ICON_START; buf[1] = 1; - retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START, - buf, 2, WAC_CMD_RETRIES); + retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, + WAC_CMD_ICON_START, buf, 2, WAC_CMD_RETRIES); if (retval < 0) goto out; @@ -741,7 +731,8 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *im buf[2] = i; memcpy(buf + 3, img + i * 256, 256); - retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_XFER, + retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, + WAC_CMD_ICON_XFER, buf, 259, WAC_CMD_RETRIES); if (retval < 0) break; @@ -750,7 +741,7 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *im /* Send 'stop' */ buf[0] = WAC_CMD_ICON_START; buf[1] = 0; - wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START, + wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, WAC_CMD_ICON_START, buf, 2, WAC_CMD_RETRIES); out: @@ -1331,7 +1322,7 @@ static int wacom_probe(struct hid_device *hdev, wacom_set_default_phy(features); /* Retrieve the physical and logical size for touch devices */ - error = wacom_retrieve_hid_descriptor(intf, features); + error = wacom_retrieve_hid_descriptor(hdev, features); if (error) goto fail1; @@ -1395,7 +1386,7 @@ static int wacom_probe(struct hid_device *hdev, } /* Note that if query fails it is not a hard failure */ - wacom_query_tablet_data(intf, features); + wacom_query_tablet_data(hdev, features); /* Regular HID work starts now */ error = hid_parse(hdev); @@ -1452,7 +1443,7 @@ static int wacom_resume(struct hid_device *hdev) mutex_lock(&wacom->lock); /* switch to wacom mode first */ - wacom_query_tablet_data(wacom->intf, features); + wacom_query_tablet_data(hdev, features); wacom_led_control(wacom); mutex_unlock(&wacom->lock); From ba9a3541fba72e1532c8288a0775a211810280c1 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 12:58:45 -0700 Subject: [PATCH 12/37] Input: wacom - use HID core to actually fetch the report descriptor HID core already retrieves the report descritor. There is no need to ask ourself for one. Signed-off-by: Benjamin Tissoires Reviewed-by: Jason Gerecke Tested-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 70 +++++--------------------------- 1 file changed, 10 insertions(+), 60 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 120ab1b5df3c..2c0983bd0504 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -15,9 +15,6 @@ #include "wacom.h" #include -/* defines to get HID report descriptor */ -#define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01) -#define HID_DEVICET_REPORT (USB_TYPE_CLASS | 0x02) #define HID_HDESC_USAGE_UNDEFINED 0x00 #define HID_HDESC_USAGE_PAGE 0x05 #define HID_HDESC_USAGE 0x09 @@ -25,15 +22,6 @@ #define HID_HDESC_COLLECTION_LOGICAL 0x02 #define HID_HDESC_COLLECTION_END 0xc0 -struct wac_hid_descriptor { - struct usb_descriptor_header header; - __le16 bcdHID; - u8 bCountryCode; - u8 bNumDescriptors; - u8 bDescriptorType; - __le16 wDescriptorLength; -} __attribute__ ((packed)); - #define WAC_MSG_RETRIES 5 #define WAC_CMD_LED_CONTROL 0x20 @@ -230,39 +218,14 @@ static void wacom_retrieve_report_data(struct hid_device *hdev, * this after returning from this function. */ static int wacom_parse_hid(struct hid_device *hdev, - struct wac_hid_descriptor *hid_desc, struct wacom_features *features) { - struct wacom *wacom = hid_get_drvdata(hdev); - struct usb_interface *intf = wacom->intf; - struct usb_device *dev = interface_to_usbdev(intf); - char limit = 0; /* result has to be defined as int for some devices */ int result = 0, touch_max = 0; int i = 0, page = 0, finger = 0, pen = 0; - unsigned char *report; + unsigned char *report = hdev->rdesc; - report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL); - if (!report) - return -ENOMEM; - - /* retrive report descriptors */ - do { - result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, - USB_RECIP_INTERFACE | USB_DIR_IN, - HID_DEVICET_REPORT << 8, - intf->altsetting[0].desc.bInterfaceNumber, /* interface */ - report, - hid_desc->wDescriptorLength, - 5000); /* 5 secs */ - } while (result < 0 && limit++ < WAC_MSG_RETRIES); - - /* No need to parse the Descriptor. It isn't an error though */ - if (result < 0) - goto out; - - for (i = 0; i < hid_desc->wDescriptorLength; i++) { + for (i = 0; i < hdev->rsize; i++) { switch (report[i]) { case HID_HDESC_USAGE_PAGE: @@ -452,11 +415,9 @@ static int wacom_parse_hid(struct hid_device *hdev, } } - out: if (!features->touch_max && touch_max) features->touch_max = touch_max; result = 0; - kfree(report); return result; } @@ -519,8 +480,6 @@ static int wacom_retrieve_hid_descriptor(struct hid_device *hdev, int error = 0; struct wacom *wacom = hid_get_drvdata(hdev); struct usb_interface *intf = wacom->intf; - struct usb_host_interface *interface = intf->cur_altsetting; - struct wac_hid_descriptor *hid_desc; /* default features */ features->device_type = BTN_TOOL_PEN; @@ -549,17 +508,7 @@ static int wacom_retrieve_hid_descriptor(struct hid_device *hdev, goto out; } - error = usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc); - if (error) { - error = usb_get_extra_descriptor(&interface->endpoint[0], - HID_DEVICET_REPORT, &hid_desc); - if (error) { - hid_err(hdev, - "can not retrieve extra class descriptor\n"); - goto out; - } - } - error = wacom_parse_hid(hdev, hid_desc, features); + error = wacom_parse_hid(hdev, features); out: return error; @@ -1296,6 +1245,13 @@ static int wacom_probe(struct hid_device *hdev, hid_set_drvdata(hdev, wacom); wacom->hdev = hdev; + /* ask for the report descriptor to be loaded by HID */ + error = hid_parse(hdev); + if (error) { + hid_err(hdev, "parse failed\n"); + goto fail1; + } + wacom_wac = &wacom->wacom_wac; wacom_wac->features = *((struct wacom_features *)id->driver_data); features = &wacom_wac->features; @@ -1389,12 +1345,6 @@ static int wacom_probe(struct hid_device *hdev, wacom_query_tablet_data(hdev, features); /* Regular HID work starts now */ - error = hid_parse(hdev); - if (error) { - hid_err(hdev, "parse failed\n"); - goto fail4; - } - error = hid_hw_start(hdev, HID_CONNECT_HIDRAW); if (error) { hid_err(hdev, "hw start failed\n"); From 01c846f9539c194c7a6e34af036b1115b8ed822a Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 12:59:11 -0700 Subject: [PATCH 13/37] Input: wacom - compute the HID report size to get the actual packet size This removes an USB dependency and is more accurate: the computed pktlen is the actual maximum size of the reports forwarded by the device. Given that the pktlen is correctly computed/validated, we can store it now in the features struct instead of having a special handling in the rest of the code. Likewise, this information is not mandatory anymore in the description of devices in wacom_wac.c. They will be removed in a separate patch. Signed-off-by: Benjamin Tissoires Reviewed-by: Jason Gerecke Tested-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 58 ++++++++++++++------------------ 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 2c0983bd0504..ce76e1ef2dbc 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -149,7 +149,6 @@ static int wacom_parse_logical_collection(unsigned char *report, if (features->type == BAMBOO_PT) { /* Logical collection is only used by 3rd gen Bamboo Touch */ - features->pktlen = WACOM_PKGLEN_BBTOUCH3; features->device_type = BTN_TOOL_FINGER; features->x_max = features->y_max = @@ -240,29 +239,6 @@ static int wacom_parse_hid(struct hid_device *hdev, features->device_type = BTN_TOOL_FINGER; /* touch device at least supports one touch point */ touch_max = 1; - switch (features->type) { - case TABLETPC2FG: - features->pktlen = WACOM_PKGLEN_TPC2FG; - break; - - case MTSCREEN: - case WACOM_24HDT: - features->pktlen = WACOM_PKGLEN_MTOUCH; - break; - - case MTTPC: - case MTTPC_B: - features->pktlen = WACOM_PKGLEN_MTTPC; - break; - - case BAMBOO_PT: - features->pktlen = WACOM_PKGLEN_BBTOUCH; - break; - - default: - features->pktlen = WACOM_PKGLEN_GRAPHIRE; - break; - } switch (features->type) { case BAMBOO_PT: @@ -305,8 +281,6 @@ static int wacom_parse_hid(struct hid_device *hdev, } } else if (pen) { /* penabled only accepts exact bytes of data */ - if (features->type >= TABLETPC) - features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->device_type = BTN_TOOL_PEN; features->x_max = get_unaligned_le16(&report[i + 3]); @@ -1224,12 +1198,34 @@ static void wacom_calculate_res(struct wacom_features *features) features->unitExpo); } +static int wacom_hid_report_len(struct hid_report *report) +{ + /* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */ + return ((report->size - 1) >> 3) + 1 + (report->id > 0); +} + +static size_t wacom_compute_pktlen(struct hid_device *hdev) +{ + struct hid_report_enum *report_enum; + struct hid_report *report; + size_t size = 0; + + report_enum = hdev->report_enum + HID_INPUT_REPORT; + + list_for_each_entry(report, &report_enum->report_list, list) { + size_t report_size = wacom_hid_report_len(report); + if (report_size > size) + size = report_size; + } + + return size; +} + static int wacom_probe(struct hid_device *hdev, const struct hid_device_id *id) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); struct usb_device *dev = interface_to_usbdev(intf); - struct usb_endpoint_descriptor *endpoint; struct wacom *wacom; struct wacom_wac *wacom_wac; struct wacom_features *features; @@ -1255,6 +1251,7 @@ static int wacom_probe(struct hid_device *hdev, wacom_wac = &wacom->wacom_wac; wacom_wac->features = *((struct wacom_features *)id->driver_data); features = &wacom_wac->features; + features->pktlen = wacom_compute_pktlen(hdev); if (features->pktlen > WACOM_PKGLEN_MAX) { error = -EINVAL; goto fail1; @@ -1272,8 +1269,6 @@ static int wacom_probe(struct hid_device *hdev, usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); - endpoint = &intf->cur_altsetting->endpoint[0].desc; - /* set the default size in case we do not get them from hid */ wacom_set_default_phy(features); @@ -1284,13 +1279,12 @@ static int wacom_probe(struct hid_device *hdev, /* * Intuos5 has no useful data about its touch interface in its - * HID descriptor. If this is the touch interface (wMaxPacketSize + * HID descriptor. If this is the touch interface (PacketSize * of WACOM_PKGLEN_BBTOUCH3), override the table values. */ if (features->type >= INTUOS5S && features->type <= INTUOSHT) { - if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) { + if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { features->device_type = BTN_TOOL_FINGER; - features->pktlen = WACOM_PKGLEN_BBTOUCH3; features->x_max = 4096; features->y_max = 4096; From c31a408f7a44cd5fd134a7f0c0d29744261de2d9 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 12:59:45 -0700 Subject: [PATCH 14/37] Input: wacom - install LED/OLED sysfs files in the HID device instead of USB Removes one more dependency over USB, but requires some changes in the user space to find the sysfs files correctly. This patch breaks the user space. However, the number of program accessing the LEDs is quite limited and we can easily patch them to handle the new HID behavior. Signed-off-by: Benjamin Tissoires Reviewed-by: Jason Gerecke Tested-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index ce76e1ef2dbc..6e21064de661 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -675,7 +675,7 @@ out: static ssize_t wacom_led_select_store(struct device *dev, int set_id, const char *buf, size_t count) { - struct hid_device *hdev = dev_get_drvdata(dev); + struct hid_device *hdev = container_of(dev, struct hid_device, dev); struct wacom *wacom = hid_get_drvdata(hdev); unsigned int id; int err; @@ -703,7 +703,7 @@ static ssize_t wacom_led##SET_ID##_select_store(struct device *dev, \ static ssize_t wacom_led##SET_ID##_select_show(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ - struct hid_device *hdev = dev_get_drvdata(dev); \ + struct hid_device *hdev = container_of(dev, struct hid_device, dev);\ struct wacom *wacom = hid_get_drvdata(hdev); \ return snprintf(buf, 2, "%d\n", wacom->led.select[SET_ID]); \ } \ @@ -738,7 +738,7 @@ static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest, static ssize_t wacom_##name##_luminance_store(struct device *dev, \ struct device_attribute *attr, const char *buf, size_t count) \ { \ - struct hid_device *hdev = dev_get_drvdata(dev); \ + struct hid_device *hdev = container_of(dev, struct hid_device, dev);\ struct wacom *wacom = hid_get_drvdata(hdev); \ \ return wacom_luminance_store(wacom, &wacom->led.field, \ @@ -754,7 +754,7 @@ DEVICE_LUMINANCE_ATTR(buttons, img_lum); static ssize_t wacom_button_image_store(struct device *dev, int button_id, const char *buf, size_t count) { - struct hid_device *hdev = dev_get_drvdata(dev); + struct hid_device *hdev = container_of(dev, struct hid_device, dev); struct wacom *wacom = hid_get_drvdata(hdev); int err; @@ -845,7 +845,7 @@ static int wacom_initialize_leds(struct wacom *wacom) wacom->led.llv = 10; wacom->led.hlv = 20; wacom->led.img_lum = 10; - error = sysfs_create_group(&wacom->intf->dev.kobj, + error = sysfs_create_group(&wacom->hdev->dev.kobj, &intuos4_led_attr_group); break; @@ -857,7 +857,7 @@ static int wacom_initialize_leds(struct wacom *wacom) wacom->led.hlv = 0; wacom->led.img_lum = 0; - error = sysfs_create_group(&wacom->intf->dev.kobj, + error = sysfs_create_group(&wacom->hdev->dev.kobj, &cintiq_led_attr_group); break; @@ -874,7 +874,7 @@ static int wacom_initialize_leds(struct wacom *wacom) wacom->led.hlv = 0; wacom->led.img_lum = 0; - error = sysfs_create_group(&wacom->intf->dev.kobj, + error = sysfs_create_group(&wacom->hdev->dev.kobj, &intuos5_led_attr_group); } else return 0; @@ -885,7 +885,7 @@ static int wacom_initialize_leds(struct wacom *wacom) } if (error) { - dev_err(&wacom->intf->dev, + hid_err(wacom->hdev, "cannot create sysfs group err: %d\n", error); return error; } @@ -900,13 +900,13 @@ static void wacom_destroy_leds(struct wacom *wacom) case INTUOS4S: case INTUOS4: case INTUOS4L: - sysfs_remove_group(&wacom->intf->dev.kobj, + sysfs_remove_group(&wacom->hdev->dev.kobj, &intuos4_led_attr_group); break; case WACOM_24HD: case WACOM_21UX2: - sysfs_remove_group(&wacom->intf->dev.kobj, + sysfs_remove_group(&wacom->hdev->dev.kobj, &cintiq_led_attr_group); break; @@ -917,7 +917,7 @@ static void wacom_destroy_leds(struct wacom *wacom) case INTUOSPM: case INTUOSPL: if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN) - sysfs_remove_group(&wacom->intf->dev.kobj, + sysfs_remove_group(&wacom->hdev->dev.kobj, &intuos5_led_attr_group); break; } From b6c79f2ca1032e2da7ad8523b83f0cf5cc04dbc0 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 13:00:03 -0700 Subject: [PATCH 15/37] Input: wacom - register the input devices on top of the HID one Matches the current behavior of the HID subsystem and removes one more dependency over USB. The current user space clients which relies on this to fetch the LEDs path need an update. However, we already break them in the kernel v3.11 for the Bluetooth Wacom devices. They are going to be fixed soon. Signed-off-by: Benjamin Tissoires Reviewed-by: Jason Gerecke Tested-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom.h | 1 - drivers/input/tablet/wacom_sys.c | 15 ++++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index b9212390db71..dd67b7da8a97 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h @@ -112,7 +112,6 @@ struct wacom { struct hid_device *hdev; struct mutex lock; struct work_struct work; - char phys[32]; struct wacom_led { u8 select[2]; /* status led selector (0..3) */ u8 llv; /* status led brightness no button (1..127) */ diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 6e21064de661..265044313fce 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -986,8 +986,7 @@ static void wacom_destroy_battery(struct wacom *wacom) static struct input_dev *wacom_allocate_input(struct wacom *wacom) { struct input_dev *input_dev; - struct usb_interface *intf = wacom->intf; - struct usb_device *dev = interface_to_usbdev(intf); + struct hid_device *hdev = wacom->hdev; struct wacom_wac *wacom_wac = &(wacom->wacom_wac); input_dev = input_allocate_device(); @@ -995,11 +994,15 @@ static struct input_dev *wacom_allocate_input(struct wacom *wacom) return NULL; input_dev->name = wacom_wac->name; - input_dev->phys = wacom->phys; - input_dev->dev.parent = &intf->dev; + input_dev->phys = hdev->phys; + input_dev->dev.parent = &hdev->dev; input_dev->open = wacom_open; input_dev->close = wacom_close; - usb_to_input_id(dev, &input_dev->id); + input_dev->uniq = hdev->uniq; + input_dev->id.bustype = hdev->bus; + input_dev->id.vendor = hdev->vendor; + input_dev->id.product = hdev->product; + input_dev->id.version = hdev->version; input_set_drvdata(input_dev, wacom); return input_dev; @@ -1266,8 +1269,6 @@ static int wacom_probe(struct hid_device *hdev, wacom->intf = intf; mutex_init(&wacom->lock); INIT_WORK(&wacom->work, wacom_wireless_work); - usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); - strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); /* set the default size in case we do not get them from hid */ wacom_set_default_phy(features); From 4451e088cf01184379da1b212913fdde6e9943c5 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 13:01:05 -0700 Subject: [PATCH 16/37] Input: wacom - remove usb dependency for siblings devices Wacom tablets can share different physical sensors on one physical device. These are called siblings in the code. The current way of implementation relies on the USB topology to be able to share data amongs those sensors. We can replace the code to match a HID subsystem, without involving the USB topology: - the first probed sensor does not find any siblings in the list wacom_udev_list, so it creates its own wacom_hdev_data with its own struct hid_device - the other sensor checks the current list of siblings in wacom_hdev_data, and if there is a match, it associates itself to the matched device. To be sure that we are not associating different sensors from different physical devices, we also check for the phys path of the hid device which contains the USB topology. Signed-off-by: Benjamin Tissoires Reviewed-by: Jason Gerecke Tested-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 78 ++++++++++++++++---------------- 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 265044313fce..8065bac5fcb3 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -488,46 +488,48 @@ static int wacom_retrieve_hid_descriptor(struct hid_device *hdev, return error; } -struct wacom_usbdev_data { +struct wacom_hdev_data { struct list_head list; struct kref kref; - struct usb_device *dev; + struct hid_device *dev; struct wacom_shared shared; }; static LIST_HEAD(wacom_udev_list); static DEFINE_MUTEX(wacom_udev_list_lock); -static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product) +static bool wacom_are_sibling(struct hid_device *hdev, + struct hid_device *sibling) { - int port1; - struct usb_device *sibling; + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_features *features = &wacom->wacom_wac.features; + int vid = features->oVid; + int pid = features->oPid; + int n1,n2; - if (vendor == 0 && product == 0) - return dev; - - if (dev->parent == NULL) - return NULL; - - usb_hub_for_each_child(dev->parent, port1, sibling) { - struct usb_device_descriptor *d; - if (sibling == NULL) - continue; - - d = &sibling->descriptor; - if (d->idVendor == vendor && d->idProduct == product) - return sibling; + if (vid == 0 && pid == 0) { + vid = hdev->vendor; + pid = hdev->product; } - return NULL; + if (vid != sibling->vendor || pid != sibling->product) + return false; + + /* Compare the physical path. */ + n1 = strrchr(hdev->phys, '.') - hdev->phys; + n2 = strrchr(sibling->phys, '.') - sibling->phys; + if (n1 != n2 || n1 <= 0 || n2 <= 0) + return false; + + return !strncmp(hdev->phys, sibling->phys, n1); } -static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev) +static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev) { - struct wacom_usbdev_data *data; + struct wacom_hdev_data *data; list_for_each_entry(data, &wacom_udev_list, list) { - if (data->dev == dev) { + if (wacom_are_sibling(hdev, data->dev)) { kref_get(&data->kref); return data; } @@ -536,28 +538,29 @@ static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev) return NULL; } -static int wacom_add_shared_data(struct wacom_wac *wacom, - struct usb_device *dev) +static int wacom_add_shared_data(struct hid_device *hdev) { - struct wacom_usbdev_data *data; + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_hdev_data *data; int retval = 0; mutex_lock(&wacom_udev_list_lock); - data = wacom_get_usbdev_data(dev); + data = wacom_get_hdev_data(hdev); if (!data) { - data = kzalloc(sizeof(struct wacom_usbdev_data), GFP_KERNEL); + data = kzalloc(sizeof(struct wacom_hdev_data), GFP_KERNEL); if (!data) { retval = -ENOMEM; goto out; } kref_init(&data->kref); - data->dev = dev; + data->dev = hdev; list_add_tail(&data->list, &wacom_udev_list); } - wacom->shared = &data->shared; + wacom_wac->shared = &data->shared; out: mutex_unlock(&wacom_udev_list_lock); @@ -566,8 +569,8 @@ out: static void wacom_release_shared_data(struct kref *kref) { - struct wacom_usbdev_data *data = - container_of(kref, struct wacom_usbdev_data, kref); + struct wacom_hdev_data *data = + container_of(kref, struct wacom_hdev_data, kref); mutex_lock(&wacom_udev_list_lock); list_del(&data->list); @@ -578,10 +581,10 @@ static void wacom_release_shared_data(struct kref *kref) static void wacom_remove_shared_data(struct wacom_wac *wacom) { - struct wacom_usbdev_data *data; + struct wacom_hdev_data *data; if (wacom->shared) { - data = container_of(wacom->shared, struct wacom_usbdev_data, shared); + data = container_of(wacom->shared, struct wacom_hdev_data, shared); kref_put(&data->kref, wacom_release_shared_data); wacom->shared = NULL; } @@ -1308,8 +1311,6 @@ static int wacom_probe(struct hid_device *hdev, "%s Pad", features->name); if (features->quirks & WACOM_QUIRK_MULTI_INPUT) { - struct usb_device *other_dev; - /* Append the device type to the name */ if (features->device_type != BTN_TOOL_FINGER) strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX); @@ -1318,10 +1319,7 @@ static int wacom_probe(struct hid_device *hdev, else strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX); - other_dev = wacom_get_sibling(dev, features->oVid, features->oPid); - if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL) - other_dev = dev; - error = wacom_add_shared_data(wacom_wac, other_dev); + error = wacom_add_shared_data(hdev); if (error) goto fail1; } From dd3181a70cb73c4f40cfe33ecdd6260ff3fbf8cc Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 13:01:40 -0700 Subject: [PATCH 17/37] Input: wacom - register power device at the HID level Use the HID device as the parent for the power device when dealing with a wireless receiver. Removes one more usb dependency and does not break user space. Signed-off-by: Benjamin Tissoires Reviewed-by: Jason Gerecke Tested-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 8065bac5fcb3..b8710594185a 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -966,12 +966,12 @@ static int wacom_initialize_battery(struct wacom *wacom) wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY; wacom->battery.use_for_apm = 0; - error = power_supply_register(&wacom->usbdev->dev, + error = power_supply_register(&wacom->hdev->dev, &wacom->battery); if (!error) power_supply_powers(&wacom->battery, - &wacom->usbdev->dev); + &wacom->hdev->dev); } return error; From e2114ce1af0dd8c1e077b6d545e346e9ac4d137c Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 13:01:56 -0700 Subject: [PATCH 18/37] Input: wacom - use hid_info instead of plain dev_info Removes one more need of usb and intf. Signed-off-by: Benjamin Tissoires Reviewed-by: Jason Gerecke Tested-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index b8710594185a..2c1d984edc7f 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -1104,12 +1104,11 @@ static void wacom_wireless_work(struct work_struct *work) wacom_unregister_inputs(wacom2); if (wacom_wac->pid == 0) { - dev_info(&wacom->intf->dev, "wireless tablet disconnected\n"); + hid_info(wacom->hdev, "wireless tablet disconnected\n"); } else { const struct hid_device_id *id = wacom_ids; - dev_info(&wacom->intf->dev, - "wireless tablet connected with PID %x\n", + hid_info(wacom->hdev, "wireless tablet connected with PID %x\n", wacom_wac->pid); while (id->bus) { @@ -1120,8 +1119,7 @@ static void wacom_wireless_work(struct work_struct *work) } if (!id->bus) { - dev_info(&wacom->intf->dev, - "ignoring unknown PID.\n"); + hid_info(wacom->hdev, "ignoring unknown PID.\n"); return; } From c669fb2b9ac47682b53f0a97d55c7ae4f2f3eaee Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 13:02:14 -0700 Subject: [PATCH 19/37] Input: wacom - use in-kernel HID parser HID already parses the report descriptor, so use it instead of implementing our own. The special case for Bamboo PT 3rd gen is also removed and handled in the same way Intuos 5 is treated, by hardcoding it in the driver. Last, the unit_exponent stored into the hid field already is signed, so there is no need to handle a two's complement anymore. Signed-off-by: Benjamin Tissoires Reviewed-by: Jason Gerecke Tested-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 348 ++++++++++--------------------- drivers/input/tablet/wacom_wac.h | 4 +- 2 files changed, 114 insertions(+), 238 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 2c1d984edc7f..ed27e7da5444 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -15,13 +15,6 @@ #include "wacom.h" #include -#define HID_HDESC_USAGE_UNDEFINED 0x00 -#define HID_HDESC_USAGE_PAGE 0x05 -#define HID_HDESC_USAGE 0x09 -#define HID_HDESC_COLLECTION 0xa1 -#define HID_HDESC_COLLECTION_LOGICAL 0x02 -#define HID_HDESC_COLLECTION_END 0xc0 - #define WAC_MSG_RETRIES 5 #define WAC_CMD_LED_CONTROL 0x20 @@ -96,19 +89,15 @@ static void wacom_close(struct input_dev *dev) * This function is little more than hidinput_calc_abs_res stripped down. */ static int wacom_calc_hid_res(int logical_extents, int physical_extents, - unsigned char unit, unsigned char exponent) + unsigned unit, int exponent) { - int prev, unit_exponent; + int prev; + int unit_exponent = exponent; /* Check if the extents are sane */ if (logical_extents <= 0 || physical_extents <= 0) return 0; - /* Get signed value of nybble-sized twos-compliment exponent */ - unit_exponent = exponent; - if (unit_exponent > 7) - unit_exponent -= 16; - /* Convert physical_extents to millimeters */ if (unit == 0x11) { /* If centimeters */ unit_exponent += 1; @@ -141,42 +130,18 @@ static int wacom_calc_hid_res(int logical_extents, int physical_extents, return logical_extents / physical_extents; } -static int wacom_parse_logical_collection(unsigned char *report, - struct wacom_features *features) +static void wacom_feature_mapping(struct hid_device *hdev, + struct hid_field *field, struct hid_usage *usage) { - int length = 0; + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_features *features = &wacom->wacom_wac.features; - if (features->type == BAMBOO_PT) { - - /* Logical collection is only used by 3rd gen Bamboo Touch */ - features->device_type = BTN_TOOL_FINGER; - - features->x_max = features->y_max = - get_unaligned_le16(&report[10]); - - length = 11; - } - return length; -} - -static void wacom_retrieve_report_data(struct hid_device *hdev, - struct wacom_features *features) -{ - int result = 0; - unsigned char *rep_data; - - rep_data = kmalloc(2, GFP_KERNEL); - if (rep_data) { - - rep_data[0] = 12; - result = wacom_get_report(hdev, HID_FEATURE_REPORT, - rep_data[0], rep_data, 2, - WAC_MSG_RETRIES); - - if (result >= 0 && rep_data[1] > 2) - features->touch_max = rep_data[1]; - - kfree(rep_data); + switch (usage->hid) { + case HID_DG_CONTACTMAX: + /* leave touch_max as is if predefined */ + if (!features->touch_max) + features->touch_max = field->value[0]; + break; } } @@ -209,190 +174,96 @@ static void wacom_retrieve_report_data(struct hid_device *hdev, * interfaces haven't supported pressure or distance, this is enough * information to override invalid values in the wacom_features table. * - * 3rd gen Bamboo Touch no longer define a Digitizer-Finger Pysical - * Collection. Instead they define a Logical Collection with a single - * Logical Maximum for both X and Y. - * - * Intuos5 touch interface does not contain useful data. We deal with - * this after returning from this function. + * Intuos5 touch interface and 3rd gen Bamboo Touch do not contain useful + * data. We deal with them after returning from this function. */ -static int wacom_parse_hid(struct hid_device *hdev, +static void wacom_usage_mapping(struct hid_device *hdev, + struct hid_field *field, struct hid_usage *usage) +{ + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_features *features = &wacom->wacom_wac.features; + bool finger = (field->logical == HID_DG_FINGER) || + (field->physical == HID_DG_FINGER); + bool pen = (field->logical == HID_DG_STYLUS) || + (field->physical == HID_DG_STYLUS); + + /* + * Requiring Stylus Usage will ignore boot mouse + * X/Y values and some cases of invalid Digitizer X/Y + * values commonly reported. + */ + if (!pen && !finger) + return; + + if (finger && !features->touch_max) + /* touch device at least supports one touch point */ + features->touch_max = 1; + + switch (usage->hid) { + case HID_GD_X: + features->x_max = field->logical_maximum; + if (finger) { + features->device_type = BTN_TOOL_FINGER; + features->x_phy = field->physical_maximum; + if (features->type != BAMBOO_PT) { + features->unit = field->unit; + features->unitExpo = field->unit_exponent; + } + } else { + features->device_type = BTN_TOOL_PEN; + } + break; + case HID_GD_Y: + features->y_max = field->logical_maximum; + if (finger) { + features->y_phy = field->physical_maximum; + if (features->type != BAMBOO_PT) { + features->unit = field->unit; + features->unitExpo = field->unit_exponent; + } + } + break; + case HID_DG_TIPPRESSURE: + if (pen) + features->pressure_max = field->logical_maximum; + break; + } +} + +static void wacom_parse_hid(struct hid_device *hdev, struct wacom_features *features) { - /* result has to be defined as int for some devices */ - int result = 0, touch_max = 0; - int i = 0, page = 0, finger = 0, pen = 0; - unsigned char *report = hdev->rdesc; + struct hid_report_enum *rep_enum; + struct hid_report *hreport; + int i, j; - for (i = 0; i < hdev->rsize; i++) { + /* check features first */ + rep_enum = &hdev->report_enum[HID_FEATURE_REPORT]; + list_for_each_entry(hreport, &rep_enum->report_list, list) { + for (i = 0; i < hreport->maxfield; i++) { + /* Ignore if report count is out of bounds. */ + if (hreport->field[i]->report_count < 1) + continue; - switch (report[i]) { - case HID_HDESC_USAGE_PAGE: - page = report[i + 1]; - i++; - break; - - case HID_HDESC_USAGE: - switch (page << 16 | report[i + 1]) { - case HID_GD_X: - if (finger) { - features->device_type = BTN_TOOL_FINGER; - /* touch device at least supports one touch point */ - touch_max = 1; - - switch (features->type) { - case BAMBOO_PT: - features->x_phy = - get_unaligned_le16(&report[i + 5]); - features->x_max = - get_unaligned_le16(&report[i + 8]); - i += 15; - break; - - case WACOM_24HDT: - features->x_max = - get_unaligned_le16(&report[i + 3]); - features->x_phy = - get_unaligned_le16(&report[i + 8]); - features->unit = report[i - 1]; - features->unitExpo = report[i - 3]; - i += 12; - break; - - case MTTPC_B: - features->x_max = - get_unaligned_le16(&report[i + 3]); - features->x_phy = - get_unaligned_le16(&report[i + 6]); - features->unit = report[i - 5]; - features->unitExpo = report[i - 3]; - i += 9; - break; - - default: - features->x_max = - get_unaligned_le16(&report[i + 3]); - features->x_phy = - get_unaligned_le16(&report[i + 6]); - features->unit = report[i + 9]; - features->unitExpo = report[i + 11]; - i += 12; - break; - } - } else if (pen) { - /* penabled only accepts exact bytes of data */ - features->device_type = BTN_TOOL_PEN; - features->x_max = - get_unaligned_le16(&report[i + 3]); - i += 4; - } - break; - - case HID_GD_Y: - if (finger) { - switch (features->type) { - case TABLETPC2FG: - case MTSCREEN: - case MTTPC: - features->y_max = - get_unaligned_le16(&report[i + 3]); - features->y_phy = - get_unaligned_le16(&report[i + 6]); - i += 7; - break; - - case WACOM_24HDT: - features->y_max = - get_unaligned_le16(&report[i + 3]); - features->y_phy = - get_unaligned_le16(&report[i - 2]); - i += 7; - break; - - case BAMBOO_PT: - features->y_phy = - get_unaligned_le16(&report[i + 3]); - features->y_max = - get_unaligned_le16(&report[i + 6]); - i += 12; - break; - - case MTTPC_B: - features->y_max = - get_unaligned_le16(&report[i + 3]); - features->y_phy = - get_unaligned_le16(&report[i + 6]); - i += 9; - break; - - default: - features->y_max = - features->x_max; - features->y_phy = - get_unaligned_le16(&report[i + 3]); - i += 4; - break; - } - } else if (pen) { - features->y_max = - get_unaligned_le16(&report[i + 3]); - i += 4; - } - break; - - case HID_DG_FINGER: - finger = 1; - i++; - break; - - /* - * Requiring Stylus Usage will ignore boot mouse - * X/Y values and some cases of invalid Digitizer X/Y - * values commonly reported. - */ - case HID_DG_STYLUS: - pen = 1; - i++; - break; - - case HID_DG_CONTACTMAX: - /* leave touch_max as is if predefined */ - if (!features->touch_max) - wacom_retrieve_report_data(hdev, features); - i++; - break; - - case HID_DG_TIPPRESSURE: - if (pen) { - features->pressure_max = - get_unaligned_le16(&report[i + 3]); - i += 4; - } - break; + for (j = 0; j < hreport->field[i]->maxusage; j++) { + wacom_feature_mapping(hdev, hreport->field[i], + hreport->field[i]->usage + j); } - break; - - case HID_HDESC_COLLECTION_END: - /* reset UsagePage and Finger */ - finger = page = 0; - break; - - case HID_HDESC_COLLECTION: - i++; - switch (report[i]) { - case HID_HDESC_COLLECTION_LOGICAL: - i += wacom_parse_logical_collection(&report[i], - features); - break; - } - break; } } - if (!features->touch_max && touch_max) - features->touch_max = touch_max; - result = 0; - return result; + /* now check the input usages */ + rep_enum = &hdev->report_enum[HID_INPUT_REPORT]; + list_for_each_entry(hreport, &rep_enum->report_list, list) { + + if (!hreport->maxfield) + continue; + + for (i = 0; i < hreport->maxfield; i++) + for (j = 0; j < hreport->field[i]->maxusage; j++) + wacom_usage_mapping(hdev, hreport->field[i], + hreport->field[i]->usage + j); + } } static int wacom_set_device_mode(struct hid_device *hdev, int report_id, @@ -448,10 +319,9 @@ static int wacom_query_tablet_data(struct hid_device *hdev, return 0; } -static int wacom_retrieve_hid_descriptor(struct hid_device *hdev, +static void wacom_retrieve_hid_descriptor(struct hid_device *hdev, struct wacom_features *features) { - int error = 0; struct wacom *wacom = hid_get_drvdata(hdev); struct usb_interface *intf = wacom->intf; @@ -478,14 +348,10 @@ static int wacom_retrieve_hid_descriptor(struct hid_device *hdev, } /* only devices that support touch need to retrieve the info */ - if (features->type < BAMBOO_PT) { - goto out; - } + if (features->type < BAMBOO_PT) + return; - error = wacom_parse_hid(hdev, features); - - out: - return error; + wacom_parse_hid(hdev, features); } struct wacom_hdev_data { @@ -1275,9 +1141,7 @@ static int wacom_probe(struct hid_device *hdev, wacom_set_default_phy(features); /* Retrieve the physical and logical size for touch devices */ - error = wacom_retrieve_hid_descriptor(hdev, features); - if (error) - goto fail1; + wacom_retrieve_hid_descriptor(hdev, features); /* * Intuos5 has no useful data about its touch interface in its @@ -1295,12 +1159,24 @@ static int wacom_probe(struct hid_device *hdev, } } + /* + * Same thing for Bamboo 3rd gen. + */ + if ((features->type == BAMBOO_PT) && + (features->pktlen == WACOM_PKGLEN_BBTOUCH3) && + (features->device_type == BTN_TOOL_PEN)) { + features->device_type = BTN_TOOL_FINGER; + + features->x_max = 4096; + features->y_max = 4096; + } + wacom_setup_device_quirks(features); /* set unit to "100th of a mm" for devices not reported by HID */ if (!features->unit) { features->unit = 0x11; - features->unitExpo = 16 - 3; + features->unitExpo = -3; } wacom_calculate_res(features); diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 8821a518abf6..2a7612ae14a6 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -127,8 +127,8 @@ struct wacom_features { int device_type; int x_phy; int y_phy; - unsigned char unit; - unsigned char unitExpo; + unsigned unit; + int unitExpo; int x_fuzz; int y_fuzz; int pressure_fuzz; From 198fdee2829547ec4ff29bb56ea668790d23bc4b Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 13:03:05 -0700 Subject: [PATCH 20/37] Input: wacom - use hidinput_calc_abs_res instead of duplicating its code This may infer a small difference with the previous implementation due to the DIV_ROUND_CLOSEST() in the hid implementation. Signed-off-by: Benjamin Tissoires Reviewed-by: Jason Gerecke Tested-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 46 ++++++-------------------------- 1 file changed, 8 insertions(+), 38 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index ed27e7da5444..06e304b3bbfd 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -85,49 +85,19 @@ static void wacom_close(struct input_dev *dev) } /* - * Calculate the resolution of the X or Y axis, given appropriate HID data. - * This function is little more than hidinput_calc_abs_res stripped down. + * Calculate the resolution of the X or Y axis using hidinput_calc_abs_res. */ static int wacom_calc_hid_res(int logical_extents, int physical_extents, unsigned unit, int exponent) { - int prev; - int unit_exponent = exponent; + struct hid_field field = { + .logical_maximum = logical_extents, + .physical_maximum = physical_extents, + .unit = unit, + .unit_exponent = exponent, + }; - /* Check if the extents are sane */ - if (logical_extents <= 0 || physical_extents <= 0) - return 0; - - /* Convert physical_extents to millimeters */ - if (unit == 0x11) { /* If centimeters */ - unit_exponent += 1; - } else if (unit == 0x13) { /* If inches */ - prev = physical_extents; - physical_extents *= 254; - if (physical_extents < prev) - return 0; - unit_exponent -= 1; - } else { - return 0; - } - - /* Apply negative unit exponent */ - for (; unit_exponent < 0; unit_exponent++) { - prev = logical_extents; - logical_extents *= 10; - if (logical_extents < prev) - return 0; - } - /* Apply positive unit exponent */ - for (; unit_exponent > 0; unit_exponent--) { - prev = physical_extents; - physical_extents *= 10; - if (physical_extents < prev) - return 0; - } - - /* Calculate resolution */ - return logical_extents / physical_extents; + return hidinput_calc_abs_res(&field, ABS_X); } static void wacom_feature_mapping(struct hid_device *hdev, From 80befa93817b661193ba6423dfa9b69ffacd7e53 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 13:05:19 -0700 Subject: [PATCH 21/37] Input: wacom - remove field pktlen declaration in the list of devices pktlen is now overwritten by the driver directly by reading the hid report descriptor. There is no need to declare it statically. We also move down the position of the field in the struct so that we can keep the current declaration of Wacom devices. Signed-off-by: Benjamin Tissoires Reviewed-by: Jason Gerecke Tested-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 514 +++++++++++++++---------------- drivers/input/tablet/wacom_wac.h | 2 +- 2 files changed, 247 insertions(+), 269 deletions(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 1c95ce78d749..15b0132265e3 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -2012,418 +2012,396 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, } static const struct wacom_features wacom_features_0x00 = - { "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255, - 0, PENPARTNER, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES }; + { "Wacom Penpartner", 5040, 3780, 255, 0, + PENPARTNER, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES }; static const struct wacom_features wacom_features_0x10 = - { "Wacom Graphire", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, - 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; + { "Wacom Graphire", 10206, 7422, 511, 63, + GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x11 = - { "Wacom Graphire2 4x5", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, - 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; + { "Wacom Graphire2 4x5", 10206, 7422, 511, 63, + GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x12 = - { "Wacom Graphire2 5x7", WACOM_PKGLEN_GRAPHIRE, 13918, 10206, 511, - 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; + { "Wacom Graphire2 5x7", 13918, 10206, 511, 63, + GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x13 = - { "Wacom Graphire3", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, - 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; + { "Wacom Graphire3", 10208, 7424, 511, 63, + GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x14 = - { "Wacom Graphire3 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, - 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; + { "Wacom Graphire3 6x8", 16704, 12064, 511, 63, + GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x15 = - { "Wacom Graphire4 4x5", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, - 63, WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; + { "Wacom Graphire4 4x5", 10208, 7424, 511, 63, + WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x16 = - { "Wacom Graphire4 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, - 63, WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; + { "Wacom Graphire4 6x8", 16704, 12064, 511, 63, + WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x17 = - { "Wacom BambooFun 4x5", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, - 63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom BambooFun 4x5", 14760, 9225, 511, 63, + WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x18 = - { "Wacom BambooFun 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 511, - 63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom BambooFun 6x8", 21648, 13530, 511, 63, + WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x19 = - { "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, - 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; + { "Wacom Bamboo1 Medium", 16704, 12064, 511, 63, + GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x60 = - { "Wacom Volito", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, - 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; + { "Wacom Volito", 5104, 3712, 511, 63, + GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; static const struct wacom_features wacom_features_0x61 = - { "Wacom PenStation2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 255, - 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; + { "Wacom PenStation2", 3250, 2320, 255, 63, + GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; static const struct wacom_features wacom_features_0x62 = - { "Wacom Volito2 4x5", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, - 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; + { "Wacom Volito2 4x5", 5104, 3712, 511, 63, + GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; static const struct wacom_features wacom_features_0x63 = - { "Wacom Volito2 2x3", WACOM_PKGLEN_GRAPHIRE, 3248, 2320, 511, - 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; + { "Wacom Volito2 2x3", 3248, 2320, 511, 63, + GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; static const struct wacom_features wacom_features_0x64 = - { "Wacom PenPartner2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 511, - 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; + { "Wacom PenPartner2", 3250, 2320, 511, 63, + GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; static const struct wacom_features wacom_features_0x65 = - { "Wacom Bamboo", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, - 63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Bamboo", 14760, 9225, 511, 63, + WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x69 = - { "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, - 63, GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES }; + { "Wacom Bamboo1", 5104, 3712, 511, 63, + GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES }; static const struct wacom_features wacom_features_0x6A = - { "Wacom Bamboo1 4x6", WACOM_PKGLEN_GRAPHIRE, 14760, 9225, 1023, - 63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Bamboo1 4x6", 14760, 9225, 1023, 63, + GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x6B = - { "Wacom Bamboo1 5x8", WACOM_PKGLEN_GRAPHIRE, 21648, 13530, 1023, - 63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Bamboo1 5x8", 21648, 13530, 1023, 63, + GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x20 = - { "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, - 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Intuos 4x5", 12700, 10600, 1023, 31, + INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x21 = - { "Wacom Intuos 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, - 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Intuos 6x8", 20320, 16240, 1023, 31, + INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x22 = - { "Wacom Intuos 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, - 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Intuos 9x12", 30480, 24060, 1023, 31, + INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x23 = - { "Wacom Intuos 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, - 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Intuos 12x12", 30480, 31680, 1023, 31, + INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x24 = - { "Wacom Intuos 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, - 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Intuos 12x18", 45720, 31680, 1023, 31, + INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x30 = - { "Wacom PL400", WACOM_PKGLEN_GRAPHIRE, 5408, 4056, 255, - 0, PL, WACOM_PL_RES, WACOM_PL_RES }; + { "Wacom PL400", 5408, 4056, 255, 0, + PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x31 = - { "Wacom PL500", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 255, - 0, PL, WACOM_PL_RES, WACOM_PL_RES }; + { "Wacom PL500", 6144, 4608, 255, 0, + PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x32 = - { "Wacom PL600", WACOM_PKGLEN_GRAPHIRE, 6126, 4604, 255, - 0, PL, WACOM_PL_RES, WACOM_PL_RES }; + { "Wacom PL600", 6126, 4604, 255, 0, + PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x33 = - { "Wacom PL600SX", WACOM_PKGLEN_GRAPHIRE, 6260, 5016, 255, - 0, PL, WACOM_PL_RES, WACOM_PL_RES }; + { "Wacom PL600SX", 6260, 5016, 255, 0, + PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x34 = - { "Wacom PL550", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 511, - 0, PL, WACOM_PL_RES, WACOM_PL_RES }; + { "Wacom PL550", 6144, 4608, 511, 0, + PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x35 = - { "Wacom PL800", WACOM_PKGLEN_GRAPHIRE, 7220, 5780, 511, - 0, PL, WACOM_PL_RES, WACOM_PL_RES }; + { "Wacom PL800", 7220, 5780, 511, 0, + PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x37 = - { "Wacom PL700", WACOM_PKGLEN_GRAPHIRE, 6758, 5406, 511, - 0, PL, WACOM_PL_RES, WACOM_PL_RES }; + { "Wacom PL700", 6758, 5406, 511, 0, + PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x38 = - { "Wacom PL510", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, - 0, PL, WACOM_PL_RES, WACOM_PL_RES }; + { "Wacom PL510", 6282, 4762, 511, 0, + PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x39 = - { "Wacom DTU710", WACOM_PKGLEN_GRAPHIRE, 34080, 27660, 511, - 0, PL, WACOM_PL_RES, WACOM_PL_RES }; + { "Wacom DTU710", 34080, 27660, 511, 0, + PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0xC4 = - { "Wacom DTF521", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, - 0, PL, WACOM_PL_RES, WACOM_PL_RES }; + { "Wacom DTF521", 6282, 4762, 511, 0, + PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0xC0 = - { "Wacom DTF720", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, - 0, PL, WACOM_PL_RES, WACOM_PL_RES }; + { "Wacom DTF720", 6858, 5506, 511, 0, + PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0xC2 = - { "Wacom DTF720a", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, - 0, PL, WACOM_PL_RES, WACOM_PL_RES }; + { "Wacom DTF720a", 6858, 5506, 511, 0, + PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x03 = - { "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE, 20480, 15360, 511, - 0, PTU, WACOM_PL_RES, WACOM_PL_RES }; + { "Wacom Cintiq Partner", 20480, 15360, 511, 0, + PTU, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x41 = - { "Wacom Intuos2 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, - 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Intuos2 4x5", 12700, 10600, 1023, 31, + INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x42 = - { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, - 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Intuos2 6x8", 20320, 16240, 1023, 31, + INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x43 = - { "Wacom Intuos2 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, - 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Intuos2 9x12", 30480, 24060, 1023, 31, + INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x44 = - { "Wacom Intuos2 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, - 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Intuos2 12x12", 30480, 31680, 1023, 31, + INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x45 = - { "Wacom Intuos2 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, - 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Intuos2 12x18", 45720, 31680, 1023, 31, + INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xB0 = - { "Wacom Intuos3 4x5", WACOM_PKGLEN_INTUOS, 25400, 20320, 1023, - 63, INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Intuos3 4x5", 25400, 20320, 1023, 63, + INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB1 = - { "Wacom Intuos3 6x8", WACOM_PKGLEN_INTUOS, 40640, 30480, 1023, - 63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Intuos3 6x8", 40640, 30480, 1023, 63, + INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB2 = - { "Wacom Intuos3 9x12", WACOM_PKGLEN_INTUOS, 60960, 45720, 1023, - 63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Intuos3 9x12", 60960, 45720, 1023, 63, + INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB3 = - { "Wacom Intuos3 12x12", WACOM_PKGLEN_INTUOS, 60960, 60960, 1023, - 63, INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Intuos3 12x12", 60960, 60960, 1023, 63, + INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB4 = - { "Wacom Intuos3 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 1023, - 63, INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Intuos3 12x19", 97536, 60960, 1023, 63, + INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB5 = - { "Wacom Intuos3 6x11", WACOM_PKGLEN_INTUOS, 54204, 31750, 1023, - 63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Intuos3 6x11", 54204, 31750, 1023, 63, + INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB7 = - { "Wacom Intuos3 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 1023, - 63, INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Intuos3 4x6", 31496, 19685, 1023, 63, + INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB8 = - { "Wacom Intuos4 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, - 63, INTUOS4S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Intuos4 4x6", 31496, 19685, 2047, 63, + INTUOS4S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB9 = - { "Wacom Intuos4 6x9", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, - 63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Intuos4 6x9", 44704, 27940, 2047, 63, + INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xBA = - { "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, - 63, INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Intuos4 8x13", 65024, 40640, 2047, 63, + INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xBB = - { "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, - 63, INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Intuos4 12x19", 97536, 60960, 2047, 63, + INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xBC = - { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40640, 25400, 2047, - 63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Intuos4 WL", 40640, 25400, 2047, 63, + INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0x26 = - { "Wacom Intuos5 touch S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, - 63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, - .touch_max = 16 }; + { "Wacom Intuos5 touch S", 31496, 19685, 2047, 63, + INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 }; static const struct wacom_features wacom_features_0x27 = - { "Wacom Intuos5 touch M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, - 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, - .touch_max = 16 }; + { "Wacom Intuos5 touch M", 44704, 27940, 2047, 63, + INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 }; static const struct wacom_features wacom_features_0x28 = - { "Wacom Intuos5 touch L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, - 63, INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, - .touch_max = 16 }; + { "Wacom Intuos5 touch L", 65024, 40640, 2047, 63, + INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 }; static const struct wacom_features wacom_features_0x29 = - { "Wacom Intuos5 S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, - 63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Intuos5 S", 31496, 19685, 2047, 63, + INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0x2A = - { "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, - 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Intuos5 M", 44704, 27940, 2047, 63, + INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0x314 = - { "Wacom Intuos Pro S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, - 63, INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, - .touch_max = 16, + { "Wacom Intuos Pro S", 31496, 19685, 2047, 63, + INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x315 = - { "Wacom Intuos Pro M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, - 63, INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, - .touch_max = 16, + { "Wacom Intuos Pro M", 44704, 27940, 2047, 63, + INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x317 = - { "Wacom Intuos Pro L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, - 63, INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, - .touch_max = 16, + { "Wacom Intuos Pro L", 65024, 40640, 2047, 63, + INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0xF4 = - { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104280, 65400, 2047, - 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; + { "Wacom Cintiq 24HD", 104280, 65400, 2047, 63, + WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; static const struct wacom_features wacom_features_0xF8 = - { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104280, 65400, 2047, /* Pen */ - 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, + { "Wacom Cintiq 24HD touch", 104280, 65400, 2047, 63, /* Pen */ + WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 }; static const struct wacom_features wacom_features_0xF6 = { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x3F = - { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, - 63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Cintiq 21UX", 87200, 65600, 1023, 63, + CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xC5 = - { "Wacom Cintiq 20WSX", WACOM_PKGLEN_INTUOS, 86680, 54180, 1023, - 63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Cintiq 20WSX", 86680, 54180, 1023, 63, + WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xC6 = - { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, - 63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Cintiq 12WX", 53020, 33440, 1023, 63, + WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0x304 = - { "Wacom Cintiq 13HD", WACOM_PKGLEN_INTUOS, 59352, 33648, 1023, - 63, WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; + { "Wacom Cintiq 13HD", 59352, 33648, 1023, 63, + WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; static const struct wacom_features wacom_features_0xC7 = - { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, - 0, PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom DTU1931", 37832, 30305, 511, 0, + PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xCE = - { "Wacom DTU2231", WACOM_PKGLEN_GRAPHIRE, 47864, 27011, 511, - 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + { "Wacom DTU2231", 47864, 27011, 511, 0, + DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .check_for_hid_type = true, .hid_type = HID_TYPE_USBMOUSE }; static const struct wacom_features wacom_features_0xF0 = - { "Wacom DTU1631", WACOM_PKGLEN_GRAPHIRE, 34623, 19553, 511, - 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom DTU1631", 34623, 19553, 511, 0, + DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xFB = - { "Wacom DTU1031", WACOM_PKGLEN_DTUS, 22096, 13960, 511, - 0, DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom DTU1031", 22096, 13960, 511, 0, + DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x57 = - { "Wacom DTK2241", WACOM_PKGLEN_INTUOS, 95640, 54060, 2047, - 63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; + { "Wacom DTK2241", 95640, 54060, 2047, 63, + DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; static const struct wacom_features wacom_features_0x59 = /* Pen */ - { "Wacom DTH2242", WACOM_PKGLEN_INTUOS, 95640, 54060, 2047, - 63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, + { "Wacom DTH2242", 95640, 54060, 2047, 63, + DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D }; static const struct wacom_features wacom_features_0x5D = /* Touch */ { "Wacom DTH2242", .type = WACOM_24HDT, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0xCC = - { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87000, 65400, 2047, - 63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; + { "Wacom Cintiq 21UX2", 87000, 65400, 2047, 63, + WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; static const struct wacom_features wacom_features_0xFA = - { "Wacom Cintiq 22HD", WACOM_PKGLEN_INTUOS, 95640, 54060, 2047, - 63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; + { "Wacom Cintiq 22HD", 95640, 54060, 2047, 63, + WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; static const struct wacom_features wacom_features_0x5B = - { "Wacom Cintiq 22HDT", WACOM_PKGLEN_INTUOS, 95640, 54060, 2047, - 63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, + { "Wacom Cintiq 22HDT", 95640, 54060, 2047, 63, + WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e }; static const struct wacom_features wacom_features_0x5E = { "Wacom Cintiq 22HDT", .type = WACOM_24HDT, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5b, .touch_max = 10, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x90 = - { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, - 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 90", 26202, 16325, 255, 0, + TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x93 = - { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, - 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 93", 26202, 16325, 255, 0, + TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x97 = - { "Wacom ISDv4 97", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 511, - 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 97", 26202, 16325, 511, 0, + TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x9A = - { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, - 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 9A", 26202, 16325, 255, 0, + TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x9F = - { "Wacom ISDv4 9F", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, - 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 9F", 26202, 16325, 255, 0, + TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xE2 = - { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, - 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 2 }; + { "Wacom ISDv4 E2", 26202, 16325, 255, 0, + TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; static const struct wacom_features wacom_features_0xE3 = - { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, - 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 2 }; + { "Wacom ISDv4 E3", 26202, 16325, 255, 0, + TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; static const struct wacom_features wacom_features_0xE5 = - { "Wacom ISDv4 E5", WACOM_PKGLEN_MTOUCH, 26202, 16325, 255, - 0, MTSCREEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 E5", 26202, 16325, 255, 0, + MTSCREEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xE6 = - { "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255, - 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 2 }; + { "Wacom ISDv4 E6", 27760, 15694, 255, 0, + TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; static const struct wacom_features wacom_features_0xEC = - { "Wacom ISDv4 EC", WACOM_PKGLEN_GRAPHIRE, 25710, 14500, 255, - 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 EC", 25710, 14500, 255, 0, + TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xED = - { "Wacom ISDv4 ED", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, - 0, TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 ED", 26202, 16325, 255, 0, + TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xEF = - { "Wacom ISDv4 EF", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, - 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 EF", 26202, 16325, 255, 0, + TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x100 = - { "Wacom ISDv4 100", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, - 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 100", 26202, 16325, 255, 0, + MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x101 = - { "Wacom ISDv4 101", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, - 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 101", 26202, 16325, 255, 0, + MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x10D = - { "Wacom ISDv4 10D", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, - 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 10D", 26202, 16325, 255, 0, + MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x10E = - { "Wacom ISDv4 10E", WACOM_PKGLEN_MTTPC, 27760, 15694, 255, - 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 10E", 27760, 15694, 255, 0, + MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x10F = - { "Wacom ISDv4 10F", WACOM_PKGLEN_MTTPC, 27760, 15694, 255, - 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 10F", 27760, 15694, 255, 0, + MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x116 = - { "Wacom ISDv4 116", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, - 0, TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 116", 26202, 16325, 255, 0, + TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x4001 = - { "Wacom ISDv4 4001", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, - 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 4001", 26202, 16325, 255, 0, + MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x4004 = - { "Wacom ISDv4 4004", WACOM_PKGLEN_MTTPC, 11060, 6220, 255, - 0, MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 4004", 11060, 6220, 255, 0, + MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x5000 = - { "Wacom ISDv4 5000", WACOM_PKGLEN_MTTPC, 27848, 15752, 1023, - 0, MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 5000", 27848, 15752, 1023, 0, + MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x5002 = - { "Wacom ISDv4 5002", WACOM_PKGLEN_MTTPC, 29576, 16724, 1023, - 0, MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom ISDv4 5002", 29576, 16724, 1023, 0, + MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x47 = - { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, - 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Intuos2 6x8", 20320, 16240, 1023, 31, + INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x84 = - { "Wacom Wireless Receiver", WACOM_PKGLEN_WIRELESS, 0, 0, 0, - 0, WIRELESS, 0, 0, .touch_max = 16 }; + { "Wacom Wireless Receiver", 0, 0, 0, 0, + WIRELESS, 0, 0, .touch_max = 16 }; static const struct wacom_features wacom_features_0xD0 = - { "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 2 }; + { "Wacom Bamboo 2FG", 14720, 9200, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; static const struct wacom_features wacom_features_0xD1 = - { "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 2 }; + { "Wacom Bamboo 2FG 4x5", 14720, 9200, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; static const struct wacom_features wacom_features_0xD2 = - { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 2 }; + { "Wacom Bamboo Craft", 14720, 9200, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; static const struct wacom_features wacom_features_0xD3 = - { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 2 }; + { "Wacom Bamboo 2FG 6x8", 21648, 13700, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; static const struct wacom_features wacom_features_0xD4 = - { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Bamboo Pen", 14720, 9200, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xD5 = - { "Wacom Bamboo Pen 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Bamboo Pen 6x8", 21648, 13700, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xD6 = - { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 2 }; + { "Wacom BambooPT 2FG 4x5", 14720, 9200, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; static const struct wacom_features wacom_features_0xD7 = - { "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 2 }; + { "Wacom BambooPT 2FG Small", 14720, 9200, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; static const struct wacom_features wacom_features_0xD8 = - { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 2 }; + { "Wacom Bamboo Comic 2FG", 21648, 13700, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; static const struct wacom_features wacom_features_0xDA = - { "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 2 }; + { "Wacom Bamboo 2FG 4x5 SE", 14720, 9200, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; static const struct wacom_features wacom_features_0xDB = - { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 2 }; + { "Wacom Bamboo 2FG 6x8 SE", 21648, 13700, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; static const struct wacom_features wacom_features_0xDD = - { "Wacom Bamboo Connect", WACOM_PKGLEN_BBPEN, 14720, 9200, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Bamboo Connect", 14720, 9200, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xDE = - { "Wacom Bamboo 16FG 4x5", WACOM_PKGLEN_BBPEN, 14720, 9200, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 16 }; + { "Wacom Bamboo 16FG 4x5", 14720, 9200, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16 }; static const struct wacom_features wacom_features_0xDF = - { "Wacom Bamboo 16FG 6x8", WACOM_PKGLEN_BBPEN, 21648, 13700, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 16 }; + { "Wacom Bamboo 16FG 6x8", 21648, 13700, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16 }; static const struct wacom_features wacom_features_0x300 = - { "Wacom Bamboo One S", WACOM_PKGLEN_BBPEN, 14720, 9225, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Bamboo One S", 14720, 9225, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x301 = - { "Wacom Bamboo One M", WACOM_PKGLEN_BBPEN, 21648, 13530, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom Bamboo One M", 21648, 13530, 1023, 31, + BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x302 = - { "Wacom Intuos PT S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023, - 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 16, + { "Wacom Intuos PT S", 15200, 9500, 1023, 31, + INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x303 = - { "Wacom Intuos PT M", WACOM_PKGLEN_BBPEN, 21600, 13500, 1023, - 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, - .touch_max = 16, + { "Wacom Intuos PT M", 21600, 13500, 1023, 31, + INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x30E = - { "Wacom Intuos S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023, - 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + { "Wacom Intuos S", 15200, 9500, 1023, 31, + INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x6004 = - { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, - 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "ISD-V4", 12800, 8000, 255, 0, + TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x0307 = - { "Wacom ISDv5 307", WACOM_PKGLEN_INTUOS, 59352, 33648, 2047, - 63, CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, + { "Wacom ISDv5 307", 59352, 33648, 2047, 63, + CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 }; static const struct wacom_features wacom_features_0x0309 = { "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */ diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 2a7612ae14a6..4c592475b237 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -114,7 +114,6 @@ enum { struct wacom_features { const char *name; - int pktlen; int x_max; int y_max; int pressure_max; @@ -137,6 +136,7 @@ struct wacom_features { unsigned touch_max; int oVid; int oPid; + int pktlen; bool check_for_hid_type; int hid_type; }; From a3e6f6543d1969f1931b4f68fdd1a230b620ead8 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 13:05:49 -0700 Subject: [PATCH 22/37] Input: wacom - keep wacom_ids ordered No Functional changes, just some reordering. Signed-off-by: Benjamin Tissoires Reviewed-by: Jason Gerecke Tested-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 79 ++++++++++++++++---------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 15b0132265e3..cd915211fcca 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -2399,11 +2399,11 @@ static const struct wacom_features wacom_features_0x30E = static const struct wacom_features wacom_features_0x6004 = { "ISD-V4", 12800, 8000, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; -static const struct wacom_features wacom_features_0x0307 = +static const struct wacom_features wacom_features_0x307 = { "Wacom ISDv5 307", 59352, 33648, 2047, 63, CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 }; -static const struct wacom_features wacom_features_0x0309 = +static const struct wacom_features wacom_features_0x309 = { "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; @@ -2418,6 +2418,7 @@ static const struct wacom_features wacom_features_0x0309 = const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x00) }, + { USB_DEVICE_WACOM(0x03) }, { USB_DEVICE_WACOM(0x10) }, { USB_DEVICE_WACOM(0x11) }, { USB_DEVICE_WACOM(0x12) }, @@ -2428,20 +2429,16 @@ const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x17) }, { USB_DEVICE_WACOM(0x18) }, { USB_DEVICE_WACOM(0x19) }, - { USB_DEVICE_WACOM(0x60) }, - { USB_DEVICE_WACOM(0x61) }, - { USB_DEVICE_WACOM(0x62) }, - { USB_DEVICE_WACOM(0x63) }, - { USB_DEVICE_WACOM(0x64) }, - { USB_DEVICE_WACOM(0x65) }, - { USB_DEVICE_WACOM(0x69) }, - { USB_DEVICE_WACOM(0x6A) }, - { USB_DEVICE_WACOM(0x6B) }, { USB_DEVICE_WACOM(0x20) }, { USB_DEVICE_WACOM(0x21) }, { USB_DEVICE_WACOM(0x22) }, { USB_DEVICE_WACOM(0x23) }, { USB_DEVICE_WACOM(0x24) }, + { USB_DEVICE_WACOM(0x26) }, + { USB_DEVICE_WACOM(0x27) }, + { USB_DEVICE_WACOM(0x28) }, + { USB_DEVICE_WACOM(0x29) }, + { USB_DEVICE_WACOM(0x2A) }, { USB_DEVICE_WACOM(0x30) }, { USB_DEVICE_WACOM(0x31) }, { USB_DEVICE_WACOM(0x32) }, @@ -2451,20 +2448,33 @@ const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x37) }, { USB_DEVICE_WACOM(0x38) }, { USB_DEVICE_WACOM(0x39) }, - { USB_DEVICE_WACOM(0xC4) }, - { USB_DEVICE_WACOM(0xC0) }, - { USB_DEVICE_WACOM(0xC2) }, - { USB_DEVICE_WACOM(0x03) }, + { USB_DEVICE_WACOM(0x3F) }, { USB_DEVICE_WACOM(0x41) }, { USB_DEVICE_WACOM(0x42) }, { USB_DEVICE_WACOM(0x43) }, { USB_DEVICE_WACOM(0x44) }, { USB_DEVICE_WACOM(0x45) }, + { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0x57) }, { USB_DEVICE_WACOM(0x59) }, - { USB_DEVICE_WACOM(0x5D) }, { USB_DEVICE_WACOM(0x5B) }, + { USB_DEVICE_WACOM(0x5D) }, { USB_DEVICE_WACOM(0x5E) }, + { USB_DEVICE_WACOM(0x60) }, + { USB_DEVICE_WACOM(0x61) }, + { USB_DEVICE_WACOM(0x62) }, + { USB_DEVICE_WACOM(0x63) }, + { USB_DEVICE_WACOM(0x64) }, + { USB_DEVICE_WACOM(0x65) }, + { USB_DEVICE_WACOM(0x69) }, + { USB_DEVICE_WACOM(0x6A) }, + { USB_DEVICE_WACOM(0x6B) }, + { USB_DEVICE_WACOM(0x84) }, + { USB_DEVICE_WACOM(0x90) }, + { USB_DEVICE_WACOM(0x93) }, + { USB_DEVICE_WACOM(0x97) }, + { USB_DEVICE_WACOM(0x9A) }, + { USB_DEVICE_WACOM(0x9F) }, { USB_DEVICE_WACOM(0xB0) }, { USB_DEVICE_WACOM(0xB1) }, { USB_DEVICE_WACOM(0xB2) }, @@ -2477,17 +2487,14 @@ const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xBA) }, { USB_DEVICE_WACOM(0xBB) }, { USB_DEVICE_WACOM(0xBC) }, - { USB_DEVICE_WACOM(0x26) }, - { USB_DEVICE_WACOM(0x27) }, - { USB_DEVICE_WACOM(0x28) }, - { USB_DEVICE_WACOM(0x29) }, - { USB_DEVICE_WACOM(0x2A) }, - { USB_DEVICE_WACOM(0x3F) }, + { USB_DEVICE_WACOM(0xC0) }, + { USB_DEVICE_WACOM(0xC2) }, + { USB_DEVICE_WACOM(0xC4) }, { USB_DEVICE_WACOM(0xC5) }, { USB_DEVICE_WACOM(0xC6) }, { USB_DEVICE_WACOM(0xC7) }, + { USB_DEVICE_WACOM(0xCC) }, { USB_DEVICE_WACOM(0xCE) }, - { USB_DEVICE_WACOM(0x84) }, { USB_DEVICE_WACOM(0xD0) }, { USB_DEVICE_WACOM(0xD1) }, { USB_DEVICE_WACOM(0xD2) }, @@ -2502,13 +2509,6 @@ const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xDD) }, { USB_DEVICE_WACOM(0xDE) }, { USB_DEVICE_WACOM(0xDF) }, - { USB_DEVICE_WACOM(0xF0) }, - { USB_DEVICE_WACOM(0xCC) }, - { USB_DEVICE_WACOM(0x90) }, - { USB_DEVICE_WACOM(0x93) }, - { USB_DEVICE_WACOM(0x97) }, - { USB_DEVICE_WACOM(0x9A) }, - { USB_DEVICE_WACOM(0x9F) }, { USB_DEVICE_WACOM(0xE2) }, { USB_DEVICE_WACOM(0xE3) }, { USB_DEVICE_WACOM(0xE5) }, @@ -2516,6 +2516,12 @@ const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xEC) }, { USB_DEVICE_WACOM(0xED) }, { USB_DEVICE_WACOM(0xEF) }, + { USB_DEVICE_WACOM(0xF0) }, + { USB_DEVICE_WACOM(0xF4) }, + { USB_DEVICE_WACOM(0xF6) }, + { USB_DEVICE_WACOM(0xF8) }, + { USB_DEVICE_WACOM(0xFA) }, + { USB_DEVICE_WACOM(0xFB) }, { USB_DEVICE_WACOM(0x100) }, { USB_DEVICE_WACOM(0x101) }, { USB_DEVICE_WACOM(0x10D) }, @@ -2526,8 +2532,10 @@ const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x301) }, { USB_DEVICE_WACOM(0x302) }, { USB_DEVICE_WACOM(0x303) }, - { USB_DEVICE_WACOM(0x30E) }, { USB_DEVICE_WACOM(0x304) }, + { USB_DEVICE_WACOM(0x307) }, + { USB_DEVICE_WACOM(0x309) }, + { USB_DEVICE_WACOM(0x30E) }, { USB_DEVICE_WACOM(0x314) }, { USB_DEVICE_WACOM(0x315) }, { USB_DEVICE_WACOM(0x317) }, @@ -2535,15 +2543,6 @@ const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x4004) }, { USB_DEVICE_WACOM(0x5000) }, { USB_DEVICE_WACOM(0x5002) }, - { USB_DEVICE_WACOM(0x47) }, - { USB_DEVICE_WACOM(0xF4) }, - { USB_DEVICE_WACOM(0xF8) }, - { USB_DEVICE_WACOM(0xF6) }, - { USB_DEVICE_WACOM(0xFA) }, - { USB_DEVICE_WACOM(0xFB) }, - { USB_DEVICE_WACOM(0x0307) }, - { USB_DEVICE_WACOM(0x0309) }, - { USB_DEVICE_LENOVO(0x6004) }, { } }; MODULE_DEVICE_TABLE(hid, wacom_ids); From 471d17148c8b4174ac5f5283a73316d12c4379bc Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 13:10:09 -0700 Subject: [PATCH 23/37] Input: wacom - move the USB (now hid) Wacom driver in drivers/hid wacom.ko is now a full HID driver, we have to move it into the proper subdirectory: drivers/hid. Signed-off-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/hid/Kconfig | 13 +++++++++++++ drivers/hid/Makefile | 3 +++ drivers/{input/tablet => hid}/wacom.h | 0 drivers/{input/tablet => hid}/wacom_sys.c | 0 drivers/{input/tablet => hid}/wacom_wac.c | 0 drivers/{input/tablet => hid}/wacom_wac.h | 0 drivers/input/tablet/Kconfig | 16 ---------------- drivers/input/tablet/Makefile | 3 --- 8 files changed, 16 insertions(+), 19 deletions(-) rename drivers/{input/tablet => hid}/wacom.h (100%) rename drivers/{input/tablet => hid}/wacom_sys.c (100%) rename drivers/{input/tablet => hid}/wacom_wac.c (100%) rename drivers/{input/tablet => hid}/wacom_wac.h (100%) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 5e79c6ad914f..64366f1feb17 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -755,6 +755,19 @@ config HID_WACOM ---help--- Support for Wacom Graphire Bluetooth and Intuos4 WL tablets. +config HID_USB_WACOM + tristate "Wacom Intuos/Graphire tablet support (USB)" + depends on HID + select POWER_SUPPLY + select NEW_LEDS + select LEDS_CLASS + help + Say Y here if you want to use the USB version of the Wacom Intuos + or Graphire tablet. + + To compile this driver as a module, choose M here: the + module will be called wacom. + config HID_WIIMOTE tristate "Nintendo Wii / Wii U peripherals" depends on HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index a6fa6baf368e..55b69acdb680 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -116,6 +116,9 @@ obj-$(CONFIG_HID_XINMO) += hid-xinmo.o obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o obj-$(CONFIG_HID_WACOM) += hid-wacom.o + +wacom-objs := wacom_wac.o wacom_sys.o +obj-$(CONFIG_HID_USB_WACOM) += wacom.o obj-$(CONFIG_HID_WALTOP) += hid-waltop.o obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o diff --git a/drivers/input/tablet/wacom.h b/drivers/hid/wacom.h similarity index 100% rename from drivers/input/tablet/wacom.h rename to drivers/hid/wacom.h diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/hid/wacom_sys.c similarity index 100% rename from drivers/input/tablet/wacom_sys.c rename to drivers/hid/wacom_sys.c diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/hid/wacom_wac.c similarity index 100% rename from drivers/input/tablet/wacom_wac.c rename to drivers/hid/wacom_wac.c diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/hid/wacom_wac.h similarity index 100% rename from drivers/input/tablet/wacom_wac.h rename to drivers/hid/wacom_wac.h diff --git a/drivers/input/tablet/Kconfig b/drivers/input/tablet/Kconfig index bed7cbf84cfd..cd9c79e0a11b 100644 --- a/drivers/input/tablet/Kconfig +++ b/drivers/input/tablet/Kconfig @@ -73,20 +73,4 @@ config TABLET_USB_KBTAB To compile this driver as a module, choose M here: the module will be called kbtab. -config TABLET_USB_WACOM - tristate "Wacom Intuos/Graphire tablet support (USB)" - depends on USB_ARCH_HAS_HCD - select POWER_SUPPLY - select USB - select NEW_LEDS - select LEDS_CLASS - help - Say Y here if you want to use the USB version of the Wacom Intuos - or Graphire tablet. Make sure to say Y to "Mouse support" - (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" - (CONFIG_INPUT_EVDEV) as well. - - To compile this driver as a module, choose M here: the - module will be called wacom. - endif diff --git a/drivers/input/tablet/Makefile b/drivers/input/tablet/Makefile index 3f6c25220638..cc3bc17d5b08 100644 --- a/drivers/input/tablet/Makefile +++ b/drivers/input/tablet/Makefile @@ -2,12 +2,9 @@ # Makefile for the tablet drivers # -# Multipart objects. -wacom-objs := wacom_wac.o wacom_sys.o obj-$(CONFIG_TABLET_USB_ACECAD) += acecad.o obj-$(CONFIG_TABLET_USB_AIPTEK) += aiptek.o obj-$(CONFIG_TABLET_USB_GTCO) += gtco.o obj-$(CONFIG_TABLET_USB_HANWANG) += hanwang.o obj-$(CONFIG_TABLET_USB_KBTAB) += kbtab.o -obj-$(CONFIG_TABLET_USB_WACOM) += wacom.o From 0b335cad73c800717856f8f5a5509d367c38b61d Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Thu, 24 Jul 2014 13:15:31 -0700 Subject: [PATCH 24/37] Input: wacom - support up to 2048 pressure levels with ISDv4 Signed-off-by: Jason Gerecke Signed-off-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/hid/wacom_wac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index cd915211fcca..2f3a3a77d0c6 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1086,7 +1086,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom) input_report_key(input, BTN_STYLUS2, data[1] & 0x10); input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); - input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x03) << 8) | data[6]); + input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x07) << 8) | data[6]); input_report_key(input, BTN_TOUCH, data[1] & 0x05); input_report_key(input, wacom->tool[0], prox); return 1; From c757cbafd6afe8e47d12320aa05edcd1b1d97186 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 24 Jul 2014 13:16:17 -0700 Subject: [PATCH 25/37] Input: wacom - put a flag when the led are initialized This solves a bug with the wireless receiver: - at plug, the wireless receiver does not know which Wacom device it is connected to, so it does not actually creates all the LEDs - when the tablet connects, wacom->wacom_wac.features.type is set to the proper device so that wacom_wac can understand the packets - when the receiver is unplugged, it detects that a LED should have been created (based on wacom->wacom_wac.features.type) and tries to remove it: crash when removing the sysfs group. Side effect, we can now safely call several times wacom_destroy_leds(). Signed-off-by: Benjamin Tissoires Acked-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/hid/wacom.h | 1 + drivers/hid/wacom_sys.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index dd67b7da8a97..a678f827e39e 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h @@ -118,6 +118,7 @@ struct wacom { u8 hlv; /* status led brightness button pressed (1..127) */ u8 img_lum; /* OLED matrix display brightness */ } led; + bool led_initialized; struct power_supply battery; }; diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 06e304b3bbfd..f1c6d3dae248 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -729,12 +729,18 @@ static int wacom_initialize_leds(struct wacom *wacom) return error; } wacom_led_control(wacom); + wacom->led_initialized = true; return 0; } static void wacom_destroy_leds(struct wacom *wacom) { + if (!wacom->led_initialized) + return; + + wacom->led_initialized = false; + switch (wacom->wacom_wac.features.type) { case INTUOS4S: case INTUOS4: From ac8d10101b0e3a0a1478f8bb51bbbb0a56fe0956 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 25 Jul 2014 17:29:48 -0700 Subject: [PATCH 26/37] Input: wacom - enhance Wireless Receiver battery reporting - Reports the current status of the battery (discharging, charging, full). - Also notify the upower daemon when there is a change in the battery value. - keep the battery value as a percentage, not the raw value - add WACOM_QUIRK_BATTERY to easily add a battery to a device (required for Bluetooth devices) Signed-off-by: Benjamin Tissoires Acked-by: Przemo Firszt Acked-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/hid/wacom.h | 7 +++++++ drivers/hid/wacom_sys.c | 19 +++++++++++++++---- drivers/hid/wacom_wac.c | 22 ++++++++++++++++++---- drivers/hid/wacom_wac.h | 3 +++ 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index a678f827e39e..98cb93f16ba4 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h @@ -128,6 +128,13 @@ static inline void wacom_schedule_work(struct wacom_wac *wacom_wac) schedule_work(&wacom->work); } +static inline void wacom_notify_battery(struct wacom_wac *wacom_wac) +{ + struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); + + power_supply_changed(&wacom->battery); +} + extern const struct hid_device_id wacom_ids[]; void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index f1c6d3dae248..f8744c4d3b18 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -769,6 +769,7 @@ static void wacom_destroy_leds(struct wacom *wacom) } static enum power_supply_property wacom_battery_props[] = { + POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_SCOPE, POWER_SUPPLY_PROP_CAPACITY }; @@ -786,7 +787,16 @@ static int wacom_battery_get_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_CAPACITY: val->intval = - wacom->wacom_wac.battery_capacity * 100 / 31; + wacom->wacom_wac.battery_capacity; + break; + case POWER_SUPPLY_PROP_STATUS: + if (wacom->wacom_wac.bat_charging) + val->intval = POWER_SUPPLY_STATUS_CHARGING; + else if (wacom->wacom_wac.battery_capacity == 100 && + wacom->wacom_wac.ps_connected) + val->intval = POWER_SUPPLY_STATUS_FULL; + else + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; break; default: ret = -EINVAL; @@ -800,7 +810,7 @@ static int wacom_initialize_battery(struct wacom *wacom) { int error = 0; - if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) { + if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) { wacom->battery.properties = wacom_battery_props; wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props); wacom->battery.get_property = wacom_battery_get_property; @@ -821,8 +831,8 @@ static int wacom_initialize_battery(struct wacom *wacom) static void wacom_destroy_battery(struct wacom *wacom) { - if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR && - wacom->battery.dev) { + if ((wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) && + wacom->battery.dev) { power_supply_unregister(&wacom->battery); wacom->battery.dev = NULL; } @@ -947,6 +957,7 @@ static void wacom_wireless_work(struct work_struct *work) if (wacom_wac->pid == 0) { hid_info(wacom->hdev, "wireless tablet disconnected\n"); + wacom_wac1->shared->type = 0; } else { const struct hid_device_id *id = wacom_ids; diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 2f3a3a77d0c6..cfd2ae13c287 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1365,7 +1365,7 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) connected = data[1] & 0x01; if (connected) { - int pid, battery; + int pid, battery, ps_connected; if ((wacom->shared->type == INTUOSHT) && wacom->shared->touch_max) { @@ -1375,17 +1375,29 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) } pid = get_unaligned_be16(&data[6]); - battery = data[5] & 0x3f; + battery = (data[5] & 0x3f) * 100 / 31; + ps_connected = !!(data[5] & 0x80); if (wacom->pid != pid) { wacom->pid = pid; wacom_schedule_work(wacom); } - wacom->battery_capacity = battery; + + if (wacom->shared->type && + (battery != wacom->battery_capacity || + ps_connected != wacom->ps_connected)) { + wacom->battery_capacity = battery; + wacom->ps_connected = ps_connected; + wacom->bat_charging = ps_connected && + wacom->battery_capacity < 100; + wacom_notify_battery(wacom); + } } else if (wacom->pid != 0) { /* disconnected while previously connected */ wacom->pid = 0; wacom_schedule_work(wacom); wacom->battery_capacity = 0; + wacom->bat_charging = 0; + wacom->ps_connected = 0; } return 0; @@ -1558,8 +1570,10 @@ void wacom_setup_device_quirks(struct wacom_features *features) features->quirks |= WACOM_QUIRK_NO_INPUT; /* must be monitor interface if no device_type set */ - if (!features->device_type) + if (!features->device_type) { features->quirks |= WACOM_QUIRK_MONITOR; + features->quirks |= WACOM_QUIRK_BATTERY; + } } } diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 4c592475b237..8a042ac0114e 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -68,6 +68,7 @@ #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002 #define WACOM_QUIRK_NO_INPUT 0x0004 #define WACOM_QUIRK_MONITOR 0x0008 +#define WACOM_QUIRK_BATTERY 0x0010 enum { PENPARTNER = 0, @@ -164,6 +165,8 @@ struct wacom_wac { int pid; int battery_capacity; int num_contacts_left; + int bat_charging; + int ps_connected; }; #endif From d70420b914c98a3758674c6e9858810e0ab4ea30 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 25 Jul 2014 17:31:51 -0700 Subject: [PATCH 27/37] Input: wacom - use a uniq name for the battery device The current implementation uses "wacom_battery" as a generic name for batteries. This prevents us to have two Wacom devices with a battery attached as the power system will complain about the name which is already registered. Use an incremental name for each battery attached. Related bug: https://sourceforge.net/p/linuxwacom/bugs/248/ Signed-off-by: Benjamin Tissoires Acked-by: Przemo Firszt Acked-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/hid/wacom_sys.c | 6 +++++- drivers/hid/wacom_wac.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index f8744c4d3b18..a27404d6e98d 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -809,12 +809,16 @@ static int wacom_battery_get_property(struct power_supply *psy, static int wacom_initialize_battery(struct wacom *wacom) { int error = 0; + static atomic_t battery_no = ATOMIC_INIT(0); + unsigned long n; if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) { + n = atomic_inc_return(&battery_no) - 1; wacom->battery.properties = wacom_battery_props; wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props); wacom->battery.get_property = wacom_battery_get_property; - wacom->battery.name = "wacom_battery"; + sprintf(wacom->wacom_wac.bat_name, "wacom_battery_%ld", n); + wacom->battery.name = wacom->wacom_wac.bat_name; wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY; wacom->battery.use_for_apm = 0; diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 8a042ac0114e..6cdf707821cd 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -154,6 +154,7 @@ struct wacom_shared { struct wacom_wac { char name[WACOM_NAME_MAX]; char pad_name[WACOM_NAME_MAX]; + char bat_name[WACOM_NAME_MAX]; unsigned char data[WACOM_PKGLEN_MAX]; int tool[2]; int id[2]; From 7dbd229e10603b3759f366007df2068dc2acfe46 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 25 Jul 2014 17:32:41 -0700 Subject: [PATCH 28/37] Input: wacom - register an ac power supply for wireless devices This is used by HID Bluetooth devices but also add some more information to the USB Wireless Receiver. We are just porting the bits from hid-wacom.c to the common driver here. Signed-off-by: Benjamin Tissoires Acked-by: Przemo Firszt Acked-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/hid/wacom.h | 1 + drivers/hid/wacom_sys.c | 58 +++++++++++++++++++++++++++++++++++++---- drivers/hid/wacom_wac.h | 1 + 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index 98cb93f16ba4..0b89ee77d7d1 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h @@ -120,6 +120,7 @@ struct wacom { } led; bool led_initialized; struct power_supply battery; + struct power_supply ac; }; static inline void wacom_schedule_work(struct wacom_wac *wacom_wac) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index a27404d6e98d..37888c3f39ba 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -774,6 +774,12 @@ static enum power_supply_property wacom_battery_props[] = { POWER_SUPPLY_PROP_CAPACITY }; +static enum power_supply_property wacom_ac_props[] = { + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_SCOPE, +}; + static int wacom_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -806,14 +812,38 @@ static int wacom_battery_get_property(struct power_supply *psy, return ret; } +static int wacom_ac_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct wacom *wacom = container_of(psy, struct wacom, ac); + int ret = 0; + + switch (psp) { + case POWER_SUPPLY_PROP_PRESENT: + /* fall through */ + case POWER_SUPPLY_PROP_ONLINE: + val->intval = wacom->wacom_wac.ps_connected; + break; + case POWER_SUPPLY_PROP_SCOPE: + val->intval = POWER_SUPPLY_SCOPE_DEVICE; + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + static int wacom_initialize_battery(struct wacom *wacom) { - int error = 0; static atomic_t battery_no = ATOMIC_INIT(0); + int error; unsigned long n; if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) { n = atomic_inc_return(&battery_no) - 1; + wacom->battery.properties = wacom_battery_props; wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props); wacom->battery.get_property = wacom_battery_get_property; @@ -822,15 +852,31 @@ static int wacom_initialize_battery(struct wacom *wacom) wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY; wacom->battery.use_for_apm = 0; + wacom->ac.properties = wacom_ac_props; + wacom->ac.num_properties = ARRAY_SIZE(wacom_ac_props); + wacom->ac.get_property = wacom_ac_get_property; + sprintf(wacom->wacom_wac.ac_name, "wacom_ac_%ld", n); + wacom->ac.name = wacom->wacom_wac.ac_name; + wacom->ac.type = POWER_SUPPLY_TYPE_MAINS; + wacom->ac.use_for_apm = 0; + error = power_supply_register(&wacom->hdev->dev, &wacom->battery); + if (error) + return error; - if (!error) - power_supply_powers(&wacom->battery, - &wacom->hdev->dev); + power_supply_powers(&wacom->battery, &wacom->hdev->dev); + + error = power_supply_register(&wacom->hdev->dev, &wacom->ac); + if (error) { + power_supply_unregister(&wacom->battery); + return error; + } + + power_supply_powers(&wacom->ac, &wacom->hdev->dev); } - return error; + return 0; } static void wacom_destroy_battery(struct wacom *wacom) @@ -839,6 +885,8 @@ static void wacom_destroy_battery(struct wacom *wacom) wacom->battery.dev) { power_supply_unregister(&wacom->battery); wacom->battery.dev = NULL; + power_supply_unregister(&wacom->ac); + wacom->ac.dev = NULL; } } diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 6cdf707821cd..3433a0e28bb4 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -155,6 +155,7 @@ struct wacom_wac { char name[WACOM_NAME_MAX]; char pad_name[WACOM_NAME_MAX]; char bat_name[WACOM_NAME_MAX]; + char ac_name[WACOM_NAME_MAX]; unsigned char data[WACOM_PKGLEN_MAX]; int tool[2]; int id[2]; From aeaf50d4e7d29d9a5f6da45fdcd9fb118f70fb93 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Mon, 28 Jul 2014 10:53:16 -0700 Subject: [PATCH 29/37] Input: wacom - add support for 0x12C ISDv4 sensor Signed-off-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/hid/wacom_wac.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index cfd2ae13c287..71646b311867 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2332,6 +2332,9 @@ static const struct wacom_features wacom_features_0x10F = static const struct wacom_features wacom_features_0x116 = { "Wacom ISDv4 116", 26202, 16325, 255, 0, TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x12C = + { "Wacom ISDv4 12C", 27848, 15752, 2047, 0, + TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x4001 = { "Wacom ISDv4 4001", 26202, 16325, 255, 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -2542,6 +2545,7 @@ const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x10E) }, { USB_DEVICE_WACOM(0x10F) }, { USB_DEVICE_WACOM(0x116) }, + { USB_DEVICE_WACOM(0x12C) }, { USB_DEVICE_WACOM(0x300) }, { USB_DEVICE_WACOM(0x301) }, { USB_DEVICE_WACOM(0x302) }, From f81a1295cd9b6d3d3d7d7126e522d80917134b41 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 6 Aug 2014 13:48:01 -0700 Subject: [PATCH 30/37] Input: wacom - prepare the driver to include BT devices Now that wacom is a hid driver, there is no point in having a separate driver for bluetooth devices. This patch prepares the common paths of Bluetooth devices in the common wacom driver. It also adds the sysfs file "speed" used by Bluetooth devices. Signed-off-by: Benjamin Tissoires Reviewed-by: Ping Cheng Tested-by: Przemo Firszt Signed-off-by: Dmitry Torokhov --- drivers/hid/wacom_sys.c | 70 +++++++++++++++++++++++++++++++++++++++-- drivers/hid/wacom_wac.h | 2 ++ 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 37888c3f39ba..18154a5459b5 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -262,6 +262,12 @@ static int wacom_set_device_mode(struct hid_device *hdev, int report_id, return error < 0 ? error : 0; } +static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed, + struct wacom_features *features) +{ + return 0; +} + /* * Switch the tablet into its most-capable mode. Wacom tablets are * typically configured to power-up in a mode which sends mouse-like @@ -272,6 +278,9 @@ static int wacom_set_device_mode(struct hid_device *hdev, int report_id, static int wacom_query_tablet_data(struct hid_device *hdev, struct wacom_features *features) { + if (hdev->bus == BUS_BLUETOOTH) + return wacom_bt_query_tablet_data(hdev, 1, features); + if (features->device_type == BTN_TOOL_FINGER) { if (features->type > TABLETPC) { /* MT Tablet PC touch */ @@ -890,6 +899,38 @@ static void wacom_destroy_battery(struct wacom *wacom) } } +static ssize_t wacom_show_speed(struct device *dev, + struct device_attribute + *attr, char *buf) +{ + struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct wacom *wacom = hid_get_drvdata(hdev); + + return snprintf(buf, PAGE_SIZE, "%i\n", wacom->wacom_wac.bt_high_speed); +} + +static ssize_t wacom_store_speed(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct wacom *wacom = hid_get_drvdata(hdev); + u8 new_speed; + + if (kstrtou8(buf, 0, &new_speed)) + return -EINVAL; + + if (new_speed != 0 && new_speed != 1) + return -EINVAL; + + wacom_bt_query_tablet_data(hdev, new_speed, &wacom->wacom_wac.features); + + return count; +} + +static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, + wacom_show_speed, wacom_store_speed); + static struct input_dev *wacom_allocate_input(struct wacom *wacom) { struct input_dev *input_dev; @@ -1210,6 +1251,9 @@ static int wacom_probe(struct hid_device *hdev, features->y_max = 4096; } + if (hdev->bus == BUS_BLUETOOTH) + features->quirks |= WACOM_QUIRK_BATTERY; + wacom_setup_device_quirks(features); /* set unit to "100th of a mm" for devices not reported by HID */ @@ -1241,10 +1285,25 @@ static int wacom_probe(struct hid_device *hdev, if (error) goto fail2; + if (!(features->quirks & WACOM_QUIRK_MONITOR) && + (features->quirks & WACOM_QUIRK_BATTERY)) { + error = wacom_initialize_battery(wacom); + if (error) + goto fail3; + } + if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) { error = wacom_register_inputs(wacom); if (error) - goto fail3; + goto fail4; + } + + if (hdev->bus == BUS_BLUETOOTH) { + error = device_create_file(&hdev->dev, &dev_attr_speed); + if (error) + hid_warn(hdev, + "can't create sysfs speed attribute err: %d\n", + error); } /* Note that if query fails it is not a hard failure */ @@ -1254,7 +1313,7 @@ static int wacom_probe(struct hid_device *hdev, error = hid_hw_start(hdev, HID_CONNECT_HIDRAW); if (error) { hid_err(hdev, "hw start failed\n"); - goto fail4; + goto fail5; } if (features->quirks & WACOM_QUIRK_MONITOR) @@ -1267,7 +1326,10 @@ static int wacom_probe(struct hid_device *hdev, return 0; - fail4: wacom_unregister_inputs(wacom); + fail5: if (hdev->bus == BUS_BLUETOOTH) + device_remove_file(&hdev->dev, &dev_attr_speed); + wacom_unregister_inputs(wacom); + fail4: wacom_destroy_battery(wacom); fail3: wacom_destroy_leds(wacom); fail2: wacom_remove_shared_data(wacom_wac); fail1: kfree(wacom); @@ -1283,6 +1345,8 @@ static void wacom_remove(struct hid_device *hdev) cancel_work_sync(&wacom->work); wacom_unregister_inputs(wacom); + if (hdev->bus == BUS_BLUETOOTH) + device_remove_file(&hdev->dev, &dev_attr_speed); wacom_destroy_battery(wacom); wacom_destroy_leds(wacom); wacom_remove_shared_data(&wacom->wacom_wac); diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 3433a0e28bb4..6cefa1e8c14b 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -169,6 +169,8 @@ struct wacom_wac { int num_contacts_left; int bat_charging; int ps_connected; + u8 bt_features; + u8 bt_high_speed; }; #endif From 387142bb8fcb263771e1fa6b1a96e6a7ca36e820 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 6 Aug 2014 13:52:56 -0700 Subject: [PATCH 31/37] Input: wacom - handle Graphire BT tablets in wacom.ko First, merge the Graphire BT tablet. Signed-off-by: Benjamin Tissoires Reviewed-by: Ping Cheng Tested-by: Przemo Firszt Signed-off-by: Dmitry Torokhov --- drivers/hid/hid-core.c | 1 - drivers/hid/hid-wacom.c | 1 - drivers/hid/wacom_sys.c | 33 +++++++++++++ drivers/hid/wacom_wac.c | 100 ++++++++++++++++++++++++++++++++++++++-- drivers/hid/wacom_wac.h | 2 + 5 files changed, 132 insertions(+), 5 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 1ce751db5a7a..cbabd8786e71 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1942,7 +1942,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 4874f4ec43f5..967c457a2785 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -952,7 +952,6 @@ static void wacom_remove(struct hid_device *hdev) } static const struct hid_device_id wacom_devices[] = { - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) }, { } diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 18154a5459b5..c21e58ba0693 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -265,6 +265,39 @@ static int wacom_set_device_mode(struct hid_device *hdev, int report_id, static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed, struct wacom_features *features) { + struct wacom *wacom = hid_get_drvdata(hdev); + int ret; + u8 rep_data[2]; + + switch (features->type) { + case GRAPHIRE_BT: + rep_data[0] = 0x03; + rep_data[1] = 0x00; + ret = wacom_set_report(hdev, HID_FEATURE_REPORT, + rep_data[0], rep_data, 2, 3); + + if (ret >= 0) { + rep_data[0] = speed == 0 ? 0x05 : 0x06; + rep_data[1] = 0x00; + + ret = wacom_set_report(hdev, HID_FEATURE_REPORT, + rep_data[0], rep_data, 2, 3); + + if (ret >= 0) { + wacom->wacom_wac.bt_high_speed = speed; + return 0; + } + } + + /* + * Note that if the raw queries fail, it's not a hard failure + * and it is safe to continue + */ + hid_warn(hdev, "failed to poke device, command %d, err %d\n", + rep_data[0], ret); + break; + } + return 0; } diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 71646b311867..fa16a5bf3df3 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -25,11 +25,18 @@ #define WACOM_INTUOS_RES 100 #define WACOM_INTUOS3_RES 200 -/* Scale factor relating reported contact size to logical contact area. +/* + * Scale factor relating reported contact size to logical contact area. * 2^14/pi is a good approximation on Intuos5 and 3rd-gen Bamboo */ #define WACOM_CONTACT_AREA_SCALE 2607 +/* + * Percent of battery capacity for Graphire. + * 8th value means AC online and show 100% capacity. + */ +static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 }; + static int wacom_penpartner_irq(struct wacom_wac *wacom) { unsigned char *data = wacom->data; @@ -263,11 +270,19 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) unsigned char *data = wacom->data; struct input_dev *input = wacom->input; struct input_dev *pad_input = wacom->pad_input; + int battery_capacity, ps_connected; int prox; int rw = 0; int retval = 0; - if (data[0] != WACOM_REPORT_PENABLED) { + if (features->type == GRAPHIRE_BT) { + if (data[0] != WACOM_REPORT_PENABLED_BT) { + dev_dbg(input->dev.parent, + "%s: received unknown report #%d\n", __func__, + data[0]); + goto exit; + } + } else if (data[0] != WACOM_REPORT_PENABLED) { dev_dbg(input->dev.parent, "%s: received unknown report #%d\n", __func__, data[0]); goto exit; @@ -301,7 +316,12 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); if (wacom->tool[0] != BTN_TOOL_MOUSE) { - input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x03) << 8)); + if (features->type == GRAPHIRE_BT) + input_report_abs(input, ABS_PRESSURE, data[6] | + (((__u16) (data[1] & 0x08)) << 5)); + else + input_report_abs(input, ABS_PRESSURE, data[6] | + ((data[7] & 0x03) << 8)); input_report_key(input, BTN_TOUCH, data[1] & 0x01); input_report_key(input, BTN_STYLUS, data[1] & 0x02); input_report_key(input, BTN_STYLUS2, data[1] & 0x04); @@ -312,6 +332,20 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) features->type == WACOM_MO) { input_report_abs(input, ABS_DISTANCE, data[6] & 0x3f); rw = (data[7] & 0x04) - (data[7] & 0x03); + } else if (features->type == GRAPHIRE_BT) { + /* Compute distance between mouse and tablet */ + rw = 44 - (data[6] >> 2); + rw = clamp_val(rw, 0, 31); + input_report_abs(input, ABS_DISTANCE, rw); + if (((data[1] >> 5) & 3) == 2) { + /* Mouse with wheel */ + input_report_key(input, BTN_MIDDLE, + data[1] & 0x04); + rw = (data[6] & 0x01) ? -1 : + (data[6] & 0x02) ? 1 : 0; + } else { + rw = 0; + } } else { input_report_abs(input, ABS_DISTANCE, data[7] & 0x3f); rw = -(signed char)data[6]; @@ -358,6 +392,31 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) retval = 1; } break; + case GRAPHIRE_BT: + prox = data[7] & 0x03; + if (prox || wacom->id[1]) { + wacom->id[1] = PAD_DEVICE_ID; + input_report_key(pad_input, BTN_0, (data[7] & 0x02)); + input_report_key(pad_input, BTN_1, (data[7] & 0x01)); + if (!prox) + wacom->id[1] = 0; + input_report_abs(pad_input, ABS_MISC, wacom->id[1]); + retval = 1; + } + break; + } + + /* Store current battery capacity and power supply state */ + if (features->type == GRAPHIRE_BT) { + rw = (data[7] >> 2 & 0x07); + battery_capacity = batcap_gr[rw]; + ps_connected = rw == 7; + if ((wacom->battery_capacity != battery_capacity) || + (wacom->ps_connected != ps_connected)) { + wacom->battery_capacity = battery_capacity; + wacom->ps_connected = ps_connected; + wacom_notify_battery(wacom); + } } exit: return retval; @@ -1418,6 +1477,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) case WACOM_G4: case GRAPHIRE: + case GRAPHIRE_BT: case WACOM_MO: sync = wacom_graphire_irq(wacom_wac); break; @@ -1654,6 +1714,27 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, __set_bit(INPUT_PROP_POINTER, input_dev->propbit); break; + case GRAPHIRE_BT: + __clear_bit(ABS_MISC, input_dev->absbit); + input_set_abs_params(input_dev, ABS_DISTANCE, 0, + features->distance_max, + 0, 0); + + input_set_capability(input_dev, EV_REL, REL_WHEEL); + + __set_bit(BTN_LEFT, input_dev->keybit); + __set_bit(BTN_RIGHT, input_dev->keybit); + __set_bit(BTN_MIDDLE, input_dev->keybit); + + __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); + __set_bit(BTN_TOOL_PEN, input_dev->keybit); + __set_bit(BTN_TOOL_MOUSE, input_dev->keybit); + __set_bit(BTN_STYLUS, input_dev->keybit); + __set_bit(BTN_STYLUS2, input_dev->keybit); + + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); + break; + case WACOM_24HD: input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0); @@ -1862,6 +1943,11 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0); switch (features->type) { + case GRAPHIRE_BT: + __set_bit(BTN_0, input_dev->keybit); + __set_bit(BTN_1, input_dev->keybit); + break; + case WACOM_MO: __set_bit(BTN_BACK, input_dev->keybit); __set_bit(BTN_LEFT, input_dev->keybit); @@ -2031,6 +2117,9 @@ static const struct wacom_features wacom_features_0x00 = static const struct wacom_features wacom_features_0x10 = { "Wacom Graphire", 10206, 7422, 511, 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; +static const struct wacom_features wacom_features_0x81 = + { "Wacom Graphire BT", 16704, 12064, 511, 32, + GRAPHIRE_BT, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x11 = { "Wacom Graphire2 4x5", 10206, 7422, 511, 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; @@ -2429,6 +2518,10 @@ static const struct wacom_features wacom_features_0x309 = HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\ .driver_data = (kernel_ulong_t)&wacom_features_##prod +#define BT_DEVICE_WACOM(prod) \ + HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\ + .driver_data = (kernel_ulong_t)&wacom_features_##prod + #define USB_DEVICE_LENOVO(prod) \ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \ .driver_data = (kernel_ulong_t)&wacom_features_##prod @@ -2486,6 +2579,7 @@ const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x69) }, { USB_DEVICE_WACOM(0x6A) }, { USB_DEVICE_WACOM(0x6B) }, + { BT_DEVICE_WACOM(0x81) }, { USB_DEVICE_WACOM(0x84) }, { USB_DEVICE_WACOM(0x90) }, { USB_DEVICE_WACOM(0x93) }, diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 6cefa1e8c14b..4f0178b9a789 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -46,6 +46,7 @@ /* wacom data packet report IDs */ #define WACOM_REPORT_PENABLED 2 +#define WACOM_REPORT_PENABLED_BT 3 #define WACOM_REPORT_INTUOSREAD 5 #define WACOM_REPORT_INTUOSWRITE 6 #define WACOM_REPORT_INTUOSPAD 12 @@ -73,6 +74,7 @@ enum { PENPARTNER = 0, GRAPHIRE, + GRAPHIRE_BT, WACOM_G4, PTU, PL, From 81af7e61a774e687ed4a7f37992ef75da57c5ddf Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 6 Aug 2014 13:55:56 -0700 Subject: [PATCH 32/37] Input: wacom - handle Intuos 4 BT in wacom.ko A good point of this change is that now, the Intuos4 bluetooth can handle the different tools (artpen, airbrush, mice), and we get a common interface between USB and BT for accessing the LEDs/OLEDs. Signed-off-by: Benjamin Tissoires Reviewed-by: Ping Cheng Tested-by: Przemo Firszt Signed-off-by: Dmitry Torokhov --- drivers/hid/hid-core.c | 1 - drivers/hid/hid-wacom.c | 1 - drivers/hid/wacom_sys.c | 16 +++++++++ drivers/hid/wacom_wac.c | 75 +++++++++++++++++++++++++++++++++++++++++ drivers/hid/wacom_wac.h | 1 + 5 files changed, 92 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index cbabd8786e71..b3181ea8f860 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1942,7 +1942,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_Q_PAD) }, diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 967c457a2785..db2d07da4b4e 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -952,7 +952,6 @@ static void wacom_remove(struct hid_device *hdev) } static const struct hid_device_id wacom_devices[] = { - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) }, { } }; diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index c21e58ba0693..f5c9c56c0975 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -296,6 +296,20 @@ static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed, hid_warn(hdev, "failed to poke device, command %d, err %d\n", rep_data[0], ret); break; + case INTUOS4WL: + if (speed == 1) + wacom->wacom_wac.bt_features &= ~0x20; + else + wacom->wacom_wac.bt_features |= 0x20; + + rep_data[0] = 0x03; + rep_data[1] = wacom->wacom_wac.bt_features; + + ret = wacom_set_report(hdev, HID_FEATURE_REPORT, + rep_data[0], rep_data, 2, 1); + if (ret >= 0) + wacom->wacom_wac.bt_high_speed = speed; + break; } return 0; @@ -720,6 +734,7 @@ static int wacom_initialize_leds(struct wacom *wacom) switch (wacom->wacom_wac.features.type) { case INTUOS4S: case INTUOS4: + case INTUOS4WL: case INTUOS4L: wacom->led.select[0] = 0; wacom->led.select[1] = 0; @@ -786,6 +801,7 @@ static void wacom_destroy_leds(struct wacom *wacom) switch (wacom->wacom_wac.features.type) { case INTUOS4S: case INTUOS4: + case INTUOS4WL: case INTUOS4L: sysfs_remove_group(&wacom->hdev->dev.kobj, &intuos4_led_attr_group); diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index fa16a5bf3df3..d4a2d533a444 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -37,6 +37,11 @@ */ static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 }; +/* + * Percent of battery capacity for Intuos4 WL, AC has a separate bit. + */ +static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 }; + static int wacom_penpartner_irq(struct wacom_wac *wacom) { unsigned char *data = wacom->data; @@ -953,6 +958,58 @@ static int int_dist(int x1, int y1, int x2, int y2) return int_sqrt(x*x + y*y); } +static void wacom_intuos_bt_process_data(struct wacom_wac *wacom, + unsigned char *data) +{ + memcpy(wacom->data, data, 10); + wacom_intuos_irq(wacom); + + input_sync(wacom->input); + if (wacom->pad_input) + input_sync(wacom->pad_input); +} + +static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len) +{ + unsigned char data[WACOM_PKGLEN_MAX]; + int i = 1; + unsigned power_raw, battery_capacity, bat_charging, ps_connected; + + memcpy(data, wacom->data, len); + + switch (data[0]) { + case 0x04: + wacom_intuos_bt_process_data(wacom, data + i); + i += 10; + /* fall through */ + case 0x03: + wacom_intuos_bt_process_data(wacom, data + i); + i += 10; + wacom_intuos_bt_process_data(wacom, data + i); + i += 10; + power_raw = data[i]; + bat_charging = (power_raw & 0x08) ? 1 : 0; + ps_connected = (power_raw & 0x10) ? 1 : 0; + battery_capacity = batcap_i4[power_raw & 0x07]; + if ((wacom->battery_capacity != battery_capacity) || + (wacom->bat_charging != bat_charging) || + (wacom->ps_connected != ps_connected)) { + wacom->battery_capacity = battery_capacity; + wacom->bat_charging = bat_charging; + wacom->ps_connected = ps_connected; + wacom_notify_battery(wacom); + } + + break; + default: + dev_dbg(wacom->input->dev.parent, + "Unknown report: %d,%d size:%zu\n", + data[0], data[1], len); + return 0; + } + return 0; +} + static int wacom_24hdt_irq(struct wacom_wac *wacom) { struct input_dev *input = wacom->input; @@ -1512,6 +1569,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) sync = wacom_intuos_irq(wacom_wac); break; + case INTUOS4WL: + sync = wacom_intuos_bt_irq(wacom_wac, len); + break; + case WACOM_24HDT: sync = wacom_24hdt_irq(wacom_wac); break; @@ -1803,6 +1864,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, break; case INTUOS4: + case INTUOS4WL: case INTUOS4L: case INTUOS4S: input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); @@ -2065,6 +2127,15 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); break; + case INTUOS4WL: + /* + * For Bluetooth devices, the udev rule does not work correctly + * for pads unless we add a stylus capability, which forces + * ID_INPUT_TABLET to be set. + */ + __set_bit(BTN_STYLUS, input_dev->keybit); + /* fall through */ + case INTUOS4: case INTUOS4L: __set_bit(BTN_7, input_dev->keybit); @@ -2279,6 +2350,9 @@ static const struct wacom_features wacom_features_0xBB = static const struct wacom_features wacom_features_0xBC = { "Wacom Intuos4 WL", 40640, 25400, 2047, 63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; +static const struct wacom_features wacom_features_0xBD = + { "Wacom Intuos4 WL", 40640, 25400, 2047, 63, + INTUOS4WL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0x26 = { "Wacom Intuos5 touch S", 31496, 19685, 2047, 63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 }; @@ -2598,6 +2672,7 @@ const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xBA) }, { USB_DEVICE_WACOM(0xBB) }, { USB_DEVICE_WACOM(0xBC) }, + { BT_DEVICE_WACOM(0xBD) }, { USB_DEVICE_WACOM(0xC0) }, { USB_DEVICE_WACOM(0xC2) }, { USB_DEVICE_WACOM(0xC4) }, diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 4f0178b9a789..339ab5d81a2d 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -86,6 +86,7 @@ enum { INTUOS3L, INTUOS4S, INTUOS4, + INTUOS4WL, INTUOS4L, INTUOS5S, INTUOS5, From 849e2f06781a0c73573024bdaea0babc0c4e31af Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 6 Aug 2014 13:58:25 -0700 Subject: [PATCH 33/37] Input: wacom - check for bluetooth protocol while setting OLEDs Bluetooth Intuos 4 use 1-bit definition while the USB ones use a 4-bits definition. This changes the size of the raw image we receive, and thus the kernel will only accept 1-bit images for Bluetooth and 4-bits for USB. Signed-off-by: Benjamin Tissoires Signed-off-by: Przemo Firszt Reviewed-by: Ping Cheng Tested-by: Przemo Firszt Signed-off-by: Dmitry Torokhov --- drivers/hid/wacom_sys.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index f5c9c56c0975..a12cd9c3a6ee 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -20,6 +20,7 @@ #define WAC_CMD_LED_CONTROL 0x20 #define WAC_CMD_ICON_START 0x21 #define WAC_CMD_ICON_XFER 0x23 +#define WAC_CMD_ICON_BT_XFER 0x26 #define WAC_CMD_RETRIES 10 static int wacom_get_report(struct hid_device *hdev, u8 type, u8 id, @@ -526,12 +527,14 @@ static int wacom_led_control(struct wacom *wacom) return retval; } -static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *img) +static int wacom_led_putimage(struct wacom *wacom, int button_id, u8 xfer_id, + const unsigned len, const void *img) { unsigned char *buf; int i, retval; + const unsigned chunk_len = len / 4; /* 4 chunks are needed to be sent */ - buf = kzalloc(259, GFP_KERNEL); + buf = kzalloc(chunk_len + 3 , GFP_KERNEL); if (!buf) return -ENOMEM; @@ -543,15 +546,15 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *im if (retval < 0) goto out; - buf[0] = WAC_CMD_ICON_XFER; + buf[0] = xfer_id; buf[1] = button_id & 0x07; for (i = 0; i < 4; i++) { buf[2] = i; - memcpy(buf + 3, img + i * 256, 256); + memcpy(buf + 3, img + i * chunk_len, chunk_len); retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, - WAC_CMD_ICON_XFER, - buf, 259, WAC_CMD_RETRIES); + xfer_id, buf, chunk_len + 3, + WAC_CMD_RETRIES); if (retval < 0) break; } @@ -652,13 +655,23 @@ static ssize_t wacom_button_image_store(struct device *dev, int button_id, struct hid_device *hdev = container_of(dev, struct hid_device, dev); struct wacom *wacom = hid_get_drvdata(hdev); int err; + unsigned len; + u8 xfer_id; - if (count != 1024) + if (hdev->bus == BUS_BLUETOOTH) { + len = 256; + xfer_id = WAC_CMD_ICON_BT_XFER; + } else { + len = 1024; + xfer_id = WAC_CMD_ICON_XFER; + } + + if (count != len) return -EINVAL; mutex_lock(&wacom->lock); - err = wacom_led_putimage(wacom, button_id, buf); + err = wacom_led_putimage(wacom, button_id, xfer_id, len, buf); mutex_unlock(&wacom->lock); From 296b737874b8a671a8f9ee5a64602f15c06ae937 Mon Sep 17 00:00:00 2001 From: Przemo Firszt Date: Wed, 6 Aug 2014 14:00:38 -0700 Subject: [PATCH 34/37] Input: wacom - remove passing id for wacom_set_report Every call of wacom_set_report was passing "id" as a separate parameter and buffer also passed the same information. We can use first u8 of the buffer instead of "id" Signed-off-by: Przemo Firszt Signed-off-by: Benjamin Tissoires Reviewed-by: Ping Cheng Tested-by: Przemo Firszt Signed-off-by: Dmitry Torokhov --- drivers/hid/wacom_sys.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index a12cd9c3a6ee..6e0c19146a79 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -36,13 +36,13 @@ static int wacom_get_report(struct hid_device *hdev, u8 type, u8 id, return retval; } -static int wacom_set_report(struct hid_device *hdev, u8 type, u8 id, - void *buf, size_t size, unsigned int retries) +static int wacom_set_report(struct hid_device *hdev, u8 type, u8 *buf, + size_t size, unsigned int retries) { int retval; do { - retval = hid_hw_raw_request(hdev, id, buf, size, type, + retval = hid_hw_raw_request(hdev, buf[0], buf, size, type, HID_REQ_SET_REPORT); } while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries); @@ -251,8 +251,8 @@ static int wacom_set_device_mode(struct hid_device *hdev, int report_id, rep_data[0] = report_id; rep_data[1] = mode; - error = wacom_set_report(hdev, HID_FEATURE_REPORT, - report_id, rep_data, length, 1); + error = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data, + length, 1); if (error >= 0) error = wacom_get_report(hdev, HID_FEATURE_REPORT, report_id, rep_data, length, 1); @@ -274,15 +274,15 @@ static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed, case GRAPHIRE_BT: rep_data[0] = 0x03; rep_data[1] = 0x00; - ret = wacom_set_report(hdev, HID_FEATURE_REPORT, - rep_data[0], rep_data, 2, 3); + ret = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data, 2, + 3); if (ret >= 0) { rep_data[0] = speed == 0 ? 0x05 : 0x06; rep_data[1] = 0x00; ret = wacom_set_report(hdev, HID_FEATURE_REPORT, - rep_data[0], rep_data, 2, 3); + rep_data, 2, 3); if (ret >= 0) { wacom->wacom_wac.bt_high_speed = speed; @@ -306,8 +306,8 @@ static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed, rep_data[0] = 0x03; rep_data[1] = wacom->wacom_wac.bt_features; - ret = wacom_set_report(hdev, HID_FEATURE_REPORT, - rep_data[0], rep_data, 2, 1); + ret = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data, 2, + 1); if (ret >= 0) wacom->wacom_wac.bt_high_speed = speed; break; @@ -520,8 +520,8 @@ static int wacom_led_control(struct wacom *wacom) buf[4] = wacom->led.img_lum; } - retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, - WAC_CMD_LED_CONTROL, buf, 9, WAC_CMD_RETRIES); + retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 9, + WAC_CMD_RETRIES); kfree(buf); return retval; @@ -541,8 +541,8 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id, u8 xfer_id, /* Send 'start' command */ buf[0] = WAC_CMD_ICON_START; buf[1] = 1; - retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, - WAC_CMD_ICON_START, buf, 2, WAC_CMD_RETRIES); + retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 2, + WAC_CMD_RETRIES); if (retval < 0) goto out; @@ -553,8 +553,7 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id, u8 xfer_id, memcpy(buf + 3, img + i * chunk_len, chunk_len); retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, - xfer_id, buf, chunk_len + 3, - WAC_CMD_RETRIES); + buf, chunk_len + 3, WAC_CMD_RETRIES); if (retval < 0) break; } @@ -562,8 +561,8 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id, u8 xfer_id, /* Send 'stop' */ buf[0] = WAC_CMD_ICON_START; buf[1] = 0; - wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, WAC_CMD_ICON_START, - buf, 2, WAC_CMD_RETRIES); + wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 2, + WAC_CMD_RETRIES); out: kfree(buf); From 1c3c52354046bae6d2b596d3ae9ff67be4e78250 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 6 Aug 2014 14:04:23 -0700 Subject: [PATCH 35/37] Input: wacom - add copyright note and bump version to 2.0 Reviewed-by: Ping Cheng Tested-by: Przemo Firszt Signed-off-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/hid/wacom.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index 0b89ee77d7d1..8cc4406b8a53 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h @@ -12,6 +12,7 @@ * Copyright (c) 2001 Frederic Lepied * Copyright (c) 2004 Panagiotis Issaris * Copyright (c) 2002-2011 Ping Cheng + * Copyright (c) 2014 Benjamin Tissoires * * ChangeLog: * v0.1 (vp) - Initial release @@ -72,6 +73,8 @@ * v1.52 (pc) - Query Wacom data upon system resume * - add defines for features->type * - add new devices (0x9F, 0xE2, and 0XE3) + * v2.00 (bt) - conversion to a HID driver + * - integration of the Bluetooth devices */ /* @@ -93,7 +96,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.53" +#define DRIVER_VERSION "v2.00" #define DRIVER_AUTHOR "Vojtech Pavlik " #define DRIVER_DESC "USB Wacom tablet driver" #define DRIVER_LICENSE "GPL" From 7403a6a448c3ed96221bb46c9da75254fd87b520 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 6 Aug 2014 14:06:26 -0700 Subject: [PATCH 36/37] Input: HID - remove hid-wacom Bluetooth driver Bluetooth Wacom tablets are now handled by the regular wacom.ko driver. Remove the now useless hid-wacom driver. Signed-off-by: Benjamin Tissoires Reviewed-by: Ping Cheng Tested-by: Przemo Firszt Signed-off-by: Dmitry Torokhov --- drivers/hid/Kconfig | 10 +- drivers/hid/Makefile | 3 +- drivers/hid/hid-wacom.c | 971 ---------------------------------------- 3 files changed, 2 insertions(+), 982 deletions(-) delete mode 100644 drivers/hid/hid-wacom.c diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 64366f1feb17..4ed682cd1236 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -748,21 +748,13 @@ config THRUSTMASTER_FF Rumble Force or Force Feedback Wheel. config HID_WACOM - tristate "Wacom Bluetooth devices support" - depends on HID - depends on LEDS_CLASS - select POWER_SUPPLY - ---help--- - Support for Wacom Graphire Bluetooth and Intuos4 WL tablets. - -config HID_USB_WACOM tristate "Wacom Intuos/Graphire tablet support (USB)" depends on HID select POWER_SUPPLY select NEW_LEDS select LEDS_CLASS help - Say Y here if you want to use the USB version of the Wacom Intuos + Say Y here if you want to use the USB or BT version of the Wacom Intuos or Graphire tablet. To compile this driver as a module, choose M here: the diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 55b69acdb680..e38c772ace76 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -115,10 +115,9 @@ obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o obj-$(CONFIG_HID_XINMO) += hid-xinmo.o obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o -obj-$(CONFIG_HID_WACOM) += hid-wacom.o wacom-objs := wacom_wac.o wacom_sys.o -obj-$(CONFIG_HID_USB_WACOM) += wacom.o +obj-$(CONFIG_HID_WACOM) += wacom.o obj-$(CONFIG_HID_WALTOP) += hid-waltop.o obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c deleted file mode 100644 index db2d07da4b4e..000000000000 --- a/drivers/hid/hid-wacom.c +++ /dev/null @@ -1,971 +0,0 @@ -/* - * Bluetooth Wacom Tablet support - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik - * Copyright (c) 2005 Michael Haboustak for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2008 Jiri Slaby - * Copyright (c) 2006 Andrew Zabolotny - * Copyright (c) 2009 Bastien Nocera - * Copyright (c) 2011 Przemysław Firszt - */ - -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include - -#include "hid-ids.h" - -#define PAD_DEVICE_ID 0x0F - -#define WAC_CMD_LED_CONTROL 0x20 -#define WAC_CMD_ICON_START_STOP 0x21 -#define WAC_CMD_ICON_TRANSFER 0x26 - -struct wacom_data { - __u16 tool; - __u16 butstate; - __u8 whlstate; - __u8 features; - __u32 id; - __u32 serial; - unsigned char high_speed; - __u8 battery_capacity; - __u8 power_raw; - __u8 ps_connected; - __u8 bat_charging; - struct power_supply battery; - struct power_supply ac; - __u8 led_selector; - struct led_classdev *leds[4]; -}; - -/*percent of battery capacity for Graphire - 8th value means AC online and show 100% capacity */ -static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 }; -/*percent of battery capacity for Intuos4 WL, AC has a separate bit*/ -static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 }; - -static enum power_supply_property wacom_battery_props[] = { - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_SCOPE, - POWER_SUPPLY_PROP_STATUS, -}; - -static enum power_supply_property wacom_ac_props[] = { - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_SCOPE, -}; - -static void wacom_scramble(__u8 *image) -{ - __u16 mask; - __u16 s1; - __u16 s2; - __u16 r1 ; - __u16 r2 ; - __u16 r; - __u8 buf[256]; - int i, w, x, y, z; - - for (x = 0; x < 32; x++) { - for (y = 0; y < 8; y++) - buf[(8 * x) + (7 - y)] = image[(8 * x) + y]; - } - - /* Change 76543210 into GECA6420 as required by Intuos4 WL - * HGFEDCBA HFDB7531 - */ - for (x = 0; x < 4; x++) { - for (y = 0; y < 4; y++) { - for (z = 0; z < 8; z++) { - mask = 0x0001; - r1 = 0; - r2 = 0; - i = (x << 6) + (y << 4) + z; - s1 = buf[i]; - s2 = buf[i+8]; - for (w = 0; w < 8; w++) { - r1 |= (s1 & mask); - r2 |= (s2 & mask); - s1 <<= 1; - s2 <<= 1; - mask <<= 2; - } - r = r1 | (r2 << 1); - i = (x << 6) + (y << 4) + (z << 1); - image[i] = 0xFF & r; - image[i+1] = (0xFF00 & r) >> 8; - } - } - } -} - -static void wacom_set_image(struct hid_device *hdev, const char *image, - __u8 icon_no) -{ - __u8 rep_data[68]; - __u8 p[256]; - int ret, i, j; - - for (i = 0; i < 256; i++) - p[i] = image[i]; - - rep_data[0] = WAC_CMD_ICON_START_STOP; - rep_data[1] = 0; - ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2, - HID_FEATURE_REPORT, HID_REQ_SET_REPORT); - if (ret < 0) - goto err; - - rep_data[0] = WAC_CMD_ICON_TRANSFER; - rep_data[1] = icon_no & 0x07; - - wacom_scramble(p); - - for (i = 0; i < 4; i++) { - for (j = 0; j < 64; j++) - rep_data[j + 3] = p[(i << 6) + j]; - - rep_data[2] = i; - ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 67, - HID_FEATURE_REPORT, HID_REQ_SET_REPORT); - } - - rep_data[0] = WAC_CMD_ICON_START_STOP; - rep_data[1] = 0; - - ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2, - HID_FEATURE_REPORT, HID_REQ_SET_REPORT); - -err: - return; -} - -static void wacom_leds_set_brightness(struct led_classdev *led_dev, - enum led_brightness value) -{ - struct device *dev = led_dev->dev->parent; - struct hid_device *hdev; - struct wacom_data *wdata; - unsigned char *buf; - __u8 led = 0; - int i; - - hdev = container_of(dev, struct hid_device, dev); - wdata = hid_get_drvdata(hdev); - for (i = 0; i < 4; ++i) { - if (wdata->leds[i] == led_dev) - wdata->led_selector = i; - } - - led = wdata->led_selector | 0x04; - buf = kzalloc(9, GFP_KERNEL); - if (buf) { - buf[0] = WAC_CMD_LED_CONTROL; - buf[1] = led; - buf[2] = value >> 2; - buf[3] = value; - /* use fixed brightness for OLEDs */ - buf[4] = 0x08; - hid_hw_raw_request(hdev, buf[0], buf, 9, HID_FEATURE_REPORT, - HID_REQ_SET_REPORT); - kfree(buf); - } - - return; -} - -static enum led_brightness wacom_leds_get_brightness(struct led_classdev *led_dev) -{ - struct wacom_data *wdata; - struct device *dev = led_dev->dev->parent; - int value = 0; - int i; - - wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); - - for (i = 0; i < 4; ++i) { - if (wdata->leds[i] == led_dev) { - value = wdata->leds[i]->brightness; - break; - } - } - - return value; -} - - -static int wacom_initialize_leds(struct hid_device *hdev) -{ - struct wacom_data *wdata = hid_get_drvdata(hdev); - struct led_classdev *led; - struct device *dev = &hdev->dev; - size_t namesz = strlen(dev_name(dev)) + 12; - char *name; - int i, ret; - - wdata->led_selector = 0; - - for (i = 0; i < 4; i++) { - led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL); - if (!led) { - hid_warn(hdev, - "can't allocate memory for LED selector\n"); - ret = -ENOMEM; - goto err; - } - - name = (void *)&led[1]; - snprintf(name, namesz, "%s:selector:%d", dev_name(dev), i); - led->name = name; - led->brightness = 0; - led->max_brightness = 127; - led->brightness_get = wacom_leds_get_brightness; - led->brightness_set = wacom_leds_set_brightness; - - wdata->leds[i] = led; - - ret = led_classdev_register(dev, wdata->leds[i]); - - if (ret) { - wdata->leds[i] = NULL; - kfree(led); - hid_warn(hdev, "can't register LED\n"); - goto err; - } - } - -err: - return ret; -} - -static void wacom_destroy_leds(struct hid_device *hdev) -{ - struct wacom_data *wdata = hid_get_drvdata(hdev); - struct led_classdev *led; - int i; - - for (i = 0; i < 4; ++i) { - if (wdata->leds[i]) { - led = wdata->leds[i]; - wdata->leds[i] = NULL; - led_classdev_unregister(led); - kfree(led); - } - } - -} - -static int wacom_battery_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct wacom_data *wdata = container_of(psy, - struct wacom_data, battery); - int ret = 0; - - switch (psp) { - case POWER_SUPPLY_PROP_PRESENT: - val->intval = 1; - break; - case POWER_SUPPLY_PROP_SCOPE: - val->intval = POWER_SUPPLY_SCOPE_DEVICE; - break; - case POWER_SUPPLY_PROP_CAPACITY: - val->intval = wdata->battery_capacity; - break; - case POWER_SUPPLY_PROP_STATUS: - if (wdata->bat_charging) - val->intval = POWER_SUPPLY_STATUS_CHARGING; - else - if (wdata->battery_capacity == 100 && wdata->ps_connected) - val->intval = POWER_SUPPLY_STATUS_FULL; - else - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -static int wacom_ac_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct wacom_data *wdata = container_of(psy, struct wacom_data, ac); - int ret = 0; - - switch (psp) { - case POWER_SUPPLY_PROP_PRESENT: - /* fall through */ - case POWER_SUPPLY_PROP_ONLINE: - val->intval = wdata->ps_connected; - break; - case POWER_SUPPLY_PROP_SCOPE: - val->intval = POWER_SUPPLY_SCOPE_DEVICE; - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -static void wacom_set_features(struct hid_device *hdev, u8 speed) -{ - struct wacom_data *wdata = hid_get_drvdata(hdev); - int limit, ret; - __u8 rep_data[2]; - - switch (hdev->product) { - case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: - rep_data[0] = 0x03 ; rep_data[1] = 0x00; - limit = 3; - do { - ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2, - HID_FEATURE_REPORT, HID_REQ_SET_REPORT); - } while (ret < 0 && limit-- > 0); - - if (ret >= 0) { - if (speed == 0) - rep_data[0] = 0x05; - else - rep_data[0] = 0x06; - - rep_data[1] = 0x00; - limit = 3; - do { - ret = hid_hw_raw_request(hdev, rep_data[0], - rep_data, 2, HID_FEATURE_REPORT, - HID_REQ_SET_REPORT); - } while (ret < 0 && limit-- > 0); - - if (ret >= 0) { - wdata->high_speed = speed; - return; - } - } - - /* - * Note that if the raw queries fail, it's not a hard failure - * and it is safe to continue - */ - hid_warn(hdev, "failed to poke device, command %d, err %d\n", - rep_data[0], ret); - break; - case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: - if (speed == 1) - wdata->features &= ~0x20; - else - wdata->features |= 0x20; - - rep_data[0] = 0x03; - rep_data[1] = wdata->features; - - ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2, - HID_FEATURE_REPORT, HID_REQ_SET_REPORT); - if (ret >= 0) - wdata->high_speed = speed; - break; - } - - return; -} - -static ssize_t wacom_show_speed(struct device *dev, - struct device_attribute - *attr, char *buf) -{ - struct wacom_data *wdata = dev_get_drvdata(dev); - - return snprintf(buf, PAGE_SIZE, "%i\n", wdata->high_speed); -} - -static ssize_t wacom_store_speed(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - int new_speed; - - if (sscanf(buf, "%1d", &new_speed ) != 1) - return -EINVAL; - - if (new_speed == 0 || new_speed == 1) { - wacom_set_features(hdev, new_speed); - return strnlen(buf, PAGE_SIZE); - } else - return -EINVAL; -} - -static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, - wacom_show_speed, wacom_store_speed); - -#define WACOM_STORE(OLED_ID) \ -static ssize_t wacom_oled##OLED_ID##_store(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct hid_device *hdev = container_of(dev, struct hid_device, \ - dev); \ - \ - if (count != 256) \ - return -EINVAL; \ - \ - wacom_set_image(hdev, buf, OLED_ID); \ - \ - return count; \ -} \ - \ -static DEVICE_ATTR(oled##OLED_ID##_img, S_IWUSR | S_IWGRP, NULL, \ - wacom_oled##OLED_ID##_store) - -WACOM_STORE(0); -WACOM_STORE(1); -WACOM_STORE(2); -WACOM_STORE(3); -WACOM_STORE(4); -WACOM_STORE(5); -WACOM_STORE(6); -WACOM_STORE(7); - -static int wacom_gr_parse_report(struct hid_device *hdev, - struct wacom_data *wdata, - struct input_dev *input, unsigned char *data) -{ - int tool, x, y, rw; - - tool = 0; - /* Get X & Y positions */ - x = le16_to_cpu(*(__le16 *) &data[2]); - y = le16_to_cpu(*(__le16 *) &data[4]); - - /* Get current tool identifier */ - if (data[1] & 0x90) { /* If pen is in the in/active area */ - switch ((data[1] >> 5) & 3) { - case 0: /* Pen */ - tool = BTN_TOOL_PEN; - break; - - case 1: /* Rubber */ - tool = BTN_TOOL_RUBBER; - break; - - case 2: /* Mouse with wheel */ - case 3: /* Mouse without wheel */ - tool = BTN_TOOL_MOUSE; - break; - } - - /* Reset tool if out of active tablet area */ - if (!(data[1] & 0x10)) - tool = 0; - } - - /* If tool changed, notify input subsystem */ - if (wdata->tool != tool) { - if (wdata->tool) { - /* Completely reset old tool state */ - if (wdata->tool == BTN_TOOL_MOUSE) { - input_report_key(input, BTN_LEFT, 0); - input_report_key(input, BTN_RIGHT, 0); - input_report_key(input, BTN_MIDDLE, 0); - input_report_abs(input, ABS_DISTANCE, - input_abs_get_max(input, ABS_DISTANCE)); - } else { - input_report_key(input, BTN_TOUCH, 0); - input_report_key(input, BTN_STYLUS, 0); - input_report_key(input, BTN_STYLUS2, 0); - input_report_abs(input, ABS_PRESSURE, 0); - } - input_report_key(input, wdata->tool, 0); - input_sync(input); - } - wdata->tool = tool; - if (tool) - input_report_key(input, tool, 1); - } - - if (tool) { - input_report_abs(input, ABS_X, x); - input_report_abs(input, ABS_Y, y); - - switch ((data[1] >> 5) & 3) { - case 2: /* Mouse with wheel */ - input_report_key(input, BTN_MIDDLE, data[1] & 0x04); - rw = (data[6] & 0x01) ? -1 : - (data[6] & 0x02) ? 1 : 0; - input_report_rel(input, REL_WHEEL, rw); - /* fall through */ - - case 3: /* Mouse without wheel */ - input_report_key(input, BTN_LEFT, data[1] & 0x01); - input_report_key(input, BTN_RIGHT, data[1] & 0x02); - /* Compute distance between mouse and tablet */ - rw = 44 - (data[6] >> 2); - if (rw < 0) - rw = 0; - else if (rw > 31) - rw = 31; - input_report_abs(input, ABS_DISTANCE, rw); - break; - - default: - input_report_abs(input, ABS_PRESSURE, - data[6] | (((__u16) (data[1] & 0x08)) << 5)); - input_report_key(input, BTN_TOUCH, data[1] & 0x01); - input_report_key(input, BTN_STYLUS, data[1] & 0x02); - input_report_key(input, BTN_STYLUS2, (tool == BTN_TOOL_PEN) && data[1] & 0x04); - break; - } - - input_sync(input); - } - - /* Report the state of the two buttons at the top of the tablet - * as two extra fingerpad keys (buttons 4 & 5). */ - rw = data[7] & 0x03; - if (rw != wdata->butstate) { - wdata->butstate = rw; - input_report_key(input, BTN_0, rw & 0x02); - input_report_key(input, BTN_1, rw & 0x01); - input_report_key(input, BTN_TOOL_FINGER, 0xf0); - input_event(input, EV_MSC, MSC_SERIAL, 0xf0); - input_sync(input); - } - - /* Store current battery capacity and power supply state*/ - rw = (data[7] >> 2 & 0x07); - if (rw != wdata->power_raw) { - wdata->power_raw = rw; - wdata->battery_capacity = batcap_gr[rw]; - if (rw == 7) - wdata->ps_connected = 1; - else - wdata->ps_connected = 0; - } - return 1; -} - -static void wacom_i4_parse_button_report(struct wacom_data *wdata, - struct input_dev *input, unsigned char *data) -{ - __u16 new_butstate; - __u8 new_whlstate; - __u8 sync = 0; - - new_whlstate = data[1]; - if (new_whlstate != wdata->whlstate) { - wdata->whlstate = new_whlstate; - if (new_whlstate & 0x80) { - input_report_key(input, BTN_TOUCH, 1); - input_report_abs(input, ABS_WHEEL, (new_whlstate & 0x7f)); - input_report_key(input, BTN_TOOL_FINGER, 1); - } else { - input_report_key(input, BTN_TOUCH, 0); - input_report_abs(input, ABS_WHEEL, 0); - input_report_key(input, BTN_TOOL_FINGER, 0); - } - sync = 1; - } - - new_butstate = (data[3] << 1) | (data[2] & 0x01); - if (new_butstate != wdata->butstate) { - wdata->butstate = new_butstate; - input_report_key(input, BTN_0, new_butstate & 0x001); - input_report_key(input, BTN_1, new_butstate & 0x002); - input_report_key(input, BTN_2, new_butstate & 0x004); - input_report_key(input, BTN_3, new_butstate & 0x008); - input_report_key(input, BTN_4, new_butstate & 0x010); - input_report_key(input, BTN_5, new_butstate & 0x020); - input_report_key(input, BTN_6, new_butstate & 0x040); - input_report_key(input, BTN_7, new_butstate & 0x080); - input_report_key(input, BTN_8, new_butstate & 0x100); - input_report_key(input, BTN_TOOL_FINGER, 1); - sync = 1; - } - - if (sync) { - input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); - input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff); - input_sync(input); - } -} - -static void wacom_i4_parse_pen_report(struct wacom_data *wdata, - struct input_dev *input, unsigned char *data) -{ - __u16 x, y, pressure; - __u8 distance; - __u8 tilt_x, tilt_y; - - switch (data[1]) { - case 0x80: /* Out of proximity report */ - input_report_key(input, BTN_TOUCH, 0); - input_report_abs(input, ABS_PRESSURE, 0); - input_report_key(input, BTN_STYLUS, 0); - input_report_key(input, BTN_STYLUS2, 0); - input_report_key(input, wdata->tool, 0); - input_report_abs(input, ABS_MISC, 0); - input_event(input, EV_MSC, MSC_SERIAL, wdata->serial); - wdata->tool = 0; - input_sync(input); - break; - case 0xC2: /* Tool report */ - wdata->id = ((data[2] << 4) | (data[3] >> 4) | - ((data[7] & 0x0f) << 20) | - ((data[8] & 0xf0) << 12)); - wdata->serial = ((data[3] & 0x0f) << 28) + - (data[4] << 20) + (data[5] << 12) + - (data[6] << 4) + (data[7] >> 4); - - switch (wdata->id) { - case 0x100802: - wdata->tool = BTN_TOOL_PEN; - break; - case 0x10080A: - wdata->tool = BTN_TOOL_RUBBER; - break; - } - break; - default: /* Position/pressure report */ - x = data[2] << 9 | data[3] << 1 | ((data[9] & 0x02) >> 1); - y = data[4] << 9 | data[5] << 1 | (data[9] & 0x01); - pressure = (data[6] << 3) | ((data[7] & 0xC0) >> 5) - | (data[1] & 0x01); - distance = (data[9] >> 2) & 0x3f; - tilt_x = ((data[7] << 1) & 0x7e) | (data[8] >> 7); - tilt_y = data[8] & 0x7f; - - input_report_key(input, BTN_TOUCH, pressure > 1); - - input_report_key(input, BTN_STYLUS, data[1] & 0x02); - input_report_key(input, BTN_STYLUS2, data[1] & 0x04); - input_report_key(input, wdata->tool, 1); - input_report_abs(input, ABS_X, x); - input_report_abs(input, ABS_Y, y); - input_report_abs(input, ABS_PRESSURE, pressure); - input_report_abs(input, ABS_DISTANCE, distance); - input_report_abs(input, ABS_TILT_X, tilt_x); - input_report_abs(input, ABS_TILT_Y, tilt_y); - input_report_abs(input, ABS_MISC, wdata->id); - input_event(input, EV_MSC, MSC_SERIAL, wdata->serial); - input_report_key(input, wdata->tool, 1); - input_sync(input); - break; - } - - return; -} - -static void wacom_i4_parse_report(struct hid_device *hdev, - struct wacom_data *wdata, - struct input_dev *input, unsigned char *data) -{ - switch (data[0]) { - case 0x00: /* Empty report */ - break; - case 0x02: /* Pen report */ - wacom_i4_parse_pen_report(wdata, input, data); - break; - case 0x03: /* Features Report */ - wdata->features = data[2]; - break; - case 0x0C: /* Button report */ - wacom_i4_parse_button_report(wdata, input, data); - break; - default: - hid_err(hdev, "Unknown report: %d,%d\n", data[0], data[1]); - break; - } -} - -static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, - u8 *raw_data, int size) -{ - struct wacom_data *wdata = hid_get_drvdata(hdev); - struct hid_input *hidinput; - struct input_dev *input; - unsigned char *data = (unsigned char *) raw_data; - int i; - __u8 power_raw; - - if (!(hdev->claimed & HID_CLAIMED_INPUT)) - return 0; - - hidinput = list_entry(hdev->inputs.next, struct hid_input, list); - input = hidinput->input; - - switch (hdev->product) { - case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: - if (data[0] == 0x03) { - return wacom_gr_parse_report(hdev, wdata, input, data); - } else { - hid_err(hdev, "Unknown report: %d,%d size:%d\n", - data[0], data[1], size); - return 0; - } - break; - case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: - i = 1; - - switch (data[0]) { - case 0x04: - wacom_i4_parse_report(hdev, wdata, input, data + i); - i += 10; - /* fall through */ - case 0x03: - wacom_i4_parse_report(hdev, wdata, input, data + i); - i += 10; - wacom_i4_parse_report(hdev, wdata, input, data + i); - power_raw = data[i+10]; - if (power_raw != wdata->power_raw) { - wdata->power_raw = power_raw; - wdata->battery_capacity = batcap_i4[power_raw & 0x07]; - wdata->bat_charging = (power_raw & 0x08) ? 1 : 0; - wdata->ps_connected = (power_raw & 0x10) ? 1 : 0; - } - - break; - default: - hid_err(hdev, "Unknown report: %d,%d size:%d\n", - data[0], data[1], size); - return 0; - } - } - return 1; -} - -static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, unsigned long **bit, - int *max) -{ - struct input_dev *input = hi->input; - - __set_bit(INPUT_PROP_POINTER, input->propbit); - - /* Basics */ - input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); - - __set_bit(REL_WHEEL, input->relbit); - - __set_bit(BTN_TOOL_PEN, input->keybit); - __set_bit(BTN_TOUCH, input->keybit); - __set_bit(BTN_STYLUS, input->keybit); - __set_bit(BTN_STYLUS2, input->keybit); - __set_bit(BTN_LEFT, input->keybit); - __set_bit(BTN_RIGHT, input->keybit); - __set_bit(BTN_MIDDLE, input->keybit); - - /* Pad */ - input_set_capability(input, EV_MSC, MSC_SERIAL); - - __set_bit(BTN_0, input->keybit); - __set_bit(BTN_1, input->keybit); - __set_bit(BTN_TOOL_FINGER, input->keybit); - - /* Distance, rubber and mouse */ - __set_bit(BTN_TOOL_RUBBER, input->keybit); - __set_bit(BTN_TOOL_MOUSE, input->keybit); - - switch (hdev->product) { - case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: - input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); - input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); - input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); - input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); - break; - case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: - __set_bit(ABS_WHEEL, input->absbit); - __set_bit(ABS_MISC, input->absbit); - __set_bit(BTN_2, input->keybit); - __set_bit(BTN_3, input->keybit); - __set_bit(BTN_4, input->keybit); - __set_bit(BTN_5, input->keybit); - __set_bit(BTN_6, input->keybit); - __set_bit(BTN_7, input->keybit); - __set_bit(BTN_8, input->keybit); - input_set_abs_params(input, ABS_WHEEL, 0, 71, 0, 0); - input_set_abs_params(input, ABS_X, 0, 40640, 4, 0); - input_set_abs_params(input, ABS_Y, 0, 25400, 4, 0); - input_set_abs_params(input, ABS_PRESSURE, 0, 2047, 0, 0); - input_set_abs_params(input, ABS_DISTANCE, 0, 63, 0, 0); - input_set_abs_params(input, ABS_TILT_X, 0, 127, 0, 0); - input_set_abs_params(input, ABS_TILT_Y, 0, 127, 0, 0); - break; - } - - return 0; -} - -static int wacom_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - struct wacom_data *wdata; - int ret; - - wdata = kzalloc(sizeof(*wdata), GFP_KERNEL); - if (wdata == NULL) { - hid_err(hdev, "can't alloc wacom descriptor\n"); - return -ENOMEM; - } - - hid_set_drvdata(hdev, wdata); - - /* Parse the HID report now */ - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err_free; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - - ret = device_create_file(&hdev->dev, &dev_attr_speed); - if (ret) - hid_warn(hdev, - "can't create sysfs speed attribute err: %d\n", ret); - -#define OLED_INIT(OLED_ID) \ - do { \ - ret = device_create_file(&hdev->dev, \ - &dev_attr_oled##OLED_ID##_img); \ - if (ret) \ - hid_warn(hdev, \ - "can't create sysfs oled attribute, err: %d\n", ret);\ - } while (0) - -OLED_INIT(0); -OLED_INIT(1); -OLED_INIT(2); -OLED_INIT(3); -OLED_INIT(4); -OLED_INIT(5); -OLED_INIT(6); -OLED_INIT(7); - - wdata->features = 0; - wacom_set_features(hdev, 1); - - if (hdev->product == USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) { - sprintf(hdev->name, "%s", "Wacom Intuos4 WL"); - ret = wacom_initialize_leds(hdev); - if (ret) - hid_warn(hdev, - "can't create led attribute, err: %d\n", ret); - } - - wdata->battery.properties = wacom_battery_props; - wdata->battery.num_properties = ARRAY_SIZE(wacom_battery_props); - wdata->battery.get_property = wacom_battery_get_property; - wdata->battery.name = "wacom_battery"; - wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; - wdata->battery.use_for_apm = 0; - - - ret = power_supply_register(&hdev->dev, &wdata->battery); - if (ret) { - hid_err(hdev, "can't create sysfs battery attribute, err: %d\n", - ret); - goto err_battery; - } - - power_supply_powers(&wdata->battery, &hdev->dev); - - wdata->ac.properties = wacom_ac_props; - wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props); - wdata->ac.get_property = wacom_ac_get_property; - wdata->ac.name = "wacom_ac"; - wdata->ac.type = POWER_SUPPLY_TYPE_MAINS; - wdata->ac.use_for_apm = 0; - - ret = power_supply_register(&hdev->dev, &wdata->ac); - if (ret) { - hid_err(hdev, - "can't create ac battery attribute, err: %d\n", ret); - goto err_ac; - } - - power_supply_powers(&wdata->ac, &hdev->dev); - return 0; - -err_ac: - power_supply_unregister(&wdata->battery); -err_battery: - wacom_destroy_leds(hdev); - device_remove_file(&hdev->dev, &dev_attr_oled0_img); - device_remove_file(&hdev->dev, &dev_attr_oled1_img); - device_remove_file(&hdev->dev, &dev_attr_oled2_img); - device_remove_file(&hdev->dev, &dev_attr_oled3_img); - device_remove_file(&hdev->dev, &dev_attr_oled4_img); - device_remove_file(&hdev->dev, &dev_attr_oled5_img); - device_remove_file(&hdev->dev, &dev_attr_oled6_img); - device_remove_file(&hdev->dev, &dev_attr_oled7_img); - device_remove_file(&hdev->dev, &dev_attr_speed); - hid_hw_stop(hdev); -err_free: - kfree(wdata); - return ret; -} - -static void wacom_remove(struct hid_device *hdev) -{ - struct wacom_data *wdata = hid_get_drvdata(hdev); - - wacom_destroy_leds(hdev); - device_remove_file(&hdev->dev, &dev_attr_oled0_img); - device_remove_file(&hdev->dev, &dev_attr_oled1_img); - device_remove_file(&hdev->dev, &dev_attr_oled2_img); - device_remove_file(&hdev->dev, &dev_attr_oled3_img); - device_remove_file(&hdev->dev, &dev_attr_oled4_img); - device_remove_file(&hdev->dev, &dev_attr_oled5_img); - device_remove_file(&hdev->dev, &dev_attr_oled6_img); - device_remove_file(&hdev->dev, &dev_attr_oled7_img); - device_remove_file(&hdev->dev, &dev_attr_speed); - hid_hw_stop(hdev); - - power_supply_unregister(&wdata->battery); - power_supply_unregister(&wdata->ac); - kfree(hid_get_drvdata(hdev)); -} - -static const struct hid_device_id wacom_devices[] = { - - { } -}; -MODULE_DEVICE_TABLE(hid, wacom_devices); - -static struct hid_driver wacom_driver = { - .name = "hid-wacom", - .id_table = wacom_devices, - .probe = wacom_probe, - .remove = wacom_remove, - .raw_event = wacom_raw_event, - .input_mapped = wacom_input_mapped, -}; -module_hid_driver(wacom_driver); - -MODULE_DESCRIPTION("Driver for Wacom Graphire Bluetooth and Wacom Intuos4 WL"); -MODULE_LICENSE("GPL"); From f2e0a7d4a0b94b4274e3b7e15bf650d45a866f3c Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 6 Aug 2014 14:07:49 -0700 Subject: [PATCH 37/37] Input: wacom - only register once the MODULE_* macros Putting the various MODULE_* makes them appear several times in modinfo because wacom.h is used both in wacom_sys.c and wacom_wac.h. Having the macros near the module declaration makes them appear only once. Add also MODULE_VERSION(DRIVER_VERSION) to export the current version number. Signed-off-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/hid/wacom.h | 4 ---- drivers/hid/wacom_sys.c | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index 8cc4406b8a53..64bc1b296d91 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h @@ -101,10 +101,6 @@ #define DRIVER_DESC "USB Wacom tablet driver" #define DRIVER_LICENSE "GPL" -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); - #define USB_VENDOR_ID_WACOM 0x056a #define USB_VENDOR_ID_LENOVO 0x17ef diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 6e0c19146a79..3e388ec31da8 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1449,3 +1449,8 @@ static struct hid_driver wacom_driver = { .raw_event = wacom_raw_event, }; module_hid_driver(wacom_driver); + +MODULE_VERSION(DRIVER_VERSION); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE(DRIVER_LICENSE);