]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Aug 2012 01:47:44 +0000 (18:47 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Aug 2012 01:47:44 +0000 (18:47 -0700)
Pull second set of media updates from Mauro Carvalho Chehab:

 - radio API: add support to work with radio frequency bands

 - new AM/FM radio drivers: radio-shark, radio-shark2

 - new Remote Controller USB driver: iguanair

 - conversion of several drivers to the v4l2 core control framework

 - new board additions at existing drivers

 - the remaining (and vast majority of the patches) are due to
   drivers/DocBook fixes/cleanups.

* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (154 commits)
  [media] radio-tea5777: use library for 64bits div
  [media] tlg2300: Declare MODULE_FIRMWARE usage
  [media] lgs8gxx: Declare MODULE_FIRMWARE usage
  [media] xc5000: Add MODULE_FIRMWARE statements
  [media] s2255drv: Add MODULE_FIRMWARE statement
  [media] dib8000: move dereference after check for NULL
  [media] Documentation: Update cardlists
  [media] bttv: add support for Aposonic W-DVR
  [media] cx25821: Remove bad strcpy to read-only char*
  [media] pms.c: remove duplicated include
  [media] smiapp-core.c: remove duplicated include
  [media] via-camera: pass correct format settings to sensor
  [media] rtl2832.c: minor cleanup
  [media] Add support for the IguanaWorks USB IR Transceiver
  [media] Minor cleanups for MCE USB
  [media] drivers/media/dvb/siano/smscoreapi.c: use list_for_each_entry
  [media] Use a named union in struct v4l2_ioctl_info
  [media] mceusb: Add Twisted Melon USB IDs
  [media] staging/media/solo6x10: use module_pci_driver macro
  [media] staging/media/dt3155v4l: use module_pci_driver macro
  ...

Conflicts:
Documentation/feature-removal-schedule.txt

1  2 
Documentation/DocBook/media/v4l/controls.xml
Documentation/feature-removal-schedule.txt
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/media/video/gspca/ov534_9.c
drivers/staging/media/easycap/easycap_main.c

index cda0dfb6769aee5d0fcadb8a30b4d19658259bc7,6c27f7b0aca40e6886b2170fc2e18df6055b01ab..b0964fb4e8348853619efd3296b7821d4e6b6803
@@@ -372,6 -372,11 +372,11 @@@ minimum value disables backlight compen
            Cr component, bits [15:8] as Cb component and bits [31:16] must be zero.
          </entry>
          </row>
+         <row>
+           <entry><constant>V4L2_CID_AUTOBRIGHTNESS</constant></entry>
+           <entry>boolean</entry>
+           <entry>Enable Automatic Brightness.</entry>
+         </row>
          <row>
            <entry><constant>V4L2_CID_ROTATE</constant></entry>
            <entry>integer</entry>
@@@ -2097,7 -2102,7 +2102,7 @@@ Possible values are:</entry
                <entry>integer</entry>
              </row>
              <row><entry spanname="descr">Cyclic intra macroblock refresh. This is the number of continuous macroblocks
 -refreshed every frame. Each frame a succesive set of macroblocks is refreshed until the cycle completes and starts from the
 +refreshed every frame. Each frame a successive set of macroblocks is refreshed until the cycle completes and starts from the
  top of the frame. Applicable to H264, H263 and MPEG4 encoder.</entry>
              </row>
  
@@@ -2257,7 -2262,7 +2262,7 @@@ Applicable to the MPEG4 and H264 encode
                <entry>integer</entry>
              </row>
              <row><entry spanname="descr">The Video Buffer Verifier size in kilobytes, it is used as a limitation of frame skip.
 -The VBV is defined in the standard as a mean to verify that the produced stream will be succesfully decoded.
 +The VBV is defined in the standard as a mean to verify that the produced stream will be successfully decoded.
  The standard describes it as "Part of a hypothetical decoder that is conceptually connected to the
  output of the encoder. Its purpose is to provide a constraint on the variability of the data rate that an
  encoder or editing process may produce.".
@@@ -2270,7 -2275,7 +2275,7 @@@ Applicable to the MPEG1, MPEG2, MPEG4 e
                <entry>integer</entry>
              </row>
              <row><entry spanname="descr">The Coded Picture Buffer size in kilobytes, it is used as a limitation of frame skip.
 -The CPB is defined in the H264 standard as a mean to verify that the produced stream will be succesfully decoded.
 +The CPB is defined in the H264 standard as a mean to verify that the produced stream will be successfully decoded.
  Applicable to the H264 encoder.</entry>
              </row>
  
index e9237fb719507abe070064c7fc62848e7307748d,dbefb17b821dbb86b439fdd3a122eff52069578e..09b132dd062d29fec269f5e18406e0f7f3a196b7
@@@ -2,14 -2,7 +2,14 @@@ The following is a list of files and fe
  removed in the kernel source tree.  Every entry should contain what
  exactly is going away, why it is happening, and who is going to be doing
  the work.  When the feature is removed from the kernel, it should also
 -be removed from this file.
 +be removed from this file.  The suggested deprecation period is 3 releases.
 +
 +---------------------------
 +
 +What: ddebug_query="query" boot cmdline param
 +When: v3.8
 +Why:  obsoleted by dyndbg="query" and module.dyndbg="query"
 +Who:  Jim Cromie <jim.cromie@gmail.com>, Jason Baron <jbaron@redhat.com>
  
  ---------------------------
  
@@@ -249,6 -242,15 +249,6 @@@ Who:      Ravikiran Thirumalai <kiran@scalex
  
  ---------------------------
  
 -What: Code that is now under CONFIG_WIRELESS_EXT_SYSFS
 -      (in net/core/net-sysfs.c)
 -When: 3.5
 -Why:  Over 1K .text/.data size reduction, data is available in other
 -      ways (ioctls)
 -Who:  Johannes Berg <johannes@sipsolutions.net>
 -
 ----------------------------
 -
  What: sysfs ui for changing p4-clockmod parameters
  When: September 2009
  Why:  See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and
@@@ -405,6 -407,21 +405,6 @@@ Who:      Jean Delvare <khali@linux-fr.org
  
  ----------------------------
  
 -What: xt_connlimit rev 0
 -When: 2012
 -Who:  Jan Engelhardt <jengelh@medozas.de>
 -Files:        net/netfilter/xt_connlimit.c
 -
 -----------------------------
 -
 -What: ipt_addrtype match include file
 -When: 2012
 -Why:  superseded by xt_addrtype
 -Who:  Florian Westphal <fw@strlen.de>
 -Files:        include/linux/netfilter_ipv4/ipt_addrtype.h
 -
 -----------------------------
 -
  What: i2c_driver.attach_adapter
        i2c_driver.detach_adapter
  When: September 2011
@@@ -425,19 -442,6 +425,19 @@@ Who:     Hans Verkuil <hans.verkuil@cisco.c
  
  ----------------------------
  
 +What: CONFIG_CFG80211_WEXT
 +When: as soon as distributions ship new wireless tools, ie. wpa_supplicant 1.0
 +      and NetworkManager/connman/etc. that are able to use nl80211
 +Why:  Wireless extensions are deprecated, and userland tools are moving to
 +      using nl80211. New drivers are no longer using wireless extensions,
 +      and while there might still be old drivers, both new drivers and new
 +      userland no longer needs them and they can't be used for an feature
 +      developed in the past couple of years. As such, compatibility with
 +      wireless extensions in new drivers will be removed.
 +Who:  Johannes Berg <johannes@sipsolutions.net>
 +
 +----------------------------
 +
  What: g_file_storage driver
  When: 3.8
  Why:  This driver has been superseded by g_mass_storage.
@@@ -512,6 -516,14 +512,6 @@@ Who:      Sebastian Andrzej Siewior <sebasti
  
  ----------------------------
  
 -What: kmap_atomic(page, km_type)
 -When: 3.5
 -Why:  The old kmap_atomic() with two arguments is deprecated, we only
 -      keep it for backward compatibility for few cycles and then drop it.
 -Who:  Cong Wang <amwang@redhat.com>
 -
 -----------------------------
 -
  What: get_robust_list syscall
  When: 2013
  Why:  There appear to be no production users of the get_robust_list syscall,
@@@ -522,18 -534,6 +522,18 @@@ Who:     Kees Cook <keescook@chromium.org
  
  ----------------------------
  
 +What: Removing the pn544 raw driver.
 +When: 3.6
 +Why:  With the introduction of the NFC HCI and SHDL kernel layers, pn544.c
 +      is being replaced by pn544_hci.c which is accessible through the netlink
 +      and socket NFC APIs. Moreover, pn544.c is outdated and does not seem to
 +      work properly with the latest Android stacks.
 +      Having 2 drivers for the same hardware is confusing and as such we
 +      should only keep the one following the kernel NFC APIs.
 +Who:  Samuel Ortiz <sameo@linux.intel.com>
 +
 +----------------------------
 +
  What: setitimer accepts user NULL pointer (value)
  When: 3.6
  Why:  setitimer is not returning -EFAULT if user pointer is NULL. This
@@@ -561,46 -561,6 +561,46 @@@ Who:     Sylwester Nawrocki <sylvester.nawr
  
  ----------------------------
  
 +What: cgroup option updates via remount
 +When: March 2013
 +Why:  Remount currently allows changing bound subsystems and
 +      release_agent.  Rebinding is hardly useful as it only works
 +      when the hierarchy is empty and release_agent itself should be
 +      replaced with conventional fsnotify.
 +
 +----------------------------
 +
 +What:  xt_recent rev 0
 +When:  2013
 +Who:   Pablo Neira Ayuso <pablo@netfilter.org>
 +Files: net/netfilter/xt_recent.c
 +
 +----------------------------
 +
 +What: KVM debugfs statistics
 +When: 2013
 +Why:  KVM tracepoints provide mostly equivalent information in a much more
 +        flexible fashion.
 +
 +----------------------------
 +
 +What: at91-mci driver ("CONFIG_MMC_AT91")
 +When: 3.7
 +Why:  There are two mci drivers: at91-mci and atmel-mci. The PDC support
 +      was added to atmel-mci as a first step to support more chips.
 +      Then at91-mci was kept only for old IP versions (on at91rm9200 and
 +      at91sam9261). The support of these IP versions has just been added
 +      to atmel-mci, so atmel-mci can be used for all chips.
 +Who:  Ludovic Desroches <ludovic.desroches@atmel.com>
 +
 +----------------------------
 +
 +What: net/wanrouter/
 +When: June 2013
 +Why:  Unsupported/unmaintained/unused since 2.6
 +
 +----------------------------
 +
  What: V4L2 selections API target rectangle and flags unification, the
        following definitions will be removed: V4L2_SEL_TGT_CROP_ACTIVE,
        V4L2_SEL_TGT_COMPOSE_ACTIVE, V4L2_SUBDEV_SEL_*, V4L2_SUBDEV_SEL_FLAG_*
@@@ -618,3 -578,15 +618,17 @@@ Why:     The regular V4L2 selections and th
  Who:  Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
  
  ----------------------------
+ What: Using V4L2_CAP_VIDEO_CAPTURE and V4L2_CAP_VIDEO_OUTPUT flags
+       to indicate a V4L2 memory-to-memory device capability
+ When: 3.8
+ Why:  New drivers should use new V4L2_CAP_VIDEO_M2M capability flag
+       to indicate a V4L2 video memory-to-memory (M2M) device and
+       applications can now identify a M2M video device by checking
+       for V4L2_CAP_VIDEO_M2M, with VIDIOC_QUERYCAP ioctl. Using ORed
+       V4L2_CAP_VIDEO_CAPTURE and V4L2_CAP_VIDEO_OUTPUT flags for M2M
+       devices is ambiguous and may lead, for example, to identifying
+       a M2M device as a video capture or output device.
+ Who:  Sylwester Nawrocki <s.nawrocki@samsung.com>
++
++----------------------------
diff --combined drivers/hid/hid-core.c
index 500844f04f93abb668f7ce57b0d841f776c074c7,540763bb7f5cbe45b94e9e9a6928bdc3feacf52f..60ea284407cea4d1f62db43a72b3e6cdbea47e31
@@@ -230,16 -230,9 +230,16 @@@ static int hid_add_field(struct hid_par
                return -1;
        }
  
 -      if (parser->global.logical_maximum < parser->global.logical_minimum) {
 -              hid_err(parser->device, "logical range invalid %d %d\n",
 -                              parser->global.logical_minimum, parser->global.logical_maximum);
 +      /* Handle both signed and unsigned cases properly */
 +      if ((parser->global.logical_minimum < 0 &&
 +              parser->global.logical_maximum <
 +              parser->global.logical_minimum) ||
 +              (parser->global.logical_minimum >= 0 &&
 +              (__u32)parser->global.logical_maximum <
 +              (__u32)parser->global.logical_minimum)) {
 +              dbg_hid("logical range invalid 0x%x 0x%x\n",
 +                      parser->global.logical_minimum,
 +                      parser->global.logical_maximum);
                return -1;
        }
  
@@@ -553,11 -546,12 +553,11 @@@ static void hid_free_report(struct hid_
  }
  
  /*
 - * Free a device structure, all reports, and all fields.
 + * Close report. This function returns the device
 + * state to the point prior to hid_open_report().
   */
 -
 -static void hid_device_release(struct device *dev)
 +static void hid_close_report(struct hid_device *device)
  {
 -      struct hid_device *device = container_of(dev, struct hid_device, dev);
        unsigned i, j;
  
        for (i = 0; i < HID_REPORT_TYPES; i++) {
                        if (report)
                                hid_free_report(report);
                }
 +              memset(report_enum, 0, sizeof(*report_enum));
 +              INIT_LIST_HEAD(&report_enum->report_list);
        }
  
        kfree(device->rdesc);
 +      device->rdesc = NULL;
 +      device->rsize = 0;
 +
        kfree(device->collection);
 -      kfree(device);
 +      device->collection = NULL;
 +      device->collection_size = 0;
 +      device->maxcollection = 0;
 +      device->maxapplication = 0;
 +
 +      device->status &= ~HID_STAT_PARSED;
 +}
 +
 +/*
 + * Free a device structure, all reports, and all fields.
 + */
 +
 +static void hid_device_release(struct device *dev)
 +{
 +      struct hid_device *hid = container_of(dev, struct hid_device, dev);
 +
 +      hid_close_report(hid);
 +      kfree(hid->dev_rdesc);
 +      kfree(hid);
  }
  
  /*
@@@ -665,60 -636,6 +665,60 @@@ static u8 *fetch_item(__u8 *start, __u
        return NULL;
  }
  
 +static void hid_scan_usage(struct hid_device *hid, u32 usage)
 +{
 +      if (usage == HID_DG_CONTACTID)
 +              hid->group = HID_GROUP_MULTITOUCH;
 +}
 +
 +/*
 + * Scan a report descriptor before the device is added to the bus.
 + * Sets device groups and other properties that determine what driver
 + * to load.
 + */
 +static int hid_scan_report(struct hid_device *hid)
 +{
 +      unsigned int page = 0, delim = 0;
 +      __u8 *start = hid->dev_rdesc;
 +      __u8 *end = start + hid->dev_rsize;
 +      unsigned int u, u_min = 0, u_max = 0;
 +      struct hid_item item;
 +
 +      hid->group = HID_GROUP_GENERIC;
 +      while ((start = fetch_item(start, end, &item)) != NULL) {
 +              if (item.format != HID_ITEM_FORMAT_SHORT)
 +                      return -EINVAL;
 +              if (item.type == HID_ITEM_TYPE_GLOBAL) {
 +                      if (item.tag == HID_GLOBAL_ITEM_TAG_USAGE_PAGE)
 +                              page = item_udata(&item) << 16;
 +              } else if (item.type == HID_ITEM_TYPE_LOCAL) {
 +                      if (delim > 1)
 +                              break;
 +                      u = item_udata(&item);
 +                      if (item.size <= 2)
 +                              u += page;
 +                      switch (item.tag) {
 +                      case HID_LOCAL_ITEM_TAG_DELIMITER:
 +                              delim += !!u;
 +                              break;
 +                      case HID_LOCAL_ITEM_TAG_USAGE:
 +                              hid_scan_usage(hid, u);
 +                              break;
 +                      case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
 +                              u_min = u;
 +                              break;
 +                      case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
 +                              u_max = u;
 +                              for (u = u_min; u <= u_max; u++)
 +                                      hid_scan_usage(hid, u);
 +                              break;
 +                      }
 +              }
 +      }
 +
 +      return 0;
 +}
 +
  /**
   * hid_parse_report - parse device report
   *
   * @start: report start
   * @size: report size
   *
 + * Allocate the device report as read by the bus driver. This function should
 + * only be called from parse() in ll drivers.
 + */
 +int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size)
 +{
 +      hid->dev_rdesc = kmemdup(start, size, GFP_KERNEL);
 +      if (!hid->dev_rdesc)
 +              return -ENOMEM;
 +      hid->dev_rsize = size;
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(hid_parse_report);
 +
 +/**
 + * hid_open_report - open a driver-specific device report
 + *
 + * @device: hid device
 + *
   * Parse a report description into a hid_device structure. Reports are
   * enumerated, fields are attached to these reports.
   * 0 returned on success, otherwise nonzero error value.
 + *
 + * This function (or the equivalent hid_parse() macro) should only be
 + * called from probe() in drivers, before starting the device.
   */
 -int hid_parse_report(struct hid_device *device, __u8 *start,
 -              unsigned size)
 +int hid_open_report(struct hid_device *device)
  {
        struct hid_parser *parser;
        struct hid_item item;
 +      unsigned int size;
 +      __u8 *start;
        __u8 *end;
        int ret;
        static int (*dispatch_type[])(struct hid_parser *parser,
                hid_parser_reserved
        };
  
 +      if (WARN_ON(device->status & HID_STAT_PARSED))
 +              return -EBUSY;
 +
 +      start = device->dev_rdesc;
 +      if (WARN_ON(!start))
 +              return -ENODEV;
 +      size = device->dev_rsize;
 +
        if (device->driver->report_fixup)
                start = device->driver->report_fixup(device, start, &size);
  
        parser->device = device;
  
        end = start + size;
 +
 +      device->collection = kcalloc(HID_DEFAULT_NUM_COLLECTIONS,
 +                                   sizeof(struct hid_collection), GFP_KERNEL);
 +      if (!device->collection) {
 +              ret = -ENOMEM;
 +              goto err;
 +      }
 +      device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
 +
        ret = -EINVAL;
        while ((start = fetch_item(start, end, &item)) != NULL) {
  
                                goto err;
                        }
                        vfree(parser);
 +                      device->status |= HID_STAT_PARSED;
                        return 0;
                }
        }
        hid_err(device, "item fetching failed at offset %d\n", (int)(end - start));
  err:
        vfree(parser);
 +      hid_close_report(device);
        return ret;
  }
 -EXPORT_SYMBOL_GPL(hid_parse_report);
 +EXPORT_SYMBOL_GPL(hid_open_report);
  
  /*
   * Convert a signed n-bit integer to signed 32-bit integer. Common
@@@ -1156,7 -1032,7 +1156,7 @@@ static struct hid_report *hid_get_repor
        return report;
  }
  
 -void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
 +int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
                int interrupt)
  {
        struct hid_report_enum *report_enum = hid->report_enum + type;
        unsigned int a;
        int rsize, csize = size;
        u8 *cdata = data;
 +      int ret = 0;
  
        report = hid_get_report(report_enum, data);
        if (!report)
 -              return;
 +              goto out;
  
        if (report_enum->numbered) {
                cdata++;
  
        if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
                hid->hiddev_report_event(hid, report);
 -      if (hid->claimed & HID_CLAIMED_HIDRAW)
 -              hidraw_report_event(hid, data, size);
 +      if (hid->claimed & HID_CLAIMED_HIDRAW) {
 +              ret = hidraw_report_event(hid, data, size);
 +              if (ret)
 +                      goto out;
 +      }
  
 -      for (a = 0; a < report->maxfield; a++)
 -              hid_input_field(hid, report->field[a], cdata, interrupt);
 +      if (hid->claimed != HID_CLAIMED_HIDRAW) {
 +              for (a = 0; a < report->maxfield; a++)
 +                      hid_input_field(hid, report->field[a], cdata, interrupt);
 +      }
  
        if (hid->claimed & HID_CLAIMED_INPUT)
                hidinput_report_event(hid, report);
 +out:
 +      return ret;
  }
  EXPORT_SYMBOL_GPL(hid_report_raw_event);
  
@@@ -1245,10 -1113,6 +1245,10 @@@ int hid_input_report(struct hid_device 
                goto unlock;
        }
  
 +      /* Avoid unnecessary overhead if debugfs is disabled */
 +      if (list_empty(&hid->debug_list))
 +              goto nomem;
 +
        buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
  
        if (!buf)
@@@ -1283,7 -1147,7 +1283,7 @@@ nomem
                }
        }
  
 -      hid_report_raw_event(hid, type, data, size, interrupt);
 +      ret = hid_report_raw_event(hid, type, data, size, interrupt);
  
  unlock:
        up(&hid->driver_lock);
@@@ -1294,8 -1158,7 +1294,8 @@@ EXPORT_SYMBOL_GPL(hid_input_report)
  static bool hid_match_one_id(struct hid_device *hdev,
                const struct hid_device_id *id)
  {
 -      return id->bus == hdev->bus &&
 +      return (id->bus == HID_BUS_ANY || id->bus == hdev->bus) &&
 +              (id->group == HID_GROUP_ANY || id->group == hdev->group) &&
                (id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) &&
                (id->product == HID_ANY_ID || id->product == hdev->product);
  }
@@@ -1371,6 -1234,10 +1371,6 @@@ int hid_connect(struct hid_device *hdev
        if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev,
                                connect_mask & HID_CONNECT_HIDINPUT_FORCE))
                hdev->claimed |= HID_CLAIMED_INPUT;
 -      if (hdev->quirks & HID_QUIRK_MULTITOUCH) {
 -              /* this device should be handled by hid-multitouch, skip it */
 -              return -ENODEV;
 -      }
  
        if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect &&
                        !hdev->hiddev_connect(hdev,
        if ((connect_mask & HID_CONNECT_HIDRAW) && !hidraw_connect(hdev))
                hdev->claimed |= HID_CLAIMED_HIDRAW;
  
 -      if (!hdev->claimed) {
 -              hid_err(hdev, "claimed by neither input, hiddev nor hidraw\n");
 +      /* Drivers with the ->raw_event callback set are not required to connect
 +       * to any other listener. */
 +      if (!hdev->claimed && !hdev->driver->raw_event) {
 +              hid_err(hdev, "device has no listeners, quitting\n");
                return -ENODEV;
        }
  
@@@ -1449,10 -1314,13 +1449,10 @@@ 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_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_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
        { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, USB_DEVICE_ID_ACTIONSTAR_1011) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_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_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },
        { 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) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
        { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
        { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
        { 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_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) },
        { 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_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
        { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) },
        { 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_BLUETOOTH_DEVICE(USB_VENDOR_ID_FRUCTEL, USB_DEVICE_ID_GAMETEL_MT_MODE) },
        { 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_GENERAL_TOUCH, USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, USB_DEVICE_ID_GOODTOUCH_000f) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT, USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6650) },
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MULTITOUCH) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH_DUAL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },
        { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_PANASONIC, USB_DEVICE_ID_PANABOARD_UBT780) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_PANASONIC, USB_DEVICE_ID_PANABOARD_UBT880) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
 -      { 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_ARVO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) },
        { 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) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL, USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_PID_0038) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_XAT, USB_DEVICE_ID_XAT_CSR) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX1) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX1) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR1) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX2) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX2) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR2) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) },
        { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
@@@ -1719,7 -1631,6 +1719,7 @@@ static ssize_t store_new_id(struct devi
                return -ENOMEM;
  
        dynid->id.bus = bus;
 +      dynid->id.group = HID_GROUP_ANY;
        dynid->id.vendor = vendor;
        dynid->id.product = product;
        dynid->id.driver_data = driver_data;
@@@ -1768,7 -1679,18 +1768,7 @@@ static int hid_bus_match(struct device 
        struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
        struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  
 -      if ((hdev->quirks & HID_QUIRK_MULTITOUCH) &&
 -              !strncmp(hdrv->name, "hid-multitouch", 14))
 -              return 1;
 -
 -      if (!hid_match_device(hdev, hdrv))
 -              return 0;
 -
 -      /* generic wants all that don't have specialized driver */
 -      if (!strncmp(hdrv->name, "generic-", 8) && !hid_ignore_special_drivers)
 -              return !hid_match_id(hdev, hid_have_special_driver);
 -
 -      return 1;
 +      return hid_match_device(hdev, hdrv) != NULL;
  }
  
  static int hid_device_probe(struct device *dev)
        if (!hdev->driver) {
                id = hid_match_device(hdev, hdrv);
                if (id == NULL) {
 -                      if (!((hdev->quirks & HID_QUIRK_MULTITOUCH) &&
 -                              !strncmp(hdrv->name, "hid-multitouch", 14))) {
 -                              ret = -ENODEV;
 -                              goto unlock;
 -                      }
 +                      ret = -ENODEV;
 +                      goto unlock;
                }
  
                hdev->driver = hdrv;
                if (hdrv->probe) {
                        ret = hdrv->probe(hdev, id);
                } else { /* default probe */
 -                      ret = hid_parse(hdev);
 +                      ret = hid_open_report(hdev);
                        if (!ret)
                                ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
                }
 -              if (ret)
 +              if (ret) {
 +                      hid_close_report(hdev);
                        hdev->driver = NULL;
 +              }
        }
  unlock:
        up(&hdev->driver_lock);
@@@ -1821,7 -1744,6 +1821,7 @@@ static int hid_device_remove(struct dev
                        hdrv->remove(hdev);
                else /* default remove */
                        hid_hw_stop(hdev);
 +              hid_close_report(hdev);
                hdev->driver = NULL;
        }
  
        return 0;
  }
  
 +static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
 +                           char *buf)
 +{
 +      struct hid_device *hdev = container_of(dev, struct hid_device, dev);
 +      int len;
 +
 +      len = snprintf(buf, PAGE_SIZE, "hid:b%04Xg%04Xv%08Xp%08X\n",
 +                     hdev->bus, hdev->group, hdev->vendor, hdev->product);
 +
 +      return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
 +}
 +
 +static struct device_attribute hid_dev_attrs[] = {
 +      __ATTR_RO(modalias),
 +      __ATTR_NULL,
 +};
 +
  static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
  {
        struct hid_device *hdev = container_of(dev, struct hid_device, dev);
        if (add_uevent_var(env, "HID_UNIQ=%s", hdev->uniq))
                return -ENOMEM;
  
 -      if (add_uevent_var(env, "MODALIAS=hid:b%04Xv%08Xp%08X",
 -                      hdev->bus, hdev->vendor, hdev->product))
 +      if (add_uevent_var(env, "MODALIAS=hid:b%04Xg%04Xv%08Xp%08X",
 +                         hdev->bus, hdev->group, hdev->vendor, hdev->product))
                return -ENOMEM;
  
        return 0;
  
  static struct bus_type hid_bus_type = {
        .name           = "hid",
 +      .dev_attrs      = hid_dev_attrs,
        .match          = hid_bus_match,
        .probe          = hid_device_probe,
        .remove         = hid_device_remove,
@@@ -1928,6 -1832,7 +1928,7 @@@ static const struct hid_device_id hid_i
        { HID_USB_DEVICE(USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_RADIOSHARK) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MCT) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_BEATPAD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) },
@@@ -2106,9 -2010,6 +2107,9 @@@ static const struct hid_device_id hid_m
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_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) },
        { }
@@@ -2176,26 -2077,6 +2177,26 @@@ int hid_add_device(struct hid_device *h
              && (hid_ignore(hdev) || (hdev->quirks & HID_QUIRK_IGNORE)))
                return -ENODEV;
  
 +      /*
 +       * Read the device report descriptor once and use as template
 +       * for the driver-specific modifications.
 +       */
 +      ret = hdev->ll_driver->parse(hdev);
 +      if (ret)
 +              return ret;
 +      if (!hdev->dev_rdesc)
 +              return -ENODEV;
 +
 +      /*
 +       * Scan generic devices for group information
 +       */
 +      if (hid_ignore_special_drivers ||
 +          !hid_match_id(hdev, hid_have_special_driver)) {
 +              ret = hid_scan_report(hdev);
 +              if (ret)
 +                      hid_warn(hdev, "bad device descriptor (%d)\n", ret);
 +      }
 +
        /* XXX hack, any other cleaner solution after the driver core
         * is converted to allow more than 20 bytes as the device name? */
        dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
@@@ -2224,6 -2105,7 +2225,6 @@@ EXPORT_SYMBOL_GPL(hid_add_device)
  struct hid_device *hid_allocate_device(void)
  {
        struct hid_device *hdev;
 -      unsigned int i;
        int ret = -ENOMEM;
  
        hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
        hdev->dev.release = hid_device_release;
        hdev->dev.bus = &hid_bus_type;
  
 -      hdev->collection = kcalloc(HID_DEFAULT_NUM_COLLECTIONS,
 -                      sizeof(struct hid_collection), GFP_KERNEL);
 -      if (hdev->collection == NULL)
 -              goto err;
 -      hdev->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
 -
 -      for (i = 0; i < HID_REPORT_TYPES; i++)
 -              INIT_LIST_HEAD(&hdev->report_enum[i].report_list);
 +      hid_close_report(hdev);
  
        init_waitqueue_head(&hdev->debug_wait);
        INIT_LIST_HEAD(&hdev->debug_list);
        sema_init(&hdev->driver_lock, 1);
  
        return hdev;
 -err:
 -      put_device(&hdev->dev);
 -      return ERR_PTR(ret);
  }
  EXPORT_SYMBOL_GPL(hid_allocate_device);
  
@@@ -2251,9 -2143,6 +2252,9 @@@ static void hid_remove_device(struct hi
                hid_debug_unregister(hdev);
                hdev->status &= ~HID_STAT_ADDED;
        }
 +      kfree(hdev->dev_rdesc);
 +      hdev->dev_rdesc = NULL;
 +      hdev->dev_rsize = 0;
  }
  
  /**
diff --combined drivers/hid/hid-ids.h
index 41c34f21bd001ee00864c596bb217db4647bde7c,909717a41a5da52c0960a5e92f5af3a98da17a32..1dcb76ff51e340a2215d735bdde23e5c370bade0
  #define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI  0x024c
  #define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO   0x024d
  #define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS   0x024e
 +#define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI  0x0262
 +#define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO   0x0263
 +#define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS   0x0264
  #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_DEVICE_ID_ATMEL_MULTITOUCH        0x211c
  #define USB_DEVICE_ID_ATMEL_MXT_DIGITIZER     0x2118
  
 +#define USB_VENDOR_ID_AUREAL          0x0755
 +#define USB_DEVICE_ID_AUREAL_W01RN    0x2626
 +
  #define USB_VENDOR_ID_AVERMEDIA               0x07ca
  #define USB_DEVICE_ID_AVER_FM_MR800   0xb800
  
  #define USB_VENDOR_ID_AXENTIA         0x12cf
  #define USB_DEVICE_ID_AXENTIA_FM_RADIO        0x7111
  
 +#define USB_VENDOR_ID_BAANTO          0x2453
 +#define USB_DEVICE_ID_BAANTO_MT_190W2 0x0100
 +
  #define USB_VENDOR_ID_BELKIN          0x050d
  #define USB_DEVICE_ID_FLIP_KVM                0x3201
  
  #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH     0xb19d
  #define USB_DEVICE_ID_CHICONY_WIRELESS        0x0618
  #define USB_DEVICE_ID_CHICONY_WIRELESS2       0x1123
 +#define USB_DEVICE_ID_CHICONY_AK1D    0x1125
  
  #define USB_VENDOR_ID_CHUNGHWAT               0x2247
  #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH    0x0001
  #define USB_DEVICE_ID_CYPRESS_BARCODE_1       0xde61
  #define USB_DEVICE_ID_CYPRESS_BARCODE_2       0xde64
  #define USB_DEVICE_ID_CYPRESS_BARCODE_3       0xbca1
 +#define USB_DEVICE_ID_CYPRESS_BARCODE_4       0xed81
  #define USB_DEVICE_ID_CYPRESS_TRUETOUCH       0xc001
  
  #define USB_VENDOR_ID_DEALEXTREAME    0x10c5
  #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_VENDOR_ID_HOLTEK          0x1241
  #define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP     0x5015
  
 +#define USB_VENDOR_ID_HOLTEK_ALT              0x04d9
 +#define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD     0xa055
 +
  #define USB_VENDOR_ID_IMATION         0x0718
  #define USB_DEVICE_ID_DISC_STAKKA     0xd000
  
  #define USB_DEVICE_ID_LD_HYBRID               0x2090
  #define USB_DEVICE_ID_LD_HEATCONTROL  0x20A0
  
 +#define USB_VENDOR_ID_LENOVO          0x17ef
 +#define USB_DEVICE_ID_LENOVO_TPKBD    0x6009
 +
  #define USB_VENDOR_ID_LG              0x1fd2
  #define USB_DEVICE_ID_LG_MULTITOUCH   0x0064
  
  #define USB_DEVICE_ID_CRYSTALTOUCH    0x0006
  #define USB_DEVICE_ID_CRYSTALTOUCH_DUAL       0x0007
  
 +#define USB_VENDOR_ID_MADCATZ         0x0738
 +#define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540
 +
  #define USB_VENDOR_ID_MCC             0x09db
  #define USB_DEVICE_ID_MCC_PMD1024LS   0x0076
  #define USB_DEVICE_ID_MCC_PMD1208LS   0x007a
  #define USB_VENDOR_ID_NINTENDO                0x057e
  #define USB_DEVICE_ID_NINTENDO_WIIMOTE        0x0306
  
 +#define USB_VENDOR_ID_NOVATEK         0x0603
 +#define USB_DEVICE_ID_NOVATEK_PCT     0x0600
 +
  #define USB_VENDOR_ID_NTRIG           0x1b96
  #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN   0x0001
  #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1   0x0003
  #define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50
  #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED       0x2c24
  #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS    0x2cf6
 +#define USB_DEVICE_ID_ROCCAT_SAVU     0x2d5a
  
  #define USB_VENDOR_ID_SAITEK          0x06a3
  #define USB_DEVICE_ID_SAITEK_RUMBLEPAD        0xff17
  #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE       0x0001
  #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE      0x0600
  
 +#define USB_VENDOR_ID_SENNHEISER      0x1395
 +#define USB_DEVICE_ID_SENNHEISER_BTD500USB    0x002c
 +
  #define USB_VENDOR_ID_SIGMA_MICRO     0x1c4f
  #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD    0x0002
  
  #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U  0x0004
  #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_VENDOR_ID_UNITEC  0x227d
  #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709   0x0709
  #define USB_DEVICE_ID_WALTOP_PID_0038                 0x0038
  #define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH   0x0501
  #define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH   0x0500
 +#define USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET       0x0502
  
  #define USB_VENDOR_ID_WISEGROUP               0x0925
  #define USB_DEVICE_ID_SMARTJOY_PLUS   0x0005
  #define USB_VENDOR_ID_ZYDACRON        0x13EC
  #define USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL 0x0006
  
 +#define USB_VENDOR_ID_ZYTRONIC                0x14c8
 +#define USB_DEVICE_ID_ZYTRONIC_ZXY100 0x0005
 +
  #define USB_VENDOR_ID_PRIMAX  0x0461
  #define USB_DEVICE_ID_PRIMAX_KEYBOARD 0x4e05
  
index 1fd41f0d2e9514a408db394e9a613bc4ee2badd7,e4c3c8fdab3eb55f773770c89afcec368b749368..c4cd028fe0b4c8ea0c662ab82fbf98695f23a722
@@@ -47,22 -47,9 +47,9 @@@ MODULE_AUTHOR("Jean-Francois Moine <moi
  MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");
  MODULE_LICENSE("GPL");
  
- /* controls */
- enum e_ctrl {
-       BRIGHTNESS,
-       CONTRAST,
-       AUTOGAIN,
-       EXPOSURE,
-       SHARPNESS,
-       SATUR,
-       LIGHTFREQ,
-       NCTRLS          /* number of controls */
- };
  /* specific webcam descriptor */
  struct sd {
        struct gspca_dev gspca_dev;     /* !! must be the first item */
-       struct gspca_ctrl ctrls[NCTRLS];
        __u32 last_pts;
        u8 last_fid;
  
@@@ -75,103 -62,6 +62,6 @@@ enum sensors 
        NSENSORS
  };
  
- /* V4L2 controls supported by the driver */
- static void setbrightness(struct gspca_dev *gspca_dev);
- static void setcontrast(struct gspca_dev *gspca_dev);
- static void setautogain(struct gspca_dev *gspca_dev);
- static void setexposure(struct gspca_dev *gspca_dev);
- static void setsharpness(struct gspca_dev *gspca_dev);
- static void setsatur(struct gspca_dev *gspca_dev);
- static void setlightfreq(struct gspca_dev *gspca_dev);
- static const struct ctrl sd_ctrls[NCTRLS] = {
- [BRIGHTNESS] = {
-       {
-               .id      = V4L2_CID_BRIGHTNESS,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Brightness",
-               .minimum = 0,
-               .maximum = 15,
-               .step    = 1,
-               .default_value = 7
-       },
-       .set_control = setbrightness
-     },
- [CONTRAST] = {
-       {
-               .id      = V4L2_CID_CONTRAST,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Contrast",
-               .minimum = 0,
-               .maximum = 15,
-               .step    = 1,
-               .default_value = 3
-       },
-       .set_control = setcontrast
-     },
- [AUTOGAIN] = {
-       {
-               .id      = V4L2_CID_AUTOGAIN,
-               .type    = V4L2_CTRL_TYPE_BOOLEAN,
-               .name    = "Autogain",
-               .minimum = 0,
-               .maximum = 1,
-               .step    = 1,
- #define AUTOGAIN_DEF 1
-               .default_value = AUTOGAIN_DEF,
-       },
-       .set_control = setautogain
-     },
- [EXPOSURE] = {
-       {
-               .id      = V4L2_CID_EXPOSURE,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Exposure",
-               .minimum = 0,
-               .maximum = 3,
-               .step    = 1,
-               .default_value = 0
-       },
-       .set_control = setexposure
-     },
- [SHARPNESS] = {
-       {
-               .id      = V4L2_CID_SHARPNESS,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Sharpness",
-               .minimum = -1,          /* -1 = auto */
-               .maximum = 4,
-               .step    = 1,
-               .default_value = -1
-       },
-       .set_control = setsharpness
-     },
- [SATUR] = {
-       {
-               .id      = V4L2_CID_SATURATION,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Saturation",
-               .minimum = 0,
-               .maximum = 4,
-               .step    = 1,
-               .default_value = 2
-       },
-       .set_control = setsatur
-     },
- [LIGHTFREQ] = {
-       {
-               .id      = V4L2_CID_POWER_LINE_FREQUENCY,
-               .type    = V4L2_CTRL_TYPE_MENU,
-               .name    = "Light frequency filter",
-               .minimum = 0,
-               .maximum = 2,   /* 0: 0, 1: 50Hz, 2:60Hz */
-               .step    = 1,
-               .default_value = 0
-       },
-       .set_control = setlightfreq
-     },
- };
  static const struct v4l2_pix_format ov965x_mode[] = {
  #define QVGA_MODE 0
        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
@@@ -1104,16 -994,14 +994,14 @@@ static void set_led(struct gspca_dev *g
        }
  }
  
- static void setbrightness(struct gspca_dev *gspca_dev)
+ static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
  {
        struct sd *sd = (struct sd *) gspca_dev;
        u8 val;
        s8 sval;
  
-       if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS))
-               return;
        if (sd->sensor == SENSOR_OV562x) {
-               sval = sd->ctrls[BRIGHTNESS].val;
+               sval = brightness;
                val = 0x76;
                val += sval;
                sccb_write(gspca_dev, 0x24, val);
                        val = 0xe6;
                sccb_write(gspca_dev, 0x26, val);
        } else {
-               val = sd->ctrls[BRIGHTNESS].val;
+               val = brightness;
                if (val < 8)
                        val = 15 - val;         /* f .. 8 */
                else
        }
  }
  
- static void setcontrast(struct gspca_dev *gspca_dev)
+ static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
  {
-       struct sd *sd = (struct sd *) gspca_dev;
-       if (gspca_dev->ctrl_dis & (1 << CONTRAST))
-               return;
        sccb_write(gspca_dev, 0x56,     /* cnst1 - contrast 1 ctrl coeff */
-                       sd->ctrls[CONTRAST].val << 4);
+                       val << 4);
  }
  
- static void setautogain(struct gspca_dev *gspca_dev)
+ static void setautogain(struct gspca_dev *gspca_dev, s32 autogain)
  {
-       struct sd *sd = (struct sd *) gspca_dev;
        u8 val;
  
-       if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
-               return;
  /*fixme: should adjust agc/awb/aec by different controls */
        val = sccb_read(gspca_dev, 0x13);               /* com8 */
        sccb_write(gspca_dev, 0xff, 0x00);
-       if (sd->ctrls[AUTOGAIN].val)
+       if (autogain)
                val |= 0x05;            /* agc & aec */
        else
                val &= 0xfa;
        sccb_write(gspca_dev, 0x13, val);
  }
  
- static void setexposure(struct gspca_dev *gspca_dev)
+ static void setexposure(struct gspca_dev *gspca_dev, s32 exposure)
  {
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 val;
        static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
+       u8 val;
  
-       if (gspca_dev->ctrl_dis & (1 << EXPOSURE))
-               return;
-       sccb_write(gspca_dev, 0x10,                     /* aec[9:2] */
-                       expo[sd->ctrls[EXPOSURE].val]);
+       sccb_write(gspca_dev, 0x10, expo[exposure]);    /* aec[9:2] */
  
        val = sccb_read(gspca_dev, 0x13);               /* com8 */
        sccb_write(gspca_dev, 0xff, 0x00);
        sccb_write(gspca_dev, 0xa1, val & 0xe0);        /* aec[15:10] = 0 */
  }
  
- static void setsharpness(struct gspca_dev *gspca_dev)
+ static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
  {
-       struct sd *sd = (struct sd *) gspca_dev;
-       s8 val;
-       if (gspca_dev->ctrl_dis & (1 << SHARPNESS))
-               return;
-       val = sd->ctrls[SHARPNESS].val;
        if (val < 0) {                          /* auto */
                val = sccb_read(gspca_dev, 0x42);       /* com17 */
                sccb_write(gspca_dev, 0xff, 0x00);
        sccb_write(gspca_dev, 0x42, val & 0xbf);
  }
  
- static void setsatur(struct gspca_dev *gspca_dev)
+ static void setsatur(struct gspca_dev *gspca_dev, s32 val)
  {
-       struct sd *sd = (struct sd *) gspca_dev;
        u8 val1, val2, val3;
        static const u8 matrix[5][2] = {
                {0x14, 0x38},
                {0x48, 0x90}
        };
  
-       if (gspca_dev->ctrl_dis & (1 << SATUR))
-               return;
-       val1 = matrix[sd->ctrls[SATUR].val][0];
-       val2 = matrix[sd->ctrls[SATUR].val][1];
+       val1 = matrix[val][0];
+       val2 = matrix[val][1];
        val3 = val1 + val2;
        sccb_write(gspca_dev, 0x4f, val3);      /* matrix coeff */
        sccb_write(gspca_dev, 0x50, val3);
        sccb_write(gspca_dev, 0x41, val1);
  }
  
- static void setlightfreq(struct gspca_dev *gspca_dev)
+ static void setlightfreq(struct gspca_dev *gspca_dev, s32 freq)
  {
-       struct sd *sd = (struct sd *) gspca_dev;
        u8 val;
  
-       if (gspca_dev->ctrl_dis & (1 << LIGHTFREQ))
-               return;
        val = sccb_read(gspca_dev, 0x13);               /* com8 */
        sccb_write(gspca_dev, 0xff, 0x00);
-       if (sd->ctrls[LIGHTFREQ].val == 0) {
+       if (freq == 0) {
                sccb_write(gspca_dev, 0x13, val & 0xdf);
                return;
        }
  
        val = sccb_read(gspca_dev, 0x42);               /* com17 */
        sccb_write(gspca_dev, 0xff, 0x00);
-       if (sd->ctrls[LIGHTFREQ].val == 1)
+       if (freq == 1)
                val |= 0x01;
        else
                val &= 0xfe;
  static int sd_config(struct gspca_dev *gspca_dev,
                     const struct usb_device_id *id)
  {
-       struct sd *sd = (struct sd *) gspca_dev;
-       gspca_dev->cam.ctrls = sd->ctrls;
- #if AUTOGAIN_DEF != 0
-       gspca_dev->ctrl_inac |= (1 << EXPOSURE);
- #endif
        return 0;
  }
  
@@@ -1330,9 -1188,6 +1188,6 @@@ static int sd_init(struct gspca_dev *gs
                gspca_dev->cam.cam_mode = ov971x_mode;
                gspca_dev->cam.nmodes = ARRAY_SIZE(ov971x_mode);
  
-               /* no control yet */
-               gspca_dev->ctrl_dis = (1 << NCTRLS) - 1;
                gspca_dev->cam.bulk = 1;
                gspca_dev->cam.bulk_size = 16384;
                gspca_dev->cam.bulk_nurbs = 2;
                        reg_w(gspca_dev, 0x56, 0x17);
        } else if ((sensor_id & 0xfff0) == 0x5620) {
                sd->sensor = SENSOR_OV562x;
-               gspca_dev->ctrl_dis = (1 << CONTRAST) |
-                                       (1 << AUTOGAIN) |
-                                       (1 << EXPOSURE) |
-                                       (1 << SHARPNESS) |
-                                       (1 << SATUR) |
-                                       (1 << LIGHTFREQ);
-               sd->ctrls[BRIGHTNESS].min = -90;
-               sd->ctrls[BRIGHTNESS].max = 90;
-               sd->ctrls[BRIGHTNESS].def = 0;
                gspca_dev->cam.cam_mode = ov562x_mode;
                gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode);
  
                                ARRAY_SIZE(ov562x_init_2));
                reg_w(gspca_dev, 0xe0, 0x00);
        } else {
 -              err("Unknown sensor %04x", sensor_id);
 +              pr_err("Unknown sensor %04x", sensor_id);
                return -EINVAL;
        }
  
@@@ -1390,10 -1235,9 +1235,9 @@@ static int sd_start(struct gspca_dev *g
  
        if (sd->sensor == SENSOR_OV971x)
                return gspca_dev->usb_err;
-       else if (sd->sensor == SENSOR_OV562x) {
-               setbrightness(gspca_dev);
+       if (sd->sensor == SENSOR_OV562x)
                return gspca_dev->usb_err;
-       }
        switch (gspca_dev->curr_mode) {
        case QVGA_MODE:                 /* 320x240 */
                sccb_w_array(gspca_dev, ov965x_start_1_vga,
                                ARRAY_SIZE(ov965x_start_2_sxga));
                break;
        }
-       setlightfreq(gspca_dev);
-       setautogain(gspca_dev);
-       setbrightness(gspca_dev);
-       setcontrast(gspca_dev);
-       setexposure(gspca_dev);
-       setsharpness(gspca_dev);
-       setsatur(gspca_dev);
  
        reg_w(gspca_dev, 0xe0, 0x00);
        reg_w(gspca_dev, 0xe0, 0x00);
@@@ -1541,38 -1378,94 +1378,94 @@@ scan_next
        } while (remaining_len > 0);
  }
  
- static int sd_querymenu(struct gspca_dev *gspca_dev,
-                       struct v4l2_querymenu *menu)
+ static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
  {
-       switch (menu->id) {
+       struct gspca_dev *gspca_dev =
+               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+       gspca_dev->usb_err = 0;
+       if (!gspca_dev->streaming)
+               return 0;
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               setsatur(gspca_dev, ctrl->val);
+               break;
        case V4L2_CID_POWER_LINE_FREQUENCY:
-               switch (menu->index) {
-               case 0:         /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
-                       strcpy((char *) menu->name, "NoFliker");
-                       return 0;
-               case 1:         /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
-                       strcpy((char *) menu->name, "50 Hz");
-                       return 0;
-               case 2:         /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
-                       strcpy((char *) menu->name, "60 Hz");
-                       return 0;
-               }
+               setlightfreq(gspca_dev, ctrl->val);
                break;
+       case V4L2_CID_SHARPNESS:
+               setsharpness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if (ctrl->is_new)
+                       setautogain(gspca_dev, ctrl->val);
+               if (!ctrl->val && gspca_dev->exposure->is_new)
+                       setexposure(gspca_dev, gspca_dev->exposure->val);
+               break;
+       }
+       return gspca_dev->usb_err;
+ }
+ static const struct v4l2_ctrl_ops sd_ctrl_ops = {
+       .s_ctrl = sd_s_ctrl,
+ };
+ static int sd_init_controls(struct gspca_dev *gspca_dev)
+ {
+       struct sd *sd = (struct sd *)gspca_dev;
+       struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+       if (sd->sensor == SENSOR_OV971x)
+               return 0;
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 7);
+       if (sd->sensor == SENSOR_OV562x) {
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, -90, 90, 1, 0);
+       } else {
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 15, 1, 7);
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 15, 1, 3);
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 4, 1, 2);
+               /* -1 = auto */
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SHARPNESS, -1, 4, 1, -1);
+               gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0, 3, 1, 0);
+               v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
+                       V4L2_CID_POWER_LINE_FREQUENCY,
+                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
+               v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
        }
-       return -EINVAL;
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       return 0;
  }
  
  /* sub-driver description */
  static const struct sd_desc sd_desc = {
        .name     = MODULE_NAME,
-       .ctrls    = sd_ctrls,
-       .nctrls   = NCTRLS,
        .config   = sd_config,
        .init     = sd_init,
+       .init_controls = sd_init_controls,
        .start    = sd_start,
        .stopN    = sd_stopN,
        .pkt_scan = sd_pkt_scan,
-       .querymenu = sd_querymenu,
  };
  
  /* -- module initialisation -- */
@@@ -1600,6 -1493,7 +1493,7 @@@ static struct usb_driver sd_driver = 
  #ifdef CONFIG_PM
        .suspend    = gspca_suspend,
        .resume     = gspca_resume,
+       .reset_resume = gspca_resume,
  #endif
  };
  
index a1c45e4dcdce37e0b1ac885fca0e8750591add80,19d2d9d64236b2aa370149515165447747854fda..8269c77dbf7df5b2a9d860d304a06c806c88448a
@@@ -3083,6 -3083,7 +3083,7 @@@ static int create_video_urbs(struct eas
                peasycap->allocation_video_urb += 1;
                pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
                if (!pdata_urb) {
+                       usb_free_urb(purb);
                        SAM("ERROR: Could not allocate struct data_urb.\n");
                        return -ENOMEM;
                }
@@@ -3467,6 -3468,7 +3468,6 @@@ static int easycap_register_video(struc
  
        if (0 != (video_register_device(&(peasycap->video_device),
                                        VFL_TYPE_GRABBER, -1))) {
 -              err("Not able to register with videodev");
                videodev_release(&(peasycap->video_device));
                return -ENODEV;
        }
@@@ -3854,11 -3856,8 +3855,11 @@@ static int easycap_usb_probe(struct usb
                        peasycap->v4l2_device.name);
  
                rc = easycap_register_video(peasycap);
 -              if (rc < 0)
 +              if (rc < 0) {
 +                      dev_err(&intf->dev,
 +                              "Not able to register with videodev\n");
                        return -ENODEV;
 +              }
                break;
        }
        /* 1: Audio control */
  
                rc = easycap_alsa_probe(peasycap);
                if (rc) {
 -                      err("easycap_alsa_probe() rc = %i\n", rc);
 +                      dev_err(&intf->dev, "easycap_alsa_probe() rc = %i\n",
 +                              rc);
                        return -ENODEV;
                }