Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 10 Jan 2011 16:15:37 +0000 (08:15 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 10 Jan 2011 16:15:37 +0000 (08:15 -0800)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (34 commits)
  HID: roccat: Update sysfs attribute doc
  HID: roccat: don't use #pragma pack
  HID: roccat: Add support for Roccat Kone[+] v2
  HID: roccat: reduce number of functions in kone and pyra drivers
  HID: roccat: declare meaning of pack pragma usage in driver headers
  HID: roccat: use class for char device for sysfs attribute creation
  sysfs: Introducing binary attributes for struct class
  HID: hidraw: add compatibility ioctl() for 32-bit applications.
  HID: hid-picolcd: Fix memory leak in picolcd_debug_out_report()
  HID: picolcd: fix misuse of logical operation in place of bitop
  HID: usbhid: base runtime PM on modern API
  HID: replace offsets values with their corresponding BTN_* defines
  HID: hid-mosart: support suspend/resume
  HID: hid-mosart: ignore buttons report
  HID: hid-picolcd: don't use flush_scheduled_work()
  HID: simplify an index check in hid_lookup_collection
  HID: Hoist assigns from ifs
  HID: Remove superfluous __inline__
  HID: Use vzalloc for vmalloc/memset(,0...)
  HID: Add and use hid_<level>: dev_<level> equivalents
  ...

1  2 
drivers/hid/Kconfig
drivers/hid/hid-3m-pct.c
drivers/hid/hid-core.c
drivers/hid/hid-egalax.c
drivers/hid/hid-ids.h
include/linux/device.h

diff --combined drivers/hid/Kconfig
@@@ -150,12 -150,21 +150,22 @@@ config DRAGONRISE_F
        Say Y here if you want to enable force feedback support for DragonRise Inc.
        game controllers.
  
+ config HID_EMS_FF
+       tristate "EMS Production Inc. force feedback support"
+       depends on USB_HID
+       select INPUT_FF_MEMLESS
+       ---help---
+       Say Y here if you want to enable force feedback support for devices by
+       EMS Production Ltd.
+       Currently the following devices are known to be supported:
+        - Trio Linker Plus II
  config HID_EGALAX
        tristate "eGalax multi-touch panel"
        depends on USB_HID
        ---help---
 -      Support for the eGalax dual-touch panel.
 +      Support for the eGalax dual-touch panels, including the
 +      Joojoo and Wetab tablets.
  
  config HID_ELECOM
        tristate "ELECOM BM084 bluetooth mouse"
@@@ -397,6 -406,13 +407,13 @@@ config HID_ROCCAT_KON
        ---help---
        Support for Roccat Kone mouse.
  
+ config HID_ROCCAT_KONEPLUS
+       tristate "Roccat Kone[+] mouse support"
+       depends on USB_HID
+       select HID_ROCCAT
+       ---help---
+       Support for Roccat Kone[+] mouse.
  config HID_ROCCAT_PYRA
        tristate "Roccat Pyra mouse support"
        depends on USB_HID
diff --combined drivers/hid/hid-3m-pct.c
@@@ -19,7 -19,6 +19,7 @@@
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/usb.h>
 +#include <linux/input/mt.h>
  
  MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
  MODULE_DESCRIPTION("3M PCT multitouch panels");
@@@ -28,6 -27,8 +28,6 @@@ MODULE_LICENSE("GPL")
  #include "hid-ids.h"
  
  #define MAX_SLOTS             60
 -#define MAX_TRKID             USHRT_MAX
 -#define MAX_EVENTS            360
  
  /* estimated signal-to-noise ratios */
  #define SN_MOVE                       2048
  
  struct mmm_finger {
        __s32 x, y, w, h;
 -      __u16 id;
 -      bool prev_touch;
        bool touch, valid;
  };
  
  struct mmm_data {
        struct mmm_finger f[MAX_SLOTS];
 -      __u16 id;
        __u8 curid;
        __u8 nexp, nreal;
        bool touch, valid;
@@@ -113,7 -117,14 +113,7 @@@ static int mmm_input_mapping(struct hid
                                        0, 1, 0, 0);
                        return 1;
                case HID_DG_CONTACTID:
 -                      field->logical_maximum = MAX_TRKID;
 -                      hid_map_usage(hi, usage, bit, max,
 -                                      EV_ABS, ABS_MT_TRACKING_ID);
 -                      input_set_abs_params(hi->input, ABS_MT_TRACKING_ID,
 -                                           0, MAX_TRKID, 0, 0);
 -                      if (!hi->input->mt)
 -                              input_mt_create_slots(hi->input, MAX_SLOTS);
 -                      input_set_events_per_packet(hi->input, MAX_EVENTS);
 +                      input_mt_init_slots(hi->input, MAX_SLOTS);
                        return 1;
                }
                /* let hid-input decide for the others */
@@@ -143,6 -154,7 +143,6 @@@ static int mmm_input_mapped(struct hid_
   */
  static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
  {
 -      struct mmm_finger *oldest = 0;
        int i;
        for (i = 0; i < MAX_SLOTS; ++i) {
                struct mmm_finger *f = &md->f[i];
                        continue;
                }
                input_mt_slot(input, i);
 +              input_mt_report_slot_state(input, MT_TOOL_FINGER, f->touch);
                if (f->touch) {
                        /* this finger is on the screen */
                        int wide = (f->w > f->h);
                        int major = max(f->w, f->h) >> 1;
                        int minor = min(f->w, f->h) >> 1;
  
 -                      if (!f->prev_touch)
 -                              f->id = md->id++;
 -                      input_event(input, EV_ABS, ABS_MT_TRACKING_ID, f->id);
                        input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x);
                        input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y);
                        input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
                        input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
                        input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
 -                      /* touchscreen emulation: pick the oldest contact */
 -                      if (!oldest || ((f->id - oldest->id) & (SHRT_MAX + 1)))
 -                              oldest = f;
 -              } else {
 -                      /* this finger took off the screen */
 -                      input_event(input, EV_ABS, ABS_MT_TRACKING_ID, -1);
                }
 -              f->prev_touch = f->touch;
                f->valid = 0;
        }
  
 -      /* touchscreen emulation */
 -      if (oldest) {
 -              input_event(input, EV_KEY, BTN_TOUCH, 1);
 -              input_event(input, EV_ABS, ABS_X, oldest->x);
 -              input_event(input, EV_ABS, ABS_Y, oldest->y);
 -      } else {
 -              input_event(input, EV_KEY, BTN_TOUCH, 0);
 -      }
 +      input_mt_report_pointer_emulation(input, true);
        input_sync(input);
  }
  
@@@ -246,7 -274,7 +246,7 @@@ static int mmm_probe(struct hid_device 
  
        md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL);
        if (!md) {
-               dev_err(&hdev->dev, "cannot allocate 3M data\n");
+               hid_err(hdev, "cannot allocate 3M data\n");
                return -ENOMEM;
        }
        hid_set_drvdata(hdev, md);
diff --combined drivers/hid/hid-core.c
@@@ -14,6 -14,8 +14,8 @@@
   * any later version.
   */
  
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/init.h>
@@@ -59,7 -61,8 +61,8 @@@ struct hid_report *hid_register_report(
        if (report_enum->report_id_hash[id])
                return report_enum->report_id_hash[id];
  
-       if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL)))
+       report = kzalloc(sizeof(struct hid_report), GFP_KERNEL);
+       if (!report)
                return NULL;
  
        if (id != 0)
@@@ -90,8 -93,11 +93,11 @@@ static struct hid_field *hid_register_f
                return NULL;
        }
  
-       if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
-               + values * sizeof(unsigned), GFP_KERNEL))) return NULL;
+       field = kzalloc((sizeof(struct hid_field) +
+                        usages * sizeof(struct hid_usage) +
+                        values * sizeof(unsigned)), GFP_KERNEL);
+       if (!field)
+               return NULL;
  
        field->index = report->maxfield++;
        report->field[field->index] = field;
@@@ -172,10 -178,14 +178,14 @@@ static int close_collection(struct hid_
  
  static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
  {
+       struct hid_collection *collection = parser->device->collection;
        int n;
-       for (n = parser->collection_stack_ptr - 1; n >= 0; n--)
-               if (parser->device->collection[parser->collection_stack[n]].type == type)
-                       return parser->device->collection[parser->collection_stack[n]].usage;
+       for (n = parser->collection_stack_ptr - 1; n >= 0; n--) {
+               unsigned index = parser->collection_stack[n];
+               if (collection[index].type == type)
+                       return collection[index].usage;
+       }
        return 0; /* we know nothing about this usage type */
  }
  
@@@ -209,7 -219,8 +219,8 @@@ static int hid_add_field(struct hid_par
        unsigned offset;
        int i;
  
-       if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
+       report = hid_register_report(parser->device, report_type, parser->global.report_id);
+       if (!report) {
                dbg_hid("hid_register_report failed\n");
                return -1;
        }
  
        usages = max_t(int, parser->local.usage_index, parser->global.report_count);
  
-       if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
+       field = hid_register_field(report, usages, parser->global.report_count);
+       if (!field)
                return 0;
  
        field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
@@@ -652,13 -664,12 +664,12 @@@ int hid_parse_report(struct hid_device 
                return -ENOMEM;
        device->rsize = size;
  
-       parser = vmalloc(sizeof(struct hid_parser));
+       parser = vzalloc(sizeof(struct hid_parser));
        if (!parser) {
                ret = -ENOMEM;
                goto err;
        }
  
-       memset(parser, 0, sizeof(struct hid_parser));
        parser->device = device;
  
        end = start + size;
  
                if (dispatch_type[item.type](parser, &item)) {
                        dbg_hid("item %u %u %u %u parsing failed\n",
-                               item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
+                               item.format, (unsigned)item.size,
+                               (unsigned)item.type, (unsigned)item.tag);
                        goto err;
                }
  
@@@ -737,13 -749,14 +749,14 @@@ static u32 s32ton(__s32 value, unsigne
   * Search linux-kernel and linux-usb-devel archives for "hid-core extract".
   */
  
- static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
+ static __u32 extract(const struct hid_device *hid, __u8 *report,
+                    unsigned offset, unsigned n)
  {
        u64 x;
  
        if (n > 32)
-               printk(KERN_WARNING "HID: extract() called with n (%d) > 32! (%s)\n",
-                               n, current->comm);
+               hid_warn(hid, "extract() called with n (%d) > 32! (%s)\n",
+                        n, current->comm);
  
        report += offset >> 3;  /* adjust byte index */
        offset &= 7;            /* now only need bit offset into one byte */
   * endianness of register values by considering a register
   * a "cached" copy of the little endiad bit stream.
   */
- static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
+ static void implement(const struct hid_device *hid, __u8 *report,
+                     unsigned offset, unsigned n, __u32 value)
  {
        u64 x;
        u64 m = (1ULL << n) - 1;
  
        if (n > 32)
-               printk(KERN_WARNING "HID: implement() called with n (%d) > 32! (%s)\n",
-                               n, current->comm);
+               hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n",
+                        __func__, n, current->comm);
  
        if (value > m)
-               printk(KERN_WARNING "HID: implement() called with too large value %d! (%s)\n",
-                               value, current->comm);
+               hid_warn(hid, "%s() called with too large value %d! (%s)\n",
+                        __func__, value, current->comm);
        WARN_ON(value > m);
        value &= m;
  
   * Search an array for a value.
   */
  
- static __inline__ int search(__s32 *array, __s32 value, unsigned n)
+ static int search(__s32 *array, __s32 value, unsigned n)
  {
        while (n--) {
                if (*array++ == value)
@@@ -887,18 -901,22 +901,22 @@@ static void hid_input_field(struct hid_
        __s32 max = field->logical_maximum;
        __s32 *value;
  
-       if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC)))
+       value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC);
+       if (!value)
                return;
  
        for (n = 0; n < count; n++) {
  
-                       value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) :
-                                                   extract(data, offset + n * size, size);
+               value[n] = min < 0 ?
+                       snto32(extract(hid, data, offset + n * size, size),
+                              size) :
+                       extract(hid, data, offset + n * size, size);
  
-                       if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */
-                           && value[n] >= min && value[n] <= max
-                           && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
-                               goto exit;
+               /* Ignore report if ErrorRollOver */
+               if (!(field->flags & HID_MAIN_ITEM_VARIABLE) &&
+                   value[n] >= min && value[n] <= max &&
+                   field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
+                       goto exit;
        }
  
        for (n = 0; n < count; n++) {
@@@ -928,7 -946,8 +946,8 @@@ exit
   * Output the field into the report.
   */
  
- static void hid_output_field(struct hid_field *field, __u8 *data)
+ static void hid_output_field(const struct hid_device *hid,
+                            struct hid_field *field, __u8 *data)
  {
        unsigned count = field->report_count;
        unsigned offset = field->report_offset;
  
        for (n = 0; n < count; n++) {
                if (field->logical_minimum < 0) /* signed values */
-                       implement(data, offset + n * size, size, s32ton(field->value[n], size));
+                       implement(hid, data, offset + n * size, size,
+                                 s32ton(field->value[n], size));
                else                            /* unsigned values */
-                       implement(data, offset + n * size, size, field->value[n]);
+                       implement(hid, data, offset + n * size, size,
+                                 field->value[n]);
        }
  }
  
@@@ -956,7 -977,7 +977,7 @@@ void hid_output_report(struct hid_repor
  
        memset(data, 0, ((report->size - 1) >> 3) + 1);
        for (n = 0; n < report->maxfield; n++)
-               hid_output_field(report->field[n], data);
+               hid_output_field(report->device, report->field[n], data);
  }
  EXPORT_SYMBOL_GPL(hid_output_report);
  
@@@ -1169,8 -1190,7 +1190,7 @@@ int hid_connect(struct hid_device *hdev
                hdev->claimed |= HID_CLAIMED_HIDRAW;
  
        if (!hdev->claimed) {
-               dev_err(&hdev->dev, "claimed by neither input, hiddev nor "
-                               "hidraw\n");
+               hid_err(hdev, "claimed by neither input, hiddev nor hidraw\n");
                return -ENODEV;
        }
  
                bus = "<UNKNOWN>";
        }
  
-       dev_info(&hdev->dev, "%s: %s HID v%x.%02x %s [%s] on %s\n",
-                       buf, bus, hdev->version >> 8, hdev->version & 0xff,
-                       type, hdev->name, hdev->phys);
+       hid_info(hdev, "%s: %s HID v%x.%02x %s [%s] on %s\n",
+                buf, bus, hdev->version >> 8, hdev->version & 0xff,
+                type, hdev->name, hdev->phys);
  
        return 0;
  }
@@@ -1230,7 -1250,7 +1250,7 @@@ void hid_disconnect(struct hid_device *
  EXPORT_SYMBOL_GPL(hid_disconnect);
  
  /* a list of devices for which there is a specialized driver on HID bus */
- static const struct hid_device_id hid_blacklist[] = {
+ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) },
        { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) },
        { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
        { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) },
        { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
        { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
@@@ -1499,9 -1525,9 +1528,9 @@@ static int hid_bus_match(struct device 
        if (!hid_match_device(hdev, hdrv))
                return 0;
  
-       /* generic wants all non-blacklisted */
+       /* generic wants all that don't have specialized driver */
        if (!strncmp(hdrv->name, "generic-", 8))
-               return !hid_match_id(hdev, hid_blacklist);
+               return !hid_match_id(hdev, hid_have_special_driver);
  
        return 1;
  }
@@@ -1607,7 -1633,6 +1636,7 @@@ static const struct hid_device_id hid_i
        { HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) },
        { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
@@@ -1761,6 -1786,12 +1790,12 @@@ static const struct hid_device_id hid_m
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
        { }
@@@ -1952,12 -1983,12 +1987,12 @@@ static int __init hid_init(void
        int ret;
  
        if (hid_debug)
-               printk(KERN_WARNING "HID: hid_debug is now used solely for parser and driver debugging.\n"
-                               "HID: debugfs is now used for inspecting the device (report descriptor, reports)\n");
+               pr_warn("hid_debug is now used solely for parser and driver debugging.\n"
+                       "debugfs is now used for inspecting the device (report descriptor, reports)\n");
  
        ret = bus_register(&hid_bus_type);
        if (ret) {
-               printk(KERN_ERR "HID: can't register hid bus\n");
+               pr_err("can't register hid bus\n");
                goto err;
        }
  
diff --combined drivers/hid/hid-egalax.c
@@@ -2,8 -2,6 +2,8 @@@
   *  HID driver for eGalax dual-touch panels
   *
   *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
 + *  Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
 + *  Copyright (c) 2010 Canonical, Ltd.
   *
   */
  
@@@ -18,7 -16,6 +18,7 @@@
  #include <linux/hid.h>
  #include <linux/module.h>
  #include <linux/usb.h>
 +#include <linux/input/mt.h>
  #include <linux/slab.h>
  #include "usbhid/usbhid.h"
  
@@@ -28,53 -25,38 +28,53 @@@ MODULE_LICENSE("GPL")
  
  #include "hid-ids.h"
  
 +#define MAX_SLOTS             2
 +
 +/* estimated signal-to-noise ratios */
 +#define SN_MOVE                       4096
 +#define SN_PRESSURE           32
 +
  struct egalax_data {
 -      __u16 x, y, z;
 -      __u8 id;
 -      bool first;             /* is this the first finger in the frame? */
 -      bool valid;             /* valid finger data, or just placeholder? */
 -      bool activity;          /* at least one active finger previously? */
 -      __u16 lastx, lasty, lastz;      /* latest valid (x, y, z) in the frame */
 +      int valid;
 +      int slot;
 +      int touch;
 +      int x, y, z;
  };
  
 +static void set_abs(struct input_dev *input, unsigned int code,
 +                  struct hid_field *field, int snratio)
 +{
 +      int fmin = field->logical_minimum;
 +      int fmax = field->logical_maximum;
 +      int fuzz = snratio ? (fmax - fmin) / snratio : 0;
 +      input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
 +}
 +
  static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
  {
 +      struct input_dev *input = hi->input;
 +
        switch (usage->hid & HID_USAGE_PAGE) {
  
        case HID_UP_GENDESK:
                switch (usage->hid) {
                case HID_GD_X:
 +                      field->logical_maximum = 32760;
                        hid_map_usage(hi, usage, bit, max,
                                        EV_ABS, ABS_MT_POSITION_X);
 +                      set_abs(input, ABS_MT_POSITION_X, field, SN_MOVE);
                        /* touchscreen emulation */
 -                      input_set_abs_params(hi->input, ABS_X,
 -                                              field->logical_minimum,
 -                                              field->logical_maximum, 0, 0);
 +                      set_abs(input, ABS_X, field, SN_MOVE);
                        return 1;
                case HID_GD_Y:
 +                      field->logical_maximum = 32760;
                        hid_map_usage(hi, usage, bit, max,
                                        EV_ABS, ABS_MT_POSITION_Y);
 +                      set_abs(input, ABS_MT_POSITION_Y, field, SN_MOVE);
                        /* touchscreen emulation */
 -                      input_set_abs_params(hi->input, ABS_Y,
 -                                              field->logical_minimum,
 -                                              field->logical_maximum, 0, 0);
 +                      set_abs(input, ABS_Y, field, SN_MOVE);
                        return 1;
                }
                return 0;
@@@ -84,7 -66,6 +84,7 @@@
                case HID_DG_TIPSWITCH:
                        /* touchscreen emulation */
                        hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
 +                      input_set_capability(input, EV_KEY, BTN_TOUCH);
                        return 1;
                case HID_DG_INRANGE:
                case HID_DG_CONFIDENCE:
                case HID_DG_CONTACTMAX:
                        return -1;
                case HID_DG_CONTACTID:
 -                      hid_map_usage(hi, usage, bit, max,
 -                                      EV_ABS, ABS_MT_TRACKING_ID);
 +                      input_mt_init_slots(input, MAX_SLOTS);
                        return 1;
                case HID_DG_TIPPRESSURE:
 +                      field->logical_minimum = 0;
                        hid_map_usage(hi, usage, bit, max,
                                        EV_ABS, ABS_MT_PRESSURE);
 +                      set_abs(input, ABS_MT_PRESSURE, field, SN_PRESSURE);
                        /* touchscreen emulation */
 -                      input_set_abs_params(hi->input, ABS_PRESSURE,
 -                                              field->logical_minimum,
 -                                              field->logical_maximum, 0, 0);
 +                      set_abs(input, ABS_PRESSURE, field, SN_PRESSURE);
                        return 1;
                }
                return 0;
@@@ -114,10 -96,10 +114,10 @@@ static int egalax_input_mapped(struct h
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
  {
 +      /* tell hid-input to skip setup of these event types */
        if (usage->type == EV_KEY || usage->type == EV_ABS)
 -              clear_bit(usage->code, *bit);
 -
 -      return 0;
 +              set_bit(usage->type, hi->input->evbit);
 +      return -1;
  }
  
  /*
   */
  static void egalax_filter_event(struct egalax_data *td, struct input_dev *input)
  {
 -      td->first = !td->first; /* touchscreen emulation */
 -
 -      if (td->valid) {
 -              /* emit multitouch events */
 -              input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
 -              input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x >> 3);
 -              input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y >> 3);
 +      input_mt_slot(input, td->slot);
 +      input_mt_report_slot_state(input, MT_TOOL_FINGER, td->touch);
 +      if (td->touch) {
 +              input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
 +              input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
                input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z);
 -
 -              input_mt_sync(input);
 -
 -              /*
 -               * touchscreen emulation: store (x, y) as
 -               * the last valid values in this frame
 -               */
 -              td->lastx = td->x;
 -              td->lasty = td->y;
 -              td->lastz = td->z;
 -      }
 -
 -      /*
 -       * touchscreen emulation: if this is the second finger and at least
 -       * one in this frame is valid, the latest valid in the frame is
 -       * the oldest on the panel, the one we want for single touch
 -       */
 -      if (!td->first && td->activity) {
 -              input_event(input, EV_ABS, ABS_X, td->lastx >> 3);
 -              input_event(input, EV_ABS, ABS_Y, td->lasty >> 3);
 -              input_event(input, EV_ABS, ABS_PRESSURE, td->lastz);
 -      }
 -
 -      if (!td->valid) {
 -              /*
 -               * touchscreen emulation: if the first finger is invalid
 -               * and there previously was finger activity, this is a release
 -               */ 
 -              if (td->first && td->activity) {
 -                      input_event(input, EV_KEY, BTN_TOUCH, 0);
 -                      td->activity = false;
 -              }
 -              return;
 -      }
 -
 -
 -      /* touchscreen emulation: if no previous activity, emit touch event */
 -      if (!td->activity) {
 -              input_event(input, EV_KEY, BTN_TOUCH, 1);
 -              td->activity = true;
        }
 +      input_mt_report_pointer_emulation(input, true);
  }
  
 -
  static int egalax_event(struct hid_device *hid, struct hid_field *field,
                                struct hid_usage *usage, __s32 value)
  {
         * uses a standard parallel multitouch protocol (product ID ==
         * 48xx).  The second is capacitive and uses an unusual "serial"
         * protocol with a different message for each multitouch finger
 -       * (product ID == 72xx).  We do not yet generate a correct event
 -       * sequence for the capacitive/serial protocol.
 +       * (product ID == 72xx).
         */
        if (hid->claimed & HID_CLAIMED_INPUT) {
                struct input_dev *input = field->hidinput->input;
  
                switch (usage->hid) {
                case HID_DG_INRANGE:
 +                      td->valid = value;
 +                      break;
                case HID_DG_CONFIDENCE:
                        /* avoid interference from generic hidinput handling */
                        break;
                case HID_DG_TIPSWITCH:
 -                      td->valid = value;
 +                      td->touch = value;
                        break;
                case HID_DG_TIPPRESSURE:
                        td->z = value;
                        break;
                case HID_DG_CONTACTID:
 -                      td->id = value;
 +                      td->slot = clamp_val(value, 0, MAX_SLOTS - 1);
                        break;
                case HID_GD_X:
                        td->x = value;
                case HID_GD_Y:
                        td->y = value;
                        /* this is the last field in a finger */
 -                      egalax_filter_event(td, input);
 +                      if (td->valid)
 +                              egalax_filter_event(td, input);
                        break;
                case HID_DG_CONTACTCOUNT:
                        /* touch emulation: this is the last field in a frame */
 -                      td->first = false;
                        break;
  
                default:
@@@ -200,7 -223,7 +200,7 @@@ static int egalax_probe(struct hid_devi
  
        td = kzalloc(sizeof(struct egalax_data), GFP_KERNEL);
        if (!td) {
-               dev_err(&hdev->dev, "cannot allocate eGalax data\n");
+               hid_err(hdev, "cannot allocate eGalax data\n");
                return -ENOMEM;
        }
        hid_set_drvdata(hdev, td);
@@@ -238,12 -261,6 +238,12 @@@ static const struct hid_device_id egala
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
 +                      USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
 +                      USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
 +                      USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
        { }
  };
  MODULE_DEVICE_TABLE(hid, egalax_devices);
diff --combined drivers/hid/hid-ids.h
  #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI  0x0236
  #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO   0x0237
  #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS   0x0238
+ #define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI  0x023f
+ #define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO   0x0240
+ #define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS   0x0241
+ #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242
+ #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO  0x0243
+ #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS  0x0244
  #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI  0x0239
  #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO   0x023a
  #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS   0x023b
  #define USB_VENDOR_ID_CHICONY         0x04f2
  #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD    0x0418
  #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH     0xb19d
+ #define USB_DEVICE_ID_CHICONY_WIRELESS        0x0618
  
  #define USB_VENDOR_ID_CIDC            0x1677
  
  #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER  0x0001
  #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH  0x480d
  #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1 0x720c
 +#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2 0x72a1
 +#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3 0x480e
 +#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4 0x726b
  
  #define USB_VENDOR_ID_ELECOM          0x056e
  #define USB_DEVICE_ID_ELECOM_BM084    0x0061
  
 +#define USB_VENDOR_ID_DREAM_CHEEKY    0x1d34
 +
  #define USB_VENDOR_ID_ELO             0x04E7
  #define USB_DEVICE_ID_ELO_TS2700      0x0020
  
+ #define USB_VENDOR_ID_EMS             0x2006
+ #define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118
  #define USB_VENDOR_ID_ESSENTIAL_REALITY       0x0d7f
  #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
  
  
  #define USB_VENDOR_ID_ROCCAT          0x1e7d
  #define USB_DEVICE_ID_ROCCAT_KONE     0x2ced
+ #define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51
  #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED       0x2c24
  #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS    0x2cf6
  
diff --combined include/linux/device.h
@@@ -197,6 -197,7 +197,7 @@@ struct class 
  
        struct class_attribute          *class_attrs;
        struct device_attribute         *dev_attrs;
+       struct bin_attribute            *dev_bin_attrs;
        struct kobject                  *dev_kobj;
  
        int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
@@@ -508,13 -509,13 +509,13 @@@ static inline int device_is_registered(
  
  static inline void device_enable_async_suspend(struct device *dev)
  {
 -      if (dev->power.status == DPM_ON)
 +      if (!dev->power.in_suspend)
                dev->power.async_suspend = true;
  }
  
  static inline void device_disable_async_suspend(struct device *dev)
  {
 -      if (dev->power.status == DPM_ON)
 +      if (!dev->power.in_suspend)
                dev->power.async_suspend = false;
  }