]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'multitouch' into for-linus
authorJiri Kosina <jkosina@suse.cz>
Mon, 1 Oct 2012 12:38:54 +0000 (14:38 +0200)
committerJiri Kosina <jkosina@suse.cz>
Mon, 1 Oct 2012 12:38:54 +0000 (14:38 +0200)
Conflicts:
drivers/hid/hid-multitouch.c

1  2 
drivers/hid/hid-ids.h
drivers/hid/hid-multitouch.c

diff --combined drivers/hid/hid-ids.h
index c1da94a81a0dbb8403073741906802fc6b020685,54e15c47b405cbd12d6b1da565e7771e534094a4..ca4d83e6e3872b1f84bf86ec496fa81ad4f7a2a6
@@@ -5,6 -5,7 +5,6 @@@
   *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
   *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
   *  Copyright (c) 2006-2007 Jiri Kosina
 - *  Copyright (c) 2007 Paul Walmsley
   */
  
  /*
  #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA     0x72fa
  #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302     0x7302
  #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349     0x7349
+ #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7     0x73f7
  #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001     0xa001
+ #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224      0x7224
+ #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0      0x72d0
+ #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4      0x72c4
  
  #define USB_VENDOR_ID_ELECOM          0x056e
  #define USB_DEVICE_ID_ELECOM_BM084    0x0061
  #define USB_VENDOR_ID_EMS             0x2006
  #define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118
  
 +#define USB_VENDOR_ID_FLATFROG                0x25b5
 +#define USB_DEVICE_ID_MULTITOUCH_3200 0x0002
 +
  #define USB_VENDOR_ID_ESSENTIAL_REALITY       0x0d7f
  #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
  
  #define USB_VENDOR_ID_EZKEY           0x0518
  #define USB_DEVICE_ID_BTC_8193                0x0002
  
 +#define USB_VENDOR_ID_FREESCALE               0x15A2
 +#define USB_DEVICE_ID_FREESCALE_MX28  0x004F
 +
  #define USB_VENDOR_ID_FRUCTEL 0x25B6
  #define USB_DEVICE_ID_GAMETEL_MT_MODE 0x0002
  
  
  #define USB_VENDOR_ID_GENERAL_TOUCH   0x0dfc
  #define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003
+ #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS 0x0100
  
  #define USB_VENDOR_ID_GLAB            0x06c2
  #define USB_DEVICE_ID_4_PHIDGETSERVO_30       0x0038
  #define USB_VENDOR_ID_GRIFFIN         0x077d
  #define USB_DEVICE_ID_POWERMATE               0x0410
  #define USB_DEVICE_ID_SOUNDKNOB               0x04AA
 +#define USB_DEVICE_ID_RADIOSHARK      0x627a
  
  #define USB_VENDOR_ID_GTCO            0x078c
  #define USB_DEVICE_ID_GTCO_90         0x0090
  #define USB_DEVICE_ID_LOGITECH_RECEIVER       0xc101
  #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST  0xc110
  #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
 +#define USB_DEVICE_ID_LOGITECH_HARMONY_PS3 0x0306
  #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD 0xc20a
  #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD      0xc211
  #define USB_DEVICE_ID_LOGITECH_EXTREME_3D     0xc215
  #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH            0x3000
  #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001               0x3001
  #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008               0x3008
 -#define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001
  
  #define USB_VENDOR_ID_ROCCAT          0x1e7d
  #define USB_DEVICE_ID_ROCCAT_ARVO     0x30d4
  
  #define USB_VENDOR_ID_SONY                    0x054c
  #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE     0x024b
 +#define USB_DEVICE_ID_SONY_PS3_BDREMOTE               0x0306
  #define USB_DEVICE_ID_SONY_PS3_CONTROLLER     0x0268
  #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER      0x042f
  
  #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U  0x0005
  #define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062   0x0064
  #define USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850 0x0522
 +#define USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60   0x0781
  
  #define USB_VENDOR_ID_UNITEC  0x227d
  #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709   0x0709
index ee0b76b398cb5a6a6fcda16dedbadff404d8f643,9f3c5bf4dde3a4c03eff895a1ea086381a339fdd..3eb02b94fc87c8a3bc903474db7c3b55efd5ead5
@@@ -51,12 -51,12 +51,12 @@@ MODULE_LICENSE("GPL")
  #define MT_QUIRK_VALID_IS_INRANGE     (1 << 5)
  #define MT_QUIRK_VALID_IS_CONFIDENCE  (1 << 6)
  #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE  (1 << 8)
 +#define MT_QUIRK_NO_AREA              (1 << 9)
  
  struct mt_slot {
        __s32 x, y, p, w, h;
        __s32 contactid;        /* the device ContactID assigned to this slot */
        bool touch_state;       /* is the touch valid? */
 -      bool seen_in_this_frame;/* has this slot been updated */
  };
  
  struct mt_class {
@@@ -92,9 -92,8 +92,9 @@@ struct mt_device 
        __u8 touches_by_report; /* how many touches are present in one report:
                                * 1 means we should use a serial protocol
                                * > 1 means hybrid (multitouch) protocol */
 +      bool serial_maybe;      /* need to check for serial protocol */
        bool curvalid;          /* is the current contact valid? */
 -      struct mt_slot *slots;
 +      unsigned mt_flags;      /* flags to pass to input-mt */
  };
  
  /* classes of device behavior */
  #define MT_CLS_EGALAX_SERIAL                  0x0104
  #define MT_CLS_TOPSEED                                0x0105
  #define MT_CLS_PANASONIC                      0x0106
 -#define MT_CLS_GENERALTOUCH_TWOFINGERS                0x0107
 -#define MT_CLS_GENERALTOUCH_PWT_TENFINGERS    0x0108
 +#define MT_CLS_FLATFROG                               0x0107
++#define MT_CLS_GENERALTOUCH_TWOFINGERS                0x0108
++#define MT_CLS_GENERALTOUCH_PWT_TENFINGERS    0x0109
  
  #define MT_DEFAULT_MAXCONTACT 10
  
@@@ -136,6 -136,25 +138,6 @@@ static int cypress_compute_slot(struct 
                return -1;
  }
  
 -static int find_slot_from_contactid(struct mt_device *td)
 -{
 -      int i;
 -      for (i = 0; i < td->maxcontacts; ++i) {
 -              if (td->slots[i].contactid == td->curdata.contactid &&
 -                      td->slots[i].touch_state)
 -                      return i;
 -      }
 -      for (i = 0; i < td->maxcontacts; ++i) {
 -              if (!td->slots[i].seen_in_this_frame &&
 -                      !td->slots[i].touch_state)
 -                      return i;
 -      }
 -      /* should not occurs. If this happens that means
 -       * that the device sent more touches that it says
 -       * in the report descriptor. It is ignored then. */
 -      return -1;
 -}
 -
  static struct mt_class mt_classes[] = {
        { .name = MT_CLS_DEFAULT,
                .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
                        MT_QUIRK_SLOT_IS_CONTACTID,
                .sn_move = 2048,
                .sn_width = 128,
 -              .sn_height = 128 },
 +              .sn_height = 128,
 +              .maxcontacts = 60,
 +      },
        { .name = MT_CLS_CYPRESS,
                .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
                        MT_QUIRK_CYPRESS,
        { .name = MT_CLS_PANASONIC,
                .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP,
                .maxcontacts = 4 },
+       { .name = MT_CLS_GENERALTOUCH_TWOFINGERS,
+               .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
+                       MT_QUIRK_VALID_IS_INRANGE |
+                       MT_QUIRK_SLOT_IS_CONTACTNUMBER,
+               .maxcontacts = 2
+       },
+       { .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
+               .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
+                       MT_QUIRK_SLOT_IS_CONTACTNUMBER,
+               .maxcontacts = 10
+       },
  
 +      { .name = MT_CLS_FLATFROG,
 +              .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
 +                      MT_QUIRK_NO_AREA,
 +              .sn_move = 2048,
 +              .maxcontacts = 40,
 +      },
        { }
  };
  
@@@ -310,16 -332,24 +323,16 @@@ static int mt_input_mapping(struct hid_
        * We need to ignore fields that belong to other collections
        * such as Mouse that might have the same GenericDesktop usages. */
        if (field->application == HID_DG_TOUCHSCREEN)
 -              set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
 +              td->mt_flags |= INPUT_MT_DIRECT;
        else if (field->application != HID_DG_TOUCHPAD)
                return 0;
  
 -      /* In case of an indirect device (touchpad), we need to add
 -       * specific BTN_TOOL_* to be handled by the synaptics xorg
 -       * driver.
 -       * We also consider that touchscreens providing buttons are touchpads.
 +      /*
 +       * Model touchscreens providing buttons as touchpads.
         */
        if (field->application == HID_DG_TOUCHPAD ||
 -          (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON ||
 -          cls->is_indirect) {
 -              set_bit(INPUT_PROP_POINTER, hi->input->propbit);
 -              set_bit(BTN_TOOL_FINGER, hi->input->keybit);
 -              set_bit(BTN_TOOL_DOUBLETAP, hi->input->keybit);
 -              set_bit(BTN_TOOL_TRIPLETAP, hi->input->keybit);
 -              set_bit(BTN_TOOL_QUADTAP, hi->input->keybit);
 -      }
 +          (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
 +              td->mt_flags |= INPUT_MT_POINTER;
  
        /* eGalax devices provide a Digitizer.Stylus input which overrides
         * the correct Digitizers.Finger X/Y ranges.
                                        EV_ABS, ABS_MT_POSITION_X);
                        set_abs(hi->input, ABS_MT_POSITION_X, field,
                                cls->sn_move);
 -                      /* touchscreen emulation */
 -                      set_abs(hi->input, ABS_X, field, cls->sn_move);
                        mt_store_field(usage, td, hi);
                        td->last_field_index = field->index;
                        return 1;
                                        EV_ABS, ABS_MT_POSITION_Y);
                        set_abs(hi->input, ABS_MT_POSITION_Y, field,
                                cls->sn_move);
 -                      /* touchscreen emulation */
 -                      set_abs(hi->input, ABS_Y, field, cls->sn_move);
                        mt_store_field(usage, td, hi);
                        td->last_field_index = field->index;
                        return 1;
                        td->last_field_index = field->index;
                        return 1;
                case HID_DG_CONTACTID:
 -                      if (!td->maxcontacts)
 -                              td->maxcontacts = MT_DEFAULT_MAXCONTACT;
 -                      input_mt_init_slots(hi->input, td->maxcontacts);
                        mt_store_field(usage, td, hi);
                        td->last_field_index = field->index;
                        td->touches_by_report++;
                case HID_DG_WIDTH:
                        hid_map_usage(hi, usage, bit, max,
                                        EV_ABS, ABS_MT_TOUCH_MAJOR);
 -                      set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
 -                              cls->sn_width);
 +                      if (!(cls->quirks & MT_QUIRK_NO_AREA))
 +                              set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
 +                                      cls->sn_width);
                        mt_store_field(usage, td, hi);
                        td->last_field_index = field->index;
                        return 1;
                case HID_DG_HEIGHT:
                        hid_map_usage(hi, usage, bit, max,
                                        EV_ABS, ABS_MT_TOUCH_MINOR);
 -                      set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
 -                              cls->sn_height);
 -                      input_set_abs_params(hi->input,
 +                      if (!(cls->quirks & MT_QUIRK_NO_AREA)) {
 +                              set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
 +                                      cls->sn_height);
 +                              input_set_abs_params(hi->input,
                                        ABS_MT_ORIENTATION, 0, 1, 0, 0);
 +                      }
                        mt_store_field(usage, td, hi);
                        td->last_field_index = field->index;
                        return 1;
                                        EV_ABS, ABS_MT_PRESSURE);
                        set_abs(hi->input, ABS_MT_PRESSURE, field,
                                cls->sn_pressure);
 -                      /* touchscreen emulation */
 -                      set_abs(hi->input, ABS_PRESSURE, field,
 -                              cls->sn_pressure);
                        mt_store_field(usage, td, hi);
                        td->last_field_index = field->index;
                        return 1;
@@@ -440,7 -477,7 +453,7 @@@ static int mt_input_mapped(struct hid_d
        return -1;
  }
  
 -static int mt_compute_slot(struct mt_device *td)
 +static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
  {
        __s32 quirks = td->mtclass.quirks;
  
        if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
                return td->curdata.contactid - 1;
  
 -      return find_slot_from_contactid(td);
 +      return input_mt_get_slot_by_key(input, td->curdata.contactid);
  }
  
  /*
   * this function is called when a whole contact has been processed,
   * so that it can assign it to a slot and store the data there
   */
 -static void mt_complete_slot(struct mt_device *td)
 +static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
  {
 -      td->curdata.seen_in_this_frame = true;
        if (td->curvalid) {
 -              int slotnum = mt_compute_slot(td);
 -
 -              if (slotnum >= 0 && slotnum < td->maxcontacts)
 -                      td->slots[slotnum] = td->curdata;
 -      }
 -      td->num_received++;
 -}
 -
 +              int slotnum = mt_compute_slot(td, input);
 +              struct mt_slot *s = &td->curdata;
  
 -/*
 - * this function is called when a whole packet has been received and processed,
 - * so that it can decide what to send to the input layer.
 - */
 -static void mt_emit_event(struct mt_device *td, struct input_dev *input)
 -{
 -      int i;
 +              if (slotnum < 0 || slotnum >= td->maxcontacts)
 +                      return;
  
 -      for (i = 0; i < td->maxcontacts; ++i) {
 -              struct mt_slot *s = &(td->slots[i]);
 -              if ((td->mtclass.quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) &&
 -                      !s->seen_in_this_frame) {
 -                      s->touch_state = false;
 -              }
 -
 -              input_mt_slot(input, i);
 +              input_mt_slot(input, slotnum);
                input_mt_report_slot_state(input, MT_TOOL_FINGER,
                        s->touch_state);
                if (s->touch_state) {
                        input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
                        input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
                }
 -              s->seen_in_this_frame = false;
 -
        }
  
 -      input_mt_report_pointer_emulation(input, true);
 +      td->num_received++;
 +}
 +
 +/*
 + * this function is called when a whole packet has been received and processed,
 + * so that it can decide what to send to the input layer.
 + */
 +static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
 +{
 +      input_mt_sync_frame(input);
        input_sync(input);
        td->num_received = 0;
  }
  
 -
 -
  static int mt_event(struct hid_device *hid, struct hid_field *field,
                                struct hid_usage *usage, __s32 value)
  {
        struct mt_device *td = hid_get_drvdata(hid);
        __s32 quirks = td->mtclass.quirks;
  
 -      if (hid->claimed & HID_CLAIMED_INPUT && td->slots) {
 +      if (hid->claimed & HID_CLAIMED_INPUT) {
                switch (usage->hid) {
                case HID_DG_INRANGE:
                        if (quirks & MT_QUIRK_ALWAYS_VALID)
                }
  
                if (usage->hid == td->last_slot_field)
 -                      mt_complete_slot(td);
 +                      mt_complete_slot(td, field->hidinput->input);
  
                if (field->index == td->last_field_index
                        && td->num_received >= td->num_expected)
 -                      mt_emit_event(td, field->hidinput->input);
 +                      mt_sync_frame(td, field->hidinput->input);
  
        }
  
@@@ -647,47 -698,16 +660,45 @@@ static void mt_post_parse(struct mt_dev
        }
  }
  
 +static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
 +
 +{
 +      struct mt_device *td = hid_get_drvdata(hdev);
 +      struct mt_class *cls = &td->mtclass;
 +      struct input_dev *input = hi->input;
 +
 +      /* Only initialize slots for MT input devices */
 +      if (!test_bit(ABS_MT_POSITION_X, input->absbit))
 +              return;
 +
 +      if (!td->maxcontacts)
 +              td->maxcontacts = MT_DEFAULT_MAXCONTACT;
 +
 +      mt_post_parse(td);
 +      if (td->serial_maybe)
 +              mt_post_parse_default_settings(td);
 +
 +      if (cls->is_indirect)
 +              td->mt_flags |= INPUT_MT_POINTER;
 +
 +      if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
 +              td->mt_flags |= INPUT_MT_DROP_UNUSED;
 +
 +      input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
 +
 +      td->mt_flags = 0;
 +}
 +
  static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
  {
        int ret, i;
        struct mt_device *td;
        struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
  
-       if (id) {
-               for (i = 0; mt_classes[i].name ; i++) {
-                       if (id->driver_data == mt_classes[i].name) {
-                               mtclass = &(mt_classes[i]);
-                               break;
-                       }
+       for (i = 0; mt_classes[i].name ; i++) {
+               if (id->driver_data == mt_classes[i].name) {
+                       mtclass = &(mt_classes[i]);
+                       break;
                }
        }
  
                goto fail;
        }
  
 +      if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
 +              td->serial_maybe = true;
 +
        ret = hid_parse(hdev);
        if (ret != 0)
                goto fail;
        if (ret)
                goto fail;
  
 -      mt_post_parse(td);
 -
 -      if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
 -              mt_post_parse_default_settings(td);
 -
 -      td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot),
 -                              GFP_KERNEL);
 -      if (!td->slots) {
 -              dev_err(&hdev->dev, "cannot allocate multitouch slots\n");
 -              hid_hw_stop(hdev);
 -              ret = -ENOMEM;
 -              goto fail;
 -      }
 -
        ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
  
        mt_set_maxcontacts(hdev);
@@@ -747,6 -778,32 +758,32 @@@ static int mt_reset_resume(struct hid_d
        mt_set_input_mode(hdev);
        return 0;
  }
+ static int mt_resume(struct hid_device *hdev)
+ {
+       struct usb_interface *intf;
+       struct usb_host_interface *interface;
+       struct usb_device *dev;
+       if (hdev->bus != BUS_USB)
+               return 0;
+       intf = to_usb_interface(hdev->dev.parent);
+       interface = intf->cur_altsetting;
+       dev = hid_to_usb_dev(hdev);
+       /* Some Elan legacy devices require SET_IDLE to be set on resume.
+        * It should be safe to send it to other devices too.
+        * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */
+       usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                       HID_REQ_SET_IDLE,
+                       USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                       0, interface->desc.bInterfaceNumber,
+                       NULL, 0, USB_CTRL_SET_TIMEOUT);
+       return 0;
+ }
  #endif
  
  static void mt_remove(struct hid_device *hdev)
        struct mt_device *td = hid_get_drvdata(hdev);
        sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
        hid_hw_stop(hdev);
 -      kfree(td->slots);
        kfree(td);
        hid_set_drvdata(hdev, NULL);
  }
@@@ -862,24 -920,34 +899,39 @@@ static const struct hid_device_id mt_de
        { .driver_data = MT_CLS_EGALAX_SERIAL,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349) },
+       { .driver_data = MT_CLS_EGALAX_SERIAL,
+               MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7) },
        { .driver_data = MT_CLS_EGALAX_SERIAL,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
+       { .driver_data = MT_CLS_EGALAX,
+               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) },
+       { .driver_data = MT_CLS_EGALAX,
+               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0) },
+       { .driver_data = MT_CLS_EGALAX,
+               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4) },
  
        /* Elo TouchSystems IntelliTouch Plus panel */
        { .driver_data = MT_CLS_DUAL_NSMU_CONTACTID,
                MT_USB_DEVICE(USB_VENDOR_ID_ELO,
                        USB_DEVICE_ID_ELO_TS2515) },
  
 +      /* Flatfrog Panels */
 +      { .driver_data = MT_CLS_FLATFROG,
 +              MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG,
 +                      USB_DEVICE_ID_MULTITOUCH_3200) },
 +
        /* GeneralTouch panel */
-       { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
+       { .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS,
                MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
                        USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
+       { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
+               MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
+                       USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS) },
  
        /* Gametel game controller */
        { .driver_data = MT_CLS_DEFAULT,
@@@ -1071,12 -1139,12 +1123,13 @@@ static struct hid_driver mt_driver = 
        .remove = mt_remove,
        .input_mapping = mt_input_mapping,
        .input_mapped = mt_input_mapped,
 +      .input_configured = mt_input_configured,
        .feature_mapping = mt_feature_mapping,
        .usage_table = mt_grabbed_usages,
        .event = mt_event,
  #ifdef CONFIG_PM
        .reset_resume = mt_reset_resume,
+       .resume = mt_resume,
  #endif
  };