Nils Kanning wrote:

> patches 0020-0023: tablet works
> patches 0020-0024: tablet works
> patches 0020-0025: does not work
> patches 0020-0026: does not work
> patches 0020-0024,0026: does not work

Thanks!  How about 0026 alone?

(0025 is more tricky to test because it depends on 0024.  Quick
two-patch series for that attached in case you are interested.)
>From 75deb2e669949031f90dadd7d0e31f2acfb6407c Mon Sep 17 00:00:00 2001
From: Ping Cheng <pingli...@gmail.com>
Date: Sun, 29 Apr 2012 21:09:17 -0700
Subject: [PATCH 1/2] Input: wacom - retrieve maximum number of touch points

commit f393ee2b814e3291c12565000210b3cf10aa5c1d upstream.

>From the HID usage table when it is supported.

Tested-by: Jason Gerecke <killert...@gmail.com>
Signed-off-by: Chris Bagwell <ch...@cnpbagwell.com>
Signed-off-by: Ping Cheng <pi...@wacom.com>
Signed-off-by: Dmitry Torokhov <d...@mail.ru>
Signed-off-by: Jonathan Nieder <jrnie...@gmail.com>
---
 drivers/input/tablet/wacom_sys.c |   29 ++++++++++++++++++++++-
 drivers/input/tablet/wacom_wac.c |   48 +++++++++++++++++++++++---------------
 drivers/input/tablet/wacom_wac.h |    1 +
 3 files changed, 58 insertions(+), 20 deletions(-)

diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 0d269212931e..f1ec4908911d 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -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
@@ -201,6 +202,27 @@ static int wacom_parse_logical_collection(unsigned char 
*report,
        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
@@ -374,6 +396,11 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                pen = 1;
                                i++;
                                break;
+
+                       case HID_USAGE_CONTACTMAX:
+                               wacom_retrieve_report_data(intf, features);
+                               i++;
+                               break;
                        }
                        break;
 
@@ -1035,7 +1062,7 @@ static int wacom_probe(struct usb_interface *intf, const 
struct usb_device_id *i
 
        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;
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index cecd35c8f0b3..fb0584fa5be7 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -1374,7 +1374,7 @@ void wacom_setup_input_capabilities(struct input_dev 
*input_dev,
        case TABLETPC2FG:
                if (features->device_type == BTN_TOOL_FINGER) {
 
-                       input_mt_init_slots(input_dev, 2);
+                       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,
@@ -1429,6 +1429,7 @@ void wacom_setup_input_capabilities(struct input_dev 
*input_dev,
 
                        __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 +1437,9 @@ void wacom_setup_input_capabilities(struct input_dev 
*input_dev,
                                __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,
@@ -1670,13 +1667,16 @@ static const struct wacom_features wacom_features_0x9F =
          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_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 };
@@ -1685,19 +1685,22 @@ static const struct wacom_features wacom_features_0x47 =
          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 +1709,35 @@ static const struct wacom_features wacom_features_0xD5 =
          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 };
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index ba5a334e54d6..93295aa1b1c1 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -95,6 +95,7 @@ struct wacom_features {
        int pressure_fuzz;
        int distance_fuzz;
        unsigned quirks;
+       unsigned touch_max;
 };
 
 struct wacom_shared {
-- 
1.7.10.4

>From b4ede6ebf876fbe2c5242e71c7eb195c6f0de6cc Mon Sep 17 00:00:00 2001
From: Ping Cheng <pingli...@gmail.com>
Date: Sun, 29 Apr 2012 21:09:18 -0700
Subject: [PATCH 2/2] Input: wacom - add 0xE5 (MT device) support

commit 1963518b9b1b8019d33b4b08deee6f873ffa2730 upstream.

Main part of patch is adding support for a new Wacom MT touch
packet and labels these devices using MTSCREEN type.

Other items of interest:

Delete some duplicate code in HID parsing for Y info since
its already done in X path.

In wacom_query_tablet_data(), only invoke the set report
that requests tablets to send Wacom Touch packets for
Finger interfaces.  Mostly, this is to make code intent clear.

Tested-by: Jason Gerecke <killert...@gmail.com>
Signed-off-by: Chris Bagwell <ch...@cnpbagwell.com>
Signed-off-by: Ping Cheng <pi...@wacom.com>
Signed-off-by: Dmitry Torokhov <d...@mail.ru>
Signed-off-by: Jonathan Nieder <jrnie...@gmail.com>
---
 drivers/input/tablet/wacom.h     |    4 +-
 drivers/input/tablet/wacom_sys.c |   91 ++++++++++++++++++++---------------
 drivers/input/tablet/wacom_wac.c |   99 ++++++++++++++++++++++++++++++++++++--
 drivers/input/tablet/wacom_wac.h |    8 +++
 4 files changed, 157 insertions(+), 45 deletions(-)

diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index b4842d0e61dd..b79d45198d82 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -135,6 +135,6 @@ extern const struct usb_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);
-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 --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index f1ec4908911d..cc4ace2b1a45 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -314,6 +314,10 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                                        /* 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;
@@ -346,18 +350,15 @@ static int wacom_parse_hid(struct usb_interface *intf,
                        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 =
@@ -371,10 +372,6 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                                        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;
@@ -437,22 +434,29 @@ static int wacom_query_tablet_data(struct usb_interface 
*intf, struct wacom_feat
        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);
+       /* ask to report Wacom data */
+       if (features->device_type == BTN_TOOL_FINGER) {
+               /* if it is an MT Tablet PC touch */
+               if (features->type == TABLETPC2FG ||
+                   features->type == MTSCREEN) {
+                       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 &&
                   features->type != WIRELESS &&
                   features->device_type == BTN_TOOL_PEN) {
@@ -474,7 +478,7 @@ static int wacom_query_tablet_data(struct usb_interface 
*intf, struct wacom_feat
 }
 
 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;
@@ -502,10 +506,13 @@ static int wacom_retrieve_hid_descriptor(struct 
usb_interface *intf,
                }
        }
 
-       /* 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 != TABLETPC &&
+           features->type != TABLETPC2FG &&
+           features->type != BAMBOO_PT &&
+           features->type != MTSCREEN) {
                goto out;
+       }
 
        if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
                if (usb_get_extra_descriptor(&interface->endpoint[0],
@@ -928,8 +935,10 @@ static int wacom_register_input(struct wacom *wacom)
        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;
@@ -939,14 +948,20 @@ static int wacom_register_input(struct wacom *wacom)
        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;
 }
 
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index fb0584fa5be7..877e20a7320c 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -729,6 +729,72 @@ static int wacom_intuos_irq(struct wacom_wac *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,6 +833,9 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, 
size_t len)
        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;
@@ -834,10 +903,10 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t 
len)
 
        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]) {
@@ -846,6 +915,9 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t 
len)
                case WACOM_REPORT_TPCST:
                        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);
                }
@@ -1116,6 +1188,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t 
len)
 
        case TABLETPC:
        case TABLETPC2FG:
+       case MTSCREEN:
                sync = wacom_tpc_irq(wacom_wac, len);
                break;
 
@@ -1188,7 +1261,8 @@ void wacom_setup_device_quirks(struct wacom_features 
*features)
 
        /* these device have multiple inputs */
        if (features->type == TABLETPC || features->type == TABLETPC2FG ||
-           features->type == BAMBOO_PT || features->type == WIRELESS)
+           features->type == BAMBOO_PT || features->type == WIRELESS ||
+           features->type == MTSCREEN)
                features->quirks |= WACOM_QUIRK_MULTI_INPUT;
 
        /* quirk for bamboo touch with 2 low res touches */
@@ -1219,8 +1293,8 @@ static unsigned int wacom_calculate_touch_res(unsigned 
int logical_max,
        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;
@@ -1372,8 +1446,18 @@ void wacom_setup_input_capabilities(struct input_dev 
*input_dev,
                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;
+
                        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);
@@ -1459,6 +1543,7 @@ void wacom_setup_input_capabilities(struct input_dev 
*input_dev,
                }
                break;
        }
+       return 0;
 }
 
 static const struct wacom_features wacom_features_0x00 =
@@ -1673,6 +1758,9 @@ 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 };
+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,
@@ -1846,6 +1934,7 @@ 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(0x47) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 93295aa1b1c1..c7f6b811dfcc 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -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
@@ -40,6 +44,7 @@
 #define WACOM_REPORT_INTUOSPAD         12
 #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
 
@@ -72,6 +77,7 @@ enum {
        WACOM_MO,
        TABLETPC,
        TABLETPC2FG,
+       MTSCREEN,
        MAX_TYPE
 };
 
@@ -114,6 +120,8 @@ struct wacom_wac {
        struct input_dev *input;
        int pid;
        int battery_capacity;
+       int num_contacts_left;
+       int *slots;
 };
 
 #endif
-- 
1.7.10.4

Reply via email to