Seperate the function into two halves: first gather data from the packet,
next report all gathered data. The input subsystem should automatically
mute any events that aren't actually declared for the tablet at hand.

Signed-off-by: Jason Gerecke <jason.gere...@wacom.com>
Signed-off-by: Jiri Kosina <jkos...@suse.cz>
[jason.gere...@wacom.com: Imported into input-wacom repository (c7f0522)]
Signed-off-by: Jason Gerecke <jason.gere...@wacom.com>
[jason.gere...@wacom.com: backported from input-wacom 9a57c1a]
Signed-off-by: Jason Gerecke <jason.gere...@wacom.com>
---
 2.6.38/wacom_wac.c | 274 +++++++++++++++++------------------------------------
 3.7/wacom_wac.c    | 274 +++++++++++++++++------------------------------------
 2 files changed, 170 insertions(+), 378 deletions(-)

diff --git a/2.6.38/wacom_wac.c b/2.6.38/wacom_wac.c
index 4485f16..da025cf 100644
--- a/2.6.38/wacom_wac.c
+++ b/2.6.38/wacom_wac.c
@@ -38,6 +38,9 @@
  */
 #define WACOM_CONTACT_AREA_SCALE 2607
 
+static void wacom_report_numbered_buttons(struct input_dev *input_dev,
+                               int button_cout, int mask);
+
 static void wacom_notify_battery(struct wacom_wac *wacom_wac,
        int bat_capacity, bool bat_charging, bool bat_connected,
        bool ps_connected)
@@ -404,6 +407,12 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
        struct wacom_features *features = &wacom->features;
        unsigned char *data = wacom->data;
        struct input_dev *input = wacom->input;
+       int i;
+       int buttons = 0, nbuttons = features->numbered_buttons;
+       int keys = 0, nkeys = 0;
+       int ring1 = 0, ring2 = 0;
+       int strip1 = 0, strip2 = 0;
+       bool prox = false;
 
        /* pad packets. Works as a second tool and is always in prox */
        if (!(data[0] == WACOM_REPORT_INTUOSPAD || data[0] == 
WACOM_REPORT_INTUOS5PAD ||
@@ -411,72 +420,16 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
                return 0;
 
        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));
-               input_report_key(input, BTN_2, (data[3] & 0x02));
-               input_report_key(input, BTN_3, (data[3] & 0x04));
-               input_report_key(input, BTN_4, (data[3] & 0x08));
-               input_report_key(input, BTN_5, (data[3] & 0x10));
-               input_report_key(input, BTN_6, (data[3] & 0x20));
-               if (data[1] & 0x80) {
-                       input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
-               } else {
-                       /* Out of proximity, clear wheel value. */
-                       input_report_abs(input, ABS_WHEEL, 0);
-               }
-               if (features->type != INTUOS4S) {
-                       input_report_key(input, BTN_7, (data[3] & 0x40));
-                       input_report_key(input, BTN_8, (data[3] & 0x80));
-               }
-               if (data[1] | (data[2] & 0x01) | data[3]) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               buttons = (data[3] << 1) | (data[2] & 0x01);
+               ring1 = data[1];
        } else if (features->type == DTK) {
-               input_report_key(input, BTN_0, (data[6] & 0x01));
-               input_report_key(input, BTN_1, (data[6] & 0x02));
-               input_report_key(input, BTN_2, (data[6] & 0x04));
-               input_report_key(input, BTN_3, (data[6] & 0x08));
-               input_report_key(input, BTN_4, (data[6] & 0x10));
-               input_report_key(input, BTN_5, (data[6] & 0x20));
-               if (data[6] & 0x3f) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               buttons = data[6];
        } else if (features->type == WACOM_13HD) {
-               input_report_key(input, BTN_0, (data[3] & 0x01));
-               input_report_key(input, BTN_1, (data[4] & 0x01));
-               input_report_key(input, BTN_2, (data[4] & 0x02));
-               input_report_key(input, BTN_3, (data[4] & 0x04));
-               input_report_key(input, BTN_4, (data[4] & 0x08));
-               input_report_key(input, BTN_5, (data[4] & 0x10));
-               input_report_key(input, BTN_6, (data[4] & 0x20));
-               input_report_key(input, BTN_7, (data[4] & 0x40));
-               input_report_key(input, BTN_8, (data[4] & 0x80));
-               if ((data[3] & 0x01) | data[4]) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               buttons = (data[4] << 1) | (data[3] & 0x01);
        } else if (features->type == WACOM_24HD) {
-               input_report_key(input, BTN_0, (data[6] & 0x01));
-               input_report_key(input, BTN_1, (data[6] & 0x02));
-               input_report_key(input, BTN_2, (data[6] & 0x04));
-               input_report_key(input, BTN_3, (data[6] & 0x08));
-               input_report_key(input, BTN_4, (data[6] & 0x10));
-               input_report_key(input, BTN_5, (data[6] & 0x20));
-               input_report_key(input, BTN_6, (data[6] & 0x40));
-               input_report_key(input, BTN_7, (data[6] & 0x80));
-               input_report_key(input, BTN_8, (data[8] & 0x01));
-               input_report_key(input, BTN_9, (data[8] & 0x02));
-               input_report_key(input, BTN_A, (data[8] & 0x04));
-               input_report_key(input, BTN_B, (data[8] & 0x08));
-               input_report_key(input, BTN_C, (data[8] & 0x10));
-               input_report_key(input, BTN_X, (data[8] & 0x20));
-               input_report_key(input, BTN_Y, (data[8] & 0x40));
-               input_report_key(input, BTN_Z, (data[8] & 0x80));
+               buttons = (data[8] << 8) | data[6];
+               ring1 = data[1];
+               ring2 = data[2];
 
                /*
                 * Three "buttons" are available on the 24HD which are
@@ -485,155 +438,85 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
                 * The raw touchstrip bits are stored at:
                 *    ((data[3] & 0x1f) << 8) | data[4])
                 */
-               input_report_key(input, KEY_PROG1, data[4] & 0x07);
-               input_report_key(input, KEY_PROG2, data[4] & 0xE0);
-               input_report_key(input, KEY_PROG3, data[3] & 0x1C);
-
-               if (data[1] & 0x80) {
-                       input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
-               } else {
-                       /* Out of proximity, clear wheel value. */
-                       input_report_abs(input, ABS_WHEEL, 0);
-               }
-
-               if (data[2] & 0x80) {
-                       input_report_abs(input, ABS_THROTTLE, (data[2] & 0x7f));
-               } else {
-                       /* Out of proximity, clear second wheel value. */
-                       input_report_abs(input, ABS_THROTTLE, 0);
-               }
-
-               if (data[1] | data[2] | (data[3] & 0x1f) | data[4] | data[6] | 
data[8]) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               nkeys = 3;
+               keys = ((data[3] & 0x1C) ? 1<<2 : 0) |
+                      ((data[4] & 0xE0) ? 1<<1 : 0) |
+                      ((data[4] & 0x07) ? 1<<0 : 0);
        } else if (features->type == WACOM_27QHD) {
-               input_report_key(input, KEY_PROG1, data[2] & 0x01);
-               input_report_key(input, KEY_PROG2, data[2] & 0x02);
-               input_report_key(input, KEY_PROG3, data[2] & 0x04);
-               if (data[2] & 0x07) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               nkeys = 3;
+               keys = data[2] & 0x07;
        } else if (features->type == CINTIQ_HYBRID) {
                /*
                 * Do not send hardware buttons under Android. They
                 * are already sent to the system through GPIO (and
                 * have different meaning).
+                *
+                * d-pad right  -> data[4] & 0x10
+                * d-pad up     -> data[4] & 0x20
+                * d-pad left   -> data[4] & 0x40
+                * d-pad down   -> data[4] & 0x80
+                * d-pad center -> data[3] & 0x01
                 */
-               input_report_key(input, BTN_1, (data[4] & 0x01));
-               input_report_key(input, BTN_2, (data[4] & 0x02));
-               input_report_key(input, BTN_3, (data[4] & 0x04));
-               input_report_key(input, BTN_4, (data[4] & 0x08));
-
-               input_report_key(input, BTN_5, (data[4] & 0x10)); /* Right  */
-               input_report_key(input, BTN_6, (data[4] & 0x20)); /* Up     */
-               input_report_key(input, BTN_7, (data[4] & 0x40)); /* Left   */
-               input_report_key(input, BTN_8, (data[4] & 0x80)); /* Down   */
-               input_report_key(input, BTN_0, (data[3] & 0x01)); /* Center */
-
-               if (data[4] | (data[3] & 0x01)) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               buttons = (data[4] << 1) | (data[3] & 0x01);
        } else if (features->type == CINTIQ_COMPANION_2) {
-               input_report_key(input, BTN_1, (data[1] & 0x02));
-               input_report_key(input, BTN_2, (data[2] & 0x01));
-               input_report_key(input, BTN_3, (data[2] & 0x02));
-               input_report_key(input, BTN_4, (data[2] & 0x04));
-               input_report_key(input, BTN_5, (data[2] & 0x08));
-               input_report_key(input, BTN_6, (data[1] & 0x04));
-
-               input_report_key(input, BTN_7, (data[2] & 0x10));  /* Right  */
-               input_report_key(input, BTN_8, (data[2] & 0x20));  /* Up        
 */
-               input_report_key(input, BTN_9, (data[2] & 0x40));  /* Left   */
-               input_report_key(input, BTN_A, (data[2] & 0x80));  /* Down   */
-               input_report_key(input, BTN_0, (data[1] & 0x01));  /* Center */
-
-               if (data[2] | (data[1] & 0x07)) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               /* d-pad right  -> data[4] & 0x10
+                * d-pad up     -> data[4] & 0x20
+                * d-pad left   -> data[4] & 0x40
+                * d-pad down   -> data[4] & 0x80
+                * d-pad center -> data[3] & 0x01
+                */
+               buttons = ((data[2] & 0xF0) << 7) |
+                         ((data[1] & 0x04) << 6) |
+                         ((data[2] & 0x0F) << 2) |
+                         (data[1] & 0x03);
        } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
-               int i;
-
-               /* Touch ring mode switch has no capacitive sensor */
-               input_report_key(input, BTN_0, (data[3] & 0x01));
-
                /*
                 * ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in
                 * addition to the mechanical switch. Switch data is
                 * stored in data[4], capacitive data in data[5].
+                *
+                * Touch ring mode switch (data[3]) has no capacitive sensor
                 */
-               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] | data[5]) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               buttons = (data[4] << 1) | (data[3] & 0x01);
+               ring1 = data[2];
        } else {
                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));
-                       input_report_key(input, BTN_3, (data[6] & 0x04));
-                       input_report_key(input, BTN_4, (data[6] & 0x08));
-                       input_report_key(input, BTN_5, (data[6] & 0x10));
-                       input_report_key(input, BTN_6, (data[6] & 0x20));
-                       input_report_key(input, BTN_7, (data[6] & 0x40));
-                       input_report_key(input, BTN_8, (data[6] & 0x80));
-                       input_report_key(input, BTN_9, (data[7] & 0x01));
-                       input_report_key(input, BTN_A, (data[8] & 0x01));
-                       input_report_key(input, BTN_B, (data[8] & 0x02));
-                       input_report_key(input, BTN_C, (data[8] & 0x04));
-                       input_report_key(input, BTN_X, (data[8] & 0x08));
-                       input_report_key(input, BTN_Y, (data[8] & 0x10));
-                       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));
+                       buttons = (data[8] << 10) | ((data[7] & 0x01) << 9) |
+                                 (data[6] << 1) | (data[5] & 0x01);
 
                        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);
+                               nkeys = 3;
+                               keys = data[9] & 0x07;
                        }
                } else {
-                       input_report_key(input, BTN_0, (data[5] & 0x01));
-                       input_report_key(input, BTN_1, (data[5] & 0x02));
-                       input_report_key(input, BTN_2, (data[5] & 0x04));
-                       input_report_key(input, BTN_3, (data[5] & 0x08));
-                       input_report_key(input, BTN_4, (data[6] & 0x01));
-                       input_report_key(input, BTN_5, (data[6] & 0x02));
-                       input_report_key(input, BTN_6, (data[6] & 0x04));
-                       input_report_key(input, BTN_7, (data[6] & 0x08));
-                       input_report_key(input, BTN_8, (data[5] & 0x10));
-                       input_report_key(input, BTN_9, (data[6] & 0x10));
-               }
-               input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | 
data[2]);
-               input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | 
data[4]);
-
-               if ((data[5] & 0x1f) | data[6] | (data[1] & 0x1f) |
-                       data[2] | (data[3] & 0x1f) | data[4] | data[8] |
-                       (data[7] & 0x01)) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
+                       buttons = ((data[6] & 0x10) << 10) |
+                                 ((data[5] & 0x10) << 9)  |
+                                 ((data[6] & 0x0F) << 4)  |
+                                 (data[5] & 0x0F);
                }
+               strip1 = (data[1] << 8) || data[2];
+               strip2 = (data[3] << 8) || data[4];
        }
+
+       prox = (buttons & ~(~0 << nbuttons)) || (keys & ~(~0 << nkeys)) ||
+              (ring1 & 0x80) || (ring2 & 0x80) || strip1 || strip2;
+
+       wacom_report_numbered_buttons(input, nbuttons, buttons);
+
+       for (i = 0; i < nkeys; i++)
+               input_report_key(input, KEY_PROG1 + i, keys & (1 << i));
+
+       input_report_abs(input, ABS_RX, strip1);
+       input_report_abs(input, ABS_RX, strip2);
+
+       input_report_abs(input, ABS_WHEEL,    ring1 & 0x7f ? ring1 : 0);
+       input_report_abs(input, ABS_THROTTLE, ring2 & 0x07 ? ring2 : 0);
+
+       input_report_key(input, wacom->tool[1], prox ? 1 : 0);
+       input_report_abs(input, ABS_MISC, prox ? PAD_DEVICE_ID : 0);
+
        input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff);
+
        return 1;
 }
 
@@ -1969,6 +1852,19 @@ static void wacom_setup_numbered_buttons(struct 
input_dev *input_dev,
                __set_bit(BTN_BASE + (i-16), input_dev->keybit);
 }
 
+static void wacom_report_numbered_buttons(struct input_dev *input_dev,
+                               int button_count, int mask)
+{
+       int i;
+
+       for (i = 0; i < button_count && i < 10; i++)
+               input_report_key(input_dev, BTN_0 + i, mask & (1 << i));
+       for (i = 10; i < button_count && i < 16; i++)
+               input_report_key(input_dev, BTN_A + (i-10), mask & (1 << i));
+       for (i = 16; i < button_count && i < 18; i++)
+               input_report_key(input_dev, BTN_BASE + (i-16), mask & (1 << i));
+}
+
 int wacom_setup_input_capabilities(struct input_dev *input_dev,
                                   struct wacom_wac *wacom_wac)
 {
diff --git a/3.7/wacom_wac.c b/3.7/wacom_wac.c
index 6f3563e..6b97d54 100644
--- a/3.7/wacom_wac.c
+++ b/3.7/wacom_wac.c
@@ -38,6 +38,9 @@
  */
 #define WACOM_CONTACT_AREA_SCALE 2607
 
+static void wacom_report_numbered_buttons(struct input_dev *input_dev,
+                               int button_cout, int mask);
+
 static void wacom_notify_battery(struct wacom_wac *wacom_wac,
        int bat_capacity, bool bat_charging, bool bat_connected,
        bool ps_connected)
@@ -404,6 +407,12 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
        struct wacom_features *features = &wacom->features;
        unsigned char *data = wacom->data;
        struct input_dev *input = wacom->input;
+       int i;
+       int buttons = 0, nbuttons = features->numbered_buttons;
+       int keys = 0, nkeys = 0;
+       int ring1 = 0, ring2 = 0;
+       int strip1 = 0, strip2 = 0;
+       bool prox = false;
 
        /* pad packets. Works as a second tool and is always in prox */
        if (!(data[0] == WACOM_REPORT_INTUOSPAD || data[0] == 
WACOM_REPORT_INTUOS5PAD ||
@@ -411,72 +420,16 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
                return 0;
 
        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));
-               input_report_key(input, BTN_2, (data[3] & 0x02));
-               input_report_key(input, BTN_3, (data[3] & 0x04));
-               input_report_key(input, BTN_4, (data[3] & 0x08));
-               input_report_key(input, BTN_5, (data[3] & 0x10));
-               input_report_key(input, BTN_6, (data[3] & 0x20));
-               if (data[1] & 0x80) {
-                       input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
-               } else {
-                       /* Out of proximity, clear wheel value. */
-                       input_report_abs(input, ABS_WHEEL, 0);
-               }
-               if (features->type != INTUOS4S) {
-                       input_report_key(input, BTN_7, (data[3] & 0x40));
-                       input_report_key(input, BTN_8, (data[3] & 0x80));
-               }
-               if (data[1] | (data[2] & 0x01) | data[3]) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               buttons = (data[3] << 1) | (data[2] & 0x01);
+               ring1 = data[1];
        } else if (features->type == DTK) {
-               input_report_key(input, BTN_0, (data[6] & 0x01));
-               input_report_key(input, BTN_1, (data[6] & 0x02));
-               input_report_key(input, BTN_2, (data[6] & 0x04));
-               input_report_key(input, BTN_3, (data[6] & 0x08));
-               input_report_key(input, BTN_4, (data[6] & 0x10));
-               input_report_key(input, BTN_5, (data[6] & 0x20));
-               if (data[6] & 0x3f) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               buttons = data[6];
        } else if (features->type == WACOM_13HD) {
-               input_report_key(input, BTN_0, (data[3] & 0x01));
-               input_report_key(input, BTN_1, (data[4] & 0x01));
-               input_report_key(input, BTN_2, (data[4] & 0x02));
-               input_report_key(input, BTN_3, (data[4] & 0x04));
-               input_report_key(input, BTN_4, (data[4] & 0x08));
-               input_report_key(input, BTN_5, (data[4] & 0x10));
-               input_report_key(input, BTN_6, (data[4] & 0x20));
-               input_report_key(input, BTN_7, (data[4] & 0x40));
-               input_report_key(input, BTN_8, (data[4] & 0x80));
-               if ((data[3] & 0x01) | data[4]) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               buttons = (data[4] << 1) | (data[3] & 0x01);
        } else if (features->type == WACOM_24HD) {
-               input_report_key(input, BTN_0, (data[6] & 0x01));
-               input_report_key(input, BTN_1, (data[6] & 0x02));
-               input_report_key(input, BTN_2, (data[6] & 0x04));
-               input_report_key(input, BTN_3, (data[6] & 0x08));
-               input_report_key(input, BTN_4, (data[6] & 0x10));
-               input_report_key(input, BTN_5, (data[6] & 0x20));
-               input_report_key(input, BTN_6, (data[6] & 0x40));
-               input_report_key(input, BTN_7, (data[6] & 0x80));
-               input_report_key(input, BTN_8, (data[8] & 0x01));
-               input_report_key(input, BTN_9, (data[8] & 0x02));
-               input_report_key(input, BTN_A, (data[8] & 0x04));
-               input_report_key(input, BTN_B, (data[8] & 0x08));
-               input_report_key(input, BTN_C, (data[8] & 0x10));
-               input_report_key(input, BTN_X, (data[8] & 0x20));
-               input_report_key(input, BTN_Y, (data[8] & 0x40));
-               input_report_key(input, BTN_Z, (data[8] & 0x80));
+               buttons = (data[8] << 8) | data[6];
+               ring1 = data[1];
+               ring2 = data[2];
 
                /*
                 * Three "buttons" are available on the 24HD which are
@@ -485,155 +438,85 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
                 * The raw touchstrip bits are stored at:
                 *    ((data[3] & 0x1f) << 8) | data[4])
                 */
-               input_report_key(input, KEY_PROG1, data[4] & 0x07);
-               input_report_key(input, KEY_PROG2, data[4] & 0xE0);
-               input_report_key(input, KEY_PROG3, data[3] & 0x1C);
-
-               if (data[1] & 0x80) {
-                       input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
-               } else {
-                       /* Out of proximity, clear wheel value. */
-                       input_report_abs(input, ABS_WHEEL, 0);
-               }
-
-               if (data[2] & 0x80) {
-                       input_report_abs(input, ABS_THROTTLE, (data[2] & 0x7f));
-               } else {
-                       /* Out of proximity, clear second wheel value. */
-                       input_report_abs(input, ABS_THROTTLE, 0);
-               }
-
-               if (data[1] | data[2] | (data[3] & 0x1f) | data[4] | data[6] | 
data[8]) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               nkeys = 3;
+               keys = ((data[3] & 0x1C) ? 1<<2 : 0) |
+                      ((data[4] & 0xE0) ? 1<<1 : 0) |
+                      ((data[4] & 0x07) ? 1<<0 : 0);
        } else if (features->type == WACOM_27QHD) {
-               input_report_key(input, KEY_PROG1, data[2] & 0x01);
-               input_report_key(input, KEY_PROG2, data[2] & 0x02);
-               input_report_key(input, KEY_PROG3, data[2] & 0x04);
-               if (data[2] & 0x07) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               nkeys = 3;
+               keys = data[2] & 0x07;
        } else if (features->type == CINTIQ_HYBRID) {
                /*
                 * Do not send hardware buttons under Android. They
                 * are already sent to the system through GPIO (and
                 * have different meaning).
+                *
+                * d-pad right  -> data[4] & 0x10
+                * d-pad up     -> data[4] & 0x20
+                * d-pad left   -> data[4] & 0x40
+                * d-pad down   -> data[4] & 0x80
+                * d-pad center -> data[3] & 0x01
                 */
-               input_report_key(input, BTN_1, (data[4] & 0x01));
-               input_report_key(input, BTN_2, (data[4] & 0x02));
-               input_report_key(input, BTN_3, (data[4] & 0x04));
-               input_report_key(input, BTN_4, (data[4] & 0x08));
-
-               input_report_key(input, BTN_5, (data[4] & 0x10));  /* Right  */
-               input_report_key(input, BTN_6, (data[4] & 0x20));  /* Up     */
-               input_report_key(input, BTN_7, (data[4] & 0x40));  /* Left   */
-               input_report_key(input, BTN_8, (data[4] & 0x80));  /* Down   */
-               input_report_key(input, BTN_0, (data[3] & 0x01));  /* Center */
-
-               if (data[4] | (data[3] & 0x01)) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               buttons = (data[4] << 1) | (data[3] & 0x01);
        } else if (features->type == CINTIQ_COMPANION_2) {
-               input_report_key(input, BTN_1, (data[1] & 0x02));
-               input_report_key(input, BTN_2, (data[2] & 0x01));
-               input_report_key(input, BTN_3, (data[2] & 0x02));
-               input_report_key(input, BTN_4, (data[2] & 0x04));
-               input_report_key(input, BTN_5, (data[2] & 0x08));
-               input_report_key(input, BTN_6, (data[1] & 0x04));
-
-               input_report_key(input, BTN_7, (data[2] & 0x10));  /* Right  */
-               input_report_key(input, BTN_8, (data[2] & 0x20));  /* Up        
 */
-               input_report_key(input, BTN_9, (data[2] & 0x40));  /* Left   */
-               input_report_key(input, BTN_A, (data[2] & 0x80));  /* Down   */
-               input_report_key(input, BTN_0, (data[1] & 0x01));  /* Center */
-
-               if (data[2] | (data[1] & 0x07)) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               /* d-pad right  -> data[4] & 0x10
+                * d-pad up     -> data[4] & 0x20
+                * d-pad left   -> data[4] & 0x40
+                * d-pad down   -> data[4] & 0x80
+                * d-pad center -> data[3] & 0x01
+                */
+               buttons = ((data[2] & 0xF0) << 7) |
+                         ((data[1] & 0x04) << 6) |
+                         ((data[2] & 0x0F) << 2) |
+                         (data[1] & 0x03);
        } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
-               int i;
-
-               /* Touch ring mode switch has no capacitive sensor */
-               input_report_key(input, BTN_0, (data[3] & 0x01));
-
                /*
                 * ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in
                 * addition to the mechanical switch. Switch data is
                 * stored in data[4], capacitive data in data[5].
+                *
+                * Touch ring mode switch (data[3]) has no capacitive sensor
                 */
-               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] | data[5]) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
-               }
+               buttons = (data[4] << 1) | (data[3] & 0x01);
+               ring1 = data[2];
        } else {
                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));
-                       input_report_key(input, BTN_3, (data[6] & 0x04));
-                       input_report_key(input, BTN_4, (data[6] & 0x08));
-                       input_report_key(input, BTN_5, (data[6] & 0x10));
-                       input_report_key(input, BTN_6, (data[6] & 0x20));
-                       input_report_key(input, BTN_7, (data[6] & 0x40));
-                       input_report_key(input, BTN_8, (data[6] & 0x80));
-                       input_report_key(input, BTN_9, (data[7] & 0x01));
-                       input_report_key(input, BTN_A, (data[8] & 0x01));
-                       input_report_key(input, BTN_B, (data[8] & 0x02));
-                       input_report_key(input, BTN_C, (data[8] & 0x04));
-                       input_report_key(input, BTN_X, (data[8] & 0x08));
-                       input_report_key(input, BTN_Y, (data[8] & 0x10));
-                       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));
+                       buttons = (data[8] << 10) | ((data[7] & 0x01) << 9) |
+                                 (data[6] << 1) | (data[5] & 0x01);
 
                        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);
+                               nkeys = 3;
+                               keys = data[9] & 0x07;
                        }
                } else {
-                       input_report_key(input, BTN_0, (data[5] & 0x01));
-                       input_report_key(input, BTN_1, (data[5] & 0x02));
-                       input_report_key(input, BTN_2, (data[5] & 0x04));
-                       input_report_key(input, BTN_3, (data[5] & 0x08));
-                       input_report_key(input, BTN_4, (data[6] & 0x01));
-                       input_report_key(input, BTN_5, (data[6] & 0x02));
-                       input_report_key(input, BTN_6, (data[6] & 0x04));
-                       input_report_key(input, BTN_7, (data[6] & 0x08));
-                       input_report_key(input, BTN_8, (data[5] & 0x10));
-                       input_report_key(input, BTN_9, (data[6] & 0x10));
-               }
-               input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | 
data[2]);
-               input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | 
data[4]);
-
-               if ((data[5] & 0x1f) | data[6] | (data[1] & 0x1f) |
-                       data[2] | (data[3] & 0x1f) | data[4] | data[8] |
-                       (data[7] & 0x01)) {
-                       input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-               } else {
-                       input_report_abs(input, ABS_MISC, 0);
+                       buttons = ((data[6] & 0x10) << 10) |
+                                 ((data[5] & 0x10) << 9)  |
+                                 ((data[6] & 0x0F) << 4)  |
+                                 (data[5] & 0x0F);
                }
+               strip1 = (data[1] << 8) || data[2];
+               strip2 = (data[3] << 8) || data[4];
        }
+
+       prox = (buttons & ~(~0 << nbuttons)) || (keys & ~(~0 << nkeys)) ||
+              (ring1 & 0x80) || (ring2 & 0x80) || strip1 || strip2;
+
+       wacom_report_numbered_buttons(input, nbuttons, buttons);
+
+       for (i = 0; i < nkeys; i++)
+               input_report_key(input, KEY_PROG1 + i, keys & (1 << i));
+
+       input_report_abs(input, ABS_RX, strip1);
+       input_report_abs(input, ABS_RX, strip2);
+
+       input_report_abs(input, ABS_WHEEL,    ring1 & 0x7f ? ring1 : 0);
+       input_report_abs(input, ABS_THROTTLE, ring2 & 0x07 ? ring2 : 0);
+
+       input_report_key(input, wacom->tool[1], prox ? 1 : 0);
+       input_report_abs(input, ABS_MISC, prox ? PAD_DEVICE_ID : 0);
+
        input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff);
+
        return 1;
 }
 
@@ -1961,6 +1844,19 @@ static void wacom_setup_numbered_buttons(struct 
input_dev *input_dev,
                __set_bit(BTN_BASE + (i-16), input_dev->keybit);
 }
 
+static void wacom_report_numbered_buttons(struct input_dev *input_dev,
+                               int button_count, int mask)
+{
+       int i;
+
+       for (i = 0; i < button_count && i < 10; i++)
+               input_report_key(input_dev, BTN_0 + i, mask & (1 << i));
+       for (i = 10; i < button_count && i < 16; i++)
+               input_report_key(input_dev, BTN_A + (i-10), mask & (1 << i));
+       for (i = 16; i < button_count && i < 18; i++)
+               input_report_key(input_dev, BTN_BASE + (i-16), mask & (1 << i));
+}
+
 int wacom_setup_input_capabilities(struct input_dev *input_dev,
                                   struct wacom_wac *wacom_wac)
 {
-- 
2.7.1


------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
Linuxwacom-devel mailing list
Linuxwacom-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to