]> Git Repo - linux.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
authorLinus Torvalds <[email protected]>
Fri, 6 Sep 2013 16:30:36 +0000 (09:30 -0700)
committerLinus Torvalds <[email protected]>
Fri, 6 Sep 2013 16:30:36 +0000 (09:30 -0700)
Pull HID updates from Jiri Kosina:
 "Highlights:

   - conversion of HID subsystem to use devm-based resource management,
     from Benjamin Tissoires

   - i2c-hid support for DT bindings, from Benjamin Tissoires

   - much improved support for Win8-multitouch devices, from Benjamin
     Tissoires

   - cleanup of core code using common hidinput_input_event(), from
     David Herrmann

   - fix for bug in implement() access to the bit stream (causing oops)
     that has been present in the code for ages, but devices that are
     able to trigger it have started to appear only now, from Jiri
     Kosina

   - fixes for CVE-2013-2899, CVE-2013-2898, CVE-2013-2896,
     CVE-2013-2892, CVE-2013-2888 (all triggerable only by specially
     crafted malicious HW devices plugged into the system), from Kees
     Cook

   - hidraw oops fix, from Manoj Chourasia

   - various smaller fixes here and there, support for a bunch of new
     devices by various contributors"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (53 commits)
  HID: MAINTAINERS: add roccat drivers
  HID: hid-sensor-hub: change kmalloc + memcpy by kmemdup
  HID: hid-sensor-hub: move to devm_kzalloc
  HID: hid-sensor-hub: fix indentation accross the code
  HID: move HID_REPORT_TYPES closer to the report-definitions
  HID: check for NULL field when setting values
  HID: picolcd_core: validate output report details
  HID: sensor-hub: validate feature report details
  HID: ntrig: validate feature report details
  HID: pantherlord: validate output report details
  HID: hid-wiimote: print small buffers via %*phC
  HID: uhid: improve uhid example client
  HID: Correct the USB IDs for the new Macbook Air 6
  HID: wiimote: add support for Guitar-Hero guitars
  HID: wiimote: add support for Guitar-Hero drums
  Input: introduce BTN/ABS bits for drums and guitars
  HID: battery: don't do DMA from stack
  HID: roccat: add support for KonePureOptical v2
  HID: picolcd: Prevent NULL pointer dereference on _remove()
  HID: usbhid: quirk for N-Trig DuoSense Touch Screen
  ...

1  2 
MAINTAINERS
drivers/hid/hid-core.c
drivers/hid/hid-roccat-arvo.c
drivers/hid/hid-roccat-isku.c
drivers/hid/hid-roccat-kone.c
drivers/hid/hid-roccat-koneplus.c
drivers/hid/hid-roccat-konepure.c
drivers/hid/hid-roccat-kovaplus.c
net/bluetooth/hidp/core.c

diff --combined MAINTAINERS
index 9d8ab7c681f9e3dd8e5c270cac5f713eb0395c89,55d946be6789ce5250112d7c096fc1a7b596b0ef..caa7c3a1fef97d7d2e42b82b7dfdd8cdd3a55ecb
@@@ -580,24 -580,12 +580,24 @@@ L:      [email protected]
  S:    Maintained
  F:    drivers/media/i2c/ad9389b*
  
 +ANALOG DEVICES INC ADV7511 DRIVER
 +M:    Hans Verkuil <[email protected]>
 +L:    [email protected]
 +S:    Maintained
 +F:    drivers/media/i2c/adv7511*
 +
  ANALOG DEVICES INC ADV7604 DRIVER
  M:    Hans Verkuil <[email protected]>
  L:    [email protected]
  S:    Maintained
  F:    drivers/media/i2c/adv7604*
  
 +ANALOG DEVICES INC ADV7842 DRIVER
 +M:    Hans Verkuil <[email protected]>
 +L:    [email protected]
 +S:    Maintained
 +F:    drivers/media/i2c/adv7842*
 +
  ANALOG DEVICES INC ASOC CODEC DRIVERS
  M:    Lars-Peter Clausen <[email protected]>
  L:    [email protected]
@@@ -607,7 -595,6 +607,7 @@@ S: Supporte
  F:    sound/soc/codecs/adau*
  F:    sound/soc/codecs/adav*
  F:    sound/soc/codecs/ad1*
 +F:    sound/soc/codecs/ad7*
  F:    sound/soc/codecs/ssm*
  F:    sound/soc/codecs/sigmadsp.*
  
@@@ -651,12 -638,6 +651,12 @@@ S:       Maintaine
  F:    drivers/net/appletalk/
  F:    net/appletalk/
  
 +APTINA CAMERA SENSOR PLL
 +M:    Laurent Pinchart <[email protected]>
 +L:    [email protected]
 +S:    Maintained
 +F:    drivers/media/i2c/aptina-pll.*
 +
  ARASAN COMPACT FLASH PATA CONTROLLER
  M:    Viresh Kumar <[email protected]>
  L:    [email protected]
@@@ -832,7 -813,7 +832,7 @@@ F: arch/arm/mach-prima2
  F:    drivers/dma/sirf-dma.c
  F:    drivers/i2c/busses/i2c-sirf.c
  F:    drivers/mmc/host/sdhci-sirf.c
 -F:    drivers/pinctrl/pinctrl-sirf.c
 +F:    drivers/pinctrl/sirf/
  F:    drivers/spi/spi-sirf.c
  
  ARM/EBSA110 MACHINE SUPPORT
@@@ -1566,13 -1547,6 +1566,13 @@@ W:    http://atmelwlandriver.sourceforge.n
  S:    Maintained
  F:    drivers/net/wireless/atmel*
  
 +ATTO EXPRESSSAS SAS/SATA RAID SCSI DRIVER
 +M:      Bradley Grove <[email protected]>
 +L:      [email protected]
 +W:      http://www.attotech.com
 +S:      Supported
 +F:      drivers/scsi/esas2r
 +
  AUDIT SUBSYSTEM
  M:    Al Viro <[email protected]>
  M:    Eric Paris <[email protected]>
  S:    Supported
  F:    drivers/scsi/bnx2fc/
  
 +BROADCOM BNX2I 1/10 GIGABIT iSCSI DRIVER
 +M:    Eddie Wai <[email protected]>
 +L:    [email protected]
 +S:    Supported
 +F:    drivers/scsi/bnx2i/
 +
  BROADCOM SPECIFIC AMBA DRIVER (BCMA)
  M:    Rafał Miłecki <[email protected]>
  L:    [email protected]
@@@ -2108,8 -2076,7 +2108,8 @@@ F:      drivers/usb/chipidea
  
  CISCO VIC ETHERNET NIC DRIVER
  M:    Christian Benvenuti <[email protected]>
 -M:    Roopa Prabhu <[email protected]>
 +M:    Sujith Sankar <[email protected]>
 +M:    Govindarajulu Varadarajan <[email protected]>
  M:    Neel Patel <[email protected]>
  M:    Nishank Trivedi <[email protected]>
  S:    Supported
@@@ -2145,13 -2112,6 +2145,13 @@@ M:    Russell King <[email protected]
  S:    Maintained
  F:    include/linux/clk.h
  
 +CLOCKSOURCE, CLOCKEVENT DRIVERS
 +M:    Daniel Lezcano <[email protected]>
 +M:    Thomas Gleixner <[email protected]>
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
 +S:    Supported
 +F:    drivers/clocksource
 +
  CISCO FCOE HBA DRIVER
  M:    Hiral Patel <[email protected]>
  M:    Suma Ramars <[email protected]>
@@@ -4405,7 -4365,7 +4405,7 @@@ F:      drivers/net/wireless/iwlegacy
  
  INTEL WIRELESS WIFI LINK (iwlwifi)
  M:    Johannes Berg <[email protected]>
 -M:    Wey-Yi Guy <wey-yi.w.guy@intel.com>
 +M:    Emmanuel Grumbach <emmanuel.grumbach@intel.com>
  M:    Intel Linux Wireless <[email protected]>
  L:    [email protected]
  W:    http://intellinuxwireless.org
@@@ -5537,7 -5497,7 +5537,7 @@@ L:      [email protected]
  S:    Supported
  F:    drivers/platform/x86/msi-wmi.c
  
 -MT9M032 SENSOR DRIVER
 +MT9M032 APTINA SENSOR DRIVER
  M:    Laurent Pinchart <[email protected]>
  L:    [email protected]
  T:    git git://linuxtv.org/media_tree.git
@@@ -5545,7 -5505,7 +5545,7 @@@ S:      Maintaine
  F:    drivers/media/i2c/mt9m032.c
  F:    include/media/mt9m032.h
  
 -MT9P031 SENSOR DRIVER
 +MT9P031 APTINA CAMERA SENSOR
  M:    Laurent Pinchart <[email protected]>
  L:    [email protected]
  T:    git git://linuxtv.org/media_tree.git
@@@ -5553,7 -5513,7 +5553,7 @@@ S:      Maintaine
  F:    drivers/media/i2c/mt9p031.c
  F:    include/media/mt9p031.h
  
 -MT9T001 SENSOR DRIVER
 +MT9T001 APTINA CAMERA SENSOR
  M:    Laurent Pinchart <[email protected]>
  L:    [email protected]
  T:    git git://linuxtv.org/media_tree.git
@@@ -5561,7 -5521,7 +5561,7 @@@ S:      Maintaine
  F:    drivers/media/i2c/mt9t001.c
  F:    include/media/mt9t001.h
  
 -MT9V032 SENSOR DRIVER
 +MT9V032 APTINA CAMERA SENSOR
  M:    Laurent Pinchart <[email protected]>
  L:    [email protected]
  T:    git git://linuxtv.org/media_tree.git
@@@ -5621,9 -5581,9 +5621,9 @@@ S:      Maintaine
  F:    drivers/media/tuners/mxl5007t.*
  
  MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
 -M:    Andrew Gallatin <gallatin@myri.com>
 +M:    Hyong-Youb Kim <hykim@myri.com>
  L:    [email protected]
 -W:    http://www.myri.com/scs/download-Myri10GE.html
 +W:    https://www.myricom.com/support/downloads/myri10ge.html
  S:    Supported
  F:    drivers/net/ethernet/myricom/myri10ge/
  
@@@ -5832,7 -5792,7 +5832,7 @@@ M:      Aloisio Almeida Jr <aloisio.almeida@
  M:    Samuel Ortiz <[email protected]>
  L:    [email protected]
  L:    [email protected] (moderated for non-subscribers)
 -S:    Maintained
 +S:    Supported
  F:    net/nfc/
  F:    include/net/nfc/
  F:    include/uapi/linux/nfc.h
@@@ -5924,7 -5884,7 +5924,7 @@@ F:      drivers/i2c/busses/i2c-omap.
  F:    include/linux/i2c-omap.h
  
  OMAP DEVICE TREE SUPPORT
 -M:    Benoît Cousson <b-cousson@ti.com>
 +M:    Benoît Cousson <bcousson@baylibre.com>
  M:    Tony Lindgren <[email protected]>
  L:    [email protected]
  L:    [email protected]
@@@ -6004,14 -5964,14 +6004,14 @@@ S:   Maintaine
  F:    drivers/char/hw_random/omap-rng.c
  
  OMAP HWMOD SUPPORT
 -M:    Benoît Cousson <b-cousson@ti.com>
 +M:    Benoît Cousson <bcousson@baylibre.com>
  M:    Paul Walmsley <[email protected]>
  L:    [email protected]
  S:    Maintained
  F:    arch/arm/mach-omap2/omap_hwmod.*
  
  OMAP HWMOD DATA FOR OMAP4-BASED DEVICES
 -M:    Benoît Cousson <b-cousson@ti.com>
 +M:    Benoît Cousson <bcousson@baylibre.com>
  L:    [email protected]
  S:    Maintained
  F:    arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@@ -6106,7 -6066,7 +6106,7 @@@ M:      Rob Herring <[email protected]
  M:    Pawel Moll <[email protected]>
  M:    Mark Rutland <[email protected]>
  M:    Stephen Warren <[email protected]>
 -M:    Ian Campbell <i[email protected]>
 +M:    Ian Campbell <i[email protected]>
  L:    [email protected]
  S:    Maintained
  F:    Documentation/devicetree/
@@@ -6716,11 -6676,11 +6716,11 @@@ F:   Documentation/scsi/LICENSE.qla2xx
  F:    drivers/scsi/qla2xxx/
  
  QLOGIC QLA4XXX iSCSI DRIVER
 -M:    Ravi Anand <[email protected]>
  M:    Vikas Chaudhary <[email protected]>
  M:    [email protected]
  L:    [email protected]
  S:    Supported
 +F:    Documentation/scsi/LICENSE.qla4xxx
  F:    drivers/scsi/qla4xxx/
  
  QLOGIC QLA3XXX NETWORK DRIVER
@@@ -6961,6 -6921,14 +6961,14 @@@ M:    Maxim Levitsky <maximlevitsky@gmail.
  S:    Maintained
  F:    drivers/memstick/host/r592.*
  
+ ROCCAT DRIVERS
+ M:    Stefan Achatz <[email protected]>
+ W:    http://sourceforge.net/projects/roccat/
+ S:    Maintained
+ F:    drivers/hid/hid-roccat*
+ F:    include/linux/hid-roccat*
+ F:    Documentation/ABI/*/sysfs-driver-hid-roccat*
  ROCKETPORT DRIVER
  P:    Comtrol Corp.
  W:    http://www.comtrol.com
@@@ -7183,7 -7151,7 +7191,7 @@@ S:      Maintaine
  F:    include/linux/mmc/dw_mmc.h
  F:    drivers/mmc/host/dw_mmc*
  
 -TIMEKEEPING, NTP
 +TIMEKEEPING, CLOCKSOURCE CORE, NTP
  M:    John Stultz <[email protected]>
  M:    Thomas Gleixner <[email protected]>
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
@@@ -7196,6 -7164,7 +7204,6 @@@ F:      include/uapi/linux/timex.
  F:    kernel/time/clocksource.c
  F:    kernel/time/time*.c
  F:    kernel/time/ntp.c
 -F:    drivers/clocksource
  
  TLG2300 VIDEO4LINUX-2 DRIVER
  M:    Huang Shijie <[email protected]>
@@@ -7275,7 -7244,6 +7283,7 @@@ W:      http://lksctp.sourceforge.ne
  S:    Maintained
  F:    Documentation/networking/sctp.txt
  F:    include/linux/sctp.h
 +F:    include/uapi/linux/sctp.h
  F:    include/net/sctp/
  F:    net/sctp/
  
@@@ -7406,6 -7374,7 +7414,6 @@@ F:      drivers/net/ethernet/sfc
  
  SGI GRU DRIVER
  M:    Dimitri Sivanich <[email protected]>
 -M:    Robin Holt <[email protected]>
  S:    Maintained
  F:    drivers/misc/sgi-gru/
  
@@@ -7425,8 -7394,7 +7433,8 @@@ S:      Maintained for 2.6
  F:    Documentation/sgi-visws.txt
  
  SGI XP/XPC/XPNET DRIVER
 -M:    Robin Holt <[email protected]>
 +M:    Cliff Whickman <[email protected]>
 +M:    Robin Holt <[email protected]>
  S:    Maintained
  F:    drivers/misc/sgi-xp/
  
@@@ -7715,17 -7683,6 +7723,17 @@@ F:    include/sound
  F:    include/uapi/sound/
  F:    sound/
  
 +SOUND - COMPRESSED AUDIO
 +M:    Vinod Koul <[email protected]>
 +L:    [email protected] (moderated for non-subscribers)
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
 +S:    Supported
 +F:    Documentation/sound/alsa/compress_offload.txt
 +F:    include/sound/compress_driver.h
 +F:    include/uapi/sound/compress_*
 +F:    sound/core/compress_offload.c
 +F:    sound/soc/soc-compress.c
 +
  SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
  M:    Liam Girdwood <[email protected]>
  M:    Mark Brown <[email protected]>
@@@ -7733,7 -7690,6 +7741,7 @@@ T:      git git://git.kernel.org/pub/scm/lin
  L:    [email protected] (moderated for non-subscribers)
  W:    http://alsa-project.org/main/index.php/ASoC
  S:    Supported
 +F:    Documentation/sound/alsa/soc/
  F:    sound/soc/
  F:    include/sound/soc*
  
@@@ -7942,11 -7898,11 +7950,11 @@@ S:   Maintaine
  F:    drivers/staging/nvec/
  
  STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON)
 -M:    Andres Salomon <[email protected]>
 -M:    Chris Ball <cjb@laptop.org>
 +M:    Jens Frederich <[email protected]>
 +M:    Daniel Drake <dsd@laptop.org>
  M:    Jon Nettleton <[email protected]>
  W:    http://wiki.laptop.org/go/DCON
 -S:    Odd Fixes
 +S:    Maintained
  F:    drivers/staging/olpc_dcon/
  
  STAGING - OZMO DEVICES USB OVER WIFI DRIVER
@@@ -8024,12 -7980,6 +8032,12 @@@ F:    arch/m68k/sun3*
  F:    arch/m68k/include/asm/sun3*
  F:    drivers/net/ethernet/i825xx/sun3*
  
 +SUNDANCE NETWORK DRIVER
 +M:    Denis Kirjanov <[email protected]>
 +L:    [email protected]
 +S:    Maintained
 +F:    drivers/net/ethernet/dlink/sundance.c
 +
  SUPERH
  M:    Paul Mundt <[email protected]>
  L:    [email protected]
@@@ -8727,11 -8677,6 +8735,11 @@@ T:    git git://git.alsa-project.org/alsa-
  S:    Maintained
  F:    sound/usb/midi.*
  
 +USB NETWORKING DRIVERS
 +L:    [email protected]
 +S:    Odd Fixes
 +F:    drivers/net/usb/
 +
  USB OHCI DRIVER
  M:    Alan Stern <[email protected]>
  L:    [email protected]
@@@ -8861,6 -8806,7 +8869,6 @@@ W:      http://www.linux-usb.or
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
  S:    Supported
  F:    Documentation/usb/
 -F:    drivers/net/usb/
  F:    drivers/usb/
  F:    include/linux/usb.h
  F:    include/linux/usb/
@@@ -9083,12 -9029,6 +9091,12 @@@ F:    drivers/staging/vme
  F:    drivers/vme/
  F:    include/linux/vme*
  
 +VMWARE HYPERVISOR INTERFACE
 +M:    Alok Kataria <[email protected]>
 +L:    [email protected]
 +S:    Supported
 +F:    arch/x86/kernel/cpu/vmware.c
 +
  VMWARE VMXNET3 ETHERNET DRIVER
  M:    Shreyas Bhatewara <[email protected]>
  M:    "VMware, Inc." <[email protected]>
@@@ -9310,9 -9250,9 +9318,9 @@@ F:      drivers/media/tuners/tuner-xc2028.
  
  XEN HYPERVISOR INTERFACE
  M:    Konrad Rzeszutek Wilk <[email protected]>
 -M:    Jeremy Fitzhardinge <[email protected]>
 -L:    [email protected] (moderated for non-subscribers)
 -L:    [email protected]
 +M:    Boris Ostrovsky <[email protected]>
 +M:    David Vrabel <[email protected]>
 +L:    [email protected] (moderated for non-subscribers)
  S:    Supported
  F:    arch/x86/xen/
  F:    drivers/*/xen-*front.c
@@@ -9323,35 -9263,35 +9331,35 @@@ F:   include/uapi/xen
  
  XEN HYPERVISOR ARM
  M:    Stefano Stabellini <[email protected]>
 -L:    [email protected]source.com (moderated for non-subscribers)
 +L:    [email protected]project.org (moderated for non-subscribers)
  S:    Supported
  F:    arch/arm/xen/
  F:    arch/arm/include/asm/xen/
  
  XEN HYPERVISOR ARM64
  M:    Stefano Stabellini <[email protected]>
 -L:    [email protected]source.com (moderated for non-subscribers)
 +L:    [email protected]project.org (moderated for non-subscribers)
  S:    Supported
  F:    arch/arm64/xen/
  F:    arch/arm64/include/asm/xen/
  
  XEN NETWORK BACKEND DRIVER
  M:    Ian Campbell <[email protected]>
 -L:    [email protected]source.com (moderated for non-subscribers)
 +L:    [email protected]project.org (moderated for non-subscribers)
  L:    [email protected]
  S:    Supported
  F:    drivers/net/xen-netback/*
  
  XEN PCI SUBSYSTEM
  M:    Konrad Rzeszutek Wilk <[email protected]>
 -L:    [email protected]source.com (moderated for non-subscribers)
 +L:    [email protected]project.org (moderated for non-subscribers)
  S:    Supported
  F:    arch/x86/pci/*xen*
  F:    drivers/pci/*xen*
  
  XEN SWIOTLB SUBSYSTEM
  M:    Konrad Rzeszutek Wilk <[email protected]>
 -L:    [email protected]source.com (moderated for non-subscribers)
 +L:    [email protected]project.org (moderated for non-subscribers)
  S:    Supported
  F:    arch/x86/xen/*swiotlb*
  F:    drivers/xen/*swiotlb*
diff --combined drivers/hid/hid-core.c
index b8f1c77f2f7708baf730b27b75d615f9adb45da2,2c778542e40ddf3bb71de1f967076cb38aac41a6..ae88a97f976e614fe776d451bd5e5abc5ec1e01e
@@@ -63,6 -63,8 +63,8 @@@ struct hid_report *hid_register_report(
        struct hid_report_enum *report_enum = device->report_enum + type;
        struct hid_report *report;
  
+       if (id >= HID_MAX_IDS)
+               return NULL;
        if (report_enum->report_id_hash[id])
                return report_enum->report_id_hash[id];
  
@@@ -404,8 -406,10 +406,10 @@@ static int hid_parser_global(struct hid
  
        case HID_GLOBAL_ITEM_TAG_REPORT_ID:
                parser->global.report_id = item_udata(item);
-               if (parser->global.report_id == 0) {
-                       hid_err(parser->device, "report_id 0 is invalid\n");
+               if (parser->global.report_id == 0 ||
+                   parser->global.report_id >= HID_MAX_IDS) {
+                       hid_err(parser->device, "report_id %u is invalid\n",
+                               parser->global.report_id);
                        return -1;
                }
                return 0;
@@@ -450,7 -454,7 +454,7 @@@ static int hid_parser_local(struct hid_
                        }
                        parser->local.delimiter_depth--;
                }
-               return 1;
+               return 0;
  
        case HID_LOCAL_ITEM_TAG_USAGE:
  
@@@ -575,7 -579,7 +579,7 @@@ static void hid_close_report(struct hid
        for (i = 0; i < HID_REPORT_TYPES; i++) {
                struct hid_report_enum *report_enum = device->report_enum + i;
  
-               for (j = 0; j < 256; j++) {
+               for (j = 0; j < HID_MAX_IDS; j++) {
                        struct hid_report *report = report_enum->report_id_hash[j];
                        if (report)
                                hid_free_report(report);
@@@ -677,12 -681,61 +681,61 @@@ static u8 *fetch_item(__u8 *start, __u
        return NULL;
  }
  
- static void hid_scan_usage(struct hid_device *hid, u32 usage)
+ static void hid_scan_input_usage(struct hid_parser *parser, u32 usage)
  {
+       struct hid_device *hid = parser->device;
        if (usage == HID_DG_CONTACTID)
                hid->group = HID_GROUP_MULTITOUCH;
  }
  
+ static void hid_scan_feature_usage(struct hid_parser *parser, u32 usage)
+ {
+       if (usage == 0xff0000c5 && parser->global.report_count == 256 &&
+           parser->global.report_size == 8)
+               parser->scan_flags |= HID_SCAN_FLAG_MT_WIN_8;
+ }
+ static void hid_scan_collection(struct hid_parser *parser, unsigned type)
+ {
+       struct hid_device *hid = parser->device;
+       if (((parser->global.usage_page << 16) == HID_UP_SENSOR) &&
+           type == HID_COLLECTION_PHYSICAL)
+               hid->group = HID_GROUP_SENSOR_HUB;
+ }
+ static int hid_scan_main(struct hid_parser *parser, struct hid_item *item)
+ {
+       __u32 data;
+       int i;
+       data = item_udata(item);
+       switch (item->tag) {
+       case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
+               hid_scan_collection(parser, data & 0xff);
+               break;
+       case HID_MAIN_ITEM_TAG_END_COLLECTION:
+               break;
+       case HID_MAIN_ITEM_TAG_INPUT:
+               for (i = 0; i < parser->local.usage_index; i++)
+                       hid_scan_input_usage(parser, parser->local.usage[i]);
+               break;
+       case HID_MAIN_ITEM_TAG_OUTPUT:
+               break;
+       case HID_MAIN_ITEM_TAG_FEATURE:
+               for (i = 0; i < parser->local.usage_index; i++)
+                       hid_scan_feature_usage(parser, parser->local.usage[i]);
+               break;
+       }
+       /* Reset the local parser environment */
+       memset(&parser->local, 0, sizeof(parser->local));
+       return 0;
+ }
  /*
   * Scan a report descriptor before the device is added to the bus.
   * Sets device groups and other properties that determine what driver
   */
  static int hid_scan_report(struct hid_device *hid)
  {
-       unsigned int page = 0, delim = 0;
+       struct hid_parser *parser;
+       struct hid_item item;
        __u8 *start = hid->dev_rdesc;
        __u8 *end = start + hid->dev_rsize;
-       unsigned int u, u_min = 0, u_max = 0;
-       struct hid_item item;
+       static int (*dispatch_type[])(struct hid_parser *parser,
+                                     struct hid_item *item) = {
+               hid_scan_main,
+               hid_parser_global,
+               hid_parser_local,
+               hid_parser_reserved
+       };
+       parser = vzalloc(sizeof(struct hid_parser));
+       if (!parser)
+               return -ENOMEM;
  
+       parser->device = hid;
        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;
-                       }
-               } else if (page == HID_UP_SENSOR &&
-                       item.type == HID_ITEM_TYPE_MAIN &&
-                       item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION &&
-                       (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL)
-                       hid->group = HID_GROUP_SENSOR_HUB;
-       }
  
+       /*
+        * The parsing is simpler than the one in hid_open_report() as we should
+        * be robust against hid errors. Those errors will be raised by
+        * hid_open_report() anyway.
+        */
+       while ((start = fetch_item(start, end, &item)) != NULL)
+               dispatch_type[item.type](parser, &item);
+       /*
+        * Handle special flags set during scanning.
+        */
+       if ((parser->scan_flags & HID_SCAN_FLAG_MT_WIN_8) &&
+           (hid->group == HID_GROUP_MULTITOUCH))
+               hid->group = HID_GROUP_MULTITOUCH_WIN_8;
+       vfree(parser);
        return 0;
  }
  
@@@ -1128,7 -1174,8 +1174,8 @@@ static void hid_output_field(const stru
  }
  
  /*
-  * Create a report.
+  * Create a report. 'data' has to be allocated using
+  * hid_alloc_report_buf() so that it has proper size.
   */
  
  void hid_output_report(struct hid_report *report, __u8 *data)
  }
  EXPORT_SYMBOL_GPL(hid_output_report);
  
+ /*
+  * Allocator for buffer that is going to be passed to hid_output_report()
+  */
+ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
+ {
+       /*
+        * 7 extra bytes are necessary to achieve proper functionality
+        * of implement() working on 8 byte chunks
+        */
+       int len = ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
+       return kmalloc(len, flags);
+ }
+ EXPORT_SYMBOL_GPL(hid_alloc_report_buf);
  /*
   * Set a field value. The report this field belongs to has to be
   * created and transferred to the device, to set this value in the
  
  int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
  {
-       unsigned size = field->report_size;
+       unsigned size;
+       if (!field)
+               return -1;
+       size = field->report_size;
  
        hid_dump_input(field->report->device, field->usage + offset, value);
  
@@@ -1597,6 -1665,7 +1665,7 @@@ static const struct hid_device_id hid_h
        { 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_GENIUS_GILA_GAMING_MOUSE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
        { 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_I405X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
        { 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_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
@@@ -1917,13 -1988,11 +1988,13 @@@ static ssize_t modalias_show(struct dev
  
        return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
  }
 +static DEVICE_ATTR_RO(modalias);
  
 -static struct device_attribute hid_dev_attrs[] = {
 -      __ATTR_RO(modalias),
 -      __ATTR_NULL,
 +static struct attribute *hid_dev_attrs[] = {
 +      &dev_attr_modalias.attr,
 +      NULL,
  };
 +ATTRIBUTE_GROUPS(hid_dev);
  
  static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
  {
  
  static struct bus_type hid_bus_type = {
        .name           = "hid",
 -      .dev_attrs      = hid_dev_attrs,
 +      .dev_groups     = hid_dev_groups,
        .match          = hid_bus_match,
        .probe          = hid_device_probe,
        .remove         = hid_device_remove,
index eed7f52084c5c16374141dd2a6583f127ab39aa5,071ee9e2fd9fea5c4d40165e60e6f1b71e5bd7a4..1948208fe0380ad2b091038d369d6502de5d2a11
@@@ -59,7 -59,7 +59,7 @@@ static ssize_t arvo_sysfs_set_mode_key(
        unsigned long state;
        int retval;
  
-       retval = strict_strtoul(buf, 10, &state);
+       retval = kstrtoul(buf, 10, &state);
        if (retval)
                return retval;
  
@@@ -75,8 -75,6 +75,8 @@@
  
        return size;
  }
 +static DEVICE_ATTR(mode_key, 0660,
 +                 arvo_sysfs_show_mode_key, arvo_sysfs_set_mode_key);
  
  static ssize_t arvo_sysfs_show_key_mask(struct device *dev,
                struct device_attribute *attr, char *buf)
@@@ -109,7 -107,7 +109,7 @@@ static ssize_t arvo_sysfs_set_key_mask(
        unsigned long key_mask;
        int retval;
  
-       retval = strict_strtoul(buf, 10, &key_mask);
+       retval = kstrtoul(buf, 10, &key_mask);
        if (retval)
                return retval;
  
  
        return size;
  }
 +static DEVICE_ATTR(key_mask, 0660,
 +                 arvo_sysfs_show_key_mask, arvo_sysfs_set_key_mask);
  
  /* retval is 1-5 on success, < 0 on error */
  static int arvo_get_actual_profile(struct usb_device *usb_dev)
@@@ -163,7 -159,7 +163,7 @@@ static ssize_t arvo_sysfs_set_actual_pr
        unsigned long profile;
        int retval;
  
-       retval = strict_strtoul(buf, 10, &profile);
+       retval = kstrtoul(buf, 10, &profile);
        if (retval)
                return retval;
  
        mutex_unlock(&arvo->arvo_lock);
        return retval;
  }
 +static DEVICE_ATTR(actual_profile, 0660,
 +                 arvo_sysfs_show_actual_profile,
 +                 arvo_sysfs_set_actual_profile);
  
  static ssize_t arvo_sysfs_write(struct file *fp,
                struct kobject *kobj, void const *buf,
@@@ -237,8 -230,6 +237,8 @@@ static ssize_t arvo_sysfs_write_button(
        return arvo_sysfs_write(fp, kobj, buf, off, count,
                        sizeof(struct arvo_button), ARVO_COMMAND_BUTTON);
  }
 +static BIN_ATTR(button, 0220, NULL, arvo_sysfs_write_button,
 +              sizeof(struct arvo_button));
  
  static ssize_t arvo_sysfs_read_info(struct file *fp,
                struct kobject *kobj, struct bin_attribute *attr, char *buf,
        return arvo_sysfs_read(fp, kobj, buf, off, count,
                        sizeof(struct arvo_info), ARVO_COMMAND_INFO);
  }
 +static BIN_ATTR(info, 0440, arvo_sysfs_read_info, NULL,
 +              sizeof(struct arvo_info));
 +
 +static struct attribute *arvo_attrs[] = {
 +      &dev_attr_mode_key.attr,
 +      &dev_attr_key_mask.attr,
 +      &dev_attr_actual_profile.attr,
 +      NULL,
 +};
  
 +static struct bin_attribute *arvo_bin_attributes[] = {
 +      &bin_attr_button,
 +      &bin_attr_info,
 +      NULL,
 +};
  
 -static struct device_attribute arvo_attributes[] = {
 -      __ATTR(mode_key, 0660,
 -                      arvo_sysfs_show_mode_key, arvo_sysfs_set_mode_key),
 -      __ATTR(key_mask, 0660,
 -                      arvo_sysfs_show_key_mask, arvo_sysfs_set_key_mask),
 -      __ATTR(actual_profile, 0660,
 -                      arvo_sysfs_show_actual_profile,
 -                      arvo_sysfs_set_actual_profile),
 -      __ATTR_NULL
 +static const struct attribute_group arvo_group = {
 +      .attrs = arvo_attrs,
 +      .bin_attrs = arvo_bin_attributes,
  };
  
 -static struct bin_attribute arvo_bin_attributes[] = {
 -      {
 -              .attr = { .name = "button", .mode = 0220 },
 -              .size = sizeof(struct arvo_button),
 -              .write = arvo_sysfs_write_button
 -      },
 -      {
 -              .attr = { .name = "info", .mode = 0440 },
 -              .size = sizeof(struct arvo_info),
 -              .read = arvo_sysfs_read_info
 -      },
 -      __ATTR_NULL
 +static const struct attribute_group *arvo_groups[] = {
 +      &arvo_group,
 +      NULL,
  };
  
  static int arvo_init_arvo_device_struct(struct usb_device *usb_dev,
@@@ -438,7 -430,8 +438,7 @@@ static int __init arvo_init(void
        arvo_class = class_create(THIS_MODULE, "arvo");
        if (IS_ERR(arvo_class))
                return PTR_ERR(arvo_class);
 -      arvo_class->dev_attrs = arvo_attributes;
 -      arvo_class->dev_bin_attrs = arvo_bin_attributes;
 +      arvo_class->dev_groups = arvo_groups;
  
        retval = hid_register_driver(&arvo_driver);
        if (retval)
index b7a4e10e112e8240dcb82815ca4a928c71e6d7f6,5dd0ea4eb4f71ec6cfc210b5a71a8b648a709461..bc62ed91e451cb51b70542cf39808aa0b58e68c6
@@@ -82,7 -82,7 +82,7 @@@ static ssize_t isku_sysfs_set_actual_pr
        isku = hid_get_drvdata(dev_get_drvdata(dev));
        usb_dev = interface_to_usbdev(to_usb_interface(dev));
  
-       retval = strict_strtoul(buf, 10, &profile);
+       retval = kstrtoul(buf, 10, &profile);
        if (retval)
                return retval;
  
  
        return size;
  }
 +static DEVICE_ATTR(actual_profile, 0660, isku_sysfs_show_actual_profile,
 +                 isku_sysfs_set_actual_profile);
  
 -static struct device_attribute isku_attributes[] = {
 -      __ATTR(actual_profile, 0660,
 -                      isku_sysfs_show_actual_profile,
 -                      isku_sysfs_set_actual_profile),
 -      __ATTR_NULL
 +static struct attribute *isku_attrs[] = {
 +      &dev_attr_actual_profile.attr,
 +      NULL,
  };
  
  static ssize_t isku_sysfs_read(struct file *fp, struct kobject *kobj,
@@@ -184,8 -184,7 +184,8 @@@ ISKU_SYSFS_R(thingy, THINGY) 
  ISKU_SYSFS_W(thingy, THINGY)
  
  #define ISKU_BIN_ATTR_RW(thingy, THINGY) \
 -{ \
 +ISKU_SYSFS_RW(thingy, THINGY); \
 +static struct bin_attribute bin_attr_##thingy = { \
        .attr = { .name = #thingy, .mode = 0660 }, \
        .size = ISKU_SIZE_ ## THINGY, \
        .read = isku_sysfs_read_ ## thingy, \
  }
  
  #define ISKU_BIN_ATTR_R(thingy, THINGY) \
 -{ \
 +ISKU_SYSFS_R(thingy, THINGY); \
 +static struct bin_attribute bin_attr_##thingy = { \
        .attr = { .name = #thingy, .mode = 0440 }, \
        .size = ISKU_SIZE_ ## THINGY, \
        .read = isku_sysfs_read_ ## thingy, \
  }
  
  #define ISKU_BIN_ATTR_W(thingy, THINGY) \
 -{ \
 +ISKU_SYSFS_W(thingy, THINGY); \
 +static struct bin_attribute bin_attr_##thingy = { \
        .attr = { .name = #thingy, .mode = 0220 }, \
        .size = ISKU_SIZE_ ## THINGY, \
        .write = isku_sysfs_write_ ## thingy \
  }
  
 -ISKU_SYSFS_RW(macro, MACRO)
 -ISKU_SYSFS_RW(keys_function, KEYS_FUNCTION)
 -ISKU_SYSFS_RW(keys_easyzone, KEYS_EASYZONE)
 -ISKU_SYSFS_RW(keys_media, KEYS_MEDIA)
 -ISKU_SYSFS_RW(keys_thumbster, KEYS_THUMBSTER)
 -ISKU_SYSFS_RW(keys_macro, KEYS_MACRO)
 -ISKU_SYSFS_RW(keys_capslock, KEYS_CAPSLOCK)
 -ISKU_SYSFS_RW(light, LIGHT)
 -ISKU_SYSFS_RW(key_mask, KEY_MASK)
 -ISKU_SYSFS_RW(last_set, LAST_SET)
 -ISKU_SYSFS_W(talk, TALK)
 -ISKU_SYSFS_W(talkfx, TALKFX)
 -ISKU_SYSFS_R(info, INFO)
 -ISKU_SYSFS_W(control, CONTROL)
 -ISKU_SYSFS_W(reset, RESET)
 -
 -static struct bin_attribute isku_bin_attributes[] = {
 -      ISKU_BIN_ATTR_RW(macro, MACRO),
 -      ISKU_BIN_ATTR_RW(keys_function, KEYS_FUNCTION),
 -      ISKU_BIN_ATTR_RW(keys_easyzone, KEYS_EASYZONE),
 -      ISKU_BIN_ATTR_RW(keys_media, KEYS_MEDIA),
 -      ISKU_BIN_ATTR_RW(keys_thumbster, KEYS_THUMBSTER),
 -      ISKU_BIN_ATTR_RW(keys_macro, KEYS_MACRO),
 -      ISKU_BIN_ATTR_RW(keys_capslock, KEYS_CAPSLOCK),
 -      ISKU_BIN_ATTR_RW(light, LIGHT),
 -      ISKU_BIN_ATTR_RW(key_mask, KEY_MASK),
 -      ISKU_BIN_ATTR_RW(last_set, LAST_SET),
 -      ISKU_BIN_ATTR_W(talk, TALK),
 -      ISKU_BIN_ATTR_W(talkfx, TALKFX),
 -      ISKU_BIN_ATTR_R(info, INFO),
 -      ISKU_BIN_ATTR_W(control, CONTROL),
 -      ISKU_BIN_ATTR_W(reset, RESET),
 -      __ATTR_NULL
 +ISKU_BIN_ATTR_RW(macro, MACRO);
 +ISKU_BIN_ATTR_RW(keys_function, KEYS_FUNCTION);
 +ISKU_BIN_ATTR_RW(keys_easyzone, KEYS_EASYZONE);
 +ISKU_BIN_ATTR_RW(keys_media, KEYS_MEDIA);
 +ISKU_BIN_ATTR_RW(keys_thumbster, KEYS_THUMBSTER);
 +ISKU_BIN_ATTR_RW(keys_macro, KEYS_MACRO);
 +ISKU_BIN_ATTR_RW(keys_capslock, KEYS_CAPSLOCK);
 +ISKU_BIN_ATTR_RW(light, LIGHT);
 +ISKU_BIN_ATTR_RW(key_mask, KEY_MASK);
 +ISKU_BIN_ATTR_RW(last_set, LAST_SET);
 +ISKU_BIN_ATTR_W(talk, TALK);
 +ISKU_BIN_ATTR_W(talkfx, TALKFX);
 +ISKU_BIN_ATTR_W(control, CONTROL);
 +ISKU_BIN_ATTR_W(reset, RESET);
 +ISKU_BIN_ATTR_R(info, INFO);
 +
 +static struct bin_attribute *isku_bin_attributes[] = {
 +      &bin_attr_macro,
 +      &bin_attr_keys_function,
 +      &bin_attr_keys_easyzone,
 +      &bin_attr_keys_media,
 +      &bin_attr_keys_thumbster,
 +      &bin_attr_keys_macro,
 +      &bin_attr_keys_capslock,
 +      &bin_attr_light,
 +      &bin_attr_key_mask,
 +      &bin_attr_last_set,
 +      &bin_attr_talk,
 +      &bin_attr_talkfx,
 +      &bin_attr_control,
 +      &bin_attr_reset,
 +      &bin_attr_info,
 +      NULL,
 +};
 +
 +static const struct attribute_group isku_group = {
 +      .attrs = isku_attrs,
 +      .bin_attrs = isku_bin_attributes,
 +};
 +
 +static const struct attribute_group *isku_groups[] = {
 +      &isku_group,
 +      NULL,
  };
  
  static int isku_init_isku_device_struct(struct usb_device *usb_dev,
@@@ -440,7 -427,8 +440,7 @@@ static int __init isku_init(void
        isku_class = class_create(THIS_MODULE, "isku");
        if (IS_ERR(isku_class))
                return PTR_ERR(isku_class);
 -      isku_class->dev_attrs = isku_attributes;
 -      isku_class->dev_bin_attrs = isku_bin_attributes;
 +      isku_class->dev_groups = isku_groups;
  
        retval = hid_register_driver(&isku_driver);
        if (retval)
index 6e614a85f1758618f13f7dd59a76f6871bb93805,00ab287f73849b94d85c3d4bf603733273396fc6..602c188e9d86cafedde93366bf3d114e69c3e552
@@@ -324,8 -324,6 +324,8 @@@ static ssize_t kone_sysfs_write_setting
  
        return sizeof(struct kone_settings);
  }
 +static BIN_ATTR(settings, 0660, kone_sysfs_read_settings,
 +              kone_sysfs_write_settings, sizeof(struct kone_settings));
  
  static ssize_t kone_sysfs_read_profilex(struct file *fp,
                struct kobject *kobj, struct bin_attribute *attr,
@@@ -380,19 -378,6 +380,19 @@@ static ssize_t kone_sysfs_write_profile
  
        return sizeof(struct kone_profile);
  }
 +#define PROFILE_ATTR(number)                                  \
 +static struct bin_attribute bin_attr_profile##number = {      \
 +      .attr = { .name = "profile##number", .mode = 0660 },    \
 +      .size = sizeof(struct kone_profile),                    \
 +      .read = kone_sysfs_read_profilex,                       \
 +      .write = kone_sysfs_write_profilex,                     \
 +      .private = &profile_numbers[number-1],                  \
 +};
 +PROFILE_ATTR(1);
 +PROFILE_ATTR(2);
 +PROFILE_ATTR(3);
 +PROFILE_ATTR(4);
 +PROFILE_ATTR(5);
  
  static ssize_t kone_sysfs_show_actual_profile(struct device *dev,
                struct device_attribute *attr, char *buf)
                        hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
        return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_profile);
  }
 +static DEVICE_ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL);
  
  static ssize_t kone_sysfs_show_actual_dpi(struct device *dev,
                struct device_attribute *attr, char *buf)
                        hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
        return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_dpi);
  }
 +static DEVICE_ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL);
  
  /* weight is read each time, since we don't get informed when it's changed */
  static ssize_t kone_sysfs_show_weight(struct device *dev,
                return retval;
        return snprintf(buf, PAGE_SIZE, "%d\n", weight);
  }
 +static DEVICE_ATTR(weight, 0440, kone_sysfs_show_weight, NULL);
  
  static ssize_t kone_sysfs_show_firmware_version(struct device *dev,
                struct device_attribute *attr, char *buf)
                        hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
        return snprintf(buf, PAGE_SIZE, "%d\n", kone->firmware_version);
  }
 +static DEVICE_ATTR(firmware_version, 0440, kone_sysfs_show_firmware_version,
 +                 NULL);
  
  static ssize_t kone_sysfs_show_tcu(struct device *dev,
                struct device_attribute *attr, char *buf)
@@@ -476,7 -456,7 +476,7 @@@ static ssize_t kone_sysfs_set_tcu(struc
        kone = hid_get_drvdata(dev_get_drvdata(dev));
        usb_dev = interface_to_usbdev(to_usb_interface(dev));
  
-       retval = strict_strtoul(buf, 10, &state);
+       retval = kstrtoul(buf, 10, &state);
        if (retval)
                return retval;
  
@@@ -544,7 -524,6 +544,7 @@@ exit_unlock
        mutex_unlock(&kone->kone_lock);
        return retval;
  }
 +static DEVICE_ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu);
  
  static ssize_t kone_sysfs_show_startup_profile(struct device *dev,
                struct device_attribute *attr, char *buf)
@@@ -566,7 -545,7 +566,7 @@@ static ssize_t kone_sysfs_set_startup_p
        kone = hid_get_drvdata(dev_get_drvdata(dev));
        usb_dev = interface_to_usbdev(to_usb_interface(dev));
  
-       retval = strict_strtoul(buf, 10, &new_startup_profile);
+       retval = kstrtoul(buf, 10, &new_startup_profile);
        if (retval)
                return retval;
  
        mutex_unlock(&kone->kone_lock);
        return size;
  }
 +static DEVICE_ATTR(startup_profile, 0660, kone_sysfs_show_startup_profile,
 +                 kone_sysfs_set_startup_profile);
  
 -static struct device_attribute kone_attributes[] = {
 +static struct attribute *kone_attrs[] = {
        /*
         * Read actual dpi settings.
         * Returns raw value for further processing. Refer to enum
         * kone_polling_rates to get real value.
         */
 -      __ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL),
 -      __ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL),
 +      &dev_attr_actual_dpi.attr,
 +      &dev_attr_actual_profile.attr,
  
        /*
         * The mouse can be equipped with one of four supplied weights from 5
         * by software. Refer to enum kone_weights to get corresponding real
         * weight.
         */
 -      __ATTR(weight, 0440, kone_sysfs_show_weight, NULL),
 +      &dev_attr_weight.attr,
  
        /*
         * Prints firmware version stored in mouse as integer.
         * to get the real version number the decimal point has to be shifted 2
         * positions to the left. E.g. a value of 138 means 1.38.
         */
 -      __ATTR(firmware_version, 0440,
 -                      kone_sysfs_show_firmware_version, NULL),
 +      &dev_attr_firmware_version.attr,
  
        /*
         * Prints state of Tracking Control Unit as number where 0 = off and
         * 1 = on. Writing 0 deactivates tcu and writing 1 calibrates and
         * activates the tcu
         */
 -      __ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu),
 +      &dev_attr_tcu.attr,
  
        /* Prints and takes the number of the profile the mouse starts with */
 -      __ATTR(startup_profile, 0660,
 -                      kone_sysfs_show_startup_profile,
 -                      kone_sysfs_set_startup_profile),
 -      __ATTR_NULL
 +      &dev_attr_startup_profile.attr,
 +      NULL,
 +};
 +
 +static struct bin_attribute *kone_bin_attributes[] = {
 +      &bin_attr_settings,
 +      &bin_attr_profile1,
 +      &bin_attr_profile2,
 +      &bin_attr_profile3,
 +      &bin_attr_profile4,
 +      &bin_attr_profile5,
 +      NULL,
 +};
 +
 +static const struct attribute_group kone_group = {
 +      .attrs = kone_attrs,
 +      .bin_attrs = kone_bin_attributes,
  };
  
 -static struct bin_attribute kone_bin_attributes[] = {
 -      {
 -              .attr = { .name = "settings", .mode = 0660 },
 -              .size = sizeof(struct kone_settings),
 -              .read = kone_sysfs_read_settings,
 -              .write = kone_sysfs_write_settings
 -      },
 -      {
 -              .attr = { .name = "profile1", .mode = 0660 },
 -              .size = sizeof(struct kone_profile),
 -              .read = kone_sysfs_read_profilex,
 -              .write = kone_sysfs_write_profilex,
 -              .private = &profile_numbers[0]
 -      },
 -      {
 -              .attr = { .name = "profile2", .mode = 0660 },
 -              .size = sizeof(struct kone_profile),
 -              .read = kone_sysfs_read_profilex,
 -              .write = kone_sysfs_write_profilex,
 -              .private = &profile_numbers[1]
 -      },
 -      {
 -              .attr = { .name = "profile3", .mode = 0660 },
 -              .size = sizeof(struct kone_profile),
 -              .read = kone_sysfs_read_profilex,
 -              .write = kone_sysfs_write_profilex,
 -              .private = &profile_numbers[2]
 -      },
 -      {
 -              .attr = { .name = "profile4", .mode = 0660 },
 -              .size = sizeof(struct kone_profile),
 -              .read = kone_sysfs_read_profilex,
 -              .write = kone_sysfs_write_profilex,
 -              .private = &profile_numbers[3]
 -      },
 -      {
 -              .attr = { .name = "profile5", .mode = 0660 },
 -              .size = sizeof(struct kone_profile),
 -              .read = kone_sysfs_read_profilex,
 -              .write = kone_sysfs_write_profilex,
 -              .private = &profile_numbers[4]
 -      },
 -      __ATTR_NULL
 +static const struct attribute_group *kone_groups[] = {
 +      &kone_group,
 +      NULL,
  };
  
  static int kone_init_kone_device_struct(struct usb_device *usb_dev,
@@@ -886,7 -891,8 +886,7 @@@ static int __init kone_init(void
        kone_class = class_create(THIS_MODULE, "kone");
        if (IS_ERR(kone_class))
                return PTR_ERR(kone_class);
 -      kone_class->dev_attrs = kone_attributes;
 -      kone_class->dev_bin_attrs = kone_bin_attributes;
 +      kone_class->dev_groups = kone_groups;
  
        retval = hid_register_driver(&kone_driver);
        if (retval)
index db4d8b6a25428aed58220eace3c17cfe8380f30c,26b9663ddf4746ce1590733745d77f512c46d8c0..5ddf605b6b890b15c2b9f94783072d951908e5db
@@@ -156,8 -156,7 +156,8 @@@ KONEPLUS_SYSFS_W(thingy, THINGY) 
  KONEPLUS_SYSFS_R(thingy, THINGY)
  
  #define KONEPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \
 -{ \
 +KONEPLUS_SYSFS_RW(thingy, THINGY); \
 +static struct bin_attribute bin_attr_##thingy = { \
        .attr = { .name = #thingy, .mode = 0660 }, \
        .size = KONEPLUS_SIZE_ ## THINGY, \
        .read = koneplus_sysfs_read_ ## thingy, \
  }
  
  #define KONEPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \
 -{ \
 +KONEPLUS_SYSFS_R(thingy, THINGY); \
 +static struct bin_attribute bin_attr_##thingy = { \
        .attr = { .name = #thingy, .mode = 0440 }, \
        .size = KONEPLUS_SIZE_ ## THINGY, \
        .read = koneplus_sysfs_read_ ## thingy, \
  }
  
  #define KONEPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
 -{ \
 +KONEPLUS_SYSFS_W(thingy, THINGY); \
 +static struct bin_attribute bin_attr_##thingy = { \
        .attr = { .name = #thingy, .mode = 0220 }, \
        .size = KONEPLUS_SIZE_ ## THINGY, \
        .write = koneplus_sysfs_write_ ## thingy \
  }
 -
 -KONEPLUS_SYSFS_W(control, CONTROL)
 -KONEPLUS_SYSFS_RW(info, INFO)
 -KONEPLUS_SYSFS_W(talk, TALK)
 -KONEPLUS_SYSFS_W(macro, MACRO)
 -KONEPLUS_SYSFS_RW(sensor, SENSOR)
 -KONEPLUS_SYSFS_RW(tcu, TCU)
 -KONEPLUS_SYSFS_R(tcu_image, TCU_IMAGE)
 -KONEPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
 -KONEPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
 +KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL);
 +KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK);
 +KONEPLUS_BIN_ATTRIBUTE_W(macro, MACRO);
 +KONEPLUS_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE);
 +KONEPLUS_BIN_ATTRIBUTE_RW(info, INFO);
 +KONEPLUS_BIN_ATTRIBUTE_RW(sensor, SENSOR);
 +KONEPLUS_BIN_ATTRIBUTE_RW(tcu, TCU);
 +KONEPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
 +KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
  
  static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
                struct kobject *kobj, struct bin_attribute *attr, char *buf,
@@@ -227,25 -225,6 +227,25 @@@ static ssize_t koneplus_sysfs_read_prof
                        KONEPLUS_COMMAND_PROFILE_BUTTONS);
  }
  
 +#define PROFILE_ATTR(number)                                          \
 +static struct bin_attribute bin_attr_profile##number##_settings = {   \
 +      .attr = { .name = "profile##number##_settings", .mode = 0440 }, \
 +      .size = KONEPLUS_SIZE_PROFILE_SETTINGS,                         \
 +      .read = koneplus_sysfs_read_profilex_settings,                  \
 +      .private = &profile_numbers[number-1],                          \
 +};                                                                    \
 +static struct bin_attribute bin_attr_profile##number##_buttons = {    \
 +      .attr = { .name = "profile##number##_buttons", .mode = 0440 },  \
 +      .size = KONEPLUS_SIZE_PROFILE_BUTTONS,                          \
 +      .read = koneplus_sysfs_read_profilex_buttons,                   \
 +      .private = &profile_numbers[number-1],                          \
 +};
 +PROFILE_ATTR(1);
 +PROFILE_ATTR(2);
 +PROFILE_ATTR(3);
 +PROFILE_ATTR(4);
 +PROFILE_ATTR(5);
 +
  static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
                struct device_attribute *attr, char *buf)
  {
@@@ -267,7 -246,7 +267,7 @@@ static ssize_t koneplus_sysfs_set_actua
        koneplus = hid_get_drvdata(dev_get_drvdata(dev));
        usb_dev = interface_to_usbdev(to_usb_interface(dev));
  
-       retval = strict_strtoul(buf, 10, &profile);
+       retval = kstrtoul(buf, 10, &profile);
        if (retval)
                return retval;
  
  
        return size;
  }
 +static DEVICE_ATTR(actual_profile, 0660,
 +                 koneplus_sysfs_show_actual_profile,
 +                 koneplus_sysfs_set_actual_profile);
 +static DEVICE_ATTR(startup_profile, 0660,
 +                 koneplus_sysfs_show_actual_profile,
 +                 koneplus_sysfs_set_actual_profile);
  
  static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
                struct device_attribute *attr, char *buf)
  
        return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
  }
 +static DEVICE_ATTR(firmware_version, 0440,
 +                 koneplus_sysfs_show_firmware_version, NULL);
 +
 +static struct attribute *koneplus_attrs[] = {
 +      &dev_attr_actual_profile.attr,
 +      &dev_attr_startup_profile.attr,
 +      &dev_attr_firmware_version.attr,
 +      NULL,
 +};
 +
 +static struct bin_attribute *koneplus_bin_attributes[] = {
 +      &bin_attr_control,
 +      &bin_attr_talk,
 +      &bin_attr_macro,
 +      &bin_attr_tcu_image,
 +      &bin_attr_info,
 +      &bin_attr_sensor,
 +      &bin_attr_tcu,
 +      &bin_attr_profile_settings,
 +      &bin_attr_profile_buttons,
 +      &bin_attr_profile1_settings,
 +      &bin_attr_profile2_settings,
 +      &bin_attr_profile3_settings,
 +      &bin_attr_profile4_settings,
 +      &bin_attr_profile5_settings,
 +      &bin_attr_profile1_buttons,
 +      &bin_attr_profile2_buttons,
 +      &bin_attr_profile3_buttons,
 +      &bin_attr_profile4_buttons,
 +      &bin_attr_profile5_buttons,
 +      NULL,
 +};
  
 -static struct device_attribute koneplus_attributes[] = {
 -      __ATTR(actual_profile, 0660,
 -                      koneplus_sysfs_show_actual_profile,
 -                      koneplus_sysfs_set_actual_profile),
 -      __ATTR(startup_profile, 0660,
 -                      koneplus_sysfs_show_actual_profile,
 -                      koneplus_sysfs_set_actual_profile),
 -      __ATTR(firmware_version, 0440,
 -                      koneplus_sysfs_show_firmware_version, NULL),
 -      __ATTR_NULL
 +static const struct attribute_group koneplus_group = {
 +      .attrs = koneplus_attrs,
 +      .bin_attrs = koneplus_bin_attributes,
  };
  
 -static struct bin_attribute koneplus_bin_attributes[] = {
 -      KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL),
 -      KONEPLUS_BIN_ATTRIBUTE_RW(info, INFO),
 -      KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK),
 -      KONEPLUS_BIN_ATTRIBUTE_W(macro, MACRO),
 -      KONEPLUS_BIN_ATTRIBUTE_RW(sensor, SENSOR),
 -      KONEPLUS_BIN_ATTRIBUTE_RW(tcu, TCU),
 -      KONEPLUS_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE),
 -      KONEPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
 -      KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
 -      {
 -              .attr = { .name = "profile1_settings", .mode = 0440 },
 -              .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
 -              .read = koneplus_sysfs_read_profilex_settings,
 -              .private = &profile_numbers[0]
 -      },
 -      {
 -              .attr = { .name = "profile2_settings", .mode = 0440 },
 -              .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
 -              .read = koneplus_sysfs_read_profilex_settings,
 -              .private = &profile_numbers[1]
 -      },
 -      {
 -              .attr = { .name = "profile3_settings", .mode = 0440 },
 -              .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
 -              .read = koneplus_sysfs_read_profilex_settings,
 -              .private = &profile_numbers[2]
 -      },
 -      {
 -              .attr = { .name = "profile4_settings", .mode = 0440 },
 -              .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
 -              .read = koneplus_sysfs_read_profilex_settings,
 -              .private = &profile_numbers[3]
 -      },
 -      {
 -              .attr = { .name = "profile5_settings", .mode = 0440 },
 -              .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
 -              .read = koneplus_sysfs_read_profilex_settings,
 -              .private = &profile_numbers[4]
 -      },
 -      {
 -              .attr = { .name = "profile1_buttons", .mode = 0440 },
 -              .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
 -              .read = koneplus_sysfs_read_profilex_buttons,
 -              .private = &profile_numbers[0]
 -      },
 -      {
 -              .attr = { .name = "profile2_buttons", .mode = 0440 },
 -              .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
 -              .read = koneplus_sysfs_read_profilex_buttons,
 -              .private = &profile_numbers[1]
 -      },
 -      {
 -              .attr = { .name = "profile3_buttons", .mode = 0440 },
 -              .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
 -              .read = koneplus_sysfs_read_profilex_buttons,
 -              .private = &profile_numbers[2]
 -      },
 -      {
 -              .attr = { .name = "profile4_buttons", .mode = 0440 },
 -              .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
 -              .read = koneplus_sysfs_read_profilex_buttons,
 -              .private = &profile_numbers[3]
 -      },
 -      {
 -              .attr = { .name = "profile5_buttons", .mode = 0440 },
 -              .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
 -              .read = koneplus_sysfs_read_profilex_buttons,
 -              .private = &profile_numbers[4]
 -      },
 -      __ATTR_NULL
 +static const struct attribute_group *koneplus_groups[] = {
 +      &koneplus_group,
 +      NULL,
  };
  
  static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
@@@ -556,7 -572,8 +556,7 @@@ static int __init koneplus_init(void
        koneplus_class = class_create(THIS_MODULE, "koneplus");
        if (IS_ERR(koneplus_class))
                return PTR_ERR(koneplus_class);
 -      koneplus_class->dev_attrs = koneplus_attributes;
 -      koneplus_class->dev_bin_attrs = koneplus_bin_attributes;
 +      koneplus_class->dev_groups = koneplus_groups;
  
        retval = hid_register_driver(&koneplus_driver);
        if (retval)
index fa02b1f44979922462df8aeaedaad799c6d2d973,5850959d48f573f64ff7b4e7d59732df512e82fe..99a605ebb665b6eb952f99922bc7103a0536819f
@@@ -94,8 -94,7 +94,8 @@@ KONEPURE_SYSFS_W(thingy, THINGY) 
  KONEPURE_SYSFS_R(thingy, THINGY)
  
  #define KONEPURE_BIN_ATTRIBUTE_RW(thingy, THINGY) \
 -{ \
 +KONEPURE_SYSFS_RW(thingy, THINGY); \
 +static struct bin_attribute bin_attr_##thingy = { \
        .attr = { .name = #thingy, .mode = 0660 }, \
        .size = KONEPURE_SIZE_ ## THINGY, \
        .read = konepure_sysfs_read_ ## thingy, \
  }
  
  #define KONEPURE_BIN_ATTRIBUTE_R(thingy, THINGY) \
 -{ \
 +KONEPURE_SYSFS_R(thingy, THINGY); \
 +static struct bin_attribute bin_attr_##thingy = { \
        .attr = { .name = #thingy, .mode = 0440 }, \
        .size = KONEPURE_SIZE_ ## THINGY, \
        .read = konepure_sysfs_read_ ## thingy, \
  }
  
  #define KONEPURE_BIN_ATTRIBUTE_W(thingy, THINGY) \
 -{ \
 +KONEPURE_SYSFS_W(thingy, THINGY); \
 +static struct bin_attribute bin_attr_##thingy = { \
        .attr = { .name = #thingy, .mode = 0220 }, \
        .size = KONEPURE_SIZE_ ## THINGY, \
        .write = konepure_sysfs_write_ ## thingy \
  }
  
 -KONEPURE_SYSFS_RW(actual_profile, ACTUAL_PROFILE)
 -KONEPURE_SYSFS_W(control, CONTROL)
 -KONEPURE_SYSFS_RW(info, INFO)
 -KONEPURE_SYSFS_W(talk, TALK)
 -KONEPURE_SYSFS_W(macro, MACRO)
 -KONEPURE_SYSFS_RW(sensor, SENSOR)
 -KONEPURE_SYSFS_RW(tcu, TCU)
 -KONEPURE_SYSFS_R(tcu_image, TCU_IMAGE)
 -KONEPURE_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
 -KONEPURE_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
 -
 -static struct bin_attribute konepure_bin_attributes[] = {
 -      KONEPURE_BIN_ATTRIBUTE_RW(actual_profile, ACTUAL_PROFILE),
 -      KONEPURE_BIN_ATTRIBUTE_W(control, CONTROL),
 -      KONEPURE_BIN_ATTRIBUTE_RW(info, INFO),
 -      KONEPURE_BIN_ATTRIBUTE_W(talk, TALK),
 -      KONEPURE_BIN_ATTRIBUTE_W(macro, MACRO),
 -      KONEPURE_BIN_ATTRIBUTE_RW(sensor, SENSOR),
 -      KONEPURE_BIN_ATTRIBUTE_RW(tcu, TCU),
 -      KONEPURE_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE),
 -      KONEPURE_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
 -      KONEPURE_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
 -      __ATTR_NULL
 +KONEPURE_BIN_ATTRIBUTE_RW(actual_profile, ACTUAL_PROFILE);
 +KONEPURE_BIN_ATTRIBUTE_RW(info, INFO);
 +KONEPURE_BIN_ATTRIBUTE_RW(sensor, SENSOR);
 +KONEPURE_BIN_ATTRIBUTE_RW(tcu, TCU);
 +KONEPURE_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
 +KONEPURE_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
 +KONEPURE_BIN_ATTRIBUTE_W(control, CONTROL);
 +KONEPURE_BIN_ATTRIBUTE_W(talk, TALK);
 +KONEPURE_BIN_ATTRIBUTE_W(macro, MACRO);
 +KONEPURE_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE);
 +
 +static struct bin_attribute *konepure_bin_attributes[] = {
 +      &bin_attr_actual_profile,
 +      &bin_attr_info,
 +      &bin_attr_sensor,
 +      &bin_attr_tcu,
 +      &bin_attr_profile_settings,
 +      &bin_attr_profile_buttons,
 +      &bin_attr_control,
 +      &bin_attr_talk,
 +      &bin_attr_macro,
 +      &bin_attr_tcu_image,
 +      NULL,
 +};
 +
 +static const struct attribute_group konepure_group = {
 +      .bin_attrs = konepure_bin_attributes,
 +};
 +
 +static const struct attribute_group *konepure_groups[] = {
 +      &konepure_group,
 +      NULL,
  };
  
 +
  static int konepure_init_konepure_device_struct(struct usb_device *usb_dev,
                struct konepure_device *konepure)
  {
@@@ -275,6 -262,7 +275,7 @@@ static int konepure_raw_event(struct hi
  
  static const struct hid_device_id konepure_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL) },
        { }
  };
  
@@@ -295,7 -283,7 +296,7 @@@ static int __init konepure_init(void
        konepure_class = class_create(THIS_MODULE, "konepure");
        if (IS_ERR(konepure_class))
                return PTR_ERR(konepure_class);
 -      konepure_class->dev_bin_attrs = konepure_bin_attributes;
 +      konepure_class->dev_groups = konepure_groups;
  
        retval = hid_register_driver(&konepure_driver);
        if (retval)
@@@ -313,5 -301,5 +314,5 @@@ module_init(konepure_init)
  module_exit(konepure_exit);
  
  MODULE_AUTHOR("Stefan Achatz");
- MODULE_DESCRIPTION("USB Roccat KonePure driver");
+ MODULE_DESCRIPTION("USB Roccat KonePure/Optical driver");
  MODULE_LICENSE("GPL v2");
index 8a0f2993411f11e5e9d077a47ed28bd13f02d1e0,c2a17e45c99cb6fa49443e68c0b37fe9f7839f99..515bc03136c0c6497b2ada738f6f8a10f7368311
@@@ -197,25 -197,31 +197,25 @@@ KOVAPLUS_SYSFS_W(thingy, THINGY) 
  KOVAPLUS_SYSFS_R(thingy, THINGY)
  
  #define KOVAPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \
 -{ \
 +KOVAPLUS_SYSFS_RW(thingy, THINGY); \
 +static struct bin_attribute bin_attr_##thingy = { \
        .attr = { .name = #thingy, .mode = 0660 }, \
        .size = KOVAPLUS_SIZE_ ## THINGY, \
        .read = kovaplus_sysfs_read_ ## thingy, \
        .write = kovaplus_sysfs_write_ ## thingy \
  }
  
 -#define KOVAPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \
 -{ \
 -      .attr = { .name = #thingy, .mode = 0440 }, \
 -      .size = KOVAPLUS_SIZE_ ## THINGY, \
 -      .read = kovaplus_sysfs_read_ ## thingy, \
 -}
 -
  #define KOVAPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
 -{ \
 +KOVAPLUS_SYSFS_W(thingy, THINGY); \
 +static struct bin_attribute bin_attr_##thingy = { \
        .attr = { .name = #thingy, .mode = 0220 }, \
        .size = KOVAPLUS_SIZE_ ## THINGY, \
        .write = kovaplus_sysfs_write_ ## thingy \
  }
 -
 -KOVAPLUS_SYSFS_W(control, CONTROL)
 -KOVAPLUS_SYSFS_RW(info, INFO)
 -KOVAPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
 -KOVAPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
 +KOVAPLUS_BIN_ATTRIBUTE_W(control, CONTROL);
 +KOVAPLUS_BIN_ATTRIBUTE_RW(info, INFO);
 +KOVAPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
 +KOVAPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
  
  static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp,
                struct kobject *kobj, struct bin_attribute *attr, char *buf,
@@@ -255,25 -261,6 +255,25 @@@ static ssize_t kovaplus_sysfs_read_prof
                        KOVAPLUS_COMMAND_PROFILE_BUTTONS);
  }
  
 +#define PROFILE_ATTR(number)                                          \
 +static struct bin_attribute bin_attr_profile##number##_settings = {   \
 +      .attr = { .name = "profile##number##_settings", .mode = 0440 }, \
 +      .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,                         \
 +      .read = kovaplus_sysfs_read_profilex_settings,                  \
 +      .private = &profile_numbers[number-1],                          \
 +};                                                                    \
 +static struct bin_attribute bin_attr_profile##number##_buttons = {    \
 +      .attr = { .name = "profile##number##_buttons", .mode = 0440 },  \
 +      .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,                          \
 +      .read = kovaplus_sysfs_read_profilex_buttons,                   \
 +      .private = &profile_numbers[number-1],                          \
 +};
 +PROFILE_ATTR(1);
 +PROFILE_ATTR(2);
 +PROFILE_ATTR(3);
 +PROFILE_ATTR(4);
 +PROFILE_ATTR(5);
 +
  static ssize_t kovaplus_sysfs_show_actual_profile(struct device *dev,
                struct device_attribute *attr, char *buf)
  {
@@@ -295,7 -282,7 +295,7 @@@ static ssize_t kovaplus_sysfs_set_actua
        kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
        usb_dev = interface_to_usbdev(to_usb_interface(dev));
  
-       retval = strict_strtoul(buf, 10, &profile);
+       retval = kstrtoul(buf, 10, &profile);
        if (retval)
                return retval;
  
  
        return size;
  }
 +static DEVICE_ATTR(actual_profile, 0660,
 +                 kovaplus_sysfs_show_actual_profile,
 +                 kovaplus_sysfs_set_actual_profile);
  
  static ssize_t kovaplus_sysfs_show_actual_cpi(struct device *dev,
                struct device_attribute *attr, char *buf)
                        hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
        return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_cpi);
  }
 +static DEVICE_ATTR(actual_cpi, 0440, kovaplus_sysfs_show_actual_cpi, NULL);
  
  static ssize_t kovaplus_sysfs_show_actual_sensitivity_x(struct device *dev,
                struct device_attribute *attr, char *buf)
                        hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
        return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_x_sensitivity);
  }
 +static DEVICE_ATTR(actual_sensitivity_x, 0440,
 +                 kovaplus_sysfs_show_actual_sensitivity_x, NULL);
  
  static ssize_t kovaplus_sysfs_show_actual_sensitivity_y(struct device *dev,
                struct device_attribute *attr, char *buf)
                        hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
        return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_y_sensitivity);
  }
 +static DEVICE_ATTR(actual_sensitivity_y, 0440,
 +                 kovaplus_sysfs_show_actual_sensitivity_y, NULL);
  
  static ssize_t kovaplus_sysfs_show_firmware_version(struct device *dev,
                struct device_attribute *attr, char *buf)
  
        return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
  }
 +static DEVICE_ATTR(firmware_version, 0440,
 +                 kovaplus_sysfs_show_firmware_version, NULL);
 +
 +static struct attribute *kovaplus_attrs[] = {
 +      &dev_attr_actual_cpi.attr,
 +      &dev_attr_firmware_version.attr,
 +      &dev_attr_actual_profile.attr,
 +      &dev_attr_actual_sensitivity_x.attr,
 +      &dev_attr_actual_sensitivity_y.attr,
 +      NULL,
 +};
 +
 +static struct bin_attribute *kovaplus_bin_attributes[] = {
 +      &bin_attr_control,
 +      &bin_attr_info,
 +      &bin_attr_profile_settings,
 +      &bin_attr_profile_buttons,
 +      &bin_attr_profile1_settings,
 +      &bin_attr_profile2_settings,
 +      &bin_attr_profile3_settings,
 +      &bin_attr_profile4_settings,
 +      &bin_attr_profile5_settings,
 +      &bin_attr_profile1_buttons,
 +      &bin_attr_profile2_buttons,
 +      &bin_attr_profile3_buttons,
 +      &bin_attr_profile4_buttons,
 +      &bin_attr_profile5_buttons,
 +      NULL,
 +};
  
 -static struct device_attribute kovaplus_attributes[] = {
 -      __ATTR(actual_cpi, 0440,
 -              kovaplus_sysfs_show_actual_cpi, NULL),
 -      __ATTR(firmware_version, 0440,
 -              kovaplus_sysfs_show_firmware_version, NULL),
 -      __ATTR(actual_profile, 0660,
 -              kovaplus_sysfs_show_actual_profile,
 -              kovaplus_sysfs_set_actual_profile),
 -      __ATTR(actual_sensitivity_x, 0440,
 -              kovaplus_sysfs_show_actual_sensitivity_x, NULL),
 -      __ATTR(actual_sensitivity_y, 0440,
 -              kovaplus_sysfs_show_actual_sensitivity_y, NULL),
 -      __ATTR_NULL
 +static const struct attribute_group kovaplus_group = {
 +      .attrs = kovaplus_attrs,
 +      .bin_attrs = kovaplus_bin_attributes,
  };
  
 -static struct bin_attribute kovaplus_bin_attributes[] = {
 -      KOVAPLUS_BIN_ATTRIBUTE_W(control, CONTROL),
 -      KOVAPLUS_BIN_ATTRIBUTE_RW(info, INFO),
 -      KOVAPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
 -      KOVAPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
 -      {
 -              .attr = { .name = "profile1_settings", .mode = 0440 },
 -              .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
 -              .read = kovaplus_sysfs_read_profilex_settings,
 -              .private = &profile_numbers[0]
 -      },
 -      {
 -              .attr = { .name = "profile2_settings", .mode = 0440 },
 -              .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
 -              .read = kovaplus_sysfs_read_profilex_settings,
 -              .private = &profile_numbers[1]
 -      },
 -      {
 -              .attr = { .name = "profile3_settings", .mode = 0440 },
 -              .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
 -              .read = kovaplus_sysfs_read_profilex_settings,
 -              .private = &profile_numbers[2]
 -      },
 -      {
 -              .attr = { .name = "profile4_settings", .mode = 0440 },
 -              .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
 -              .read = kovaplus_sysfs_read_profilex_settings,
 -              .private = &profile_numbers[3]
 -      },
 -      {
 -              .attr = { .name = "profile5_settings", .mode = 0440 },
 -              .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
 -              .read = kovaplus_sysfs_read_profilex_settings,
 -              .private = &profile_numbers[4]
 -      },
 -      {
 -              .attr = { .name = "profile1_buttons", .mode = 0440 },
 -              .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
 -              .read = kovaplus_sysfs_read_profilex_buttons,
 -              .private = &profile_numbers[0]
 -      },
 -      {
 -              .attr = { .name = "profile2_buttons", .mode = 0440 },
 -              .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
 -              .read = kovaplus_sysfs_read_profilex_buttons,
 -              .private = &profile_numbers[1]
 -      },
 -      {
 -              .attr = { .name = "profile3_buttons", .mode = 0440 },
 -              .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
 -              .read = kovaplus_sysfs_read_profilex_buttons,
 -              .private = &profile_numbers[2]
 -      },
 -      {
 -              .attr = { .name = "profile4_buttons", .mode = 0440 },
 -              .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
 -              .read = kovaplus_sysfs_read_profilex_buttons,
 -              .private = &profile_numbers[3]
 -      },
 -      {
 -              .attr = { .name = "profile5_buttons", .mode = 0440 },
 -              .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
 -              .read = kovaplus_sysfs_read_profilex_buttons,
 -              .private = &profile_numbers[4]
 -      },
 -      __ATTR_NULL
 +static const struct attribute_group *kovaplus_groups[] = {
 +      &kovaplus_group,
 +      NULL,
  };
  
  static int kovaplus_init_kovaplus_device_struct(struct usb_device *usb_dev,
@@@ -639,7 -662,8 +639,7 @@@ static int __init kovaplus_init(void
        kovaplus_class = class_create(THIS_MODULE, "kovaplus");
        if (IS_ERR(kovaplus_class))
                return PTR_ERR(kovaplus_class);
 -      kovaplus_class->dev_attrs = kovaplus_attributes;
 -      kovaplus_class->dev_bin_attrs = kovaplus_bin_attributes;
 +      kovaplus_class->dev_groups = kovaplus_groups;
  
        retval = hid_register_driver(&kovaplus_driver);
        if (retval)
index 13863de433a4f2bd6c96ce67716163f00cff2a1a,d38ab152700698baf92f3e7dc128495f3beca713..bdc35a7a7feeaf4ac7a918547e82d5d19a7ef537
@@@ -225,44 -225,24 +225,49 @@@ static void hidp_input_report(struct hi
  
  static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
  {
-       unsigned char buf[32], hdr;
-       int rsize;
+       unsigned char hdr;
+       u8 *buf;
+       int rsize, ret;
  
-       rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
-       if (rsize > sizeof(buf))
+       buf = hid_alloc_report_buf(report, GFP_ATOMIC);
+       if (!buf)
                return -EIO;
  
        hid_output_report(report, buf);
        hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
  
-       return hidp_send_intr_message(session, hdr, buf, rsize);
+       rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
+       ret = hidp_send_intr_message(session, hdr, buf, rsize);
+       kfree(buf);
+       return ret;
  }
  
 +static int hidp_hidinput_event(struct input_dev *dev, unsigned int type,
 +                             unsigned int code, int value)
 +{
 +      struct hid_device *hid = input_get_drvdata(dev);
 +      struct hidp_session *session = hid->driver_data;
 +      struct hid_field *field;
 +      int offset;
 +
 +      BT_DBG("session %p type %d code %d value %d",
 +             session, type, code, value);
 +
 +      if (type != EV_LED)
 +              return -1;
 +
 +      offset = hidinput_find_field(hid, type, code, &field);
 +      if (offset == -1) {
 +              hid_warn(dev, "event field not found\n");
 +              return -1;
 +      }
 +
 +      hid_set_field(field, offset, value);
 +
 +      return hidp_send_report(session, field->report);
 +}
 +
  static int hidp_get_raw_report(struct hid_device *hid,
                unsigned char report_number,
                unsigned char *data, size_t count,
@@@ -703,6 -683,20 +708,6 @@@ static int hidp_parse(struct hid_devic
  
  static int hidp_start(struct hid_device *hid)
  {
 -      struct hidp_session *session = hid->driver_data;
 -      struct hid_report *report;
 -
 -      if (hid->quirks & HID_QUIRK_NO_INIT_REPORTS)
 -              return 0;
 -
 -      list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].
 -                      report_list, list)
 -              hidp_send_report(session, report);
 -
 -      list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].
 -                      report_list, list)
 -              hidp_send_report(session, report);
 -
        return 0;
  }
  
@@@ -722,7 -716,6 +727,7 @@@ static struct hid_ll_driver hidp_hid_dr
        .stop = hidp_stop,
        .open  = hidp_open,
        .close = hidp_close,
 +      .hidinput_input_event = hidp_hidinput_event,
  };
  
  /* This function sets up the hid device. It does not add it
This page took 0.15559 seconds and 4 git commands to generate.