input: use %*pb[l] to print bitmaps including cpumasks and nodemasks
[deliverable/linux.git] / drivers / hid / wacom_wac.c
index ac7447c7b82e35ff81209c31dd417fb8a53de112..1a6507999a6534f0b851e209bb702696d1f50e58 100644 (file)
@@ -15,7 +15,6 @@
 #include "wacom_wac.h"
 #include "wacom.h"
 #include <linux/input/mt.h>
-#include <linux/hid.h>
 
 /* resolution for penabled devices */
 #define WACOM_PL_RES           20
@@ -444,9 +443,6 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
 
        /* Enter report */
        if ((data[1] & 0xfc) == 0xc0) {
-               if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
-                       wacom->shared->stylus_in_proximity = true;
-
                /* serial number of the tool */
                wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
                        (data[4] << 20) + (data[5] << 12) +
@@ -535,24 +531,46 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
                return 1;
        }
 
+       /*
+        * don't report events for invalid data
+        */
        /* older I4 styli don't work with new Cintiqs */
-       if (!((wacom->id[idx] >> 20) & 0x01) &&
-                       (features->type == WACOM_21UX2))
+       if ((!((wacom->id[idx] >> 20) & 0x01) &&
+                       (features->type == WACOM_21UX2)) ||
+           /* Only large Intuos support Lense Cursor */
+           (wacom->tool[idx] == BTN_TOOL_LENS &&
+               (features->type == INTUOS3 ||
+                features->type == INTUOS3S ||
+                features->type == INTUOS4 ||
+                features->type == INTUOS4S ||
+                features->type == INTUOS5 ||
+                features->type == INTUOS5S ||
+                features->type == INTUOSPM ||
+                features->type == INTUOSPS)) ||
+          /* Cintiq doesn't send data when RDY bit isn't set */
+          (features->type == CINTIQ && !(data[1] & 0x40)))
                return 1;
 
-       /* Range Report */
-       if ((data[1] & 0xfe) == 0x20) {
+       if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
+               wacom->shared->stylus_in_proximity = true;
+
+       /* in Range while exiting */
+       if (((data[1] & 0xfe) == 0x20) && wacom->reporting_data) {
                input_report_key(input, BTN_TOUCH, 0);
                input_report_abs(input, ABS_PRESSURE, 0);
                input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max);
-               if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
-                       wacom->shared->stylus_in_proximity = true;
+               return 2;
        }
 
        /* Exit report */
        if ((data[1] & 0xfe) == 0x80) {
                if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
                        wacom->shared->stylus_in_proximity = false;
+               wacom->reporting_data = false;
+
+               /* don't report exit if we don't know the ID */
+               if (!wacom->id[idx])
+                       return 1;
 
                /*
                 * Reset all states otherwise we lose the initial states
@@ -586,6 +604,11 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
                wacom->id[idx] = 0;
                return 2;
        }
+
+       /* don't report other events if we don't know the ID */
+       if (!wacom->id[idx])
+               return 1;
+
        return 0;
 }
 
@@ -633,6 +656,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
            data[0] != WACOM_REPORT_INTUOSREAD &&
            data[0] != WACOM_REPORT_INTUOSWRITE &&
            data[0] != WACOM_REPORT_INTUOSPAD &&
+           data[0] != WACOM_REPORT_CINTIQ &&
+           data[0] != WACOM_REPORT_CINTIQPAD &&
            data[0] != WACOM_REPORT_INTUOS5PAD) {
                dev_dbg(input->dev.parent,
                        "%s: received unknown report #%d\n", __func__, data[0]);
@@ -644,7 +669,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                idx = data[1] & 0x01;
 
        /* pad packets. Works as a second tool and is always in prox */
-       if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD) {
+       if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD ||
+           data[0] == WACOM_REPORT_CINTIQPAD) {
                input = wacom->pad_input;
                if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
                        input_report_key(input, BTN_0, (data[2] & 0x01));
@@ -744,6 +770,14 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                        } else {
                                input_report_abs(input, ABS_MISC, 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);
+
+                       input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[4]));
+                       input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[6]));
+                       input_report_abs(input, ABS_Z, be16_to_cpup((__be16 *)&data[8]));
                } else if (features->type == CINTIQ_HYBRID) {
                        /*
                         * Do not send hardware buttons under Android. They
@@ -760,6 +794,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                        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);
+                       }
                } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
                        int i;
 
@@ -843,28 +883,6 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
        if (result)
                 return result - 1;
 
-       /* don't proceed if we don't know the ID */
-       if (!wacom->id[idx])
-               return 0;
-
-       /* Only large Intuos support Lense Cursor */
-       if (wacom->tool[idx] == BTN_TOOL_LENS &&
-           (features->type == INTUOS3 ||
-            features->type == INTUOS3S ||
-            features->type == INTUOS4 ||
-            features->type == INTUOS4S ||
-            features->type == INTUOS5 ||
-            features->type == INTUOS5S ||
-            features->type == INTUOSPM ||
-            features->type == INTUOSPS)) {
-
-               return 0;
-       }
-
-       /* Cintiq doesn't send data when RDY bit isn't set */
-       if (features->type == CINTIQ && !(data[1] & 0x40))
-                 return 0;
-
        if (features->type >= INTUOS3S) {
                input_report_abs(input, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
                input_report_abs(input, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
@@ -951,6 +969,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
        input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */
        input_report_key(input, wacom->tool[idx], 1);
        input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+       wacom->reporting_data = true;
        return 1;
 }
 
@@ -1019,8 +1038,20 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
        struct input_dev *input = wacom->input;
        unsigned char *data = wacom->data;
        int i;
-       int current_num_contacts = data[61];
+       int current_num_contacts = 0;
        int contacts_to_send = 0;
+       int num_contacts_left = 4; /* maximum contacts per packet */
+       int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET;
+       int y_offset = 2;
+
+       if (wacom->features.type == WACOM_27QHDT) {
+               current_num_contacts = data[63];
+               num_contacts_left = 10;
+               byte_per_packet = WACOM_BYTES_PER_QHDTHID_PACKET;
+               y_offset = 0;
+       } else {
+               current_num_contacts = data[61];
+       }
 
        /*
         * First packet resets the counter since only the first
@@ -1029,12 +1060,11 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
        if (current_num_contacts)
                wacom->num_contacts_left = current_num_contacts;
 
-       /* There are at most 4 contacts per packet */
-       contacts_to_send = min(4, wacom->num_contacts_left);
+       contacts_to_send = min(num_contacts_left, wacom->num_contacts_left);
 
        for (i = 0; i < contacts_to_send; i++) {
-               int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1;
-               bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity;
+               int offset = (byte_per_packet * i) + 1;
+               bool touch = (data[offset] & 0x1) && !wacom->shared->stylus_in_proximity;
                int slot = input_mt_get_slot_by_key(input, data[offset + 1]);
 
                if (slot < 0)
@@ -1044,18 +1074,23 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
 
                if (touch) {
                        int t_x = get_unaligned_le16(&data[offset + 2]);
-                       int c_x = get_unaligned_le16(&data[offset + 4]);
-                       int t_y = get_unaligned_le16(&data[offset + 6]);
-                       int c_y = get_unaligned_le16(&data[offset + 8]);
-                       int w = get_unaligned_le16(&data[offset + 10]);
-                       int h = get_unaligned_le16(&data[offset + 12]);
+                       int t_y = get_unaligned_le16(&data[offset + 4 + y_offset]);
 
                        input_report_abs(input, ABS_MT_POSITION_X, t_x);
                        input_report_abs(input, ABS_MT_POSITION_Y, t_y);
-                       input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h));
-                       input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y));
-                       input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
-                       input_report_abs(input, ABS_MT_ORIENTATION, w > h);
+
+                       if (wacom->features.type != WACOM_27QHDT) {
+                               int c_x = get_unaligned_le16(&data[offset + 4]);
+                               int c_y = get_unaligned_le16(&data[offset + 8]);
+                               int w = get_unaligned_le16(&data[offset + 10]);
+                               int h = get_unaligned_le16(&data[offset + 12]);
+
+                               input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h));
+                               input_report_abs(input, ABS_MT_WIDTH_MAJOR,
+                                                min(w, h) + int_dist(t_x, t_y, c_x, c_y));
+                               input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
+                               input_report_abs(input, ABS_MT_ORIENTATION, w > h);
+                       }
                }
        }
        input_mt_report_pointer_emulation(input, true);
@@ -1064,6 +1099,7 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
        if (wacom->num_contacts_left <= 0)
                wacom->num_contacts_left = 0;
 
+       wacom->shared->touch_down = (wacom->num_contacts_left > 0);
        return 1;
 }
 
@@ -1092,7 +1128,7 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
 
        for (i = 0; i < contacts_to_send; i++) {
                int offset = (WACOM_BYTES_PER_MT_PACKET + x_offset) * i + 3;
-               bool touch = data[offset] & 0x1;
+               bool touch = (data[offset] & 0x1) && !wacom->shared->stylus_in_proximity;
                int id = get_unaligned_le16(&data[offset + 1]);
                int slot = input_mt_get_slot_by_key(input, id);
 
@@ -1114,6 +1150,7 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
        if (wacom->num_contacts_left < 0)
                wacom->num_contacts_left = 0;
 
+       wacom->shared->touch_down = (wacom->num_contacts_left > 0);
        return 1;
 }
 
@@ -1514,13 +1551,6 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
        wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(hdev);
 }
 
-#define WACOM_PEN_FIELD(f)     (((f)->logical == HID_DG_STYLUS) || \
-                                ((f)->physical == HID_DG_STYLUS) || \
-                                ((f)->application == HID_DG_PEN))
-#define WACOM_FINGER_FIELD(f)  (((f)->logical == HID_DG_FINGER) || \
-                                ((f)->physical == HID_DG_FINGER) || \
-                                ((f)->application == HID_DG_TOUCHSCREEN))
-
 void wacom_wac_usage_mapping(struct hid_device *hdev,
                struct hid_field *field, struct hid_usage *usage)
 {
@@ -1891,6 +1921,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
        case WACOM_21UX2:
        case WACOM_22HD:
        case WACOM_24HD:
+       case WACOM_27QHD:
        case DTK:
        case CINTIQ_HYBRID:
                sync = wacom_intuos_irq(wacom_wac);
@@ -1901,6 +1932,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
                break;
 
        case WACOM_24HDT:
+       case WACOM_27QHDT:
                sync = wacom_24hdt_irq(wacom_wac);
                break;
 
@@ -2086,32 +2118,17 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
        wacom_abs_set_axis(input_dev, wacom_wac);
 
        switch (features->type) {
-       case WACOM_MO:
-       case WACOM_G4:
-               /* fall through */
-
-       case GRAPHIRE:
-               input_set_capability(input_dev, EV_REL, REL_WHEEL);
-
-               __set_bit(BTN_LEFT, input_dev->keybit);
-               __set_bit(BTN_RIGHT, input_dev->keybit);
-               __set_bit(BTN_MIDDLE, input_dev->keybit);
-
-               __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
-               __set_bit(BTN_TOOL_PEN, input_dev->keybit);
-               __set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
-               __set_bit(BTN_STYLUS, input_dev->keybit);
-               __set_bit(BTN_STYLUS2, input_dev->keybit);
-
-               __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
-               break;
-
        case GRAPHIRE_BT:
                __clear_bit(ABS_MISC, input_dev->absbit);
+
+       case WACOM_MO:
+       case WACOM_G4:
                input_set_abs_params(input_dev, ABS_DISTANCE, 0,
                                              features->distance_max,
                                              0, 0);
+               /* fall through */
 
+       case GRAPHIRE:
                input_set_capability(input_dev, EV_REL, REL_WHEEL);
 
                __set_bit(BTN_LEFT, input_dev->keybit);
@@ -2127,31 +2144,15 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
                __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
                break;
 
+       case WACOM_27QHD:
        case WACOM_24HD:
-               input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-               input_abs_set_res(input_dev, ABS_Z, 287);
-               input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
-               /* fall through */
-
        case DTK:
-               __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-
-               wacom_setup_cintiq(wacom_wac);
-               break;
-
        case WACOM_22HD:
        case WACOM_21UX2:
        case WACOM_BEE:
        case CINTIQ:
-               input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-               input_abs_set_res(input_dev, ABS_Z, 287);
-
-               __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-
-               wacom_setup_cintiq(wacom_wac);
-               break;
-
        case WACOM_13HD:
+       case CINTIQ_HYBRID:
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
                input_abs_set_res(input_dev, ABS_Z, 287);
                __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
@@ -2161,6 +2162,10 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
        case INTUOS3:
        case INTUOS3L:
        case INTUOS3S:
+       case INTUOS4:
+       case INTUOS4WL:
+       case INTUOS4L:
+       case INTUOS4S:
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
                input_abs_set_res(input_dev, ABS_Z, 287);
                /* fall through */
@@ -2199,17 +2204,6 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
                }
                break;
 
-       case INTUOS4:
-       case INTUOS4WL:
-       case INTUOS4L:
-       case INTUOS4S:
-               input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-               input_abs_set_res(input_dev, ABS_Z, 287);
-               wacom_setup_intuos(wacom_wac);
-
-               __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
-               break;
-
        case WACOM_24HDT:
                if (features->device_type == BTN_TOOL_FINGER) {
                        input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0);
@@ -2219,6 +2213,7 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
                }
                /* fall through */
 
+       case WACOM_27QHDT:
        case MTSCREEN:
        case MTTPC:
        case MTTPC_B:
@@ -2305,14 +2300,6 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
                                              0, 0);
                }
                break;
-
-       case CINTIQ_HYBRID:
-               input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-               input_abs_set_res(input_dev, ABS_Z, 287);
-               __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-
-               wacom_setup_cintiq(wacom_wac);
-               break;
        }
        return 0;
 }
@@ -2374,6 +2361,19 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
                input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
                break;
 
+       case WACOM_27QHD:
+               __set_bit(KEY_PROG1, input_dev->keybit);
+               __set_bit(KEY_PROG2, input_dev->keybit);
+               __set_bit(KEY_PROG3, input_dev->keybit);
+               input_set_abs_params(input_dev, ABS_X, -2048, 2048, 0, 0);
+               input_abs_set_res(input_dev, ABS_X, 1024); /* points/g */
+               input_set_abs_params(input_dev, ABS_Y, -2048, 2048, 0, 0);
+               input_abs_set_res(input_dev, ABS_Y, 1024);
+               input_set_abs_params(input_dev, ABS_Z, -2048, 2048, 0, 0);
+               input_abs_set_res(input_dev, ABS_Z, 1024);
+               __set_bit(INPUT_PROP_ACCELEROMETER, input_dev->propbit);
+               break;
+
        case DTK:
                for (i = 0; i < 6; i++)
                        __set_bit(BTN_0 + i, input_dev->keybit);
@@ -2724,6 +2724,18 @@ static const struct wacom_features wacom_features_0xF6 =
        { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */
          .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10,
          .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x32A =
+       { "Wacom Cintiq 27QHD", 119740, 67520, 2047,
+         63, WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+         WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0x32B =
+       { "Wacom Cintiq 27QHD touch", 119740, 67520, 2047, 63,
+         WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+         WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32C };
+static const struct wacom_features wacom_features_0x32C =
+       { "Wacom Cintiq 27QHD touch", .type = WACOM_27QHDT,
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32B, .touch_max = 10 };
 static const struct wacom_features wacom_features_0x3F =
        { "Wacom Cintiq 21UX", 87200, 65600, 1023, 63,
          CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
@@ -3090,6 +3102,9 @@ const struct hid_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x315) },
        { USB_DEVICE_WACOM(0x317) },
        { USB_DEVICE_WACOM(0x323) },
+       { USB_DEVICE_WACOM(0x32A) },
+       { USB_DEVICE_WACOM(0x32B) },
+       { USB_DEVICE_WACOM(0x32C) },
        { USB_DEVICE_WACOM(0x32F) },
        { USB_DEVICE_WACOM(0x4001) },
        { USB_DEVICE_WACOM(0x4004) },
This page took 0.038427 seconds and 5 git commands to generate.