Mageia Bugzilla – Attachment 2904 Details for
Bug 7659
Update linux kernel to version >= 3.5 (current stable is 3.3.4) OR backport wacom driver into an earlier version for Intuos 5 support
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
New Account
|
Forgot Password
[patch]
Backport of wacom driver from 3.5.4 into 3.4.11 linux kernel (in particular Wacom Intuos 5 support)
linux-3.4.11_intuos5_support.patch (text/plain), 43.41 KB, created by
Jehan Hysseo
on 2012-10-02 19:31:38 CEST
(
hide
)
Description:
Backport of wacom driver from 3.5.4 into 3.4.11 linux kernel (in particular Wacom Intuos 5 support)
Filename:
MIME Type:
Creator:
Jehan Hysseo
Created:
2012-10-02 19:31:38 CEST
Size:
43.41 KB
patch
obsolete
>diff -rup linux-3.4.11/drivers/input/tablet/wacom.h linux-3.4.11_patched/drivers/input/tablet/wacom.h >--- linux-3.4.11/drivers/input/tablet/wacom.h 2012-09-15 07:18:55.000000000 +0900 >+++ linux-3.4.11_patched/drivers/input/tablet/wacom.h 2012-10-01 19:48:59.834492696 +0900 >@@ -135,6 +135,6 @@ extern const struct usb_device_id wacom_ > > void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); > void wacom_setup_device_quirks(struct wacom_features *features); >-void wacom_setup_input_capabilities(struct input_dev *input_dev, >- struct wacom_wac *wacom_wac); >+int wacom_setup_input_capabilities(struct input_dev *input_dev, >+ struct wacom_wac *wacom_wac); > #endif >diff -rup linux-3.4.11/drivers/input/tablet/wacom_sys.c linux-3.4.11_patched/drivers/input/tablet/wacom_sys.c >--- linux-3.4.11/drivers/input/tablet/wacom_sys.c 2012-09-15 07:18:55.000000000 +0900 >+++ linux-3.4.11_patched/drivers/input/tablet/wacom_sys.c 2012-10-01 19:46:34.702484829 +0900 >@@ -28,6 +28,7 @@ > #define HID_USAGE_Y_TILT 0x3e > #define HID_USAGE_FINGER 0x22 > #define HID_USAGE_STYLUS 0x20 >+#define HID_USAGE_CONTACTMAX 0x55 > #define HID_COLLECTION 0xa1 > #define HID_COLLECTION_LOGICAL 0x02 > #define HID_COLLECTION_END 0xc0 >@@ -99,6 +100,7 @@ static int wacom_set_report(struct usb_i > static void wacom_sys_irq(struct urb *urb) > { > struct wacom *wacom = urb->context; >+ struct device *dev = &wacom->intf->dev; > int retval; > > switch (urb->status) { >@@ -109,10 +111,12 @@ static void wacom_sys_irq(struct urb *ur > case -ENOENT: > case -ESHUTDOWN: > /* this urb is terminated, clean up */ >- dbg("%s - urb shutting down with status: %d", __func__, urb->status); >+ dev_dbg(dev, "%s - urb shutting down with status: %d\n", >+ __func__, urb->status); > return; > default: >- dbg("%s - nonzero urb status received: %d", __func__, urb->status); >+ dev_dbg(dev, "%s - nonzero urb status received: %d\n", >+ __func__, urb->status); > goto exit; > } > >@@ -122,8 +126,8 @@ static void wacom_sys_irq(struct urb *ur > usb_mark_last_busy(wacom->usbdev); > retval = usb_submit_urb(urb, GFP_ATOMIC); > if (retval) >- err ("%s - usb_submit_urb failed with result %d", >- __func__, retval); >+ dev_err(dev, "%s - usb_submit_urb failed with result %d\n", >+ __func__, retval); > } > > static int wacom_open(struct input_dev *dev) >@@ -201,6 +205,27 @@ static int wacom_parse_logical_collectio > return length; > } > >+static void wacom_retrieve_report_data(struct usb_interface *intf, >+ 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(intf, WAC_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); >+ } >+} >+ > /* > * Interface Descriptor of wacom devices can be incomplete and > * inconsistent so wacom_features table is used to store stylus >@@ -233,6 +258,9 @@ static int wacom_parse_logical_collectio > * 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. > */ > static int wacom_parse_hid(struct usb_interface *intf, > struct hid_descriptor *hid_desc, >@@ -292,6 +320,10 @@ static int wacom_parse_hid(struct usb_in > /* need to reset back */ > features->pktlen = WACOM_PKGLEN_TPC2FG; > } >+ >+ if (features->type == MTSCREEN) >+ features->pktlen = WACOM_PKGLEN_MTOUCH; >+ > if (features->type == BAMBOO_PT) { > /* need to reset back */ > features->pktlen = WACOM_PKGLEN_BBTOUCH; >@@ -324,18 +356,15 @@ static int wacom_parse_hid(struct usb_in > case HID_USAGE_Y: > if (usage == WCM_DESKTOP) { > if (finger) { >- features->device_type = BTN_TOOL_FINGER; >- if (features->type == TABLETPC2FG) { >- /* need to reset back */ >- features->pktlen = WACOM_PKGLEN_TPC2FG; >+ int type = features->type; >+ >+ if (type == TABLETPC2FG || type == MTSCREEN) { > features->y_max = > get_unaligned_le16(&report[i + 3]); > features->y_phy = > get_unaligned_le16(&report[i + 6]); > i += 7; >- } else if (features->type == BAMBOO_PT) { >- /* need to reset back */ >- features->pktlen = WACOM_PKGLEN_BBTOUCH; >+ } else if (type == BAMBOO_PT) { > features->y_phy = > get_unaligned_le16(&report[i + 3]); > features->y_max = >@@ -349,10 +378,6 @@ static int wacom_parse_hid(struct usb_in > i += 4; > } > } else if (pen) { >- /* penabled only accepts exact bytes of data */ >- if (features->type == TABLETPC2FG) >- features->pktlen = WACOM_PKGLEN_GRAPHIRE; >- features->device_type = BTN_TOOL_PEN; > features->y_max = > get_unaligned_le16(&report[i + 3]); > i += 4; >@@ -374,6 +399,13 @@ static int wacom_parse_hid(struct usb_in > pen = 1; > i++; > break; >+ >+ case HID_USAGE_CONTACTMAX: >+ /* leave touch_max as is if predefined */ >+ if (!features->touch_max) >+ wacom_retrieve_report_data(intf, features); >+ i++; >+ break; > } > break; > >@@ -410,23 +442,29 @@ static int wacom_query_tablet_data(struc > if (!rep_data) > return error; > >- /* ask to report tablet data if it is MT Tablet PC or >- * not a Tablet PC */ >- if (features->type == TABLETPC2FG) { >- do { >- rep_data[0] = 3; >- rep_data[1] = 4; >- rep_data[2] = 0; >- rep_data[3] = 0; >- report_id = 3; >- error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, >- report_id, rep_data, 4, 1); >- if (error >= 0) >- error = wacom_get_report(intf, >- WAC_HID_FEATURE_REPORT, >- report_id, rep_data, 4, 1); >- } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); >- } else if (features->type != TABLETPC && >+ /* ask to report Wacom data */ >+ if (features->device_type == BTN_TOOL_FINGER) { >+ /* if it is an MT Tablet PC touch */ >+ if (features->type > TABLETPC) { >+ do { >+ rep_data[0] = 3; >+ rep_data[1] = 4; >+ rep_data[2] = 0; >+ rep_data[3] = 0; >+ report_id = 3; >+ error = wacom_set_report(intf, >+ WAC_HID_FEATURE_REPORT, >+ report_id, >+ rep_data, 4, 1); >+ if (error >= 0) >+ error = wacom_get_report(intf, >+ WAC_HID_FEATURE_REPORT, >+ report_id, >+ rep_data, 4, 1); >+ } while ((error < 0 || rep_data[1] != 4) && >+ limit++ < WAC_MSG_RETRIES); >+ } >+ } else if (features->type <= BAMBOO_PT && > features->type != WIRELESS && > features->device_type == BTN_TOOL_PEN) { > do { >@@ -447,7 +485,7 @@ static int wacom_query_tablet_data(struc > } > > static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, >- struct wacom_features *features) >+ struct wacom_features *features) > { > int error = 0; > struct usb_host_interface *interface = intf->cur_altsetting; >@@ -470,21 +508,23 @@ static int wacom_retrieve_hid_descriptor > if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { > features->device_type = 0; > } else if (intf->cur_altsetting->desc.bInterfaceNumber == 2) { >- features->device_type = BTN_TOOL_DOUBLETAP; >+ features->device_type = BTN_TOOL_FINGER; > features->pktlen = WACOM_PKGLEN_BBTOUCH3; > } > } > >- /* only Tablet PCs and Bamboo P&T need to retrieve the info */ >- if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) && >- (features->type != BAMBOO_PT)) >+ /* only devices that support touch need to retrieve the info */ >+ if (features->type < BAMBOO_PT) { > goto out; >+ } > >- if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { >- if (usb_get_extra_descriptor(&interface->endpoint[0], >- HID_DEVICET_REPORT, &hid_desc)) { >- printk("wacom: can not retrieve extra class descriptor\n"); >- error = 1; >+ 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) { >+ dev_err(&intf->dev, >+ "can not retrieve extra class descriptor\n"); > goto out; > } > } >@@ -574,23 +614,39 @@ static void wacom_remove_shared_data(str > static int wacom_led_control(struct wacom *wacom) > { > unsigned char *buf; >- int retval, led = 0; >+ int retval; > > buf = kzalloc(9, GFP_KERNEL); > if (!buf) > return -ENOMEM; > >- if (wacom->wacom_wac.features.type == WACOM_21UX2 || >- wacom->wacom_wac.features.type == WACOM_24HD) >- led = (wacom->led.select[1] << 4) | 0x40; >- >- led |= wacom->led.select[0] | 0x4; >- >- buf[0] = WAC_CMD_LED_CONTROL; >- buf[1] = led; >- buf[2] = wacom->led.llv; >- buf[3] = wacom->led.hlv; >- buf[4] = wacom->led.img_lum; >+ if (wacom->wacom_wac.features.type >= INTUOS5S && >+ wacom->wacom_wac.features.type <= INTUOS5L) { >+ /* >+ * Touch Ring and crop mark LED luminance may take on >+ * one of four values: >+ * 0 = Low; 1 = Medium; 2 = High; 3 = Off >+ */ >+ int ring_led = wacom->led.select[0] & 0x03; >+ int ring_lum = (((wacom->led.llv & 0x60) >> 5) - 1) & 0x03; >+ int crop_lum = 0; >+ >+ buf[0] = WAC_CMD_LED_CONTROL; >+ buf[1] = (crop_lum << 4) | (ring_lum << 2) | (ring_led); >+ } >+ else { >+ int led = wacom->led.select[0] | 0x4; >+ >+ if (wacom->wacom_wac.features.type == WACOM_21UX2 || >+ wacom->wacom_wac.features.type == WACOM_24HD) >+ led |= (wacom->led.select[1] << 4) | 0x40; >+ >+ buf[0] = WAC_CMD_LED_CONTROL; >+ buf[1] = led; >+ buf[2] = wacom->led.llv; >+ buf[3] = wacom->led.hlv; >+ buf[4] = wacom->led.img_lum; >+ } > > retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL, > buf, 9, WAC_CMD_RETRIES); >@@ -783,12 +839,24 @@ static struct attribute_group intuos4_le > .attrs = intuos4_led_attrs, > }; > >+static struct attribute *intuos5_led_attrs[] = { >+ &dev_attr_status0_luminance.attr, >+ &dev_attr_status_led0_select.attr, >+ NULL >+}; >+ >+static struct attribute_group intuos5_led_attr_group = { >+ .name = "wacom_led", >+ .attrs = intuos5_led_attrs, >+}; >+ > static int wacom_initialize_leds(struct wacom *wacom) > { > int error; > > /* Initialize default values */ > switch (wacom->wacom_wac.features.type) { >+ case INTUOS4S: > case INTUOS4: > case INTUOS4L: > wacom->led.select[0] = 0; >@@ -812,6 +880,19 @@ static int wacom_initialize_leds(struct > &cintiq_led_attr_group); > break; > >+ case INTUOS5S: >+ case INTUOS5: >+ case INTUOS5L: >+ wacom->led.select[0] = 0; >+ wacom->led.select[1] = 0; >+ wacom->led.llv = 32; >+ wacom->led.hlv = 0; >+ wacom->led.img_lum = 0; >+ >+ error = sysfs_create_group(&wacom->intf->dev.kobj, >+ &intuos5_led_attr_group); >+ break; >+ > default: > return 0; > } >@@ -829,6 +910,7 @@ static int wacom_initialize_leds(struct > static void wacom_destroy_leds(struct wacom *wacom) > { > switch (wacom->wacom_wac.features.type) { >+ case INTUOS4S: > case INTUOS4: > case INTUOS4L: > sysfs_remove_group(&wacom->intf->dev.kobj, >@@ -840,6 +922,13 @@ static void wacom_destroy_leds(struct wa > sysfs_remove_group(&wacom->intf->dev.kobj, > &cintiq_led_attr_group); > break; >+ >+ case INTUOS5S: >+ case INTUOS5: >+ case INTUOS5L: >+ sysfs_remove_group(&wacom->intf->dev.kobj, >+ &intuos5_led_attr_group); >+ break; > } > } > >@@ -881,6 +970,10 @@ static int wacom_initialize_battery(stru > > error = power_supply_register(&wacom->usbdev->dev, > &wacom->battery); >+ >+ if (!error) >+ power_supply_powers(&wacom->battery, >+ &wacom->usbdev->dev); > } > > return error; >@@ -888,8 +981,11 @@ static int wacom_initialize_battery(stru > > static void wacom_destroy_battery(struct wacom *wacom) > { >- if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) >+ if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR && >+ wacom->battery.dev) { > power_supply_unregister(&wacom->battery); >+ wacom->battery.dev = NULL; >+ } > } > > static int wacom_register_input(struct wacom *wacom) >@@ -901,8 +997,10 @@ static int wacom_register_input(struct w > int error; > > input_dev = input_allocate_device(); >- if (!input_dev) >- return -ENOMEM; >+ if (!input_dev) { >+ error = -ENOMEM; >+ goto fail1; >+ } > > input_dev->name = wacom_wac->name; > input_dev->dev.parent = &intf->dev; >@@ -912,14 +1010,20 @@ static int wacom_register_input(struct w > input_set_drvdata(input_dev, wacom); > > wacom_wac->input = input_dev; >- wacom_setup_input_capabilities(input_dev, wacom_wac); >+ error = wacom_setup_input_capabilities(input_dev, wacom_wac); >+ if (error) >+ goto fail1; > > error = input_register_device(input_dev); >- if (error) { >- input_free_device(input_dev); >- wacom_wac->input = NULL; >- } >+ if (error) >+ goto fail2; > >+ return 0; >+ >+fail2: >+ input_free_device(input_dev); >+ wacom_wac->input = NULL; >+fail1: > return error; > } > >@@ -928,32 +1032,39 @@ static void wacom_wireless_work(struct w > struct wacom *wacom = container_of(work, struct wacom, work); > struct usb_device *usbdev = wacom->usbdev; > struct wacom_wac *wacom_wac = &wacom->wacom_wac; >+ struct wacom *wacom1, *wacom2; >+ struct wacom_wac *wacom_wac1, *wacom_wac2; >+ int error; > > /* > * Regardless if this is a disconnect or a new tablet, >- * remove any existing input devices. >+ * remove any existing input and battery devices. > */ > >+ wacom_destroy_battery(wacom); >+ > /* Stylus interface */ >- wacom = usb_get_intfdata(usbdev->config->interface[1]); >- if (wacom->wacom_wac.input) >- input_unregister_device(wacom->wacom_wac.input); >- wacom->wacom_wac.input = 0; >+ 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; > > /* Touch interface */ >- wacom = usb_get_intfdata(usbdev->config->interface[2]); >- if (wacom->wacom_wac.input) >- input_unregister_device(wacom->wacom_wac.input); >- wacom->wacom_wac.input = 0; >+ 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; > > if (wacom_wac->pid == 0) { >- printk(KERN_INFO "wacom: wireless tablet disconnected\n"); >+ dev_info(&wacom->intf->dev, "wireless tablet disconnected\n"); > } else { > const struct usb_device_id *id = wacom_ids; > >- printk(KERN_INFO >- "wacom: wireless tablet connected with PID %x\n", >- wacom_wac->pid); >+ 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 && >@@ -963,30 +1074,45 @@ static void wacom_wireless_work(struct w > } > > if (!id->match_flags) { >- printk(KERN_INFO >- "wacom: ignorning unknown PID.\n"); >+ dev_info(&wacom->intf->dev, >+ "ignoring unknown PID.\n"); > return; > } > > /* Stylus interface */ >- wacom = usb_get_intfdata(usbdev->config->interface[1]); >- wacom_wac = &wacom->wacom_wac; >- wacom_wac->features = >+ wacom_wac1->features = > *((struct wacom_features *)id->driver_info); >- wacom_wac->features.device_type = BTN_TOOL_PEN; >- wacom_register_input(wacom); >+ wacom_wac1->features.device_type = BTN_TOOL_PEN; >+ error = wacom_register_input(wacom1); >+ if (error) >+ goto fail1; > > /* Touch interface */ >- wacom = usb_get_intfdata(usbdev->config->interface[2]); >- wacom_wac = &wacom->wacom_wac; >- wacom_wac->features = >+ wacom_wac2->features = > *((struct wacom_features *)id->driver_info); >- wacom_wac->features.pktlen = WACOM_PKGLEN_BBTOUCH3; >- wacom_wac->features.device_type = BTN_TOOL_FINGER; >- wacom_set_phy_from_res(&wacom_wac->features); >- wacom_wac->features.x_max = wacom_wac->features.y_max = 4096; >- wacom_register_input(wacom); >+ wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; >+ wacom_wac2->features.device_type = BTN_TOOL_FINGER; >+ wacom_set_phy_from_res(&wacom_wac2->features); >+ wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096; >+ error = wacom_register_input(wacom2); >+ if (error) >+ goto fail2; >+ >+ error = wacom_initialize_battery(wacom); >+ if (error) >+ goto fail3; > } >+ >+ return; >+ >+fail3: >+ input_unregister_device(wacom_wac2->input); >+ wacom_wac2->input = NULL; >+fail2: >+ input_unregister_device(wacom_wac1->input); >+ wacom_wac1->input = NULL; >+fail1: >+ return; > } > > static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) >@@ -1035,11 +1161,30 @@ static int wacom_probe(struct usb_interf > > endpoint = &intf->cur_altsetting->endpoint[0].desc; > >- /* Retrieve the physical and logical size for OEM devices */ >+ /* Retrieve the physical and logical size for touch devices */ > error = wacom_retrieve_hid_descriptor(intf, features); > if (error) > goto fail3; > >+ /* >+ * Intuos5 has no useful data about its touch interface in its >+ * HID descriptor. If this is the touch interface (wMaxPacketSize >+ * of WACOM_PKGLEN_BBTOUCH3), override the table values. >+ */ >+ if (features->type >= INTUOS5S && features->type <= INTUOS5L) { >+ if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) { >+ features->device_type = BTN_TOOL_FINGER; >+ features->pktlen = WACOM_PKGLEN_BBTOUCH3; >+ >+ wacom_set_phy_from_res(features); >+ >+ features->x_max = 4096; >+ features->y_max = 4096; >+ } else { >+ features->device_type = BTN_TOOL_PEN; >+ } >+ } >+ > wacom_setup_device_quirks(features); > > strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); >@@ -1067,14 +1212,10 @@ static int wacom_probe(struct usb_interf > if (error) > goto fail4; > >- error = wacom_initialize_battery(wacom); >- if (error) >- goto fail5; >- > if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) { > error = wacom_register_input(wacom); > if (error) >- goto fail6; >+ goto fail5; > } > > /* Note that if query fails it is not a hard failure */ >@@ -1089,7 +1230,6 @@ static int wacom_probe(struct usb_interf > > return 0; > >- fail6: wacom_destroy_battery(wacom); > fail5: wacom_destroy_leds(wacom); > fail4: wacom_remove_shared_data(wacom_wac); > fail3: usb_free_urb(wacom->irq); >diff -rup linux-3.4.11/drivers/input/tablet/wacom_wac.c linux-3.4.11_patched/drivers/input/tablet/wacom_wac.c >--- linux-3.4.11/drivers/input/tablet/wacom_wac.c 2012-09-15 07:18:55.000000000 +0900 >+++ linux-3.4.11_patched/drivers/input/tablet/wacom_wac.c 2012-10-01 19:45:25.147481057 +0900 >@@ -61,7 +61,8 @@ static int wacom_penpartner_irq(struct w > break; > > default: >- printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); >+ dev_dbg(input->dev.parent, >+ "%s: received unknown report #%d\n", __func__, data[0]); > return 0; > } > >@@ -76,7 +77,8 @@ static int wacom_pl_irq(struct wacom_wac > int prox, pressure; > > if (data[0] != WACOM_REPORT_PENABLED) { >- dbg("wacom_pl_irq: received unknown report #%d", data[0]); >+ dev_dbg(input->dev.parent, >+ "%s: received unknown report #%d\n", __func__, data[0]); > return 0; > } > >@@ -146,7 +148,8 @@ static int wacom_ptu_irq(struct wacom_wa > struct input_dev *input = wacom->input; > > if (data[0] != WACOM_REPORT_PENABLED) { >- printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); >+ dev_dbg(input->dev.parent, >+ "%s: received unknown report #%d\n", __func__, data[0]); > return 0; > } > >@@ -175,7 +178,8 @@ static int wacom_dtu_irq(struct wacom_wa > struct input_dev *input = wacom->input; > int prox = data[1] & 0x20, pressure; > >- dbg("wacom_dtu_irq: received report #%d", data[0]); >+ dev_dbg(input->dev.parent, >+ "%s: received report #%d", __func__, data[0]); > > if (prox) { > /* Going into proximity select tool */ >@@ -211,7 +215,8 @@ static int wacom_graphire_irq(struct wac > int retval = 0; > > if (data[0] != WACOM_REPORT_PENABLED) { >- dbg("wacom_graphire_irq: received unknown report #%d", data[0]); >+ dev_dbg(input->dev.parent, >+ "%s: received unknown report #%d\n", __func__, data[0]); > goto exit; > } > >@@ -321,6 +326,9 @@ static int wacom_intuos_inout(struct wac > > /* Enter report */ > if ((data[1] & 0xfc) == 0xc0) { >+ if (features->type >= INTUOS5S && features->type <= INTUOS5L) >+ wacom->shared->stylus_in_proximity = true; >+ > /* serial number of the tool */ > wacom->serial[idx] = ((data[3] & 0x0f) << 28) + > (data[4] << 20) + (data[5] << 12) + >@@ -406,6 +414,9 @@ static int wacom_intuos_inout(struct wac > > /* Exit report */ > if ((data[1] & 0xfe) == 0x80) { >+ if (features->type >= INTUOS5S && features->type <= INTUOS5L) >+ wacom->shared->stylus_in_proximity = false; >+ > /* > * Reset all states otherwise we lose the initial states > * when in-prox next time >@@ -452,7 +463,8 @@ static void wacom_intuos_general(struct > if ((data[1] & 0xb8) == 0xa0) { > t = (data[6] << 2) | ((data[7] >> 6) & 3); > if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || >- features->type == WACOM_21UX2 || features->type == WACOM_24HD) { >+ (features->type >= INTUOS5S && features->type <= INTUOS5L) || >+ (features->type >= WACOM_21UX2 && features->type <= WACOM_24HD)) { > t = (t << 1) | (data[1] & 1); > } > input_report_abs(input, ABS_PRESSURE, t); >@@ -482,9 +494,13 @@ static int wacom_intuos_irq(struct wacom > unsigned int t; > int idx = 0, result; > >- if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_INTUOSREAD >- && data[0] != WACOM_REPORT_INTUOSWRITE && data[0] != WACOM_REPORT_INTUOSPAD) { >- dbg("wacom_intuos_irq: received unknown report #%d", data[0]); >+ if (data[0] != WACOM_REPORT_PENABLED && >+ data[0] != WACOM_REPORT_INTUOSREAD && >+ data[0] != WACOM_REPORT_INTUOSWRITE && >+ data[0] != WACOM_REPORT_INTUOSPAD && >+ data[0] != WACOM_REPORT_INTUOS5PAD) { >+ dev_dbg(input->dev.parent, >+ "%s: received unknown report #%d\n", __func__, data[0]); > return 0; > } > >@@ -493,7 +509,7 @@ static int wacom_intuos_irq(struct wacom > idx = data[1] & 0x01; > > /* pad packets. Works as a second tool and is always in prox */ >- if (data[0] == WACOM_REPORT_INTUOSPAD) { >+ if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD) { > 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)); >@@ -569,8 +585,36 @@ static int wacom_intuos_irq(struct wacom > input_report_key(input, wacom->tool[1], 0); > input_report_abs(input, ABS_MISC, 0); > } >+ } else if (features->type >= INTUOS5S && features->type <= INTUOS5L) { >+ int i; >+ >+ /* Touch ring mode switch has no capacitive sensor */ >+ input_report_key(input, BTN_0, (data[3] & 0x01)); >+ >+ /* >+ * ExpressKeys on Intuos5 have a capacitive sensor in >+ * addition to the mechanical switch. Switch data is >+ * stored in data[4], capacitive data in data[5]. >+ */ >+ for (i = 0; i < 8; i++) >+ input_report_key(input, BTN_1 + i, data[4] & (1 << i)); >+ >+ if (data[2] & 0x80) { >+ input_report_abs(input, ABS_WHEEL, (data[2] & 0x7f)); >+ } else { >+ /* Out of proximity, clear wheel value. */ >+ input_report_abs(input, ABS_WHEEL, 0); >+ } >+ >+ if (data[2] | (data[3] & 0x01) | data[4]) { >+ input_report_key(input, wacom->tool[1], 1); >+ input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); >+ } else { >+ input_report_key(input, wacom->tool[1], 0); >+ input_report_abs(input, ABS_MISC, 0); >+ } > } else { >- if (features->type == WACOM_21UX2) { >+ if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) { > input_report_key(input, BTN_0, (data[5] & 0x01)); > input_report_key(input, BTN_1, (data[6] & 0x01)); > input_report_key(input, BTN_2, (data[6] & 0x02)); >@@ -589,6 +633,12 @@ static int wacom_intuos_irq(struct wacom > input_report_key(input, BTN_Z, (data[8] & 0x20)); > input_report_key(input, BTN_BASE, (data[8] & 0x40)); > input_report_key(input, BTN_BASE2, (data[8] & 0x80)); >+ >+ if (features->type == WACOM_22HD) { >+ input_report_key(input, KEY_PROG1, data[9] & 0x01); >+ input_report_key(input, KEY_PROG2, data[9] & 0x02); >+ input_report_key(input, KEY_PROG3, data[9] & 0x04); >+ } > } else { > input_report_key(input, BTN_0, (data[5] & 0x01)); > input_report_key(input, BTN_1, (data[5] & 0x02)); >@@ -632,7 +682,9 @@ static int wacom_intuos_irq(struct wacom > (features->type == INTUOS3 || > features->type == INTUOS3S || > features->type == INTUOS4 || >- features->type == INTUOS4S)) { >+ features->type == INTUOS4S || >+ features->type == INTUOS5 || >+ features->type == INTUOS5S)) { > > return 0; > } >@@ -685,7 +737,8 @@ static int wacom_intuos_irq(struct wacom > > } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { > /* I4 mouse */ >- if (features->type >= INTUOS4S && features->type <= INTUOS4L) { >+ if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || >+ (features->type >= INTUOS5S && features->type <= INTUOS5L)) { > input_report_key(input, BTN_LEFT, data[6] & 0x01); > input_report_key(input, BTN_MIDDLE, data[6] & 0x02); > input_report_key(input, BTN_RIGHT, data[6] & 0x04); >@@ -712,7 +765,7 @@ static int wacom_intuos_irq(struct wacom > } > } > } else if ((features->type < INTUOS3S || features->type == INTUOS3L || >- features->type == INTUOS4L) && >+ features->type == INTUOS4L || features->type == INTUOS5L) && > wacom->tool[idx] == BTN_TOOL_LENS) { > /* Lens cursor packets */ > input_report_key(input, BTN_LEFT, data[8] & 0x01); >@@ -729,6 +782,72 @@ static int wacom_intuos_irq(struct wacom > return 1; > } > >+static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid) >+{ >+ int touch_max = wacom->features.touch_max; >+ int i; >+ >+ if (!wacom->slots) >+ return -1; >+ >+ for (i = 0; i < touch_max; ++i) { >+ if (wacom->slots[i] == contactid) >+ return i; >+ } >+ for (i = 0; i < touch_max; ++i) { >+ if (wacom->slots[i] == -1) >+ return i; >+ } >+ return -1; >+} >+ >+static int wacom_mt_touch(struct wacom_wac *wacom) >+{ >+ struct input_dev *input = wacom->input; >+ char *data = wacom->data; >+ int i; >+ int current_num_contacts = data[2]; >+ int contacts_to_send = 0; >+ >+ /* >+ * First packet resets the counter since only the first >+ * packet in series will have non-zero current_num_contacts. >+ */ >+ if (current_num_contacts) >+ wacom->num_contacts_left = current_num_contacts; >+ >+ /* There are at most 5 contacts per packet */ >+ contacts_to_send = min(5, wacom->num_contacts_left); >+ >+ for (i = 0; i < contacts_to_send; i++) { >+ int offset = (WACOM_BYTES_PER_MT_PACKET * i) + 3; >+ bool touch = data[offset] & 0x1; >+ int id = le16_to_cpup((__le16 *)&data[offset + 1]); >+ int slot = find_slot_from_contactid(wacom, id); >+ >+ if (slot < 0) >+ continue; >+ >+ input_mt_slot(input, slot); >+ input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); >+ if (touch) { >+ int x = le16_to_cpup((__le16 *)&data[offset + 7]); >+ int y = le16_to_cpup((__le16 *)&data[offset + 9]); >+ input_report_abs(input, ABS_MT_POSITION_X, x); >+ input_report_abs(input, ABS_MT_POSITION_Y, y); >+ } >+ wacom->slots[slot] = touch ? id : -1; >+ } >+ >+ input_mt_report_pointer_emulation(input, true); >+ >+ wacom->num_contacts_left -= contacts_to_send; >+ if (wacom->num_contacts_left < 0) >+ wacom->num_contacts_left = 0; >+ >+ return 1; >+} >+ > static int wacom_tpc_mt_touch(struct wacom_wac *wacom) > { > struct input_dev *input = wacom->input; >@@ -767,12 +886,15 @@ static int wacom_tpc_single_touch(struct > bool prox; > int x = 0, y = 0; > >+ if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG) >+ return 0; >+ > if (!wacom->shared->stylus_in_proximity) { > if (len == WACOM_PKGLEN_TPC1FG) { > prox = data[0] & 0x01; > x = get_unaligned_le16(&data[1]); > y = get_unaligned_le16(&data[3]); >- } else { /* with capacity */ >+ } else { > prox = data[1] & 0x01; > x = le16_to_cpup((__le16 *)&data[2]); > y = le16_to_cpup((__le16 *)&data[4]); >@@ -830,22 +952,27 @@ static int wacom_tpc_irq(struct wacom_wa > { > char *data = wacom->data; > >- dbg("wacom_tpc_irq: received report #%d", data[0]); >+ dev_dbg(wacom->input->dev.parent, >+ "%s: received report #%d\n", __func__, data[0]); > > switch (len) { > case WACOM_PKGLEN_TPC1FG: >- return wacom_tpc_single_touch(wacom, len); >+ return wacom_tpc_single_touch(wacom, len); > > case WACOM_PKGLEN_TPC2FG: >- return wacom_tpc_mt_touch(wacom); >+ return wacom_tpc_mt_touch(wacom); > > default: > switch (data[0]) { > case WACOM_REPORT_TPC1FG: > case WACOM_REPORT_TPCHID: > case WACOM_REPORT_TPCST: >+ case WACOM_REPORT_TPC1FGE: > return wacom_tpc_single_touch(wacom, len); > >+ case WACOM_REPORT_TPCMT: >+ return wacom_mt_touch(wacom); >+ > case WACOM_REPORT_PENABLED: > return wacom_tpc_pen(wacom); > } >@@ -1110,12 +1237,24 @@ void wacom_wac_irq(struct wacom_wac *wac > case CINTIQ: > case WACOM_BEE: > case WACOM_21UX2: >+ case WACOM_22HD: > case WACOM_24HD: > sync = wacom_intuos_irq(wacom_wac); > break; > >+ case INTUOS5S: >+ case INTUOS5: >+ case INTUOS5L: >+ if (len == WACOM_PKGLEN_BBTOUCH3) >+ sync = wacom_bpt3_touch(wacom_wac); >+ else >+ sync = wacom_intuos_irq(wacom_wac); >+ break; >+ > case TABLETPC: >+ case TABLETPCE: > case TABLETPC2FG: >+ case MTSCREEN: > sync = wacom_tpc_irq(wacom_wac, len); > break; > >@@ -1187,8 +1326,8 @@ void wacom_setup_device_quirks(struct wa > } > > /* these device have multiple inputs */ >- if (features->type == TABLETPC || features->type == TABLETPC2FG || >- features->type == BAMBOO_PT || features->type == WIRELESS) >+ if (features->type >= WIRELESS || >+ (features->type >= INTUOS5S && features->type <= INTUOS5L)) > features->quirks |= WACOM_QUIRK_MULTI_INPUT; > > /* quirk for bamboo touch with 2 low res touches */ >@@ -1219,8 +1358,8 @@ static unsigned int wacom_calculate_touc > return (logical_max * 100) / physical_max; > } > >-void wacom_setup_input_capabilities(struct input_dev *input_dev, >- struct wacom_wac *wacom_wac) >+int wacom_setup_input_capabilities(struct input_dev *input_dev, >+ struct wacom_wac *wacom_wac) > { > struct wacom_features *features = &wacom_wac->features; > int i; >@@ -1300,6 +1439,12 @@ void wacom_setup_input_capabilities(stru > 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); >@@ -1355,6 +1500,50 @@ void wacom_setup_input_capabilities(stru > wacom_setup_intuos(wacom_wac); > break; > >+ case INTUOS5: >+ case INTUOS5L: >+ 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: >+ __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); >+ >+ input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); >+ >+ wacom_setup_intuos(wacom_wac); >+ } else if (features->device_type == BTN_TOOL_FINGER) { >+ __clear_bit(ABS_MISC, input_dev->absbit); >+ >+ __set_bit(BTN_TOOL_FINGER, input_dev->keybit); >+ __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); >+ __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); >+ __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); >+ >+ input_mt_init_slots(input_dev, features->touch_max); >+ >+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, >+ 0, 255, 0, 0); >+ >+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, >+ 0, features->x_max, >+ features->x_fuzz, 0); >+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, >+ 0, features->y_max, >+ features->y_fuzz, 0); >+ } >+ break; >+ > case INTUOS4: > case INTUOS4L: > __set_bit(BTN_7, input_dev->keybit); >@@ -1371,10 +1560,22 @@ void wacom_setup_input_capabilities(stru > __set_bit(INPUT_PROP_POINTER, input_dev->propbit); > break; > >- case TABLETPC2FG: >+ case MTSCREEN: > if (features->device_type == BTN_TOOL_FINGER) { >+ wacom_wac->slots = kmalloc(features->touch_max * >+ sizeof(int), >+ GFP_KERNEL); >+ if (!wacom_wac->slots) >+ return -ENOMEM; >+ >+ for (i = 0; i < features->touch_max; i++) >+ wacom_wac->slots[i] = -1; >+ } >+ /* fall through */ > >- input_mt_init_slots(input_dev, 2); >+ case TABLETPC2FG: >+ if (features->device_type == BTN_TOOL_FINGER) { >+ input_mt_init_slots(input_dev, features->touch_max); > input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, > 0, MT_TOOL_MAX, 0, 0); > input_set_abs_params(input_dev, ABS_MT_POSITION_X, >@@ -1385,6 +1586,7 @@ void wacom_setup_input_capabilities(stru > /* fall through */ > > case TABLETPC: >+ case TABLETPCE: > __clear_bit(ABS_MISC, input_dev->absbit); > > __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); >@@ -1429,6 +1631,7 @@ void wacom_setup_input_capabilities(stru > > __set_bit(BTN_TOOL_FINGER, input_dev->keybit); > __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); >+ input_mt_init_slots(input_dev, features->touch_max); > > if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { > __set_bit(BTN_TOOL_TRIPLETAP, >@@ -1436,13 +1639,9 @@ void wacom_setup_input_capabilities(stru > __set_bit(BTN_TOOL_QUADTAP, > input_dev->keybit); > >- input_mt_init_slots(input_dev, 16); >- > input_set_abs_params(input_dev, > ABS_MT_TOUCH_MAJOR, > 0, 255, 0, 0); >- } else { >- input_mt_init_slots(input_dev, 2); > } > > input_set_abs_params(input_dev, ABS_MT_POSITION_X, >@@ -1462,6 +1661,7 @@ void wacom_setup_input_capabilities(stru > } > break; > } >+ return 0; > } > > static const struct wacom_features wacom_features_0x00 = >@@ -1629,8 +1829,29 @@ static const struct wacom_features wacom > static const struct wacom_features wacom_features_0xBC = > { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40840, 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 }; >+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 }; >+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 }; >+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 }; >+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 }; > static const struct wacom_features wacom_features_0xF4 = >- { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, >+ { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, >+ 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; >+static const struct wacom_features wacom_features_0xF8 = >+ { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, > 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; > static const struct wacom_features wacom_features_0x3F = > { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, >@@ -1653,6 +1874,9 @@ static const struct wacom_features wacom > static const struct wacom_features wacom_features_0xCC = > { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047, > 63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; >+static const struct wacom_features wacom_features_0xFA = >+ { "Wacom Cintiq 22HD", WACOM_PKGLEN_INTUOS, 95840, 54260, 2047, >+ 63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; > 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 }; >@@ -1670,34 +1894,49 @@ static const struct wacom_features wacom > 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 }; >+ 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 }; >+ 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 }; > 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 }; >+ 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 }; >+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 }; >+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 }; > 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 }; > static const struct wacom_features wacom_features_0x84 = > { "Wacom Wireless Receiver", WACOM_PKGLEN_WIRELESS, 0, 0, 0, >- 0, WIRELESS, 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 }; >+ 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 }; >+ 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 }; > 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 }; >+ 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 }; >@@ -1706,28 +1945,35 @@ static const struct wacom_features wacom > 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 }; >+ 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 }; >+ 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 }; >+ 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 }; >+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, >+ .touch_max = 2 }; > static 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 }; >+ 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 }; > 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 }; >+ 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 }; >+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, >+ .touch_max = 16 }; > static const struct wacom_features wacom_features_0x6004 = > { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, > 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; >@@ -1801,6 +2047,11 @@ const struct usb_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(0xC5) }, > { USB_DEVICE_WACOM(0xC6) }, >@@ -1836,10 +2087,15 @@ const struct usb_device_id wacom_ids[] = > { USB_DEVICE_WACOM(0x9F) }, > { USB_DEVICE_WACOM(0xE2) }, > { USB_DEVICE_WACOM(0xE3) }, >+ { USB_DEVICE_WACOM(0xE5) }, > { USB_DEVICE_WACOM(0xE6) }, > { USB_DEVICE_WACOM(0xEC) }, >+ { USB_DEVICE_WACOM(0xED) }, >+ { USB_DEVICE_WACOM(0xEF) }, > { USB_DEVICE_WACOM(0x47) }, > { USB_DEVICE_WACOM(0xF4) }, >+ { USB_DEVICE_WACOM(0xF8) }, >+ { USB_DEVICE_WACOM(0xFA) }, > { USB_DEVICE_LENOVO(0x6004) }, > { } > }; >diff -rup linux-3.4.11/drivers/input/tablet/wacom_wac.h linux-3.4.11_patched/drivers/input/tablet/wacom_wac.h >--- linux-3.4.11/drivers/input/tablet/wacom_wac.h 2012-09-15 07:18:55.000000000 +0900 >+++ linux-3.4.11_patched/drivers/input/tablet/wacom_wac.h 2012-10-01 19:46:09.709483474 +0900 >@@ -25,6 +25,10 @@ > #define WACOM_PKGLEN_BBTOUCH3 64 > #define WACOM_PKGLEN_BBPEN 10 > #define WACOM_PKGLEN_WIRELESS 32 >+#define WACOM_PKGLEN_MTOUCH 62 >+ >+/* wacom data size per MT contact */ >+#define WACOM_BYTES_PER_MT_PACKET 11 > > /* device IDs */ > #define STYLUS_DEVICE_ID 0x02 >@@ -38,10 +42,13 @@ > #define WACOM_REPORT_INTUOSREAD 5 > #define WACOM_REPORT_INTUOSWRITE 6 > #define WACOM_REPORT_INTUOSPAD 12 >+#define WACOM_REPORT_INTUOS5PAD 3 > #define WACOM_REPORT_TPC1FG 6 > #define WACOM_REPORT_TPC2FG 13 >+#define WACOM_REPORT_TPCMT 13 > #define WACOM_REPORT_TPCHID 15 > #define WACOM_REPORT_TPCST 16 >+#define WACOM_REPORT_TPC1FGE 18 > > /* device quirks */ > #define WACOM_QUIRK_MULTI_INPUT 0x0001 >@@ -56,8 +63,6 @@ enum { > PTU, > PL, > DTU, >- BAMBOO_PT, >- WIRELESS, > INTUOS, > INTUOS3S, > INTUOS3, >@@ -65,13 +70,21 @@ enum { > INTUOS4S, > INTUOS4, > INTUOS4L, >- WACOM_24HD, >+ INTUOS5S, >+ INTUOS5, >+ INTUOS5L, > WACOM_21UX2, >+ WACOM_22HD, >+ WACOM_24HD, > CINTIQ, > WACOM_BEE, > WACOM_MO, >- TABLETPC, >+ WIRELESS, >+ BAMBOO_PT, >+ TABLETPC, /* add new TPC below */ >+ TABLETPCE, > TABLETPC2FG, >+ MTSCREEN, > MAX_TYPE > }; > >@@ -95,6 +108,7 @@ struct wacom_features { > int pressure_fuzz; > int distance_fuzz; > unsigned quirks; >+ unsigned touch_max; > }; > > struct wacom_shared { >@@ -113,6 +127,8 @@ struct wacom_wac { > struct input_dev *input; > int pid; > int battery_capacity; >+ int num_contacts_left; >+ int *slots; > }; > > #endif
diff -rup linux-3.4.11/drivers/input/tablet/wacom.h linux-3.4.11_patched/drivers/input/tablet/wacom.h --- linux-3.4.11/drivers/input/tablet/wacom.h 2012-09-15 07:18:55.000000000 +0900 +++ linux-3.4.11_patched/drivers/input/tablet/wacom.h 2012-10-01 19:48:59.834492696 +0900 @@ -135,6 +135,6 @@ extern const struct usb_device_id wacom_ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); void wacom_setup_device_quirks(struct wacom_features *features); -void wacom_setup_input_capabilities(struct input_dev *input_dev, - struct wacom_wac *wacom_wac); +int wacom_setup_input_capabilities(struct input_dev *input_dev, + struct wacom_wac *wacom_wac); #endif diff -rup linux-3.4.11/drivers/input/tablet/wacom_sys.c linux-3.4.11_patched/drivers/input/tablet/wacom_sys.c --- linux-3.4.11/drivers/input/tablet/wacom_sys.c 2012-09-15 07:18:55.000000000 +0900 +++ linux-3.4.11_patched/drivers/input/tablet/wacom_sys.c 2012-10-01 19:46:34.702484829 +0900 @@ -28,6 +28,7 @@ #define HID_USAGE_Y_TILT 0x3e #define HID_USAGE_FINGER 0x22 #define HID_USAGE_STYLUS 0x20 +#define HID_USAGE_CONTACTMAX 0x55 #define HID_COLLECTION 0xa1 #define HID_COLLECTION_LOGICAL 0x02 #define HID_COLLECTION_END 0xc0 @@ -99,6 +100,7 @@ static int wacom_set_report(struct usb_i static void wacom_sys_irq(struct urb *urb) { struct wacom *wacom = urb->context; + struct device *dev = &wacom->intf->dev; int retval; switch (urb->status) { @@ -109,10 +111,12 @@ static void wacom_sys_irq(struct urb *ur case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, urb->status); + dev_dbg(dev, "%s - urb shutting down with status: %d\n", + __func__, urb->status); return; default: - dbg("%s - nonzero urb status received: %d", __func__, urb->status); + dev_dbg(dev, "%s - nonzero urb status received: %d\n", + __func__, urb->status); goto exit; } @@ -122,8 +126,8 @@ static void wacom_sys_irq(struct urb *ur usb_mark_last_busy(wacom->usbdev); retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - err ("%s - usb_submit_urb failed with result %d", - __func__, retval); + dev_err(dev, "%s - usb_submit_urb failed with result %d\n", + __func__, retval); } static int wacom_open(struct input_dev *dev) @@ -201,6 +205,27 @@ static int wacom_parse_logical_collectio return length; } +static void wacom_retrieve_report_data(struct usb_interface *intf, + 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(intf, WAC_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); + } +} + /* * Interface Descriptor of wacom devices can be incomplete and * inconsistent so wacom_features table is used to store stylus @@ -233,6 +258,9 @@ static int wacom_parse_logical_collectio * 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. */ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, @@ -292,6 +320,10 @@ static int wacom_parse_hid(struct usb_in /* need to reset back */ features->pktlen = WACOM_PKGLEN_TPC2FG; } + + if (features->type == MTSCREEN) + features->pktlen = WACOM_PKGLEN_MTOUCH; + if (features->type == BAMBOO_PT) { /* need to reset back */ features->pktlen = WACOM_PKGLEN_BBTOUCH; @@ -324,18 +356,15 @@ static int wacom_parse_hid(struct usb_in case HID_USAGE_Y: if (usage == WCM_DESKTOP) { if (finger) { - features->device_type = BTN_TOOL_FINGER; - if (features->type == TABLETPC2FG) { - /* need to reset back */ - features->pktlen = WACOM_PKGLEN_TPC2FG; + int type = features->type; + + if (type == TABLETPC2FG || type == MTSCREEN) { features->y_max = get_unaligned_le16(&report[i + 3]); features->y_phy = get_unaligned_le16(&report[i + 6]); i += 7; - } else if (features->type == BAMBOO_PT) { - /* need to reset back */ - features->pktlen = WACOM_PKGLEN_BBTOUCH; + } else if (type == BAMBOO_PT) { features->y_phy = get_unaligned_le16(&report[i + 3]); features->y_max = @@ -349,10 +378,6 @@ static int wacom_parse_hid(struct usb_in i += 4; } } else if (pen) { - /* penabled only accepts exact bytes of data */ - if (features->type == TABLETPC2FG) - features->pktlen = WACOM_PKGLEN_GRAPHIRE; - features->device_type = BTN_TOOL_PEN; features->y_max = get_unaligned_le16(&report[i + 3]); i += 4; @@ -374,6 +399,13 @@ static int wacom_parse_hid(struct usb_in pen = 1; i++; break; + + case HID_USAGE_CONTACTMAX: + /* leave touch_max as is if predefined */ + if (!features->touch_max) + wacom_retrieve_report_data(intf, features); + i++; + break; } break; @@ -410,23 +442,29 @@ static int wacom_query_tablet_data(struc if (!rep_data) return error; - /* ask to report tablet data if it is MT Tablet PC or - * not a Tablet PC */ - if (features->type == TABLETPC2FG) { - do { - rep_data[0] = 3; - rep_data[1] = 4; - rep_data[2] = 0; - rep_data[3] = 0; - report_id = 3; - error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, - report_id, rep_data, 4, 1); - if (error >= 0) - error = wacom_get_report(intf, - WAC_HID_FEATURE_REPORT, - report_id, rep_data, 4, 1); - } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); - } else if (features->type != TABLETPC && + /* ask to report Wacom data */ + if (features->device_type == BTN_TOOL_FINGER) { + /* if it is an MT Tablet PC touch */ + if (features->type > TABLETPC) { + do { + rep_data[0] = 3; + rep_data[1] = 4; + rep_data[2] = 0; + rep_data[3] = 0; + report_id = 3; + error = wacom_set_report(intf, + WAC_HID_FEATURE_REPORT, + report_id, + rep_data, 4, 1); + if (error >= 0) + error = wacom_get_report(intf, + WAC_HID_FEATURE_REPORT, + report_id, + rep_data, 4, 1); + } while ((error < 0 || rep_data[1] != 4) && + limit++ < WAC_MSG_RETRIES); + } + } else if (features->type <= BAMBOO_PT && features->type != WIRELESS && features->device_type == BTN_TOOL_PEN) { do { @@ -447,7 +485,7 @@ static int wacom_query_tablet_data(struc } static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, - struct wacom_features *features) + struct wacom_features *features) { int error = 0; struct usb_host_interface *interface = intf->cur_altsetting; @@ -470,21 +508,23 @@ static int wacom_retrieve_hid_descriptor if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { features->device_type = 0; } else if (intf->cur_altsetting->desc.bInterfaceNumber == 2) { - features->device_type = BTN_TOOL_DOUBLETAP; + features->device_type = BTN_TOOL_FINGER; features->pktlen = WACOM_PKGLEN_BBTOUCH3; } } - /* only Tablet PCs and Bamboo P&T need to retrieve the info */ - if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) && - (features->type != BAMBOO_PT)) + /* only devices that support touch need to retrieve the info */ + if (features->type < BAMBOO_PT) { goto out; + } - if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { - if (usb_get_extra_descriptor(&interface->endpoint[0], - HID_DEVICET_REPORT, &hid_desc)) { - printk("wacom: can not retrieve extra class descriptor\n"); - error = 1; + 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) { + dev_err(&intf->dev, + "can not retrieve extra class descriptor\n"); goto out; } } @@ -574,23 +614,39 @@ static void wacom_remove_shared_data(str static int wacom_led_control(struct wacom *wacom) { unsigned char *buf; - int retval, led = 0; + int retval; buf = kzalloc(9, GFP_KERNEL); if (!buf) return -ENOMEM; - if (wacom->wacom_wac.features.type == WACOM_21UX2 || - wacom->wacom_wac.features.type == WACOM_24HD) - led = (wacom->led.select[1] << 4) | 0x40; - - led |= wacom->led.select[0] | 0x4; - - buf[0] = WAC_CMD_LED_CONTROL; - buf[1] = led; - buf[2] = wacom->led.llv; - buf[3] = wacom->led.hlv; - buf[4] = wacom->led.img_lum; + if (wacom->wacom_wac.features.type >= INTUOS5S && + wacom->wacom_wac.features.type <= INTUOS5L) { + /* + * Touch Ring and crop mark LED luminance may take on + * one of four values: + * 0 = Low; 1 = Medium; 2 = High; 3 = Off + */ + int ring_led = wacom->led.select[0] & 0x03; + int ring_lum = (((wacom->led.llv & 0x60) >> 5) - 1) & 0x03; + int crop_lum = 0; + + buf[0] = WAC_CMD_LED_CONTROL; + buf[1] = (crop_lum << 4) | (ring_lum << 2) | (ring_led); + } + else { + int led = wacom->led.select[0] | 0x4; + + if (wacom->wacom_wac.features.type == WACOM_21UX2 || + wacom->wacom_wac.features.type == WACOM_24HD) + led |= (wacom->led.select[1] << 4) | 0x40; + + buf[0] = WAC_CMD_LED_CONTROL; + buf[1] = led; + buf[2] = wacom->led.llv; + buf[3] = wacom->led.hlv; + buf[4] = wacom->led.img_lum; + } retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL, buf, 9, WAC_CMD_RETRIES); @@ -783,12 +839,24 @@ static struct attribute_group intuos4_le .attrs = intuos4_led_attrs, }; +static struct attribute *intuos5_led_attrs[] = { + &dev_attr_status0_luminance.attr, + &dev_attr_status_led0_select.attr, + NULL +}; + +static struct attribute_group intuos5_led_attr_group = { + .name = "wacom_led", + .attrs = intuos5_led_attrs, +}; + static int wacom_initialize_leds(struct wacom *wacom) { int error; /* Initialize default values */ switch (wacom->wacom_wac.features.type) { + case INTUOS4S: case INTUOS4: case INTUOS4L: wacom->led.select[0] = 0; @@ -812,6 +880,19 @@ static int wacom_initialize_leds(struct &cintiq_led_attr_group); break; + case INTUOS5S: + case INTUOS5: + case INTUOS5L: + wacom->led.select[0] = 0; + wacom->led.select[1] = 0; + wacom->led.llv = 32; + wacom->led.hlv = 0; + wacom->led.img_lum = 0; + + error = sysfs_create_group(&wacom->intf->dev.kobj, + &intuos5_led_attr_group); + break; + default: return 0; } @@ -829,6 +910,7 @@ static int wacom_initialize_leds(struct static void wacom_destroy_leds(struct wacom *wacom) { switch (wacom->wacom_wac.features.type) { + case INTUOS4S: case INTUOS4: case INTUOS4L: sysfs_remove_group(&wacom->intf->dev.kobj, @@ -840,6 +922,13 @@ static void wacom_destroy_leds(struct wa sysfs_remove_group(&wacom->intf->dev.kobj, &cintiq_led_attr_group); break; + + case INTUOS5S: + case INTUOS5: + case INTUOS5L: + sysfs_remove_group(&wacom->intf->dev.kobj, + &intuos5_led_attr_group); + break; } } @@ -881,6 +970,10 @@ static int wacom_initialize_battery(stru error = power_supply_register(&wacom->usbdev->dev, &wacom->battery); + + if (!error) + power_supply_powers(&wacom->battery, + &wacom->usbdev->dev); } return error; @@ -888,8 +981,11 @@ static int wacom_initialize_battery(stru static void wacom_destroy_battery(struct wacom *wacom) { - if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) + if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR && + wacom->battery.dev) { power_supply_unregister(&wacom->battery); + wacom->battery.dev = NULL; + } } static int wacom_register_input(struct wacom *wacom) @@ -901,8 +997,10 @@ static int wacom_register_input(struct w int error; input_dev = input_allocate_device(); - if (!input_dev) - return -ENOMEM; + if (!input_dev) { + error = -ENOMEM; + goto fail1; + } input_dev->name = wacom_wac->name; input_dev->dev.parent = &intf->dev; @@ -912,14 +1010,20 @@ static int wacom_register_input(struct w input_set_drvdata(input_dev, wacom); wacom_wac->input = input_dev; - wacom_setup_input_capabilities(input_dev, wacom_wac); + error = wacom_setup_input_capabilities(input_dev, wacom_wac); + if (error) + goto fail1; error = input_register_device(input_dev); - if (error) { - input_free_device(input_dev); - wacom_wac->input = NULL; - } + if (error) + goto fail2; + return 0; + +fail2: + input_free_device(input_dev); + wacom_wac->input = NULL; +fail1: return error; } @@ -928,32 +1032,39 @@ static void wacom_wireless_work(struct w struct wacom *wacom = container_of(work, struct wacom, work); struct usb_device *usbdev = wacom->usbdev; struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom *wacom1, *wacom2; + struct wacom_wac *wacom_wac1, *wacom_wac2; + int error; /* * Regardless if this is a disconnect or a new tablet, - * remove any existing input devices. + * remove any existing input and battery devices. */ + wacom_destroy_battery(wacom); + /* Stylus interface */ - wacom = usb_get_intfdata(usbdev->config->interface[1]); - if (wacom->wacom_wac.input) - input_unregister_device(wacom->wacom_wac.input); - wacom->wacom_wac.input = 0; + 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; /* Touch interface */ - wacom = usb_get_intfdata(usbdev->config->interface[2]); - if (wacom->wacom_wac.input) - input_unregister_device(wacom->wacom_wac.input); - wacom->wacom_wac.input = 0; + 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; if (wacom_wac->pid == 0) { - printk(KERN_INFO "wacom: wireless tablet disconnected\n"); + dev_info(&wacom->intf->dev, "wireless tablet disconnected\n"); } else { const struct usb_device_id *id = wacom_ids; - printk(KERN_INFO - "wacom: wireless tablet connected with PID %x\n", - wacom_wac->pid); + 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 && @@ -963,30 +1074,45 @@ static void wacom_wireless_work(struct w } if (!id->match_flags) { - printk(KERN_INFO - "wacom: ignorning unknown PID.\n"); + dev_info(&wacom->intf->dev, + "ignoring unknown PID.\n"); return; } /* Stylus interface */ - wacom = usb_get_intfdata(usbdev->config->interface[1]); - wacom_wac = &wacom->wacom_wac; - wacom_wac->features = + wacom_wac1->features = *((struct wacom_features *)id->driver_info); - wacom_wac->features.device_type = BTN_TOOL_PEN; - wacom_register_input(wacom); + wacom_wac1->features.device_type = BTN_TOOL_PEN; + error = wacom_register_input(wacom1); + if (error) + goto fail1; /* Touch interface */ - wacom = usb_get_intfdata(usbdev->config->interface[2]); - wacom_wac = &wacom->wacom_wac; - wacom_wac->features = + wacom_wac2->features = *((struct wacom_features *)id->driver_info); - wacom_wac->features.pktlen = WACOM_PKGLEN_BBTOUCH3; - wacom_wac->features.device_type = BTN_TOOL_FINGER; - wacom_set_phy_from_res(&wacom_wac->features); - wacom_wac->features.x_max = wacom_wac->features.y_max = 4096; - wacom_register_input(wacom); + wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; + wacom_wac2->features.device_type = BTN_TOOL_FINGER; + wacom_set_phy_from_res(&wacom_wac2->features); + wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096; + error = wacom_register_input(wacom2); + if (error) + goto fail2; + + error = wacom_initialize_battery(wacom); + if (error) + goto fail3; } + + return; + +fail3: + input_unregister_device(wacom_wac2->input); + wacom_wac2->input = NULL; +fail2: + input_unregister_device(wacom_wac1->input); + wacom_wac1->input = NULL; +fail1: + return; } static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -1035,11 +1161,30 @@ static int wacom_probe(struct usb_interf endpoint = &intf->cur_altsetting->endpoint[0].desc; - /* Retrieve the physical and logical size for OEM devices */ + /* Retrieve the physical and logical size for touch devices */ error = wacom_retrieve_hid_descriptor(intf, features); if (error) goto fail3; + /* + * Intuos5 has no useful data about its touch interface in its + * HID descriptor. If this is the touch interface (wMaxPacketSize + * of WACOM_PKGLEN_BBTOUCH3), override the table values. + */ + if (features->type >= INTUOS5S && features->type <= INTUOS5L) { + if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) { + features->device_type = BTN_TOOL_FINGER; + features->pktlen = WACOM_PKGLEN_BBTOUCH3; + + wacom_set_phy_from_res(features); + + features->x_max = 4096; + features->y_max = 4096; + } else { + features->device_type = BTN_TOOL_PEN; + } + } + wacom_setup_device_quirks(features); strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); @@ -1067,14 +1212,10 @@ static int wacom_probe(struct usb_interf if (error) goto fail4; - error = wacom_initialize_battery(wacom); - if (error) - goto fail5; - if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) { error = wacom_register_input(wacom); if (error) - goto fail6; + goto fail5; } /* Note that if query fails it is not a hard failure */ @@ -1089,7 +1230,6 @@ static int wacom_probe(struct usb_interf return 0; - fail6: wacom_destroy_battery(wacom); fail5: wacom_destroy_leds(wacom); fail4: wacom_remove_shared_data(wacom_wac); fail3: usb_free_urb(wacom->irq); diff -rup linux-3.4.11/drivers/input/tablet/wacom_wac.c linux-3.4.11_patched/drivers/input/tablet/wacom_wac.c --- linux-3.4.11/drivers/input/tablet/wacom_wac.c 2012-09-15 07:18:55.000000000 +0900 +++ linux-3.4.11_patched/drivers/input/tablet/wacom_wac.c 2012-10-01 19:45:25.147481057 +0900 @@ -61,7 +61,8 @@ static int wacom_penpartner_irq(struct w break; default: - printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); + dev_dbg(input->dev.parent, + "%s: received unknown report #%d\n", __func__, data[0]); return 0; } @@ -76,7 +77,8 @@ static int wacom_pl_irq(struct wacom_wac int prox, pressure; if (data[0] != WACOM_REPORT_PENABLED) { - dbg("wacom_pl_irq: received unknown report #%d", data[0]); + dev_dbg(input->dev.parent, + "%s: received unknown report #%d\n", __func__, data[0]); return 0; } @@ -146,7 +148,8 @@ static int wacom_ptu_irq(struct wacom_wa struct input_dev *input = wacom->input; if (data[0] != WACOM_REPORT_PENABLED) { - printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); + dev_dbg(input->dev.parent, + "%s: received unknown report #%d\n", __func__, data[0]); return 0; } @@ -175,7 +178,8 @@ static int wacom_dtu_irq(struct wacom_wa struct input_dev *input = wacom->input; int prox = data[1] & 0x20, pressure; - dbg("wacom_dtu_irq: received report #%d", data[0]); + dev_dbg(input->dev.parent, + "%s: received report #%d", __func__, data[0]); if (prox) { /* Going into proximity select tool */ @@ -211,7 +215,8 @@ static int wacom_graphire_irq(struct wac int retval = 0; if (data[0] != WACOM_REPORT_PENABLED) { - dbg("wacom_graphire_irq: received unknown report #%d", data[0]); + dev_dbg(input->dev.parent, + "%s: received unknown report #%d\n", __func__, data[0]); goto exit; } @@ -321,6 +326,9 @@ static int wacom_intuos_inout(struct wac /* Enter report */ if ((data[1] & 0xfc) == 0xc0) { + if (features->type >= INTUOS5S && features->type <= INTUOS5L) + wacom->shared->stylus_in_proximity = true; + /* serial number of the tool */ wacom->serial[idx] = ((data[3] & 0x0f) << 28) + (data[4] << 20) + (data[5] << 12) + @@ -406,6 +414,9 @@ static int wacom_intuos_inout(struct wac /* Exit report */ if ((data[1] & 0xfe) == 0x80) { + if (features->type >= INTUOS5S && features->type <= INTUOS5L) + wacom->shared->stylus_in_proximity = false; + /* * Reset all states otherwise we lose the initial states * when in-prox next time @@ -452,7 +463,8 @@ static void wacom_intuos_general(struct if ((data[1] & 0xb8) == 0xa0) { t = (data[6] << 2) | ((data[7] >> 6) & 3); if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || - features->type == WACOM_21UX2 || features->type == WACOM_24HD) { + (features->type >= INTUOS5S && features->type <= INTUOS5L) || + (features->type >= WACOM_21UX2 && features->type <= WACOM_24HD)) { t = (t << 1) | (data[1] & 1); } input_report_abs(input, ABS_PRESSURE, t); @@ -482,9 +494,13 @@ static int wacom_intuos_irq(struct wacom unsigned int t; int idx = 0, result; - if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_INTUOSREAD - && data[0] != WACOM_REPORT_INTUOSWRITE && data[0] != WACOM_REPORT_INTUOSPAD) { - dbg("wacom_intuos_irq: received unknown report #%d", data[0]); + if (data[0] != WACOM_REPORT_PENABLED && + data[0] != WACOM_REPORT_INTUOSREAD && + data[0] != WACOM_REPORT_INTUOSWRITE && + data[0] != WACOM_REPORT_INTUOSPAD && + data[0] != WACOM_REPORT_INTUOS5PAD) { + dev_dbg(input->dev.parent, + "%s: received unknown report #%d\n", __func__, data[0]); return 0; } @@ -493,7 +509,7 @@ static int wacom_intuos_irq(struct wacom idx = data[1] & 0x01; /* pad packets. Works as a second tool and is always in prox */ - if (data[0] == WACOM_REPORT_INTUOSPAD) { + if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD) { 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)); @@ -569,8 +585,36 @@ static int wacom_intuos_irq(struct wacom input_report_key(input, wacom->tool[1], 0); input_report_abs(input, ABS_MISC, 0); } + } else if (features->type >= INTUOS5S && features->type <= INTUOS5L) { + int i; + + /* Touch ring mode switch has no capacitive sensor */ + input_report_key(input, BTN_0, (data[3] & 0x01)); + + /* + * ExpressKeys on Intuos5 have a capacitive sensor in + * addition to the mechanical switch. Switch data is + * stored in data[4], capacitive data in data[5]. + */ + for (i = 0; i < 8; i++) + input_report_key(input, BTN_1 + i, data[4] & (1 << i)); + + if (data[2] & 0x80) { + input_report_abs(input, ABS_WHEEL, (data[2] & 0x7f)); + } else { + /* Out of proximity, clear wheel value. */ + input_report_abs(input, ABS_WHEEL, 0); + } + + if (data[2] | (data[3] & 0x01) | data[4]) { + input_report_key(input, wacom->tool[1], 1); + input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); + } else { + input_report_key(input, wacom->tool[1], 0); + input_report_abs(input, ABS_MISC, 0); + } } else { - if (features->type == WACOM_21UX2) { + if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) { input_report_key(input, BTN_0, (data[5] & 0x01)); input_report_key(input, BTN_1, (data[6] & 0x01)); input_report_key(input, BTN_2, (data[6] & 0x02)); @@ -589,6 +633,12 @@ static int wacom_intuos_irq(struct wacom input_report_key(input, BTN_Z, (data[8] & 0x20)); input_report_key(input, BTN_BASE, (data[8] & 0x40)); input_report_key(input, BTN_BASE2, (data[8] & 0x80)); + + if (features->type == WACOM_22HD) { + input_report_key(input, KEY_PROG1, data[9] & 0x01); + input_report_key(input, KEY_PROG2, data[9] & 0x02); + input_report_key(input, KEY_PROG3, data[9] & 0x04); + } } else { input_report_key(input, BTN_0, (data[5] & 0x01)); input_report_key(input, BTN_1, (data[5] & 0x02)); @@ -632,7 +682,9 @@ static int wacom_intuos_irq(struct wacom (features->type == INTUOS3 || features->type == INTUOS3S || features->type == INTUOS4 || - features->type == INTUOS4S)) { + features->type == INTUOS4S || + features->type == INTUOS5 || + features->type == INTUOS5S)) { return 0; } @@ -685,7 +737,8 @@ static int wacom_intuos_irq(struct wacom } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* I4 mouse */ - if (features->type >= INTUOS4S && features->type <= INTUOS4L) { + if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || + (features->type >= INTUOS5S && features->type <= INTUOS5L)) { input_report_key(input, BTN_LEFT, data[6] & 0x01); input_report_key(input, BTN_MIDDLE, data[6] & 0x02); input_report_key(input, BTN_RIGHT, data[6] & 0x04); @@ -712,7 +765,7 @@ static int wacom_intuos_irq(struct wacom } } } else if ((features->type < INTUOS3S || features->type == INTUOS3L || - features->type == INTUOS4L) && + features->type == INTUOS4L || features->type == INTUOS5L) && wacom->tool[idx] == BTN_TOOL_LENS) { /* Lens cursor packets */ input_report_key(input, BTN_LEFT, data[8] & 0x01); @@ -729,6 +782,72 @@ static int wacom_intuos_irq(struct wacom return 1; } +static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid) +{ + int touch_max = wacom->features.touch_max; + int i; + + if (!wacom->slots) + return -1; + + for (i = 0; i < touch_max; ++i) { + if (wacom->slots[i] == contactid) + return i; + } + for (i = 0; i < touch_max; ++i) { + if (wacom->slots[i] == -1) + return i; + } + return -1; +} + +static int wacom_mt_touch(struct wacom_wac *wacom) +{ + struct input_dev *input = wacom->input; + char *data = wacom->data; + int i; + int current_num_contacts = data[2]; + int contacts_to_send = 0; + + /* + * First packet resets the counter since only the first + * packet in series will have non-zero current_num_contacts. + */ + if (current_num_contacts) + wacom->num_contacts_left = current_num_contacts; + + /* There are at most 5 contacts per packet */ + contacts_to_send = min(5, wacom->num_contacts_left); + + for (i = 0; i < contacts_to_send; i++) { + int offset = (WACOM_BYTES_PER_MT_PACKET * i) + 3; + bool touch = data[offset] & 0x1; + int id = le16_to_cpup((__le16 *)&data[offset + 1]); + int slot = find_slot_from_contactid(wacom, id); + + if (slot < 0) + continue; + + input_mt_slot(input, slot); + input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); + if (touch) { + int x = le16_to_cpup((__le16 *)&data[offset + 7]); + int y = le16_to_cpup((__le16 *)&data[offset + 9]); + input_report_abs(input, ABS_MT_POSITION_X, x); + input_report_abs(input, ABS_MT_POSITION_Y, y); + } + wacom->slots[slot] = touch ? id : -1; + } + + input_mt_report_pointer_emulation(input, true); + + wacom->num_contacts_left -= contacts_to_send; + if (wacom->num_contacts_left < 0) + wacom->num_contacts_left = 0; + + return 1; +} + static int wacom_tpc_mt_touch(struct wacom_wac *wacom) { struct input_dev *input = wacom->input; @@ -767,12 +886,15 @@ static int wacom_tpc_single_touch(struct bool prox; int x = 0, y = 0; + if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG) + return 0; + if (!wacom->shared->stylus_in_proximity) { if (len == WACOM_PKGLEN_TPC1FG) { prox = data[0] & 0x01; x = get_unaligned_le16(&data[1]); y = get_unaligned_le16(&data[3]); - } else { /* with capacity */ + } else { prox = data[1] & 0x01; x = le16_to_cpup((__le16 *)&data[2]); y = le16_to_cpup((__le16 *)&data[4]); @@ -830,22 +952,27 @@ static int wacom_tpc_irq(struct wacom_wa { char *data = wacom->data; - dbg("wacom_tpc_irq: received report #%d", data[0]); + dev_dbg(wacom->input->dev.parent, + "%s: received report #%d\n", __func__, data[0]); switch (len) { case WACOM_PKGLEN_TPC1FG: - return wacom_tpc_single_touch(wacom, len); + return wacom_tpc_single_touch(wacom, len); case WACOM_PKGLEN_TPC2FG: - return wacom_tpc_mt_touch(wacom); + return wacom_tpc_mt_touch(wacom); default: switch (data[0]) { case WACOM_REPORT_TPC1FG: case WACOM_REPORT_TPCHID: case WACOM_REPORT_TPCST: + case WACOM_REPORT_TPC1FGE: return wacom_tpc_single_touch(wacom, len); + case WACOM_REPORT_TPCMT: + return wacom_mt_touch(wacom); + case WACOM_REPORT_PENABLED: return wacom_tpc_pen(wacom); } @@ -1110,12 +1237,24 @@ void wacom_wac_irq(struct wacom_wac *wac case CINTIQ: case WACOM_BEE: case WACOM_21UX2: + case WACOM_22HD: case WACOM_24HD: sync = wacom_intuos_irq(wacom_wac); break; + case INTUOS5S: + case INTUOS5: + case INTUOS5L: + if (len == WACOM_PKGLEN_BBTOUCH3) + sync = wacom_bpt3_touch(wacom_wac); + else + sync = wacom_intuos_irq(wacom_wac); + break; + case TABLETPC: + case TABLETPCE: case TABLETPC2FG: + case MTSCREEN: sync = wacom_tpc_irq(wacom_wac, len); break; @@ -1187,8 +1326,8 @@ void wacom_setup_device_quirks(struct wa } /* these device have multiple inputs */ - if (features->type == TABLETPC || features->type == TABLETPC2FG || - features->type == BAMBOO_PT || features->type == WIRELESS) + if (features->type >= WIRELESS || + (features->type >= INTUOS5S && features->type <= INTUOS5L)) features->quirks |= WACOM_QUIRK_MULTI_INPUT; /* quirk for bamboo touch with 2 low res touches */ @@ -1219,8 +1358,8 @@ static unsigned int wacom_calculate_touc return (logical_max * 100) / physical_max; } -void wacom_setup_input_capabilities(struct input_dev *input_dev, - struct wacom_wac *wacom_wac) +int wacom_setup_input_capabilities(struct input_dev *input_dev, + struct wacom_wac *wacom_wac) { struct wacom_features *features = &wacom_wac->features; int i; @@ -1300,6 +1439,12 @@ void wacom_setup_input_capabilities(stru 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); @@ -1355,6 +1500,50 @@ void wacom_setup_input_capabilities(stru wacom_setup_intuos(wacom_wac); break; + case INTUOS5: + case INTUOS5L: + 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: + __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); + + input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); + + wacom_setup_intuos(wacom_wac); + } else if (features->device_type == BTN_TOOL_FINGER) { + __clear_bit(ABS_MISC, input_dev->absbit); + + __set_bit(BTN_TOOL_FINGER, input_dev->keybit); + __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); + __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); + __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); + + input_mt_init_slots(input_dev, features->touch_max); + + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, + 0, 255, 0, 0); + + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + 0, features->x_max, + features->x_fuzz, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, + 0, features->y_max, + features->y_fuzz, 0); + } + break; + case INTUOS4: case INTUOS4L: __set_bit(BTN_7, input_dev->keybit); @@ -1371,10 +1560,22 @@ void wacom_setup_input_capabilities(stru __set_bit(INPUT_PROP_POINTER, input_dev->propbit); break; - case TABLETPC2FG: + case MTSCREEN: if (features->device_type == BTN_TOOL_FINGER) { + wacom_wac->slots = kmalloc(features->touch_max * + sizeof(int), + GFP_KERNEL); + if (!wacom_wac->slots) + return -ENOMEM; + + for (i = 0; i < features->touch_max; i++) + wacom_wac->slots[i] = -1; + } + /* fall through */ - input_mt_init_slots(input_dev, 2); + case TABLETPC2FG: + if (features->device_type == BTN_TOOL_FINGER) { + input_mt_init_slots(input_dev, features->touch_max); input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0); input_set_abs_params(input_dev, ABS_MT_POSITION_X, @@ -1385,6 +1586,7 @@ void wacom_setup_input_capabilities(stru /* fall through */ case TABLETPC: + case TABLETPCE: __clear_bit(ABS_MISC, input_dev->absbit); __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); @@ -1429,6 +1631,7 @@ void wacom_setup_input_capabilities(stru __set_bit(BTN_TOOL_FINGER, input_dev->keybit); __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); + input_mt_init_slots(input_dev, features->touch_max); if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { __set_bit(BTN_TOOL_TRIPLETAP, @@ -1436,13 +1639,9 @@ void wacom_setup_input_capabilities(stru __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); - input_mt_init_slots(input_dev, 16); - input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); - } else { - input_mt_init_slots(input_dev, 2); } input_set_abs_params(input_dev, ABS_MT_POSITION_X, @@ -1462,6 +1661,7 @@ void wacom_setup_input_capabilities(stru } break; } + return 0; } static const struct wacom_features wacom_features_0x00 = @@ -1629,8 +1829,29 @@ static const struct wacom_features wacom static const struct wacom_features wacom_features_0xBC = { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40840, 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 }; +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 }; +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 }; +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 }; +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 }; static const struct wacom_features wacom_features_0xF4 = - { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, + { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, + 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; +static const struct wacom_features wacom_features_0xF8 = + { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0x3F = { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, @@ -1653,6 +1874,9 @@ static const struct wacom_features wacom static const struct wacom_features wacom_features_0xCC = { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047, 63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; +static const struct wacom_features wacom_features_0xFA = + { "Wacom Cintiq 22HD", WACOM_PKGLEN_INTUOS, 95840, 54260, 2047, + 63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; 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 }; @@ -1670,34 +1894,49 @@ static const struct wacom_features wacom 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 }; + 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 }; + 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 }; 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 }; + 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 }; +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 }; +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 }; 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 }; static const struct wacom_features wacom_features_0x84 = { "Wacom Wireless Receiver", WACOM_PKGLEN_WIRELESS, 0, 0, 0, - 0, WIRELESS, 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 }; + 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 }; + 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 }; 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 }; + 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 }; @@ -1706,28 +1945,35 @@ static const struct wacom_features wacom 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 }; + 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 }; + 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 }; + 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 }; + 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + .touch_max = 2 }; static 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 }; + 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 }; 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 }; + 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 }; + 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + .touch_max = 16 }; static const struct wacom_features wacom_features_0x6004 = { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -1801,6 +2047,11 @@ const struct usb_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(0xC5) }, { USB_DEVICE_WACOM(0xC6) }, @@ -1836,10 +2087,15 @@ const struct usb_device_id wacom_ids[] = { USB_DEVICE_WACOM(0x9F) }, { USB_DEVICE_WACOM(0xE2) }, { USB_DEVICE_WACOM(0xE3) }, + { USB_DEVICE_WACOM(0xE5) }, { USB_DEVICE_WACOM(0xE6) }, { USB_DEVICE_WACOM(0xEC) }, + { USB_DEVICE_WACOM(0xED) }, + { USB_DEVICE_WACOM(0xEF) }, { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0xF4) }, + { USB_DEVICE_WACOM(0xF8) }, + { USB_DEVICE_WACOM(0xFA) }, { USB_DEVICE_LENOVO(0x6004) }, { } }; diff -rup linux-3.4.11/drivers/input/tablet/wacom_wac.h linux-3.4.11_patched/drivers/input/tablet/wacom_wac.h --- linux-3.4.11/drivers/input/tablet/wacom_wac.h 2012-09-15 07:18:55.000000000 +0900 +++ linux-3.4.11_patched/drivers/input/tablet/wacom_wac.h 2012-10-01 19:46:09.709483474 +0900 @@ -25,6 +25,10 @@ #define WACOM_PKGLEN_BBTOUCH3 64 #define WACOM_PKGLEN_BBPEN 10 #define WACOM_PKGLEN_WIRELESS 32 +#define WACOM_PKGLEN_MTOUCH 62 + +/* wacom data size per MT contact */ +#define WACOM_BYTES_PER_MT_PACKET 11 /* device IDs */ #define STYLUS_DEVICE_ID 0x02 @@ -38,10 +42,13 @@ #define WACOM_REPORT_INTUOSREAD 5 #define WACOM_REPORT_INTUOSWRITE 6 #define WACOM_REPORT_INTUOSPAD 12 +#define WACOM_REPORT_INTUOS5PAD 3 #define WACOM_REPORT_TPC1FG 6 #define WACOM_REPORT_TPC2FG 13 +#define WACOM_REPORT_TPCMT 13 #define WACOM_REPORT_TPCHID 15 #define WACOM_REPORT_TPCST 16 +#define WACOM_REPORT_TPC1FGE 18 /* device quirks */ #define WACOM_QUIRK_MULTI_INPUT 0x0001 @@ -56,8 +63,6 @@ enum { PTU, PL, DTU, - BAMBOO_PT, - WIRELESS, INTUOS, INTUOS3S, INTUOS3, @@ -65,13 +70,21 @@ enum { INTUOS4S, INTUOS4, INTUOS4L, - WACOM_24HD, + INTUOS5S, + INTUOS5, + INTUOS5L, WACOM_21UX2, + WACOM_22HD, + WACOM_24HD, CINTIQ, WACOM_BEE, WACOM_MO, - TABLETPC, + WIRELESS, + BAMBOO_PT, + TABLETPC, /* add new TPC below */ + TABLETPCE, TABLETPC2FG, + MTSCREEN, MAX_TYPE }; @@ -95,6 +108,7 @@ struct wacom_features { int pressure_fuzz; int distance_fuzz; unsigned quirks; + unsigned touch_max; }; struct wacom_shared { @@ -113,6 +127,8 @@ struct wacom_wac { struct input_dev *input; int pid; int battery_capacity; + int num_contacts_left; + int *slots; }; #endif
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 7659
: 2904