Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 23 May 2011 16:10:03 +0000 (09:10 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 23 May 2011 16:10:03 +0000 (09:10 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (36 commits)
  HID: hid-multitouch: cosmetic changes, sort classes and devices
  HID: hid-multitouch: class MT_CLS_STANTUM is redundant with MT_CLS_CONFIDENCE
  HID: hid-multitouch: add support for Unitec panels
  HID: hid-multitouch: add support for Touch International panels
  HID: hid-multitouch: add support for GoodTouch panels
  HID: hid-multitouch: add support for CVTouch panels
  HID: hid-multitouch: add support for ActionStar panels
  HID: hiddev: fix race between hiddev_disconnect and hiddev_release
  HID: magicmouse: ignore 'ivalid report id' while switching modes
  HID: fix a crash in hid_report_raw_event() function.
  HID: hid-multitouch: add support for Elo TouchSystems 2515 IntelliTouch Plus
  HID: assorted usage updates from hut 1.12
  HID: roccat: fix actual/startup profile sysfs attribute in koneplus
  HID: hid-multitouch: Add support for Lumio panels
  HID: 'name' and 'phys' in 'struct hid_device' can never be NULL
  HID: hid-multitouch: add support for Ilitek dual-touch panel
  HID: picolcd: Avoid compile warning/error triggered by copy_from_user()
  HID: add support for Logitech G27 wheel
  HID: hiddev: fix error path in hiddev_read when interrupted
  HID: add support for Sony Navigation Controller
  ...

29 files changed:
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus [new file with mode: 0644]
Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
Documentation/hid/hiddev.txt [moved from Documentation/usb/hiddev.txt with 100% similarity]
Documentation/hid/hidraw.txt [new file with mode: 0644]
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-3m-pct.c [deleted file]
drivers/hid/hid-cando.c [deleted file]
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-lg.c
drivers/hid/hid-lgff.c
drivers/hid/hid-magicmouse.c
drivers/hid/hid-mosart.c [deleted file]
drivers/hid/hid-multitouch.c
drivers/hid/hid-picolcd.c
drivers/hid/hid-roccat-koneplus.c
drivers/hid/hid-roccat-koneplus.h
drivers/hid/hid-sony.c
drivers/hid/hid-stantum.c [deleted file]
drivers/hid/hidraw.c
drivers/hid/usbhid/hid-quirks.c
drivers/hid/usbhid/hiddev.c
net/bluetooth/hidp/hidp.h
samples/Kconfig
samples/Makefile
samples/hidraw/Makefile [new file with mode: 0644]
samples/hidraw/hid-example.c [new file with mode: 0644]

diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
new file mode 100644 (file)
index 0000000..c2a270b
--- /dev/null
@@ -0,0 +1,10 @@
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/startup_profile
+Date:          October 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The integer value of this attribute ranges from 0-4.
+                When read, this attribute returns the number of the actual
+                profile. This value is persistent, so its equivalent to the
+                profile that's active when the mouse is powered on next time.
+               When written, this file sets the number of the startup profile
+               and the mouse activates this profile immediately.
+               Please use actual_profile, it does the same thing.
index 326e054..c1b53b8 100644 (file)
@@ -1,9 +1,12 @@
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/actual_profile
 Date:          October 2010
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   When read, this file returns the number of the actual profile in
-               range 0-4.
-               This file is readonly.
+Description:   The integer value of this attribute ranges from 0-4.
+                When read, this attribute returns the number of the actual
+                profile. This value is persistent, so its equivalent to the
+                profile that's active when the mouse is powered on next time.
+               When written, this file sets the number of the startup profile
+               and the mouse activates this profile immediately.
 Users:         http://roccat.sourceforge.net
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version
@@ -89,16 +92,6 @@ Description: The mouse has a tracking- and a distance-control-unit. These
                This file is writeonly.
 Users:         http://roccat.sourceforge.net
 
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/startup_profile
-Date:          October 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The integer value of this attribute ranges from 0-4.
-                When read, this attribute returns the number of the profile
-                that's active when the mouse is powered on.
-               When written, this file sets the number of the startup profile
-               and the mouse activates this profile immediately.
-Users:         http://roccat.sourceforge.net
-
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu
 Date:          October 2010
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
diff --git a/Documentation/hid/hidraw.txt b/Documentation/hid/hidraw.txt
new file mode 100644 (file)
index 0000000..029e6cb
--- /dev/null
@@ -0,0 +1,119 @@
+      HIDRAW - Raw Access to USB and Bluetooth Human Interface Devices
+     ==================================================================
+
+The hidraw driver provides a raw interface to USB and Bluetooth Human
+Interface Devices (HIDs).  It differs from hiddev in that reports sent and
+received are not parsed by the HID parser, but are sent to and received from
+the device unmodified.
+
+Hidraw should be used if the userspace application knows exactly how to
+communicate with the hardware device, and is able to construct the HID
+reports manually.  This is often the case when making userspace drivers for
+custom HID devices.
+
+Hidraw is also useful for communicating with non-conformant HID devices
+which send and receive data in a way that is inconsistent with their report
+descriptors.  Because hiddev parses reports which are sent and received
+through it, checking them against the device's report descriptor, such
+communication with these non-conformant devices is impossible using hiddev.
+Hidraw is the only alternative, short of writing a custom kernel driver, for
+these non-conformant devices.
+
+A benefit of hidraw is that its use by userspace applications is independent
+of the underlying hardware type.  Currently, Hidraw is implemented for USB
+and Bluetooth.  In the future, as new hardware bus types are developed which
+use the HID specification, hidraw will be expanded to add support for these
+new bus types.
+
+Hidraw uses a dynamic major number, meaning that udev should be relied on to
+create hidraw device nodes.  Udev will typically create the device nodes
+directly under /dev (eg: /dev/hidraw0).  As this location is distribution-
+and udev rule-dependent, applications should use libudev to locate hidraw
+devices attached to the system.  There is a tutorial on libudev with a
+working example at:
+       http://www.signal11.us/oss/udev/
+
+The HIDRAW API
+---------------
+
+read()
+-------
+read() will read a queued report received from the HID device. On USB
+devices, the reports read using read() are the reports sent from the device
+on the INTERRUPT IN endpoint.  By default, read() will block until there is
+a report available to be read.  read() can be made non-blocking, by passing
+the O_NONBLOCK flag to open(), or by setting the O_NONBLOCK flag using
+fcntl().
+
+On a device which uses numbered reports, the first byte of the returned data
+will be the report number; the report data follows, beginning in the second
+byte.  For devices which do not use numbered reports, the report data
+will begin at the first byte.
+
+write()
+--------
+The write() function will write a report to the device. For USB devices, if
+the device has an INTERRUPT OUT endpoint, the report will be sent on that
+endpoint. If it does not, the report will be sent over the control endpoint,
+using a SET_REPORT transfer.
+
+The first byte of the buffer passed to write() should be set to the report
+number.  If the device does not use numbered reports, the first byte should
+be set to 0. The report data itself should begin at the second byte.
+
+ioctl()
+--------
+Hidraw supports the following ioctls:
+
+HIDIOCGRDESCSIZE: Get Report Descriptor Size
+This ioctl will get the size of the device's report descriptor.
+
+HIDIOCGRDESC: Get Report Descriptor
+This ioctl returns the device's report descriptor using a
+hidraw_report_descriptor struct.  Make sure to set the size field of the
+hidraw_report_descriptor struct to the size returned from HIDIOCGRDESCSIZE.
+
+HIDIOCGRAWINFO: Get Raw Info
+This ioctl will return a hidraw_devinfo struct containing the bus type, the
+vendor ID (VID), and product ID (PID) of the device. The bus type can be one
+of:
+       BUS_USB
+       BUS_HIL
+       BUS_BLUETOOTH
+       BUS_VIRTUAL
+which are defined in linux/input.h.
+
+HIDIOCGRAWNAME(len): Get Raw Name
+This ioctl returns a string containing the vendor and product strings of
+the device.  The returned string is Unicode, UTF-8 encoded.
+
+HIDIOCGRAWPHYS(len): Get Physical Address
+This ioctl returns a string representing the physical address of the device.
+For USB devices, the string contains the physical path to the device (the
+USB controller, hubs, ports, etc).  For Bluetooth devices, the string
+contains the hardware (MAC) address of the device.
+
+HIDIOCSFEATURE(len): Send a Feature Report
+This ioctl will send a feature report to the device.  Per the HID
+specification, feature reports are always sent using the control endpoint.
+Set the first byte of the supplied buffer to the report number.  For devices
+which do not use numbered reports, set the first byte to 0. The report data
+begins in the second byte. Make sure to set len accordingly, to one more
+than the length of the report (to account for the report number).
+
+HIDIOCGFEATURE(len): Get a Feature Report
+This ioctl will request a feature report from the device using the control
+endpoint.  The first byte of the supplied buffer should be set to the report
+number of the requested report.  For devices which do not use numbered
+reports, set the first byte to 0.  The report will be returned starting at
+the first byte of the buffer (ie: the report number is not returned).
+
+Example
+---------
+In samples/, find hid-example.c, which shows examples of read(), write(),
+and all the ioctls for hidraw.  The code may be used by anyone for any
+purpose, and can serve as a starting point for developing applications using
+hidraw.
+
+Document by:
+       Alan Ott <alan@signal11.us>, Signal 11 Software
index 9de9e97..67d2a75 100644 (file)
@@ -55,12 +55,6 @@ source "drivers/hid/usbhid/Kconfig"
 menu "Special HID drivers"
        depends on HID
 
-config HID_3M_PCT
-       tristate "3M PCT touchscreen"
-       depends on USB_HID
-       ---help---
-       Support for 3M PCT touch screens.
-
 config HID_A4TECH
        tristate "A4 tech mice" if EXPERT
        depends on USB_HID
@@ -100,12 +94,6 @@ config HID_BELKIN
        ---help---
        Support for Belkin Flip KVM and Wireless keyboard.
 
-config HID_CANDO
-       tristate "Cando dual touch panel"
-       depends on USB_HID
-       ---help---
-       Support for Cando dual touch panel.
-
 config HID_CHERRY
        tristate "Cherry Cymotion keyboard" if EXPERT
        depends on USB_HID
@@ -300,12 +288,6 @@ config HID_MICROSOFT
        ---help---
        Support for Microsoft devices that are not fully compliant with HID standard.
 
-config HID_MOSART
-       tristate "MosArt dual-touch panels"
-       depends on USB_HID
-       ---help---
-       Support for MosArt dual-touch panels.
-
 config HID_MONTEREY
        tristate "Monterey Genius KB29E keyboard" if EXPERT
        depends on USB_HID
@@ -320,13 +302,25 @@ config HID_MULTITOUCH
          Generic support for HID multitouch panels.
 
          Say Y here if you have one of the following devices:
+         - 3M PCT touch screens
+         - ActionStar dual touch panels
+         - Cando dual touch panels
+         - CVTouch panels
          - Cypress TrueTouch panels
+         - Elo TouchSystems IntelliTouch Plus panels
+         - GeneralTouch 'Sensing Win7-TwoFinger' panels
+         - GoodTouch panels
          - Hanvon dual touch panels
+         - Ilitek dual touch panels
          - IrTouch Infrared USB panels
+         - Lumio CrystalTouch panels
+         - MosArt dual-touch panels
+         - PenMount dual touch panels
          - Pixcir dual touch panels
-         - 'Sensing Win7-TwoFinger' panel by GeneralTouch
-          - eGalax dual-touch panels, including the
-           Joojoo and Wetab tablets
+         - eGalax dual-touch panels, including the Joojoo and Wetab tablets
+         - Stantum multitouch panels
+         - Touch International Panels
+         - Unitec Panels
 
          If unsure, say N.
 
@@ -500,12 +494,6 @@ config HID_SONY
        ---help---
        Support for Sony PS3 controller.
 
-config HID_STANTUM
-       tristate "Stantum multitouch panel"
-       depends on USB_HID
-       ---help---
-       Support for Stantum multitouch panel.
-
 config HID_SUNPLUS
        tristate "Sunplus wireless desktop"
        depends on USB_HID
index 06c68ae..f8cc4ea 100644 (file)
@@ -25,12 +25,10 @@ ifdef CONFIG_LOGIWII_FF
        hid-logitech-y  += hid-lg4ff.o
 endif
 
-obj-$(CONFIG_HID_3M_PCT)       += hid-3m-pct.o
 obj-$(CONFIG_HID_A4TECH)       += hid-a4tech.o
 obj-$(CONFIG_HID_ACRUX)                += hid-axff.o
 obj-$(CONFIG_HID_APPLE)                += hid-apple.o
 obj-$(CONFIG_HID_BELKIN)       += hid-belkin.o
-obj-$(CONFIG_HID_CANDO)                += hid-cando.o
 obj-$(CONFIG_HID_CHERRY)       += hid-cherry.o
 obj-$(CONFIG_HID_CHICONY)      += hid-chicony.o
 obj-$(CONFIG_HID_CYPRESS)      += hid-cypress.o
@@ -47,7 +45,6 @@ obj-$(CONFIG_HID_LOGITECH)    += hid-logitech.o
 obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
 obj-$(CONFIG_HID_MICROSOFT)    += hid-microsoft.o
 obj-$(CONFIG_HID_MONTEREY)     += hid-monterey.o
-obj-$(CONFIG_HID_MOSART)       += hid-mosart.o
 obj-$(CONFIG_HID_MULTITOUCH)   += hid-multitouch.o
 obj-$(CONFIG_HID_NTRIG)                += hid-ntrig.o
 obj-$(CONFIG_HID_ORTEK)                += hid-ortek.o
@@ -66,7 +63,6 @@ obj-$(CONFIG_HID_ROCCAT_PYRA) += hid-roccat-pyra.o
 obj-$(CONFIG_HID_SAMSUNG)      += hid-samsung.o
 obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
 obj-$(CONFIG_HID_SONY)         += hid-sony.o
-obj-$(CONFIG_HID_STANTUM)      += hid-stantum.o
 obj-$(CONFIG_HID_SUNPLUS)      += hid-sunplus.o
 obj-$(CONFIG_HID_GREENASIA)    += hid-gaff.o
 obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o
diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c
deleted file mode 100644 (file)
index 5243ae2..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- *  HID driver for 3M PCT multitouch panels
- *
- *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
- *  Copyright (c) 2010      Henrik Rydberg <rydberg@euromail.se>
- *  Copyright (c) 2010      Canonical, Ltd.
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/input/mt.h>
-
-MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("3M PCT multitouch panels");
-MODULE_LICENSE("GPL");
-
-#include "hid-ids.h"
-
-#define MAX_SLOTS              60
-
-/* estimated signal-to-noise ratios */
-#define SN_MOVE                        2048
-#define SN_WIDTH               128
-
-struct mmm_finger {
-       __s32 x, y, w, h;
-       bool touch, valid;
-};
-
-struct mmm_data {
-       struct mmm_finger f[MAX_SLOTS];
-       __u8 curid;
-       __u8 nexp, nreal;
-       bool touch, valid;
-};
-
-static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-               struct hid_field *field, struct hid_usage *usage,
-               unsigned long **bit, int *max)
-{
-       int f1 = field->logical_minimum;
-       int f2 = field->logical_maximum;
-       int df = f2 - f1;
-
-       switch (usage->hid & HID_USAGE_PAGE) {
-
-       case HID_UP_BUTTON:
-               return -1;
-
-       case HID_UP_GENDESK:
-               switch (usage->hid) {
-               case HID_GD_X:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_POSITION_X);
-                       input_set_abs_params(hi->input, ABS_MT_POSITION_X,
-                                            f1, f2, df / SN_MOVE, 0);
-                       /* touchscreen emulation */
-                       input_set_abs_params(hi->input, ABS_X,
-                                            f1, f2, df / SN_MOVE, 0);
-                       return 1;
-               case HID_GD_Y:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_POSITION_Y);
-                       input_set_abs_params(hi->input, ABS_MT_POSITION_Y,
-                                            f1, f2, df / SN_MOVE, 0);
-                       /* touchscreen emulation */
-                       input_set_abs_params(hi->input, ABS_Y,
-                                            f1, f2, df / SN_MOVE, 0);
-                       return 1;
-               }
-               return 0;
-
-       case HID_UP_DIGITIZER:
-               switch (usage->hid) {
-               /* we do not want to map these: no input-oriented meaning */
-               case 0x14:
-               case 0x23:
-               case HID_DG_INPUTMODE:
-               case HID_DG_DEVICEINDEX:
-               case HID_DG_CONTACTCOUNT:
-               case HID_DG_CONTACTMAX:
-               case HID_DG_INRANGE:
-               case HID_DG_CONFIDENCE:
-                       return -1;
-               case HID_DG_TIPSWITCH:
-                       /* touchscreen emulation */
-                       hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-                       input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
-                       return 1;
-               case HID_DG_WIDTH:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_TOUCH_MAJOR);
-                       input_set_abs_params(hi->input, ABS_MT_TOUCH_MAJOR,
-                                            f1, f2, df / SN_WIDTH, 0);
-                       return 1;
-               case HID_DG_HEIGHT:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_TOUCH_MINOR);
-                       input_set_abs_params(hi->input, ABS_MT_TOUCH_MINOR,
-                                            f1, f2, df / SN_WIDTH, 0);
-                       input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
-                                       0, 1, 0, 0);
-                       return 1;
-               case HID_DG_CONTACTID:
-                       input_mt_init_slots(hi->input, MAX_SLOTS);
-                       return 1;
-               }
-               /* let hid-input decide for the others */
-               return 0;
-
-       case 0xff000000:
-               /* we do not want to map these: no input-oriented meaning */
-               return -1;
-       }
-
-       return 0;
-}
-
-static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-               struct hid_field *field, struct hid_usage *usage,
-               unsigned long **bit, int *max)
-{
-       /* tell hid-input to skip setup of these event types */
-       if (usage->type == EV_KEY || usage->type == EV_ABS)
-               set_bit(usage->type, hi->input->evbit);
-       return -1;
-}
-
-/*
- * this function is called when a whole packet has been received and processed,
- * so that it can decide what to send to the input layer.
- */
-static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
-{
-       int i;
-       for (i = 0; i < MAX_SLOTS; ++i) {
-               struct mmm_finger *f = &md->f[i];
-               if (!f->valid) {
-                       /* this finger is just placeholder data, ignore */
-                       continue;
-               }
-               input_mt_slot(input, i);
-               input_mt_report_slot_state(input, MT_TOOL_FINGER, f->touch);
-               if (f->touch) {
-                       /* this finger is on the screen */
-                       int wide = (f->w > f->h);
-                       /* divided by two to match visual scale of touch */
-                       int major = max(f->w, f->h) >> 1;
-                       int minor = min(f->w, f->h) >> 1;
-
-                       input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x);
-                       input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y);
-                       input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
-                       input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
-                       input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
-               }
-               f->valid = 0;
-       }
-
-       input_mt_report_pointer_emulation(input, true);
-       input_sync(input);
-}
-
-/*
- * this function is called upon all reports
- * so that we can accumulate contact point information,
- * and call input_mt_sync after each point.
- */
-static int mmm_event(struct hid_device *hid, struct hid_field *field,
-                               struct hid_usage *usage, __s32 value)
-{
-       struct mmm_data *md = hid_get_drvdata(hid);
-       /*
-        * strangely, this function can be called before
-        * field->hidinput is initialized!
-        */
-       if (hid->claimed & HID_CLAIMED_INPUT) {
-               struct input_dev *input = field->hidinput->input;
-               switch (usage->hid) {
-               case HID_DG_TIPSWITCH:
-                       md->touch = value;
-                       break;
-               case HID_DG_CONFIDENCE:
-                       md->valid = value;
-                       break;
-               case HID_DG_WIDTH:
-                       if (md->valid)
-                               md->f[md->curid].w = value;
-                       break;
-               case HID_DG_HEIGHT:
-                       if (md->valid)
-                               md->f[md->curid].h = value;
-                       break;
-               case HID_DG_CONTACTID:
-                       value = clamp_val(value, 0, MAX_SLOTS - 1);
-                       if (md->valid) {
-                               md->curid = value;
-                               md->f[value].touch = md->touch;
-                               md->f[value].valid = 1;
-                               md->nreal++;
-                       }
-                       break;
-               case HID_GD_X:
-                       if (md->valid)
-                               md->f[md->curid].x = value;
-                       break;
-               case HID_GD_Y:
-                       if (md->valid)
-                               md->f[md->curid].y = value;
-                       break;
-               case HID_DG_CONTACTCOUNT:
-                       if (value)
-                               md->nexp = value;
-                       if (md->nreal >= md->nexp) {
-                               mmm_filter_event(md, input);
-                               md->nreal = 0;
-                       }
-                       break;
-               }
-       }
-
-       /* we have handled the hidinput part, now remains hiddev */
-       if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-               hid->hiddev_hid_event(hid, field, usage, value);
-
-       return 1;
-}
-
-static int mmm_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-       int ret;
-       struct mmm_data *md;
-
-       hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
-
-       md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL);
-       if (!md) {
-               hid_err(hdev, "cannot allocate 3M data\n");
-               return -ENOMEM;
-       }
-       hid_set_drvdata(hdev, md);
-
-       ret = hid_parse(hdev);
-       if (!ret)
-               ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-
-       if (ret)
-               kfree(md);
-       return ret;
-}
-
-static void mmm_remove(struct hid_device *hdev)
-{
-       hid_hw_stop(hdev);
-       kfree(hid_get_drvdata(hdev));
-       hid_set_drvdata(hdev, NULL);
-}
-
-static const struct hid_device_id mmm_devices[] = {
-       { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) },
-       { }
-};
-MODULE_DEVICE_TABLE(hid, mmm_devices);
-
-static const struct hid_usage_id mmm_grabbed_usages[] = {
-       { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-       { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
-};
-
-static struct hid_driver mmm_driver = {
-       .name = "3m-pct",
-       .id_table = mmm_devices,
-       .probe = mmm_probe,
-       .remove = mmm_remove,
-       .input_mapping = mmm_input_mapping,
-       .input_mapped = mmm_input_mapped,
-       .usage_table = mmm_grabbed_usages,
-       .event = mmm_event,
-};
-
-static int __init mmm_init(void)
-{
-       return hid_register_driver(&mmm_driver);
-}
-
-static void __exit mmm_exit(void)
-{
-       hid_unregister_driver(&mmm_driver);
-}
-
-module_init(mmm_init);
-module_exit(mmm_exit);
-
diff --git a/drivers/hid/hid-cando.c b/drivers/hid/hid-cando.c
deleted file mode 100644 (file)
index 1ea066c..0000000
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- *  HID driver for Cando dual-touch panels
- *
- *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("Cando dual-touch panel");
-MODULE_LICENSE("GPL");
-
-#include "hid-ids.h"
-
-struct cando_data {
-       __u16 x, y;
-       __u8 id;
-       __s8 oldest;            /* id of the oldest finger in previous frame */
-       bool valid;             /* valid finger data, or just placeholder? */
-       bool first;             /* is this the first finger in this frame? */
-       __s8 firstid;           /* id of the first finger in the frame */
-       __u16 firstx, firsty;   /* (x, y) of the first finger in the frame */
-};
-
-static int cando_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-               struct hid_field *field, struct hid_usage *usage,
-               unsigned long **bit, int *max)
-{
-       switch (usage->hid & HID_USAGE_PAGE) {
-
-       case HID_UP_GENDESK:
-               switch (usage->hid) {
-               case HID_GD_X:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_POSITION_X);
-                       /* touchscreen emulation */
-                       input_set_abs_params(hi->input, ABS_X,
-                                               field->logical_minimum,
-                                               field->logical_maximum, 0, 0);
-                       return 1;
-               case HID_GD_Y:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_POSITION_Y);
-                       /* touchscreen emulation */
-                       input_set_abs_params(hi->input, ABS_Y,
-                                               field->logical_minimum,
-                                               field->logical_maximum, 0, 0);
-                       return 1;
-               }
-               return 0;
-
-       case HID_UP_DIGITIZER:
-               switch (usage->hid) {
-               case HID_DG_TIPSWITCH:
-               case HID_DG_CONTACTMAX:
-                       return -1;
-               case HID_DG_INRANGE:
-                       /* touchscreen emulation */
-                       hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-                       return 1;
-               case HID_DG_CONTACTID:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_TRACKING_ID);
-                       return 1;
-               }
-               return 0;
-       }
-
-       return 0;
-}
-
-static int cando_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-               struct hid_field *field, struct hid_usage *usage,
-               unsigned long **bit, int *max)
-{
-       if (usage->type == EV_KEY || usage->type == EV_ABS)
-               clear_bit(usage->code, *bit);
-
-       return 0;
-}
-
-/*
- * this function is called when a whole finger has been parsed,
- * so that it can decide what to send to the input layer.
- */
-static void cando_filter_event(struct cando_data *td, struct input_dev *input)
-{
-       td->first = !td->first; /* touchscreen emulation */
-
-       if (!td->valid) {
-               /*
-                * touchscreen emulation: if this is the second finger and
-                * the first was valid, the first was the oldest; if the
-                * first was not valid and there was a valid finger in the
-                * previous frame, this is a release.
-                */
-               if (td->first) {
-                       td->firstid = -1;
-               } else if (td->firstid >= 0) {
-                       input_event(input, EV_ABS, ABS_X, td->firstx);
-                       input_event(input, EV_ABS, ABS_Y, td->firsty);
-                       td->oldest = td->firstid;
-               } else if (td->oldest >= 0) {
-                       input_event(input, EV_KEY, BTN_TOUCH, 0);
-                       td->oldest = -1;
-               }
-
-               return;
-       }
-       
-       input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
-       input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
-       input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
-
-       input_mt_sync(input);
-
-       /*
-        * touchscreen emulation: if there was no touching finger previously,
-        * emit touch event
-        */
-       if (td->oldest < 0) {
-               input_event(input, EV_KEY, BTN_TOUCH, 1);
-               td->oldest = td->id;
-       }
-
-       /*
-        * touchscreen emulation: if this is the first finger, wait for the
-        * second; the oldest is then the second if it was the oldest already
-        * or if there was no first, the first otherwise.
-        */
-       if (td->first) {
-               td->firstx = td->x;
-               td->firsty = td->y;
-               td->firstid = td->id;
-       } else {
-               int x, y, oldest;
-               if (td->id == td->oldest || td->firstid < 0) {
-                       x = td->x;
-                       y = td->y;
-                       oldest = td->id;
-               } else {
-                       x = td->firstx;
-                       y = td->firsty;
-                       oldest = td->firstid;
-               }
-               input_event(input, EV_ABS, ABS_X, x);
-               input_event(input, EV_ABS, ABS_Y, y);
-               td->oldest = oldest;
-       }
-}
-
-
-static int cando_event(struct hid_device *hid, struct hid_field *field,
-                               struct hid_usage *usage, __s32 value)
-{
-       struct cando_data *td = hid_get_drvdata(hid);
-
-       if (hid->claimed & HID_CLAIMED_INPUT) {
-               struct input_dev *input = field->hidinput->input;
-
-               switch (usage->hid) {
-               case HID_DG_INRANGE:
-                       td->valid = value;
-                       break;
-               case HID_DG_CONTACTID:
-                       td->id = value;
-                       break;
-               case HID_GD_X:
-                       td->x = value;
-                       break;
-               case HID_GD_Y:
-                       td->y = value;
-                       cando_filter_event(td, input);
-                       break;
-               case HID_DG_TIPSWITCH:
-                       /* avoid interference from generic hidinput handling */
-                       break;
-
-               default:
-                       /* fallback to the generic hidinput handling */
-                       return 0;
-               }
-       }
-
-       /* we have handled the hidinput part, now remains hiddev */
-       if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-               hid->hiddev_hid_event(hid, field, usage, value);
-
-       return 1;
-}
-
-static int cando_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-       int ret;
-       struct cando_data *td;
-
-       td = kmalloc(sizeof(struct cando_data), GFP_KERNEL);
-       if (!td) {
-               hid_err(hdev, "cannot allocate Cando Touch data\n");
-               return -ENOMEM;
-       }
-       hid_set_drvdata(hdev, td);
-       td->first = false;
-       td->oldest = -1;
-       td->valid = false;
-
-       ret = hid_parse(hdev);
-       if (!ret)
-               ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-
-       if (ret)
-               kfree(td);
-
-       return ret;
-}
-
-static void cando_remove(struct hid_device *hdev)
-{
-       hid_hw_stop(hdev);
-       kfree(hid_get_drvdata(hdev));
-       hid_set_drvdata(hdev, NULL);
-}
-
-static const struct hid_device_id cando_devices[] = {
-       { 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) },
-       { }
-};
-MODULE_DEVICE_TABLE(hid, cando_devices);
-
-static const struct hid_usage_id cando_grabbed_usages[] = {
-       { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-       { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
-};
-
-static struct hid_driver cando_driver = {
-       .name = "cando-touch",
-       .id_table = cando_devices,
-       .probe = cando_probe,
-       .remove = cando_remove,
-       .input_mapping = cando_input_mapping,
-       .input_mapped = cando_input_mapped,
-       .usage_table = cando_grabbed_usages,
-       .event = cando_event,
-};
-
-static int __init cando_init(void)
-{
-       return hid_register_driver(&cando_driver);
-}
-
-static void __exit cando_exit(void)
-{
-       hid_unregister_driver(&cando_driver);
-}
-
-module_init(cando_init);
-module_exit(cando_exit);
-
index 408c4be..4140fd2 100644 (file)
@@ -1045,6 +1045,9 @@ void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
 
        rsize = ((report->size - 1) >> 3) + 1;
 
+       if (rsize > HID_MAX_BUFFER_SIZE)
+               rsize = HID_MAX_BUFFER_SIZE;
+
        if (csize < rsize) {
                dbg_hid("report %d is too short, (%d < %d)\n", report->id,
                                csize, rsize);
@@ -1290,6 +1293,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { 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) },
@@ -1356,6 +1360,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_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) },
@@ -1369,17 +1374,20 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
        { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_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_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_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_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
@@ -1408,10 +1416,12 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) },
        { 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_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_SIDEWINDER_GV) },
@@ -1441,6 +1451,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { 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_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_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
@@ -1454,6 +1465,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
+       { 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) },
@@ -1470,12 +1482,15 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a) },
        { 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_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_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
index 00a94b5..e715c43 100644 (file)
@@ -37,6 +37,9 @@
 
 #define USB_VENDOR_ID_ACRUX            0x1a34
 
+#define USB_VENDOR_ID_ACTIONSTAR       0x2101
+#define USB_DEVICE_ID_ACTIONSTAR_1011  0x1011
+
 #define USB_VENDOR_ID_ADS_TECH                 0x06e1
 #define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X    0xa155
 
 #define USB_VENDOR_ID_CREATIVELABS     0x041e
 #define USB_DEVICE_ID_PRODIKEYS_PCMIDI 0x2801
 
+#define USB_VENDOR_ID_CVTOUCH          0x1ff7
+#define USB_DEVICE_ID_CVTOUCH_SCREEN   0x0013
+
 #define USB_VENDOR_ID_CYGNAL           0x10c4
 #define USB_DEVICE_ID_CYGNAL_RADIO_SI470X      0x818a
 
 #define USB_VENDOR_ID_DREAM_CHEEKY     0x1d34
 
 #define USB_VENDOR_ID_ELO              0x04E7
+#define USB_DEVICE_ID_ELO_TS2515       0x0022
 #define USB_DEVICE_ID_ELO_TS2700       0x0020
 
 #define USB_VENDOR_ID_EMS              0x2006
 #define USB_DEVICE_ID_0_8_8_IF_KIT     0x0053
 #define USB_DEVICE_ID_PHIDGET_MOTORCONTROL     0x0058
 
+#define USB_VENDOR_ID_GOODTOUCH                0x1aad
+#define USB_DEVICE_ID_GOODTOUCH_000f   0x000f
+
 #define USB_VENDOR_ID_GOTOP            0x08f2
 #define USB_DEVICE_ID_SUPER_Q2         0x007f
 #define USB_DEVICE_ID_GOGOPEN          0x00ce
 #define USB_DEVICE_ID_UGCI_FLYING      0x0020
 #define USB_DEVICE_ID_UGCI_FIGHTING    0x0030
 
+#define USB_VENDOR_ID_ILITEK           0x222a
+#define USB_DEVICE_ID_ILITEK_MULTITOUCH        0x0001
+
 #define USB_VENDOR_ID_IMATION          0x0718
 #define USB_DEVICE_ID_DISC_STAKKA      0xd000
 
 #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL      0xc295
 #define USB_DEVICE_ID_LOGITECH_DFP_WHEEL       0xc298
 #define USB_DEVICE_ID_LOGITECH_G25_WHEEL       0xc299
+#define USB_DEVICE_ID_LOGITECH_G27_WHEEL       0xc29b
 #define USB_DEVICE_ID_LOGITECH_WII_WHEEL       0xc29c
 #define USB_DEVICE_ID_LOGITECH_ELITE_KBD       0xc30a
 #define USB_DEVICE_ID_S510_RECEIVER    0xc50c
 #define USB_DEVICE_ID_DINOVO_MINI      0xc71f
 #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2     0xca03
 
+#define USB_VENDOR_ID_LUMIO            0x202e
+#define USB_DEVICE_ID_CRYSTALTOUCH     0x0006
+
 #define USB_VENDOR_ID_MCC              0x09db
 #define USB_DEVICE_ID_MCC_PMD1024LS    0x0076
 #define USB_DEVICE_ID_MCC_PMD1208LS    0x007a
 #define USB_VENDOR_ID_PANTHERLORD      0x0810
 #define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK    0x0001
 
+#define USB_VENDOR_ID_PENMOUNT         0x14e1
+#define USB_DEVICE_ID_PENMOUNT_PCI     0x3500
+
 #define USB_VENDOR_ID_PETALYNX         0x18b1
 #define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE   0x0037
 
 #define USB_VENDOR_ID_SONY                     0x054c
 #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE      0x024b
 #define USB_DEVICE_ID_SONY_PS3_CONTROLLER      0x0268
+#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER       0x042f
 
 #define USB_VENDOR_ID_SOUNDGRAPH       0x15c2
 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST    0x0034
 #define USB_VENDOR_ID_SUNPLUS          0x04fc
 #define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8
 
+#define USB_VENDOR_ID_SYMBOL           0x05e0
+#define USB_DEVICE_ID_SYMBOL_SCANNER_1 0x0800
+#define USB_DEVICE_ID_SYMBOL_SCANNER_2 0x1300
+
 #define USB_VENDOR_ID_THRUSTMASTER     0x044f
 
 #define USB_VENDOR_ID_TOPSEED          0x0766
 #define USB_VENDOR_ID_TOPMAX           0x0663
 #define USB_DEVICE_ID_TOPMAX_COBRAPAD  0x0103
 
+#define USB_VENDOR_ID_TOUCH_INTL       0x1e5e
+#define USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH   0x0313
+
 #define USB_VENDOR_ID_TOUCHPACK                0x1bfd
 #define USB_DEVICE_ID_TOUCHPACK_RTS    0x1688
 
 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U   0x0004
 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U   0x0005
 
+#define USB_VENDOR_ID_UNITEC   0x227d
+#define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709    0x0709
+#define USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19    0x0a19
+
 #define USB_VENDOR_ID_VERNIER          0x08f7
 #define USB_DEVICE_ID_VERNIER_LABPRO   0x0001
 #define USB_DEVICE_ID_VERNIER_GOTEMP   0x0002
index 33dde87..6559e2e 100644 (file)
@@ -44,11 +44,11 @@ static const unsigned char hid_keyboard[256] = {
         72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
        191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
        115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk,
-       122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+       122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,
        unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
        unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk,
        unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
-       unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+       unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk,
         29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
        150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
 };
@@ -357,6 +357,18 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                        case 0x1: map_key_clear(KEY_POWER);  break;
                        case 0x2: map_key_clear(KEY_SLEEP);  break;
                        case 0x3: map_key_clear(KEY_WAKEUP); break;
+                       case 0x4: map_key_clear(KEY_CONTEXT_MENU); break;
+                       case 0x5: map_key_clear(KEY_MENU); break;
+                       case 0x6: map_key_clear(KEY_PROG1); break;
+                       case 0x7: map_key_clear(KEY_HELP); break;
+                       case 0x8: map_key_clear(KEY_EXIT); break;
+                       case 0x9: map_key_clear(KEY_SELECT); break;
+                       case 0xa: map_key_clear(KEY_RIGHT); break;
+                       case 0xb: map_key_clear(KEY_LEFT); break;
+                       case 0xc: map_key_clear(KEY_UP); break;
+                       case 0xd: map_key_clear(KEY_DOWN); break;
+                       case 0xe: map_key_clear(KEY_POWER2); break;
+                       case 0xf: map_key_clear(KEY_RESTART); break;
                        default: goto unknown;
                        }
                        break;
@@ -466,16 +478,39 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                }
                break;
 
-       case HID_UP_CONSUMER:   /* USB HUT v1.1, pages 56-62 */
+       case HID_UP_CONSUMER:   /* USB HUT v1.12, pages 75-84 */
                switch (usage->hid & HID_USAGE) {
                case 0x000: goto ignore;
+               case 0x030: map_key_clear(KEY_POWER);           break;
+               case 0x031: map_key_clear(KEY_RESTART);         break;
+               case 0x032: map_key_clear(KEY_SLEEP);           break;
                case 0x034: map_key_clear(KEY_SLEEP);           break;
+               case 0x035: map_key_clear(KEY_KBDILLUMTOGGLE);  break;
                case 0x036: map_key_clear(BTN_MISC);            break;
 
-               case 0x040: map_key_clear(KEY_MENU);            break;
-               case 0x045: map_key_clear(KEY_RADIO);           break;
-
+               case 0x040: map_key_clear(KEY_MENU);            break; /* Menu */
+               case 0x041: map_key_clear(KEY_SELECT);          break; /* Menu Pick */
+               case 0x042: map_key_clear(KEY_UP);              break; /* Menu Up */
+               case 0x043: map_key_clear(KEY_DOWN);            break; /* Menu Down */
+               case 0x044: map_key_clear(KEY_LEFT);            break; /* Menu Left */
+               case 0x045: map_key_clear(KEY_RIGHT);           break; /* Menu Right */
+               case 0x046: map_key_clear(KEY_ESC);             break; /* Menu Escape */
+               case 0x047: map_key_clear(KEY_KPPLUS);          break; /* Menu Value Increase */
+               case 0x048: map_key_clear(KEY_KPMINUS);         break; /* Menu Value Decrease */
+
+               case 0x060: map_key_clear(KEY_INFO);            break; /* Data On Screen */
+               case 0x061: map_key_clear(KEY_SUBTITLE);        break; /* Closed Caption */
+               case 0x063: map_key_clear(KEY_VCR);             break; /* VCR/TV */
+               case 0x065: map_key_clear(KEY_CAMERA);          break; /* Snapshot */
+               case 0x069: map_key_clear(KEY_RED);             break;
+               case 0x06a: map_key_clear(KEY_GREEN);           break;
+               case 0x06b: map_key_clear(KEY_BLUE);            break;
+               case 0x06c: map_key_clear(KEY_YELLOW);          break;
+               case 0x06d: map_key_clear(KEY_ZOOM);            break;
+
+               case 0x082: map_key_clear(KEY_VIDEO_NEXT);      break;
                case 0x083: map_key_clear(KEY_LAST);            break;
+               case 0x084: map_key_clear(KEY_ENTER);           break;
                case 0x088: map_key_clear(KEY_PC);              break;
                case 0x089: map_key_clear(KEY_TV);              break;
                case 0x08a: map_key_clear(KEY_WWW);             break;
@@ -509,6 +544,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case 0x0b7: map_key_clear(KEY_STOPCD);          break;
                case 0x0b8: map_key_clear(KEY_EJECTCD);         break;
                case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT);    break;
+               case 0x0b9: map_key_clear(KEY_SHUFFLE);         break;
+               case 0x0bf: map_key_clear(KEY_SLOW);            break;
 
                case 0x0cd: map_key_clear(KEY_PLAYPAUSE);       break;
                case 0x0e0: map_abs_clear(ABS_VOLUME);          break;
@@ -516,6 +553,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case 0x0e5: map_key_clear(KEY_BASSBOOST);       break;
                case 0x0e9: map_key_clear(KEY_VOLUMEUP);        break;
                case 0x0ea: map_key_clear(KEY_VOLUMEDOWN);      break;
+               case 0x0f5: map_key_clear(KEY_SLOW);            break;
 
                case 0x182: map_key_clear(KEY_BOOKMARKS);       break;
                case 0x183: map_key_clear(KEY_CONFIG);          break;
@@ -532,6 +570,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case 0x18e: map_key_clear(KEY_CALENDAR);        break;
                case 0x191: map_key_clear(KEY_FINANCE);         break;
                case 0x192: map_key_clear(KEY_CALC);            break;
+               case 0x193: map_key_clear(KEY_PLAYER);          break;
                case 0x194: map_key_clear(KEY_FILE);            break;
                case 0x196: map_key_clear(KEY_WWW);             break;
                case 0x199: map_key_clear(KEY_CHAT);            break;
@@ -540,8 +579,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case 0x1a6: map_key_clear(KEY_HELP);            break;
                case 0x1a7: map_key_clear(KEY_DOCUMENTS);       break;
                case 0x1ab: map_key_clear(KEY_SPELLCHECK);      break;
-               case 0x1b6: map_key_clear(KEY_MEDIA);           break;
-               case 0x1b7: map_key_clear(KEY_SOUND);           break;
+               case 0x1ae: map_key_clear(KEY_KEYBOARD);        break;
+               case 0x1b6: map_key_clear(KEY_IMAGES);          break;
+               case 0x1b7: map_key_clear(KEY_AUDIO);           break;
+               case 0x1b8: map_key_clear(KEY_VIDEO);           break;
                case 0x1bc: map_key_clear(KEY_MESSENGER);       break;
                case 0x1bd: map_key_clear(KEY_INFO);            break;
                case 0x201: map_key_clear(KEY_NEW);             break;
@@ -570,7 +611,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case 0x233: map_key_clear(KEY_SCROLLUP);        break;
                case 0x234: map_key_clear(KEY_SCROLLDOWN);      break;
                case 0x238: map_rel(REL_HWHEEL);                break;
+               case 0x23d: map_key_clear(KEY_EDIT);            break;
                case 0x25f: map_key_clear(KEY_CANCEL);          break;
+               case 0x269: map_key_clear(KEY_INSERT);          break;
+               case 0x26a: map_key_clear(KEY_DELETE);          break;
                case 0x279: map_key_clear(KEY_REDO);            break;
 
                case 0x289: map_key_clear(KEY_REPLY);           break;
index 3da9040..21f205f 100644 (file)
@@ -377,6 +377,8 @@ static const struct hid_device_id lg_devices[] = {
                .driver_data = LG_FF },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
                .driver_data = LG_FF },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL),
+               .driver_data = LG_FF },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
                .driver_data = LG_FF },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
index f099079..088f850 100644 (file)
@@ -72,6 +72,9 @@ static const struct dev_type devices[] = {
        { 0x046d, 0xc287, ff_joystick_ac },
        { 0x046d, 0xc293, ff_joystick },
        { 0x046d, 0xc294, ff_wheel },
+       { 0x046d, 0xc298, ff_wheel },
+       { 0x046d, 0xc299, ff_wheel },
+       { 0x046d, 0xc29b, ff_wheel },
        { 0x046d, 0xc295, ff_joystick },
        { 0x046d, 0xc298, ff_wheel },
        { 0x046d, 0xc299, ff_wheel },
index 0ec91c1..a5eda4c 100644 (file)
@@ -501,9 +501,17 @@ static int magicmouse_probe(struct hid_device *hdev,
        }
        report->size = 6;
 
+       /*
+        * The device reponds with 'invalid report id' when feature
+        * report switching it into multitouch mode is sent to it.
+        *
+        * This results in -EIO from the _raw low-level transport callback,
+        * but there seems to be no other way of switching the mode.
+        * Thus the super-ugly hacky success check below.
+        */
        ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature),
                        HID_FEATURE_REPORT);
-       if (ret != sizeof(feature)) {
+       if (ret != -EIO) {
                hid_err(hdev, "unable to request touch data (%d)\n", ret);
                goto err_stop_hw;
        }
diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c
deleted file mode 100644 (file)
index aed7ffe..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- *  HID driver for the multitouch panel on the ASUS EeePC T91MT
- *
- *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
- *  Copyright (c) 2010 Teemu Tuominen <teemu.tuominen@cybercom.com>
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include "usbhid/usbhid.h"
-
-MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("MosArt dual-touch panel");
-MODULE_LICENSE("GPL");
-
-#include "hid-ids.h"
-
-struct mosart_data {
-       __u16 x, y;
-       __u8 id;
-       bool valid;             /* valid finger data, or just placeholder? */
-       bool first;             /* is this the first finger in this frame? */
-       bool activity_now;      /* at least one active finger in this frame? */
-       bool activity;          /* at least one active finger previously? */
-};
-
-static int mosart_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-               struct hid_field *field, struct hid_usage *usage,
-               unsigned long **bit, int *max)
-{
-       switch (usage->hid & HID_USAGE_PAGE) {
-
-       case HID_UP_GENDESK:
-               switch (usage->hid) {
-               case HID_GD_X:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_POSITION_X);
-                       /* touchscreen emulation */
-                       input_set_abs_params(hi->input, ABS_X,
-                                               field->logical_minimum,
-                                               field->logical_maximum, 0, 0);
-                       return 1;
-               case HID_GD_Y:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_POSITION_Y);
-                       /* touchscreen emulation */
-                       input_set_abs_params(hi->input, ABS_Y,
-                                               field->logical_minimum,
-                                               field->logical_maximum, 0, 0);
-                       return 1;
-               }
-               return 0;
-
-       case HID_UP_DIGITIZER:
-               switch (usage->hid) {
-               case HID_DG_CONFIDENCE:
-               case HID_DG_TIPSWITCH:
-               case HID_DG_INPUTMODE:
-               case HID_DG_DEVICEINDEX:
-               case HID_DG_CONTACTCOUNT:
-               case HID_DG_CONTACTMAX:
-               case HID_DG_TIPPRESSURE:
-               case HID_DG_WIDTH:
-               case HID_DG_HEIGHT:
-                       return -1;
-               case HID_DG_INRANGE:
-                       /* touchscreen emulation */
-                       hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-                       return 1;
-
-               case HID_DG_CONTACTID:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_TRACKING_ID);
-                       return 1;
-
-               }
-               return 0;
-
-       case 0xff000000:
-               /* ignore HID features */
-               return -1;
-
-       case HID_UP_BUTTON:
-               /* ignore buttons */
-               return -1;
-       }
-
-       return 0;
-}
-
-static int mosart_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-               struct hid_field *field, struct hid_usage *usage,
-               unsigned long **bit, int *max)
-{
-       if (usage->type == EV_KEY || usage->type == EV_ABS)
-               clear_bit(usage->code, *bit);
-
-       return 0;
-}
-
-/*
- * this function is called when a whole finger has been parsed,
- * so that it can decide what to send to the input layer.
- */
-static void mosart_filter_event(struct mosart_data *td, struct input_dev *input)
-{
-       td->first = !td->first; /* touchscreen emulation */
-
-       if (!td->valid) {
-               /*
-                * touchscreen emulation: if no finger in this frame is valid
-                * and there previously was finger activity, this is a release
-                */ 
-               if (!td->first && !td->activity_now && td->activity) {
-                       input_event(input, EV_KEY, BTN_TOUCH, 0);
-                       td->activity = false;
-               }
-               return;
-       }
-
-       input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
-       input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
-       input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
-
-       input_mt_sync(input);
-       td->valid = false;
-
-       /* touchscreen emulation: if first active finger in this frame... */
-       if (!td->activity_now) {
-               /* if there was no previous activity, emit touch event */
-               if (!td->activity) {
-                       input_event(input, EV_KEY, BTN_TOUCH, 1);
-                       td->activity = true;
-               }
-               td->activity_now = true;
-               /* and in any case this is our preferred finger */
-               input_event(input, EV_ABS, ABS_X, td->x);
-               input_event(input, EV_ABS, ABS_Y, td->y);
-       }
-}
-
-
-static int mosart_event(struct hid_device *hid, struct hid_field *field,
-                               struct hid_usage *usage, __s32 value)
-{
-       struct mosart_data *td = hid_get_drvdata(hid);
-
-       if (hid->claimed & HID_CLAIMED_INPUT) {
-               struct input_dev *input = field->hidinput->input;
-               switch (usage->hid) {
-               case HID_DG_INRANGE:
-                       td->valid = !!value;
-                       break;
-               case HID_GD_X:
-                       td->x = value;
-                       break;
-               case HID_GD_Y:
-                       td->y = value;
-                       mosart_filter_event(td, input);
-                       break;
-               case HID_DG_CONTACTID:
-                       td->id = value;
-                       break;
-               case HID_DG_CONTACTCOUNT:
-                       /* touch emulation: this is the last field in a frame */
-                       td->first = false;
-                       td->activity_now = false;
-                       break;
-               case HID_DG_CONFIDENCE:
-               case HID_DG_TIPSWITCH:
-                       /* avoid interference from generic hidinput handling */
-                       break;
-
-               default:
-                       /* fallback to the generic hidinput handling */
-                       return 0;
-               }
-       }
-
-       /* we have handled the hidinput part, now remains hiddev */
-       if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-               hid->hiddev_hid_event(hid, field, usage, value);
-
-       return 1;
-}
-
-static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-       int ret;
-       struct mosart_data *td;
-
-
-       td = kmalloc(sizeof(struct mosart_data), GFP_KERNEL);
-       if (!td) {
-               hid_err(hdev, "cannot allocate MosArt data\n");
-               return -ENOMEM;
-       }
-       td->valid = false;
-       td->activity = false;
-       td->activity_now = false;
-       td->first = false;
-       hid_set_drvdata(hdev, td);
-
-       /* currently, it's better to have one evdev device only */
-#if 0
-       hdev->quirks |= HID_QUIRK_MULTI_INPUT;
-#endif
-
-       ret = hid_parse(hdev);
-       if (ret == 0)
-               ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-
-       if (ret == 0) {
-               struct hid_report_enum *re = hdev->report_enum
-                                               + HID_FEATURE_REPORT;
-               struct hid_report *r = re->report_id_hash[7];
-
-               r->field[0]->value[0] = 0x02;
-               usbhid_submit_report(hdev, r, USB_DIR_OUT);
-       } else 
-               kfree(td);
-
-       return ret;
-}
-
-#ifdef CONFIG_PM
-static int mosart_reset_resume(struct hid_device *hdev)
-{
-       struct hid_report_enum *re = hdev->report_enum
-                                               + HID_FEATURE_REPORT;
-       struct hid_report *r = re->report_id_hash[7];
-
-       r->field[0]->value[0] = 0x02;
-       usbhid_submit_report(hdev, r, USB_DIR_OUT);
-       return 0;
-}
-#endif
-
-static void mosart_remove(struct hid_device *hdev)
-{
-       hid_hw_stop(hdev);
-       kfree(hid_get_drvdata(hdev));
-       hid_set_drvdata(hdev, NULL);
-}
-
-static const struct hid_device_id mosart_devices[] = {
-       { 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_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
-       { }
-};
-MODULE_DEVICE_TABLE(hid, mosart_devices);
-
-static const struct hid_usage_id mosart_grabbed_usages[] = {
-       { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-       { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
-};
-
-static struct hid_driver mosart_driver = {
-       .name = "mosart",
-       .id_table = mosart_devices,
-       .probe = mosart_probe,
-       .remove = mosart_remove,
-       .input_mapping = mosart_input_mapping,
-       .input_mapped = mosart_input_mapped,
-       .usage_table = mosart_grabbed_usages,
-       .event = mosart_event,
-#ifdef CONFIG_PM
-       .reset_resume = mosart_reset_resume,
-#endif
-};
-
-static int __init mosart_init(void)
-{
-       return hid_register_driver(&mosart_driver);
-}
-
-static void __exit mosart_exit(void)
-{
-       hid_unregister_driver(&mosart_driver);
-}
-
-module_init(mosart_init);
-module_exit(mosart_exit);
-
index ee01e65..ecd4d2d 100644 (file)
  *  Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
  *  Copyright (c) 2010 Canonical, Ltd.
  *
+ *  This code is partly based on hid-3m-pct.c:
+ *
+ *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
+ *  Copyright (c) 2010      Henrik Rydberg <rydberg@euromail.se>
+ *  Copyright (c) 2010      Canonical, Ltd.
+ *
  */
 
 /*
@@ -44,6 +50,7 @@ MODULE_LICENSE("GPL");
 #define MT_QUIRK_VALID_IS_INRANGE      (1 << 4)
 #define MT_QUIRK_VALID_IS_CONFIDENCE   (1 << 5)
 #define MT_QUIRK_EGALAX_XYZ_FIXUP      (1 << 6)
+#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE   (1 << 7)
 
 struct mt_slot {
        __s32 x, y, p, w, h;
@@ -60,24 +67,36 @@ struct mt_device {
        __s8 inputmode;         /* InputMode HID feature, -1 if non-existent */
        __u8 num_received;      /* how many contacts we received */
        __u8 num_expected;      /* expected last contact index */
+       __u8 maxcontacts;
        bool curvalid;          /* is the current contact valid? */
-       struct mt_slot slots[0];        /* first slot */
+       struct mt_slot *slots;
 };
 
 struct mt_class {
        __s32 name;     /* MT_CLS */
        __s32 quirks;
        __s32 sn_move;  /* Signal/noise ratio for move events */
+       __s32 sn_width; /* Signal/noise ratio for width events */
+       __s32 sn_height;        /* Signal/noise ratio for height events */
        __s32 sn_pressure;      /* Signal/noise ratio for pressure events */
        __u8 maxcontacts;
 };
 
 /* classes of device behavior */
-#define MT_CLS_DEFAULT                         1
-#define MT_CLS_DUAL_INRANGE_CONTACTID          2
-#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER      3
-#define MT_CLS_CYPRESS                         4
-#define MT_CLS_EGALAX                          5
+#define MT_CLS_DEFAULT                         0x0001
+
+#define MT_CLS_CONFIDENCE                      0x0002
+#define MT_CLS_CONFIDENCE_MINUS_ONE            0x0003
+#define MT_CLS_DUAL_INRANGE_CONTACTID          0x0004
+#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER      0x0005
+#define MT_CLS_DUAL_NSMU_CONTACTID             0x0006
+
+/* vendor specific classes */
+#define MT_CLS_3M                              0x0101
+#define MT_CLS_CYPRESS                         0x0102
+#define MT_CLS_EGALAX                          0x0103
+
+#define MT_DEFAULT_MAXCONTACT  10
 
 /*
  * these device-dependent functions determine what slot corresponds
@@ -95,12 +114,12 @@ static int cypress_compute_slot(struct mt_device *td)
 static int find_slot_from_contactid(struct mt_device *td)
 {
        int i;
-       for (i = 0; i < td->mtclass->maxcontacts; ++i) {
+       for (i = 0; i < td->maxcontacts; ++i) {
                if (td->slots[i].contactid == td->curdata.contactid &&
                        td->slots[i].touch_state)
                        return i;
        }
-       for (i = 0; i < td->mtclass->maxcontacts; ++i) {
+       for (i = 0; i < td->maxcontacts; ++i) {
                if (!td->slots[i].seen_in_this_frame &&
                        !td->slots[i].touch_state)
                        return i;
@@ -113,8 +132,12 @@ static int find_slot_from_contactid(struct mt_device *td)
 
 struct mt_class mt_classes[] = {
        { .name = MT_CLS_DEFAULT,
-               .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP,
-               .maxcontacts = 10 },
+               .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
+       { .name = MT_CLS_CONFIDENCE,
+               .quirks = MT_QUIRK_VALID_IS_CONFIDENCE },
+       { .name = MT_CLS_CONFIDENCE_MINUS_ONE,
+               .quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
+                       MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE },
        { .name = MT_CLS_DUAL_INRANGE_CONTACTID,
                .quirks = MT_QUIRK_VALID_IS_INRANGE |
                        MT_QUIRK_SLOT_IS_CONTACTID,
@@ -123,11 +146,24 @@ struct mt_class mt_classes[] = {
                .quirks = MT_QUIRK_VALID_IS_INRANGE |
                        MT_QUIRK_SLOT_IS_CONTACTNUMBER,
                .maxcontacts = 2 },
+       { .name = MT_CLS_DUAL_NSMU_CONTACTID,
+               .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
+                       MT_QUIRK_SLOT_IS_CONTACTID,
+               .maxcontacts = 2 },
+
+       /*
+        * vendor specific classes
+        */
+       { .name = MT_CLS_3M,
+               .quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
+                       MT_QUIRK_SLOT_IS_CONTACTID,
+               .sn_move = 2048,
+               .sn_width = 128,
+               .sn_height = 128 },
        { .name = MT_CLS_CYPRESS,
                .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
                        MT_QUIRK_CYPRESS,
                .maxcontacts = 10 },
-
        { .name = MT_CLS_EGALAX,
                .quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
                        MT_QUIRK_VALID_IS_INRANGE |
@@ -136,15 +172,26 @@ struct mt_class mt_classes[] = {
                .sn_move = 4096,
                .sn_pressure = 32,
        },
+
        { }
 };
 
 static void mt_feature_mapping(struct hid_device *hdev,
                struct hid_field *field, struct hid_usage *usage)
 {
-       if (usage->hid == HID_DG_INPUTMODE) {
-               struct mt_device *td = hid_get_drvdata(hdev);
+       struct mt_device *td = hid_get_drvdata(hdev);
+
+       switch (usage->hid) {
+       case HID_DG_INPUTMODE:
                td->inputmode = field->report->id;
+               break;
+       case HID_DG_CONTACTMAX:
+               td->maxcontacts = field->value[0];
+               if (td->mtclass->maxcontacts)
+                       /* check if the maxcontacts is given by the class */
+                       td->maxcontacts = td->mtclass->maxcontacts;
+
+               break;
        }
 }
 
@@ -179,6 +226,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        /* touchscreen emulation */
                        set_abs(hi->input, ABS_X, field, cls->sn_move);
                        td->last_slot_field = usage->hid;
+                       td->last_field_index = field->index;
                        return 1;
                case HID_GD_Y:
                        if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
@@ -190,6 +238,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        /* touchscreen emulation */
                        set_abs(hi->input, ABS_Y, field, cls->sn_move);
                        td->last_slot_field = usage->hid;
+                       td->last_field_index = field->index;
                        return 1;
                }
                return 0;
@@ -198,32 +247,40 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                switch (usage->hid) {
                case HID_DG_INRANGE:
                        td->last_slot_field = usage->hid;
+                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_CONFIDENCE:
                        td->last_slot_field = usage->hid;
+                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_TIPSWITCH:
                        hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
                        input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
                        td->last_slot_field = usage->hid;
+                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_CONTACTID:
-                       input_mt_init_slots(hi->input,
-                                       td->mtclass->maxcontacts);
+                       input_mt_init_slots(hi->input, td->maxcontacts);
                        td->last_slot_field = usage->hid;
+                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_WIDTH:
                        hid_map_usage(hi, usage, bit, max,
                                        EV_ABS, ABS_MT_TOUCH_MAJOR);
+                       set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
+                               cls->sn_width);
                        td->last_slot_field = usage->hid;
+                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_HEIGHT:
                        hid_map_usage(hi, usage, bit, max,
                                        EV_ABS, ABS_MT_TOUCH_MINOR);
-                       field->logical_maximum = 1;
-                       field->logical_minimum = 0;
-                       set_abs(hi->input, ABS_MT_ORIENTATION, field, 0);
+                       set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
+                               cls->sn_height);
+                       input_set_abs_params(hi->input,
+                                       ABS_MT_ORIENTATION, 0, 1, 0, 0);
                        td->last_slot_field = usage->hid;
+                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_TIPPRESSURE:
                        if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
@@ -236,13 +293,15 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        set_abs(hi->input, ABS_PRESSURE, field,
                                cls->sn_pressure);
                        td->last_slot_field = usage->hid;
+                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_CONTACTCOUNT:
-                       td->last_field_index = field->report->maxfield - 1;
+                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_CONTACTMAX:
                        /* we don't set td->last_slot_field as contactcount and
                         * contact max are global to the report */
+                       td->last_field_index = field->index;
                        return -1;
                }
                /* let hid-input decide for the others */
@@ -279,6 +338,9 @@ static int mt_compute_slot(struct mt_device *td)
        if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER)
                return td->num_received;
 
+       if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
+               return td->curdata.contactid - 1;
+
        return find_slot_from_contactid(td);
 }
 
@@ -292,7 +354,7 @@ static void mt_complete_slot(struct mt_device *td)
        if (td->curvalid) {
                int slotnum = mt_compute_slot(td);
 
-               if (slotnum >= 0 && slotnum < td->mtclass->maxcontacts)
+               if (slotnum >= 0 && slotnum < td->maxcontacts)
                        td->slots[slotnum] = td->curdata;
        }
        td->num_received++;
@@ -307,7 +369,7 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input)
 {
        int i;
 
-       for (i = 0; i < td->mtclass->maxcontacts; ++i) {
+       for (i = 0; i < td->maxcontacts; ++i) {
                struct mt_slot *s = &(td->slots[i]);
                if ((td->mtclass->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) &&
                        !s->seen_in_this_frame) {
@@ -318,11 +380,18 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input)
                input_mt_report_slot_state(input, MT_TOOL_FINGER,
                        s->touch_state);
                if (s->touch_state) {
+                       /* this finger is on the screen */
+                       int wide = (s->w > s->h);
+                       /* divided by two to match visual scale of touch */
+                       int major = max(s->w, s->h) >> 1;
+                       int minor = min(s->w, s->h) >> 1;
+
                        input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
                        input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
+                       input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
                        input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
-                       input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, s->w);
-                       input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, s->h);
+                       input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
+                       input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
                }
                s->seen_in_this_frame = false;
 
@@ -341,7 +410,7 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
        struct mt_device *td = hid_get_drvdata(hid);
        __s32 quirks = td->mtclass->quirks;
 
-       if (hid->claimed & HID_CLAIMED_INPUT) {
+       if (hid->claimed & HID_CLAIMED_INPUT && td->slots) {
                switch (usage->hid) {
                case HID_DG_INRANGE:
                        if (quirks & MT_QUIRK_VALID_IS_INRANGE)
@@ -390,8 +459,6 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
 
                if (usage->hid == td->last_slot_field) {
                        mt_complete_slot(td);
-                       if (!td->last_field_index)
-                               mt_emit_event(td, field->hidinput->input);
                }
 
                if (field->index == td->last_field_index
@@ -442,9 +509,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
         */
        hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
 
-       td = kzalloc(sizeof(struct mt_device) +
-                               mtclass->maxcontacts * sizeof(struct mt_slot),
-                               GFP_KERNEL);
+       td = kzalloc(sizeof(struct mt_device), GFP_KERNEL);
        if (!td) {
                dev_err(&hdev->dev, "cannot allocate multitouch data\n");
                return -ENOMEM;
@@ -461,6 +526,18 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
        if (ret)
                goto fail;
 
+       if (!td->maxcontacts)
+               td->maxcontacts = MT_DEFAULT_MAXCONTACT;
+
+       td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot),
+                               GFP_KERNEL);
+       if (!td->slots) {
+               dev_err(&hdev->dev, "cannot allocate multitouch slots\n");
+               hid_hw_stop(hdev);
+               ret = -ENOMEM;
+               goto fail;
+       }
+
        mt_set_input_mode(hdev);
 
        return 0;
@@ -482,27 +559,115 @@ static void mt_remove(struct hid_device *hdev)
 {
        struct mt_device *td = hid_get_drvdata(hdev);
        hid_hw_stop(hdev);
+       kfree(td->slots);
        kfree(td);
        hid_set_drvdata(hdev, NULL);
 }
 
 static const struct hid_device_id mt_devices[] = {
 
+       /* 3M panels */
+       { .driver_data = MT_CLS_3M,
+               HID_USB_DEVICE(USB_VENDOR_ID_3M,
+                       USB_DEVICE_ID_3M1968) },
+       { .driver_data = MT_CLS_3M,
+               HID_USB_DEVICE(USB_VENDOR_ID_3M,
+                       USB_DEVICE_ID_3M2256) },
+
+       /* ActionStar panels */
+       { .driver_data = MT_CLS_DEFAULT,
+               HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR,
+                       USB_DEVICE_ID_ACTIONSTAR_1011) },
+
+       /* Cando panels */
+       { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
+               HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+                       USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
+       { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
+               HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+                       USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
+       { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
+               HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+                       USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
+       { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
+               HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+                       USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
+
+       /* CVTouch panels */
+       { .driver_data = MT_CLS_DEFAULT,
+               HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
+                       USB_DEVICE_ID_CVTOUCH_SCREEN) },
+
        /* Cypress panel */
        { .driver_data = MT_CLS_CYPRESS,
                HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS,
                        USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
 
+       /* eGalax devices (resistive) */
+       {  .driver_data = MT_CLS_EGALAX,
+               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
+       {  .driver_data = MT_CLS_EGALAX,
+               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
+
+       /* eGalax devices (capacitive) */
+       {  .driver_data = MT_CLS_EGALAX,
+               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
+       {  .driver_data = MT_CLS_EGALAX,
+               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
+       {  .driver_data = MT_CLS_EGALAX,
+               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
+
+       /* Elo TouchSystems IntelliTouch Plus panel */
+       { .driver_data = MT_CLS_DUAL_NSMU_CONTACTID,
+               HID_USB_DEVICE(USB_VENDOR_ID_ELO,
+                       USB_DEVICE_ID_ELO_TS2515) },
+
        /* GeneralTouch panel */
        { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
                HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
                        USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
 
+       /* GoodTouch panels */
+       { .driver_data = MT_CLS_DEFAULT,
+               HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,
+                       USB_DEVICE_ID_GOODTOUCH_000f) },
+
+       /* Ilitek dual touch panel */
+       {  .driver_data = MT_CLS_DEFAULT,
+               HID_USB_DEVICE(USB_VENDOR_ID_ILITEK,
+                       USB_DEVICE_ID_ILITEK_MULTITOUCH) },
+
        /* IRTOUCH panels */
        { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
                HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
                        USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
 
+       /* Lumio panels */
+       { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
+               HID_USB_DEVICE(USB_VENDOR_ID_LUMIO,
+                       USB_DEVICE_ID_CRYSTALTOUCH) },
+
+       /* MosArt panels */
+       { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
+               HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
+                       USB_DEVICE_ID_ASUS_T91MT)},
+       { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
+               HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
+                       USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
+       { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
+               HID_USB_DEVICE(USB_VENDOR_ID_TURBOX,
+                       USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
+
+       /* PenMount panels */
+       { .driver_data = MT_CLS_CONFIDENCE,
+               HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT,
+                       USB_DEVICE_ID_PENMOUNT_PCI) },
+
        /* PixCir-based panels */
        { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
                HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
@@ -511,24 +676,29 @@ static const struct hid_device_id mt_devices[] = {
                HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
                        USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
 
-       /* Resistive eGalax devices */
-       {  .driver_data = MT_CLS_EGALAX,
-               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
-       {  .driver_data = MT_CLS_EGALAX,
-               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
-
-       /* Capacitive eGalax devices */
-       {  .driver_data = MT_CLS_EGALAX,
-               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
-       {  .driver_data = MT_CLS_EGALAX,
-               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
-       {  .driver_data = MT_CLS_EGALAX,
-               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
+       /* Stantum panels */
+       { .driver_data = MT_CLS_CONFIDENCE,
+               HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
+                       USB_DEVICE_ID_MTP)},
+       { .driver_data = MT_CLS_CONFIDENCE,
+               HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
+                       USB_DEVICE_ID_MTP_STM)},
+       { .driver_data = MT_CLS_CONFIDENCE,
+               HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
+                       USB_DEVICE_ID_MTP_SITRONIX)},
+
+       /* Touch International panels */
+       { .driver_data = MT_CLS_DEFAULT,
+               HID_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL,
+                       USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) },
+
+       /* Unitec panels */
+       { .driver_data = MT_CLS_DEFAULT,
+               HID_USB_DEVICE(USB_VENDOR_ID_UNITEC,
+                       USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
+       { .driver_data = MT_CLS_DEFAULT,
+               HID_USB_DEVICE(USB_VENDOR_ID_UNITEC,
+                       USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
 
        { }
 };
index b2f56a1..9d8710f 100644 (file)
@@ -1585,11 +1585,11 @@ static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u,
        memset(raw_data, 0, sizeof(raw_data));
        raw_data[0] = *off & 0xff;
        raw_data[1] = (*off >> 8) & 0xff;
-       raw_data[2] = s < 20 ? s : 20;
+       raw_data[2] = min((size_t)20, s);
        if (*off + raw_data[2] > 0xff)
                raw_data[2] = 0x100 - *off;
 
-       if (copy_from_user(raw_data+3, u, raw_data[2]))
+       if (copy_from_user(raw_data+3, u, min((u8)20, raw_data[2])))
                return -EFAULT;
        resp = picolcd_send_and_wait(data->hdev, REPORT_EE_WRITE, raw_data,
                        sizeof(raw_data));
index 33eec74..5b640a7 100644 (file)
@@ -167,28 +167,28 @@ static int koneplus_set_profile_buttons(struct usb_device *usb_dev,
 }
 
 /* retval is 0-4 on success, < 0 on error */
-static int koneplus_get_startup_profile(struct usb_device *usb_dev)
+static int koneplus_get_actual_profile(struct usb_device *usb_dev)
 {
-       struct koneplus_startup_profile buf;
+       struct koneplus_actual_profile buf;
        int retval;
 
-       retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
-                       &buf, sizeof(struct koneplus_startup_profile));
+       retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_ACTUAL_PROFILE,
+                       &buf, sizeof(struct koneplus_actual_profile));
 
-       return retval ? retval : buf.startup_profile;
+       return retval ? retval : buf.actual_profile;
 }
 
-static int koneplus_set_startup_profile(struct usb_device *usb_dev,
-               int startup_profile)
+static int koneplus_set_actual_profile(struct usb_device *usb_dev,
+               int new_profile)
 {
-       struct koneplus_startup_profile buf;
+       struct koneplus_actual_profile buf;
 
-       buf.command = KONEPLUS_COMMAND_STARTUP_PROFILE;
-       buf.size = sizeof(struct koneplus_startup_profile);
-       buf.startup_profile = startup_profile;
+       buf.command = KONEPLUS_COMMAND_ACTUAL_PROFILE;
+       buf.size = sizeof(struct koneplus_actual_profile);
+       buf.actual_profile = new_profile;
 
-       return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
-                       &buf, sizeof(struct koneplus_profile_buttons));
+       return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_ACTUAL_PROFILE,
+                       &buf, sizeof(struct koneplus_actual_profile));
 }
 
 static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
@@ -398,21 +398,22 @@ static ssize_t koneplus_sysfs_write_profile_buttons(struct file *fp,
        return sizeof(struct koneplus_profile_buttons);
 }
 
-static ssize_t koneplus_sysfs_show_startup_profile(struct device *dev,
+static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
        struct koneplus_device *koneplus =
                        hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
-       return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->startup_profile);
+       return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile);
 }
 
-static ssize_t koneplus_sysfs_set_startup_profile(struct device *dev,
+static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
                struct device_attribute *attr, char const *buf, size_t size)
 {
        struct koneplus_device *koneplus;
        struct usb_device *usb_dev;
        unsigned long profile;
        int retval;
+       struct koneplus_roccat_report roccat_report;
 
        dev = dev->parent->parent;
        koneplus = hid_get_drvdata(dev_get_drvdata(dev));
@@ -423,20 +424,25 @@ static ssize_t koneplus_sysfs_set_startup_profile(struct device *dev,
                return retval;
 
        mutex_lock(&koneplus->koneplus_lock);
-       retval = koneplus_set_startup_profile(usb_dev, profile);
-       mutex_unlock(&koneplus->koneplus_lock);
-       if (retval)
+
+       retval = koneplus_set_actual_profile(usb_dev, profile);
+       if (retval) {
+               mutex_unlock(&koneplus->koneplus_lock);
                return retval;
+       }
 
-       return size;
-}
+       koneplus->actual_profile = profile;
 
-static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct koneplus_device *koneplus =
-                       hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
-       return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile);
+       roccat_report.type = KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE;
+       roccat_report.data1 = profile + 1;
+       roccat_report.data2 = 0;
+       roccat_report.profile = profile + 1;
+       roccat_report_event(koneplus->chrdev_minor,
+                       (uint8_t const *)&roccat_report);
+
+       mutex_unlock(&koneplus->koneplus_lock);
+
+       return size;
 }
 
 static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
@@ -448,11 +454,12 @@ static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
 }
 
 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_startup_profile,
-                       koneplus_sysfs_set_startup_profile),
-       __ATTR(actual_profile, 0440,
-                       koneplus_sysfs_show_actual_profile, NULL),
+                       koneplus_sysfs_show_actual_profile,
+                       koneplus_sysfs_set_actual_profile),
        __ATTR(firmware_version, 0440,
                        koneplus_sysfs_show_firmware_version, NULL),
        __ATTR_NULL
@@ -557,15 +564,10 @@ static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
                struct koneplus_device *koneplus)
 {
        int retval, i;
-       static uint wait = 100; /* device will freeze with just 60 */
+       static uint wait = 200;
 
        mutex_init(&koneplus->koneplus_lock);
 
-       koneplus->startup_profile = koneplus_get_startup_profile(usb_dev);
-       if (koneplus->startup_profile < 0)
-               return koneplus->startup_profile;
-
-       msleep(wait);
        retval = koneplus_get_info(usb_dev, &koneplus->info);
        if (retval)
                return retval;
@@ -584,7 +586,11 @@ static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
                        return retval;
        }
 
-       koneplus_profile_activated(koneplus, koneplus->startup_profile);
+       msleep(wait);
+       retval = koneplus_get_actual_profile(usb_dev);
+       if (retval < 0)
+               return retval;
+       koneplus_profile_activated(koneplus, retval);
 
        return 0;
 }
index 57a5c1a..c57a376 100644 (file)
@@ -40,10 +40,10 @@ enum koneplus_control_values {
        KONEPLUS_CONTROL_REQUEST_STATUS_WAIT = 3,
 };
 
-struct koneplus_startup_profile {
-       uint8_t command; /* KONEPLUS_COMMAND_STARTUP_PROFILE */
+struct koneplus_actual_profile {
+       uint8_t command; /* KONEPLUS_COMMAND_ACTUAL_PROFILE */
        uint8_t size; /* always 3 */
-       uint8_t startup_profile; /* Range 0-4! */
+       uint8_t actual_profile; /* Range 0-4! */
 } __attribute__ ((__packed__));
 
 struct koneplus_profile_settings {
@@ -132,7 +132,7 @@ struct koneplus_tcu_image {
 
 enum koneplus_commands {
        KONEPLUS_COMMAND_CONTROL = 0x4,
-       KONEPLUS_COMMAND_STARTUP_PROFILE = 0x5,
+       KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
        KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
        KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
        KONEPLUS_COMMAND_MACRO = 0x8,
@@ -145,7 +145,7 @@ enum koneplus_commands {
 
 enum koneplus_usb_commands {
        KONEPLUS_USB_COMMAND_CONTROL = 0x304,
-       KONEPLUS_USB_COMMAND_STARTUP_PROFILE = 0x305,
+       KONEPLUS_USB_COMMAND_ACTUAL_PROFILE = 0x305,
        KONEPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306,
        KONEPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307,
        KONEPLUS_USB_COMMAND_MACRO = 0x308,
@@ -215,7 +215,6 @@ struct koneplus_device {
 
        struct mutex koneplus_lock;
 
-       int startup_profile;
        struct koneplus_info info;
        struct koneplus_profile_settings profile_settings[5];
        struct koneplus_profile_buttons profile_buttons[5];
index 93819a0..936c911 100644 (file)
@@ -178,6 +178,8 @@ static void sony_remove(struct hid_device *hdev)
 static const struct hid_device_id sony_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
                .driver_data = SIXAXIS_CONTROLLER_USB },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
+               .driver_data = SIXAXIS_CONTROLLER_USB },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
                .driver_data = SIXAXIS_CONTROLLER_BT },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
diff --git a/drivers/hid/hid-stantum.c b/drivers/hid/hid-stantum.c
deleted file mode 100644 (file)
index b2be1d1..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- *  HID driver for Stantum multitouch panels
- *
- *  Copyright (c) 2009 Stephane Chatty <chatty@enac.fr>
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("Stantum HID multitouch panels");
-MODULE_LICENSE("GPL");
-
-#include "hid-ids.h"
-
-struct stantum_data {
-       __s32 x, y, z, w, h;    /* x, y, pressure, width, height */
-       __u16 id;               /* touch id */
-       bool valid;             /* valid finger data, or just placeholder? */
-       bool first;             /* first finger in the HID packet? */
-       bool activity;          /* at least one active finger so far? */
-};
-
-static int stantum_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-               struct hid_field *field, struct hid_usage *usage,
-               unsigned long **bit, int *max)
-{
-       switch (usage->hid & HID_USAGE_PAGE) {
-
-       case HID_UP_GENDESK:
-               switch (usage->hid) {
-               case HID_GD_X:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_POSITION_X);
-                       /* touchscreen emulation */
-                       input_set_abs_params(hi->input, ABS_X,
-                                               field->logical_minimum,
-                                               field->logical_maximum, 0, 0);
-                       return 1;
-               case HID_GD_Y:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_POSITION_Y);
-                       /* touchscreen emulation */
-                       input_set_abs_params(hi->input, ABS_Y,
-                                               field->logical_minimum,
-                                               field->logical_maximum, 0, 0);
-                       return 1;
-               }
-               return 0;
-
-       case HID_UP_DIGITIZER:
-               switch (usage->hid) {
-               case HID_DG_INRANGE:
-               case HID_DG_CONFIDENCE:
-               case HID_DG_INPUTMODE:
-               case HID_DG_DEVICEINDEX:
-               case HID_DG_CONTACTCOUNT:
-               case HID_DG_CONTACTMAX:
-                       return -1;
-
-               case HID_DG_TIPSWITCH:
-                       /* touchscreen emulation */
-                       hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-                       return 1;
-
-               case HID_DG_WIDTH:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_TOUCH_MAJOR);
-                       return 1;
-               case HID_DG_HEIGHT:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_TOUCH_MINOR);
-                       input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
-                                       1, 1, 0, 0);
-                       return 1;
-               case HID_DG_TIPPRESSURE:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_PRESSURE);
-                       return 1;
-
-               case HID_DG_CONTACTID:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_TRACKING_ID);
-                       return 1;
-
-               }
-               return 0;
-
-       case 0xff000000:
-               /* no input-oriented meaning */
-               return -1;
-       }
-
-       return 0;
-}
-
-static int stantum_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-               struct hid_field *field, struct hid_usage *usage,
-               unsigned long **bit, int *max)
-{
-       if (usage->type == EV_KEY || usage->type == EV_ABS)
-               clear_bit(usage->code, *bit);
-
-       return 0;
-}
-
-/*
- * this function is called when a whole finger has been parsed,
- * so that it can decide what to send to the input layer.
- */
-static void stantum_filter_event(struct stantum_data *sd,
-                                       struct input_dev *input)
-{
-       bool wide;
-
-       if (!sd->valid) {
-               /*
-                * touchscreen emulation: if the first finger is not valid and
-                * there previously was finger activity, this is a release
-                */
-               if (sd->first && sd->activity) {
-                       input_event(input, EV_KEY, BTN_TOUCH, 0);
-                       sd->activity = false;
-               }
-               return;
-       }
-
-       input_event(input, EV_ABS, ABS_MT_TRACKING_ID, sd->id);
-       input_event(input, EV_ABS, ABS_MT_POSITION_X, sd->x);
-       input_event(input, EV_ABS, ABS_MT_POSITION_Y, sd->y);
-
-       wide = (sd->w > sd->h);
-       input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
-       input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, wide ? sd->w : sd->h);
-       input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, wide ? sd->h : sd->w);
-
-       input_event(input, EV_ABS, ABS_MT_PRESSURE, sd->z);
-
-       input_mt_sync(input);
-       sd->valid = false;
-
-       /* touchscreen emulation */
-       if (sd->first) {
-               if (!sd->activity) {
-                       input_event(input, EV_KEY, BTN_TOUCH, 1);
-                       sd->activity = true;
-               }
-               input_event(input, EV_ABS, ABS_X, sd->x);
-               input_event(input, EV_ABS, ABS_Y, sd->y);
-       }
-       sd->first = false;
-}
-
-
-static int stantum_event(struct hid_device *hid, struct hid_field *field,
-                               struct hid_usage *usage, __s32 value)
-{
-       struct stantum_data *sd = hid_get_drvdata(hid);
-
-       if (hid->claimed & HID_CLAIMED_INPUT) {
-               struct input_dev *input = field->hidinput->input;
-
-               switch (usage->hid) {
-               case HID_DG_INRANGE:
-                       /* this is the last field in a finger */
-                       stantum_filter_event(sd, input);
-                       break;
-               case HID_DG_WIDTH:
-                       sd->w = value;
-                       break;
-               case HID_DG_HEIGHT:
-                       sd->h = value;
-                       break;
-               case HID_GD_X:
-                       sd->x = value;
-                       break;
-               case HID_GD_Y:
-                       sd->y = value;
-                       break;
-               case HID_DG_TIPPRESSURE:
-                       sd->z = value;
-                       break;
-               case HID_DG_CONTACTID:
-                       sd->id = value;
-                       break;
-               case HID_DG_CONFIDENCE:
-                       sd->valid = !!value;
-                       break;
-               case 0xff000002:
-                       /* this comes only before the first finger */
-                       sd->first = true;
-                       break;
-
-               default:
-                       /* ignore the others */
-                       return 1;
-               }
-       }
-
-       /* we have handled the hidinput part, now remains hiddev */
-       if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-               hid->hiddev_hid_event(hid, field, usage, value);
-
-       return 1;
-}
-
-static int stantum_probe(struct hid_device *hdev,
-                               const struct hid_device_id *id)
-{
-       int ret;
-       struct stantum_data *sd;
-
-       sd = kmalloc(sizeof(struct stantum_data), GFP_KERNEL);
-       if (!sd) {
-               hid_err(hdev, "cannot allocate Stantum data\n");
-               return -ENOMEM;
-       }
-       sd->valid = false;
-       sd->first = false;
-       sd->activity = false;
-       hid_set_drvdata(hdev, sd);
-
-       ret = hid_parse(hdev);
-       if (!ret)
-               ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-
-       if (ret)
-               kfree(sd);
-
-       return ret;
-}
-
-static void stantum_remove(struct hid_device *hdev)
-{
-       hid_hw_stop(hdev);
-       kfree(hid_get_drvdata(hdev));
-       hid_set_drvdata(hdev, NULL);
-}
-
-static const struct hid_device_id stantum_devices[] = {
-       { 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) },
-       { }
-};
-MODULE_DEVICE_TABLE(hid, stantum_devices);
-
-static const struct hid_usage_id stantum_grabbed_usages[] = {
-       { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-       { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
-};
-
-static struct hid_driver stantum_driver = {
-       .name = "stantum",
-       .id_table = stantum_devices,
-       .probe = stantum_probe,
-       .remove = stantum_remove,
-       .input_mapping = stantum_input_mapping,
-       .input_mapped = stantum_input_mapped,
-       .usage_table = stantum_grabbed_usages,
-       .event = stantum_event,
-};
-
-static int __init stantum_init(void)
-{
-       return hid_register_driver(&stantum_driver);
-}
-
-static void __exit stantum_exit(void)
-{
-       hid_unregister_driver(&stantum_driver);
-}
-
-module_init(stantum_init);
-module_exit(stantum_exit);
-
index 54409cb..c79578b 100644 (file)
@@ -101,8 +101,8 @@ out:
        return ret;
 }
 
-/* the first byte is expected to be a report number */
-/* This function is to be called with the minors_lock mutex held */
+/* The first byte is expected to be a report number.
+ * This function is to be called with the minors_lock mutex held */
 static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, size_t count, unsigned char report_type)
 {
        unsigned int minor = iminor(file->f_path.dentry->d_inode);
@@ -166,11 +166,11 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
 
 
 /* This function performs a Get_Report transfer over the control endpoint
  per section 7.2.1 of the HID specification, version 1.1.  The first byte
  of buffer is the report number to request, or 0x0 if the defice does not
  use numbered reports. The report_type parameter can be HID_FEATURE_REPORT
  or HID_INPUT_REPORT.  This function is to be called with the minors_lock
  mutex held.  */
* per section 7.2.1 of the HID specification, version 1.1.  The first byte
* of buffer is the report number to request, or 0x0 if the defice does not
* use numbered reports. The report_type parameter can be HID_FEATURE_REPORT
* or HID_INPUT_REPORT.  This function is to be called with the minors_lock
*  mutex held. */
 static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t count, unsigned char report_type)
 {
        unsigned int minor = iminor(file->f_path.dentry->d_inode);
@@ -207,7 +207,7 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t
        }
 
        /* Read the first byte from the user. This is the report number,
-          which is passed to dev->hid_get_raw_report(). */
+        * which is passed to dev->hid_get_raw_report(). */
        if (copy_from_user(&report_number, buffer, 1)) {
                ret = -EFAULT;
                goto out_free;
@@ -395,12 +395,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
                                }
 
                                if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
-                                       int len;
-                                       if (!hid->name) {
-                                               ret = 0;
-                                               break;
-                                       }
-                                       len = strlen(hid->name) + 1;
+                                       int len = strlen(hid->name) + 1;
                                        if (len > _IOC_SIZE(cmd))
                                                len = _IOC_SIZE(cmd);
                                        ret = copy_to_user(user_arg, hid->name, len) ?
@@ -409,12 +404,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
                                }
 
                                if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
-                                       int len;
-                                       if (!hid->phys) {
-                                               ret = 0;
-                                               break;
-                                       }
-                                       len = strlen(hid->phys) + 1;
+                                       int len = strlen(hid->phys) + 1;
                                        if (len > _IOC_SIZE(cmd))
                                                len = _IOC_SIZE(cmd);
                                        ret = copy_to_user(user_arg, hid->phys, len) ?
index a8426f1..0e30b14 100644 (file)
@@ -68,6 +68,8 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT },
index af0a7c1..ff3c644 100644 (file)
@@ -242,6 +242,7 @@ static int hiddev_release(struct inode * inode, struct file * file)
        list_del(&list->node);
        spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
 
+       mutex_lock(&list->hiddev->existancelock);
        if (!--list->hiddev->open) {
                if (list->hiddev->exist) {
                        usbhid_close(list->hiddev->hid);
@@ -252,6 +253,7 @@ static int hiddev_release(struct inode * inode, struct file * file)
        }
 
        kfree(list);
+       mutex_unlock(&list->hiddev->existancelock);
 
        return 0;
 }
@@ -300,17 +302,21 @@ static int hiddev_open(struct inode *inode, struct file *file)
        list_add_tail(&list->node, &hiddev->list);
        spin_unlock_irq(&list->hiddev->list_lock);
 
+       mutex_lock(&hiddev->existancelock);
        if (!list->hiddev->open++)
                if (list->hiddev->exist) {
                        struct hid_device *hid = hiddev->hid;
                        res = usbhid_get_power(hid);
                        if (res < 0) {
                                res = -EIO;
-                               goto bail;
+                               goto bail_unlock;
                        }
                        usbhid_open(hid);
                }
+       mutex_unlock(&hiddev->existancelock);
        return 0;
+bail_unlock:
+       mutex_unlock(&hiddev->existancelock);
 bail:
        file->private_data = NULL;
        kfree(list);
@@ -367,8 +373,10 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
                                /* let O_NONBLOCK tasks run */
                                mutex_unlock(&list->thread_lock);
                                schedule();
-                               if (mutex_lock_interruptible(&list->thread_lock))
+                               if (mutex_lock_interruptible(&list->thread_lock)) {
+                                       finish_wait(&list->hiddev->wait, &wait);
                                        return -EINTR;
+                               }
                                set_current_state(TASK_INTERRUPTIBLE);
                        }
                        finish_wait(&list->hiddev->wait, &wait);
@@ -509,7 +517,7 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
                                 (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
                                  uref->usage_index + uref_multi->num_values > field->report_count))
                                goto inval;
-                       }
+               }
 
                switch (cmd) {
                case HIDIOCGUSAGE:
@@ -801,14 +809,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        break;
 
                if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) {
-                       int len;
-
-                       if (!hid->name) {
-                               r = 0;
-                               break;
-                       }
-
-                       len = strlen(hid->name) + 1;
+                       int len = strlen(hid->name) + 1;
                        if (len > _IOC_SIZE(cmd))
                                 len = _IOC_SIZE(cmd);
                        r = copy_to_user(user_arg, hid->name, len) ?
@@ -817,14 +818,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                }
 
                if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) {
-                       int len;
-
-                       if (!hid->phys) {
-                               r = 0;
-                               break;
-                       }
-
-                       len = strlen(hid->phys) + 1;
+                       int len = strlen(hid->phys) + 1;
                        if (len > _IOC_SIZE(cmd))
                                len = _IOC_SIZE(cmd);
                        r = copy_to_user(user_arg, hid->phys, len) ?
@@ -925,7 +919,6 @@ void hiddev_disconnect(struct hid_device *hid)
 
        mutex_lock(&hiddev->existancelock);
        hiddev->exist = 0;
-       mutex_unlock(&hiddev->existancelock);
 
        usb_deregister_dev(usbhid->intf, &hiddev_class);
 
@@ -935,4 +928,5 @@ void hiddev_disconnect(struct hid_device *hid)
        } else {
                kfree(hiddev);
        }
+       mutex_unlock(&hiddev->existancelock);
 }
index 12822cd..19e9500 100644 (file)
@@ -80,7 +80,7 @@
 #define HIDP_VIRTUAL_CABLE_UNPLUG      0
 #define HIDP_BOOT_PROTOCOL_MODE                1
 #define HIDP_BLUETOOTH_VENDOR_ID       9
-#define        HIDP_WAITING_FOR_RETURN         10
+#define HIDP_WAITING_FOR_RETURN                10
 #define HIDP_WAITING_FOR_SEND_ACK      11
 
 struct hidp_connadd_req {
index 41063e7..96a7572 100644 (file)
@@ -61,4 +61,10 @@ config SAMPLE_KDB
          Build an example of how to dynamically add the hello
          command to the kdb shell.
 
+config SAMPLE_HIDRAW
+       bool "Build simple hidraw example"
+       depends on HIDRAW && HEADERS_CHECK
+       help
+         Build an example of how to use hidraw from userspace.
+
 endif # SAMPLES
index f26c095..6280817 100644 (file)
@@ -1,4 +1,4 @@
 # Makefile for Linux samples code
 
 obj-$(CONFIG_SAMPLES)  += kobject/ kprobes/ tracepoints/ trace_events/ \
-                          hw_breakpoint/ kfifo/ kdb/
+                          hw_breakpoint/ kfifo/ kdb/ hidraw/
diff --git a/samples/hidraw/Makefile b/samples/hidraw/Makefile
new file mode 100644 (file)
index 0000000..382eeae
--- /dev/null
@@ -0,0 +1,10 @@
+# kbuild trick to avoid linker error. Can be omitted if a module is built.
+obj- := dummy.o
+
+# List of programs to build
+hostprogs-y := hid-example
+
+# Tell kbuild to always build the programs
+always := $(hostprogs-y)
+
+HOSTCFLAGS_hid-example.o += -I$(objtree)/usr/include
diff --git a/samples/hidraw/hid-example.c b/samples/hidraw/hid-example.c
new file mode 100644 (file)
index 0000000..816e2dc
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Hidraw Userspace Example
+ *
+ * Copyright (c) 2010 Alan Ott <alan@signal11.us>
+ * Copyright (c) 2010 Signal 11 Software
+ *
+ * The code may be used by anyone for any purpose,
+ * and can serve as a starting point for developing
+ * applications using hidraw.
+ */
+
+/* Linux */
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/hidraw.h>
+
+/*
+ * Ugly hack to work around failing compilation on systems that don't
+ * yet populate new version of hidraw.h to userspace.
+ *
+ * If you need this, please have your distro update the kernel headers.
+ */
+#ifndef HIDIOCSFEATURE
+#define HIDIOCSFEATURE(len)    _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
+#define HIDIOCGFEATURE(len)    _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
+#endif
+
+/* Unix */
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+/* C */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+const char *bus_str(int bus);
+
+int main(int argc, char **argv)
+{
+       int fd;
+       int i, res, desc_size = 0;
+       char buf[256];
+       struct hidraw_report_descriptor rpt_desc;
+       struct hidraw_devinfo info;
+
+       /* Open the Device with non-blocking reads. In real life,
+          don't use a hard coded path; use libudev instead. */
+       fd = open("/dev/hidraw0", O_RDWR|O_NONBLOCK);
+
+       if (fd < 0) {
+               perror("Unable to open device");
+               return 1;
+       }
+
+       memset(&rpt_desc, 0x0, sizeof(rpt_desc));
+       memset(&info, 0x0, sizeof(info));
+       memset(buf, 0x0, sizeof(buf));
+
+       /* Get Report Descriptor Size */
+       res = ioctl(fd, HIDIOCGRDESCSIZE, &desc_size);
+       if (res < 0)
+               perror("HIDIOCGRDESCSIZE");
+       else
+               printf("Report Descriptor Size: %d\n", desc_size);
+
+       /* Get Report Descriptor */
+       rpt_desc.size = desc_size;
+       res = ioctl(fd, HIDIOCGRDESC, &rpt_desc);
+       if (res < 0) {
+               perror("HIDIOCGRDESC");
+       } else {
+               printf("Report Descriptor:\n");
+               for (i = 0; i < rpt_desc.size; i++)
+                       printf("%hhx ", rpt_desc.value[i]);
+               puts("\n");
+       }
+
+       /* Get Raw Name */
+       res = ioctl(fd, HIDIOCGRAWNAME(256), buf);
+       if (res < 0)
+               perror("HIDIOCGRAWNAME");
+       else
+               printf("Raw Name: %s\n", buf);
+
+       /* Get Physical Location */
+       res = ioctl(fd, HIDIOCGRAWPHYS(256), buf);
+       if (res < 0)
+               perror("HIDIOCGRAWPHYS");
+       else
+               printf("Raw Phys: %s\n", buf);
+
+       /* Get Raw Info */
+       res = ioctl(fd, HIDIOCGRAWINFO, &info);
+       if (res < 0) {
+               perror("HIDIOCGRAWINFO");
+       } else {
+               printf("Raw Info:\n");
+               printf("\tbustype: %d (%s)\n",
+                       info.bustype, bus_str(info.bustype));
+               printf("\tvendor: 0x%04hx\n", info.vendor);
+               printf("\tproduct: 0x%04hx\n", info.product);
+       }
+
+       /* Set Feature */
+       buf[0] = 0x9; /* Report Number */
+       buf[1] = 0xff;
+       buf[2] = 0xff;
+       buf[3] = 0xff;
+       res = ioctl(fd, HIDIOCSFEATURE(4), buf);
+       if (res < 0)
+               perror("HIDIOCSFEATURE");
+       else
+               printf("ioctl HIDIOCGFEATURE returned: %d\n", res);
+
+       /* Get Feature */
+       buf[0] = 0x9; /* Report Number */
+       res = ioctl(fd, HIDIOCGFEATURE(256), buf);
+       if (res < 0) {
+               perror("HIDIOCGFEATURE");
+       } else {
+               printf("ioctl HIDIOCGFEATURE returned: %d\n", res);
+               printf("Report data (not containing the report number):\n\t");
+               for (i = 0; i < res; i++)
+                       printf("%hhx ", buf[i]);
+               puts("\n");
+       }
+
+       /* Send a Report to the Device */
+       buf[0] = 0x1; /* Report Number */
+       buf[1] = 0x77;
+       res = write(fd, buf, 2);
+       if (res < 0) {
+               printf("Error: %d\n", errno);
+               perror("write");
+       } else {
+               printf("write() wrote %d bytes\n", res);
+       }
+
+       /* Get a report from the device */
+       res = read(fd, buf, 16);
+       if (res < 0) {
+               perror("read");
+       } else {
+               printf("read() read %d bytes:\n\t", res);
+               for (i = 0; i < res; i++)
+                       printf("%hhx ", buf[i]);
+               puts("\n");
+       }
+       close(fd);
+       return 0;
+}
+
+const char *
+bus_str(int bus)
+{
+       switch (bus) {
+       case BUS_USB:
+               return "USB";
+               break;
+       case BUS_HIL:
+               return "HIL";
+               break;
+       case BUS_BLUETOOTH:
+               return "Bluetooth";
+               break;
+       case BUS_VIRTUAL:
+               return "Virtual";
+               break;
+       default:
+               return "Other";
+               break;
+       }
+}