HID: wacom: Consult the application usage when determining field type
[firefly-linux-kernel-4.4.55.git] / drivers / hid / wacom_wac.c
index aa6a08eb7ad686ced04e04fffee1561cde6da533..1468f008bfbdcd718f5ac8dd626fa68b39a314c2 100644 (file)
@@ -600,8 +600,8 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
                }
                input_report_abs(input, ABS_PRESSURE, t);
                input_report_abs(input, ABS_TILT_X,
-                               ((data[7] << 1) & 0x7e) | (data[8] >> 7));
-               input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f);
+                                (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
+               input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
                input_report_key(input, BTN_STYLUS, data[1] & 2);
                input_report_key(input, BTN_STYLUS2, data[1] & 4);
                input_report_key(input, BTN_TOUCH, t > 10);
@@ -612,8 +612,8 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
                input_report_abs(input, ABS_WHEEL,
                                (data[6] << 2) | ((data[7] >> 6) & 3));
                input_report_abs(input, ABS_TILT_X,
-                               ((data[7] << 1) & 0x7e) | (data[8] >> 7));
-               input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f);
+                                (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
+               input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
        }
 }
 
@@ -915,8 +915,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                                input_report_key(input, BTN_EXTRA,  data[6] & 0x10);
 
                                input_report_abs(input, ABS_TILT_X,
-                                       ((data[7] << 1) & 0x7e) | (data[8] >> 7));
-                               input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f);
+                                       (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
+                               input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
                        } else {
                                /* 2D mouse packet */
                                input_report_key(input, BTN_LEFT,   data[8] & 0x04);
@@ -1248,6 +1248,298 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
        return 0;
 }
 
+static void wacom_map_usage(struct wacom *wacom, struct hid_usage *usage,
+               struct hid_field *field, __u8 type, __u16 code, int fuzz)
+{
+       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+       struct input_dev *input = wacom_wac->input;
+       int fmin = field->logical_minimum;
+       int fmax = field->logical_maximum;
+
+       usage->type = type;
+       usage->code = code;
+
+       set_bit(type, input->evbit);
+
+       switch (type) {
+       case EV_ABS:
+               input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
+               input_abs_set_res(input, code,
+                                 hidinput_calc_abs_res(field, code));
+               break;
+       case EV_KEY:
+               input_set_capability(input, EV_KEY, code);
+               break;
+       case EV_MSC:
+               input_set_capability(input, EV_MSC, code);
+               break;
+       }
+}
+
+static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
+               struct hid_field *field, struct hid_usage *usage)
+{
+       struct wacom *wacom = hid_get_drvdata(hdev);
+
+       switch (usage->hid) {
+       case HID_GD_X:
+               wacom_map_usage(wacom, usage, field, EV_ABS, ABS_X, 4);
+               break;
+       case HID_GD_Y:
+               wacom_map_usage(wacom, usage, field, EV_ABS, ABS_Y, 4);
+               break;
+       case HID_DG_TIPPRESSURE:
+               wacom_map_usage(wacom, usage, field, EV_ABS, ABS_PRESSURE, 0);
+               break;
+       case HID_DG_INRANGE:
+               wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
+               break;
+       case HID_DG_INVERT:
+               wacom_map_usage(wacom, usage, field, EV_KEY,
+                               BTN_TOOL_RUBBER, 0);
+               break;
+       case HID_DG_ERASER:
+       case HID_DG_TIPSWITCH:
+               wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOUCH, 0);
+               break;
+       case HID_DG_BARRELSWITCH:
+               wacom_map_usage(wacom, usage, field, EV_KEY, BTN_STYLUS, 0);
+               break;
+       case HID_DG_BARRELSWITCH2:
+               wacom_map_usage(wacom, usage, field, EV_KEY, BTN_STYLUS2, 0);
+               break;
+       case HID_DG_TOOLSERIALNUMBER:
+               wacom_map_usage(wacom, usage, field, EV_MSC, MSC_SERIAL, 0);
+               break;
+       }
+}
+
+static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
+               struct hid_usage *usage, __s32 value)
+{
+       struct wacom *wacom = hid_get_drvdata(hdev);
+       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+       struct input_dev *input = wacom_wac->input;
+
+       /* checking which Tool / tip switch to send */
+       switch (usage->hid) {
+       case HID_DG_INRANGE:
+               wacom_wac->hid_data.inrange_state = value;
+               return 0;
+       case HID_DG_INVERT:
+               wacom_wac->hid_data.invert_state = value;
+               return 0;
+       case HID_DG_ERASER:
+       case HID_DG_TIPSWITCH:
+               wacom_wac->hid_data.tipswitch |= value;
+               return 0;
+       }
+
+       /* send pen events only when touch is up or forced out */
+       if (!usage->type || wacom_wac->shared->touch_down)
+               return 0;
+
+       input_event(input, usage->type, usage->code, value);
+
+       return 0;
+}
+
+static void wacom_wac_pen_report(struct hid_device *hdev,
+               struct hid_report *report)
+{
+       struct wacom *wacom = hid_get_drvdata(hdev);
+       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+       struct input_dev *input = wacom_wac->input;
+       bool prox = wacom_wac->hid_data.inrange_state;
+
+       if (!wacom_wac->shared->stylus_in_proximity) /* first in prox */
+               /* Going into proximity select tool */
+               wacom_wac->tool[0] = wacom_wac->hid_data.invert_state ?
+                                               BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+
+       /* keep pen state for touch events */
+       wacom_wac->shared->stylus_in_proximity = prox;
+
+       /* send pen events only when touch is up or forced out */
+       if (!wacom_wac->shared->touch_down) {
+               input_report_key(input, BTN_TOUCH,
+                               wacom_wac->hid_data.tipswitch);
+               input_report_key(input, wacom_wac->tool[0], prox);
+
+               wacom_wac->hid_data.tipswitch = false;
+
+               input_sync(input);
+       }
+}
+
+static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
+               struct hid_field *field, struct hid_usage *usage)
+{
+       struct wacom *wacom = hid_get_drvdata(hdev);
+       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+       struct input_dev *input = wacom_wac->input;
+       unsigned touch_max = wacom_wac->features.touch_max;
+
+       switch (usage->hid) {
+       case HID_GD_X:
+               if (touch_max == 1)
+                       wacom_map_usage(wacom, usage, field, EV_ABS, ABS_X, 4);
+               else
+                       wacom_map_usage(wacom, usage, field, EV_ABS,
+                                       ABS_MT_POSITION_X, 4);
+               break;
+       case HID_GD_Y:
+               if (touch_max == 1)
+                       wacom_map_usage(wacom, usage, field, EV_ABS, ABS_Y, 4);
+               else
+                       wacom_map_usage(wacom, usage, field, EV_ABS,
+                                       ABS_MT_POSITION_Y, 4);
+               break;
+       case HID_DG_CONTACTID:
+               input_mt_init_slots(input, wacom_wac->features.touch_max,
+                       INPUT_MT_DIRECT);
+               break;
+       case HID_DG_INRANGE:
+               break;
+       case HID_DG_INVERT:
+               break;
+       case HID_DG_TIPSWITCH:
+               wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOUCH, 0);
+               break;
+       }
+}
+
+static int wacom_wac_finger_event(struct hid_device *hdev,
+               struct hid_field *field, struct hid_usage *usage, __s32 value)
+{
+       struct wacom *wacom = hid_get_drvdata(hdev);
+       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+
+       switch (usage->hid) {
+       case HID_GD_X:
+               wacom_wac->hid_data.x = value;
+               break;
+       case HID_GD_Y:
+               wacom_wac->hid_data.y = value;
+               break;
+       case HID_DG_CONTACTID:
+               wacom_wac->hid_data.id = value;
+               break;
+       case HID_DG_TIPSWITCH:
+               wacom_wac->hid_data.tipswitch = value;
+               break;
+       }
+
+
+       return 0;
+}
+
+static void wacom_wac_finger_mt_report(struct wacom_wac *wacom_wac,
+               struct input_dev *input, bool touch)
+{
+       int slot;
+       struct hid_data *hid_data = &wacom_wac->hid_data;
+
+       slot = input_mt_get_slot_by_key(input, hid_data->id);
+
+       input_mt_slot(input, slot);
+       input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+       if (touch) {
+               input_report_abs(input, ABS_MT_POSITION_X, hid_data->x);
+               input_report_abs(input, ABS_MT_POSITION_Y, hid_data->y);
+       }
+       input_mt_sync_frame(input);
+}
+
+static void wacom_wac_finger_single_touch_report(struct wacom_wac *wacom_wac,
+               struct input_dev *input, bool touch)
+{
+       struct hid_data *hid_data = &wacom_wac->hid_data;
+
+       if (touch) {
+               input_report_abs(input, ABS_X, hid_data->x);
+               input_report_abs(input, ABS_Y, hid_data->y);
+       }
+       input_report_key(input, BTN_TOUCH, touch);
+}
+
+static void wacom_wac_finger_report(struct hid_device *hdev,
+               struct hid_report *report)
+{
+       struct wacom *wacom = hid_get_drvdata(hdev);
+       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+       struct input_dev *input = wacom_wac->input;
+       bool touch = wacom_wac->hid_data.tipswitch &&
+                    !wacom_wac->shared->stylus_in_proximity;
+       unsigned touch_max = wacom_wac->features.touch_max;
+
+       if (touch_max > 1)
+               wacom_wac_finger_mt_report(wacom_wac, input, touch);
+       else
+               wacom_wac_finger_single_touch_report(wacom_wac, input, touch);
+       input_sync(input);
+
+       /* keep touch state for pen event */
+       wacom_wac->shared->touch_down = touch;
+}
+
+#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)
+{
+       struct wacom *wacom = hid_get_drvdata(hdev);
+       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+       struct input_dev *input = wacom_wac->input;
+
+       /* currently, only direct devices have proper hid report descriptors */
+       __set_bit(INPUT_PROP_DIRECT, input->propbit);
+
+       if (WACOM_PEN_FIELD(field))
+               return wacom_wac_pen_usage_mapping(hdev, field, usage);
+
+       if (WACOM_FINGER_FIELD(field))
+               return wacom_wac_finger_usage_mapping(hdev, field, usage);
+}
+
+int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
+               struct hid_usage *usage, __s32 value)
+{
+       struct wacom *wacom = hid_get_drvdata(hdev);
+
+       if (wacom->wacom_wac.features.type != HID_GENERIC)
+               return 0;
+
+       if (WACOM_PEN_FIELD(field))
+               return wacom_wac_pen_event(hdev, field, usage, value);
+
+       if (WACOM_FINGER_FIELD(field))
+               return wacom_wac_finger_event(hdev, field, usage, value);
+
+       return 0;
+}
+
+void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
+{
+       struct wacom *wacom = hid_get_drvdata(hdev);
+       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+       struct hid_field *field = report->field[0];
+
+       if (wacom_wac->features.type != HID_GENERIC)
+               return;
+
+       if (WACOM_PEN_FIELD(field))
+               return wacom_wac_pen_report(hdev, report);
+
+       if (WACOM_FINGER_FIELD(field))
+               return wacom_wac_finger_report(hdev, report);
+}
+
 static int wacom_bpt_touch(struct wacom_wac *wacom)
 {
        struct wacom_features *features = &wacom->features;
@@ -1391,7 +1683,9 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
            return 0;
 
        if (data[0] == WACOM_REPORT_USB) {
-               if (features->type == INTUOSHT && features->touch_max) {
+               if (features->type == INTUOSHT &&
+                   wacom->shared->touch_input &&
+                   features->touch_max) {
                        input_report_switch(wacom->shared->touch_input,
                                            SW_MUTE_DEVICE, data[8] & 0x40);
                        input_sync(wacom->shared->touch_input);
@@ -1484,7 +1778,8 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
                int pid, battery, ps_connected;
 
                if ((wacom->shared->type == INTUOSHT) &&
-                               wacom->shared->touch_max) {
+                   wacom->shared->touch_input &&
+                   wacom->shared->touch_max) {
                        input_report_switch(wacom->shared->touch_input,
                                        SW_MUTE_DEVICE, data[5] & 0x40);
                        input_sync(wacom->shared->touch_input);
@@ -1636,8 +1931,10 @@ static void wacom_setup_cintiq(struct wacom_wac *wacom_wac)
        input_set_abs_params(input_dev, ABS_DISTANCE,
                             0, wacom_wac->features.distance_max, 0, 0);
        input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
-       input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
-       input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
+       input_set_abs_params(input_dev, ABS_TILT_X, -64, 63, 0, 0);
+       input_abs_set_res(input_dev, ABS_TILT_X, 57);
+       input_set_abs_params(input_dev, ABS_TILT_Y, -64, 63, 0, 0);
+       input_abs_set_res(input_dev, ABS_TILT_Y, 57);
 }
 
 static void wacom_setup_intuos(struct wacom_wac *wacom_wac)
@@ -1657,6 +1954,7 @@ static void wacom_setup_intuos(struct wacom_wac *wacom_wac)
        __set_bit(BTN_TOOL_LENS, input_dev->keybit);
 
        input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
+       input_abs_set_res(input_dev, ABS_RZ, 287);
        input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
 }
 
@@ -1739,13 +2037,17 @@ static void wacom_abs_set_axis(struct input_dev *input_dev,
        }
 }
 
-int wacom_setup_input_capabilities(struct input_dev *input_dev,
+int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
                                   struct wacom_wac *wacom_wac)
 {
        struct wacom_features *features = &wacom_wac->features;
 
        input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 
+       if (features->type == HID_GENERIC)
+               /* setup has already been done */
+               return 0;
+
        __set_bit(BTN_TOUCH, input_dev->keybit);
        __set_bit(ABS_MISC, input_dev->absbit);
 
@@ -1753,9 +2055,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 
        switch (features->type) {
        case WACOM_MO:
-               input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
-               /* fall through */
-
        case WACOM_G4:
                /* fall through */
 
@@ -1798,6 +2097,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 
        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 */
 
@@ -1812,6 +2112,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
        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);
 
@@ -1820,6 +2121,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 
        case WACOM_13HD:
                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;
@@ -1828,6 +2130,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
        case INTUOS3L:
        case INTUOS3S:
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+               input_abs_set_res(input_dev, ABS_Z, 287);
                /* fall through */
 
        case INTUOS:
@@ -1850,6 +2153,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
                                              0, 0);
 
                        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);
                } else if (features->device_type == BTN_TOOL_FINGER) {
@@ -1868,6 +2172,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
        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);
@@ -1952,6 +2257,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
                                __clear_bit(ABS_X, input_dev->absbit);
                                __clear_bit(ABS_Y, input_dev->absbit);
                                __clear_bit(BTN_TOUCH, input_dev->keybit);
+
+                               /* PAD is setup by wacom_setup_pad_input_capabilities later */
+                               return 1;
                        }
                } else if (features->device_type == BTN_TOOL_PEN) {
                        __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
@@ -1967,6 +2275,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 
        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);
@@ -1990,6 +2299,9 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
        input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0);
        input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0);
 
+       /* kept for making udev and libwacom accepting the pad */
+       __set_bit(BTN_STYLUS, input_dev->keybit);
+
        switch (features->type) {
        case GRAPHIRE_BT:
                __set_bit(BTN_0, input_dev->keybit);
@@ -2006,9 +2318,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
 
        case WACOM_G4:
                __set_bit(BTN_BACK, input_dev->keybit);
-               __set_bit(BTN_LEFT, input_dev->keybit);
                __set_bit(BTN_FORWARD, input_dev->keybit);
-               __set_bit(BTN_RIGHT, input_dev->keybit);
                input_set_capability(input_dev, EV_REL, REL_WHEEL);
                break;
 
@@ -2105,7 +2415,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
        case INTUOSPS:
                /* touch interface does not have the pad device */
                if (features->device_type != BTN_TOOL_PEN)
-                       return 1;
+                       return -ENODEV;
 
                for (i = 0; i < 7; i++)
                        __set_bit(BTN_0 + i, input_dev->keybit);
@@ -2149,8 +2459,10 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
        case INTUOSHT:
        case BAMBOO_PT:
                /* pad device is on the touch interface */
-               if (features->device_type != BTN_TOOL_FINGER)
-                       return 1;
+               if ((features->device_type != BTN_TOOL_FINGER) ||
+                   /* Bamboo Pen only tablet does not have pad */
+                   ((features->type == BAMBOO_PT) && !features->touch_max))
+                       return -ENODEV;
 
                __clear_bit(ABS_MISC, input_dev->absbit);
 
@@ -2163,7 +2475,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
 
        default:
                /* no pad supported */
-               return 1;
+               return -ENODEV;
        }
        return 0;
 }
@@ -2573,6 +2885,21 @@ static const struct wacom_features wacom_features_0x309 =
        { "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */
          .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10,
          .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x30A =
+       { "Wacom ISDv5 30A", 59352, 33648, 2047, 63,
+         CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30C };
+static const struct wacom_features wacom_features_0x30C =
+       { "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30A, .touch_max = 10,
+         .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x323 =
+       { "Wacom Intuos P M", 21600, 13500, 1023, 31,
+         INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+         .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+
+static const struct wacom_features wacom_features_HID_ANY_ID =
+       { "Wacom HID", .type = HID_GENERIC };
 
 #define USB_DEVICE_WACOM(prod)                                         \
        HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
@@ -2708,14 +3035,19 @@ const struct hid_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x304) },
        { USB_DEVICE_WACOM(0x307) },
        { USB_DEVICE_WACOM(0x309) },
+       { USB_DEVICE_WACOM(0x30A) },
+       { USB_DEVICE_WACOM(0x30C) },
        { USB_DEVICE_WACOM(0x30E) },
        { USB_DEVICE_WACOM(0x314) },
        { USB_DEVICE_WACOM(0x315) },
        { USB_DEVICE_WACOM(0x317) },
+       { USB_DEVICE_WACOM(0x323) },
        { USB_DEVICE_WACOM(0x4001) },
        { USB_DEVICE_WACOM(0x4004) },
        { USB_DEVICE_WACOM(0x5000) },
        { USB_DEVICE_WACOM(0x5002) },
+
+       { USB_DEVICE_WACOM(HID_ANY_ID) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, wacom_ids);