]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge branch 'master' into for-3.12/upstream
authorJiri Kosina <jkosina@suse.cz>
Wed, 4 Sep 2013 08:49:39 +0000 (10:49 +0200)
committerJiri Kosina <jkosina@suse.cz>
Wed, 4 Sep 2013 08:49:57 +0000 (10:49 +0200)
Sync with Linus' tree to be able to apply fixup patch on top
of 9d9a04ee75 ("HID: apple: Add support for the 2013 Macbook Air")

Signed-off-by: Jiri Kosina <jkosina@suse.cz>
34 files changed:
Documentation/input/gamepad.txt [new file with mode: 0644]
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-core.c
drivers/hid/hid-holtekff.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-kye.c
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-magicmouse.c
drivers/hid/hid-ntrig.c
drivers/hid/hid-picolcd_cir.c
drivers/hid/hid-picolcd_debugfs.c
drivers/hid/hid-picolcd_fb.c
drivers/hid/hid-roccat-arvo.c
drivers/hid/hid-roccat-isku.c
drivers/hid/hid-roccat-kone.c
drivers/hid/hid-roccat-koneplus.c
drivers/hid/hid-roccat-konepure.c
drivers/hid/hid-roccat-kovaplus.c
drivers/hid/hid-sensor-hub.c
drivers/hid/hid-speedlink.c
drivers/hid/hid-xinmo.c [new file with mode: 0644]
drivers/hid/hidraw.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/uhid.c
drivers/hid/usbhid/hid-core.c
drivers/hid/usbhid/hid-quirks.c
include/linux/hid-sensor-hub.h
include/linux/hid-sensor-ids.h
include/linux/hid.h
include/linux/hidraw.h
net/bluetooth/hidp/core.c
samples/hidraw/.gitignore [new file with mode: 0644]

diff --git a/Documentation/input/gamepad.txt b/Documentation/input/gamepad.txt
new file mode 100644 (file)
index 0000000..8002c89
--- /dev/null
@@ -0,0 +1,156 @@
+                            Linux Gamepad API
+----------------------------------------------------------------------------
+
+1. Intro
+~~~~~~~~
+Linux provides many different input drivers for gamepad hardware. To avoid
+having user-space deal with different button-mappings for each gamepad, this
+document defines how gamepads are supposed to report their data.
+
+2. Geometry
+~~~~~~~~~~~
+As "gamepad" we define devices which roughly look like this:
+
+            ____________________________              __
+           / [__ZL__]          [__ZR__] \               |
+          / [__ TL __]        [__ TR __] \              | Front Triggers
+       __/________________________________\__         __|
+      /                                  _   \          |
+     /      /\           __             (N)   \         |
+    /       ||      __  |MO|  __     _       _ \        | Main Pad
+   |    <===DP===> |SE|      |ST|   (W) -|- (E) |       |
+    \       ||    ___          ___       _     /        |
+    /\      \/   /   \        /   \     (S)   /\      __|
+   /  \________ | LS  | ____ |  RS | ________/  \       |
+  |         /  \ \___/ /    \ \___/ /  \         |      | Control Sticks
+  |        /    \_____/      \_____/    \        |    __|
+  |       /                              \       |
+   \_____/                                \_____/
+
+       |________|______|    |______|___________|
+         D-Pad    Left       Right   Action Pad
+                 Stick       Stick
+
+                   |_____________|
+                      Menu Pad
+
+Most gamepads have the following features:
+  - Action-Pad
+    4 buttons in diamonds-shape (on the right side). The buttons are
+    differently labeled on most devices so we define them as NORTH,
+    SOUTH, WEST and EAST.
+  - D-Pad (Direction-pad)
+    4 buttons (on the left side) that point up, down, left and right.
+  - Menu-Pad
+    Different constellations, but most-times 2 buttons: SELECT - START
+    Furthermore, many gamepads have a fancy branded button that is used as
+    special system-button. It often looks different to the other buttons and
+    is used to pop up system-menus or system-settings.
+  - Analog-Sticks
+    Analog-sticks provide freely moveable sticks to control directions. Not
+    all devices have both or any, but they are present at most times.
+    Analog-sticks may also provide a digital button if you press them.
+  - Triggers
+    Triggers are located on the upper-side of the pad in vertical direction.
+    Not all devices provide them, but the upper buttons are normally named
+    Left- and Right-Triggers, the lower buttons Z-Left and Z-Right.
+  - Rumble
+    Many devices provide force-feedback features. But are mostly just
+    simple rumble motors.
+
+3. Detection
+~~~~~~~~~~~~
+All gamepads that follow the protocol described here map BTN_GAMEPAD. This is
+an alias for BTN_SOUTH/BTN_A. It can be used to identify a gamepad as such.
+However, not all gamepads provide all features, so you need to test for all
+features that you need, first. How each feature is mapped is described below.
+
+Legacy drivers often don't comply to these rules. As we cannot change them
+for backwards-compatibility reasons, you need to provide fixup mappings in
+user-space yourself. Some of them might also provide module-options that
+change the mappings so you can adivce users to set these.
+
+All new gamepads are supposed to comply with this mapping. Please report any
+bugs, if they don't.
+
+There are a lot of less-featured/less-powerful devices out there, which re-use
+the buttons from this protocol. However, they try to do this in a compatible
+fashion. For example, the "Nintendo Wii Nunchuk" provides two trigger buttons
+and one analog stick. It reports them as if it were a gamepad with only one
+analog stick and two trigger buttons on the right side.
+But that means, that if you only support "real" gamepads, you must test
+devices for _all_ reported events that you need. Otherwise, you will also get
+devices that report a small subset of the events.
+
+No other devices, that do not look/feel like a gamepad, shall report these
+events.
+
+4. Events
+~~~~~~~~~
+Gamepads report the following events:
+
+Action-Pad:
+  Every gamepad device has at least 2 action buttons. This means, that every
+  device reports BTN_SOUTH (which BTN_GAMEPAD is an alias for). Regardless
+  of the labels on the buttons, the codes are sent according to the
+  physical position of the buttons.
+  Please note that 2- and 3-button pads are fairly rare and old. You might
+  want to filter gamepads that do not report all four.
+    2-Button Pad:
+      If only 2 action-buttons are present, they are reported as BTN_SOUTH and
+      BTN_EAST. For vertical layouts, the upper button is BTN_EAST. For
+      horizontal layouts, the button more on the right is BTN_EAST.
+    3-Button Pad:
+      If only 3 action-buttons are present, they are reported as (from left
+      to right): BTN_WEST, BTN_SOUTH, BTN_EAST
+      If the buttons are aligned perfectly vertically, they are reported as
+      (from top down): BTN_WEST, BTN_SOUTH, BTN_EAST
+    4-Button Pad:
+      If all 4 action-buttons are present, they can be aligned in two
+      different formations. If diamond-shaped, they are reported as BTN_NORTH,
+      BTN_WEST, BTN_SOUTH, BTN_EAST according to their physical location.
+      If rectangular-shaped, the upper-left button is BTN_NORTH, lower-left
+      is BTN_WEST, lower-right is BTN_SOUTH and upper-right is BTN_EAST.
+
+D-Pad:
+  Every gamepad provides a D-Pad with four directions: Up, Down, Left, Right
+  Some of these are available as digital buttons, some as analog buttons. Some
+  may even report both. The kernel does not convert between these so
+  applications should support both and choose what is more appropriate if
+  both are reported.
+    Digital buttons are reported as:
+      BTN_DPAD_*
+    Analog buttons are reported as:
+      ABS_HAT0X and ABS_HAT0Y
+
+Analog-Sticks:
+  The left analog-stick is reported as ABS_X, ABS_Y. The right analog stick is
+  reported as ABS_RX, ABS_RY. Zero, one or two sticks may be present.
+  If analog-sticks provide digital buttons, they are mapped accordingly as
+  BTN_THUMBL (first/left) and BTN_THUMBR (second/right).
+
+Triggers:
+  Trigger buttons can be available as digital or analog buttons or both. User-
+  space must correctly deal with any situation and choose the most appropriate
+  mode.
+  Upper trigger buttons are reported as BTN_TR or ABS_HAT1X (right) and BTN_TL
+  or ABS_HAT1Y (left). Lower trigger buttons are reported as BTN_TR2 or
+  ABS_HAT2X (right/ZR) and BTN_TL2 or ABS_HAT2Y (left/ZL).
+  If only one trigger-button combination is present (upper+lower), they are
+  reported as "right" triggers (BTN_TR/ABS_HAT1X).
+
+Menu-Pad:
+  Menu buttons are always digital and are mapped according to their location
+  instead of their labels. That is:
+    1-button Pad: Mapped as BTN_START
+    2-button Pad: Left button mapped as BTN_SELECT, right button mapped as
+                  BTN_START
+  Many pads also have a third button which is branded or has a special symbol
+  and meaning. Such buttons are mapped as BTN_MODE. Examples are the Nintendo
+  "HOME" button, the XBox "X"-button or Sony "P" button.
+
+Rumble:
+  Rumble is adverticed as FF_RUMBLE.
+
+----------------------------------------------------------------------------
+  Written 2013 by David Herrmann <dh.herrmann@gmail.com>
index 14ef6ab6979093605784dfe824c03ff931dd108c..3d7c9f67b6d7631504b9fbaed82fff152e295bb0 100644 (file)
@@ -743,6 +743,14 @@ config HID_WIIMOTE
        To compile this driver as a module, choose M here: the
        module will be called hid-wiimote.
 
+config HID_XINMO
+       tristate "Xin-Mo non-fully compliant devices"
+       depends on HID
+       ---help---
+       Support for Xin-Mo devices that are not fully compliant with the HID
+       standard. Currently only supports the Xin-Mo Dual Arcade. Say Y here
+       if you have a Xin-Mo Dual Arcade controller.
+
 config HID_ZEROPLUS
        tristate "Zeroplus based game controller support"
        depends on HID
index 6f687287e2125168fbfa46ab0f8d9384a08dc797..a959f4aecaf5754d1fd9499b1bad386e57615df5 100644 (file)
@@ -110,6 +110,7 @@ obj-$(CONFIG_HID_TIVO)              += hid-tivo.o
 obj-$(CONFIG_HID_TOPSEED)      += hid-topseed.o
 obj-$(CONFIG_HID_TWINHAN)      += hid-twinhan.o
 obj-$(CONFIG_HID_UCLOGIC)      += hid-uclogic.o
+obj-$(CONFIG_HID_XINMO)                += hid-xinmo.o
 obj-$(CONFIG_HID_ZEROPLUS)     += hid-zpff.o
 obj-$(CONFIG_HID_ZYDACRON)     += hid-zydacron.o
 obj-$(CONFIG_HID_WACOM)                += hid-wacom.o
index 36668d1aca8fc2133299e93cf994857d78cbea2e..ebf57813d31a0a6c78034301689a6ca5da766bb9 100644 (file)
@@ -450,7 +450,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
                        }
                        parser->local.delimiter_depth--;
                }
-               return 1;
+               return 0;
 
        case HID_LOCAL_ITEM_TAG_USAGE:
 
@@ -1128,7 +1128,8 @@ static void hid_output_field(const struct hid_device *hid,
 }
 
 /*
- * Create a report.
+ * Create a report. 'data' has to be allocated using
+ * hid_alloc_report_buf() so that it has proper size.
  */
 
 void hid_output_report(struct hid_report *report, __u8 *data)
@@ -1144,6 +1145,22 @@ void hid_output_report(struct hid_report *report, __u8 *data)
 }
 EXPORT_SYMBOL_GPL(hid_output_report);
 
+/*
+ * Allocator for buffer that is going to be passed to hid_output_report()
+ */
+u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
+{
+       /*
+        * 7 extra bytes are necessary to achieve proper functionality
+        * of implement() working on 8 byte chunks
+        */
+
+       int len = ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
+
+       return kmalloc(len, flags);
+}
+EXPORT_SYMBOL_GPL(hid_alloc_report_buf);
+
 /*
  * Set a field value. The report this field belongs to has to be
  * created and transferred to the device, to set this value in the
@@ -1597,6 +1614,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
@@ -1679,6 +1697,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
@@ -1736,6 +1755,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) },
        { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
index 9a8f051245258973f53ad84f8debef8b2f6db7e9..9325545fc3ae1cac4e3919c1120af6841590d4f4 100644 (file)
@@ -98,7 +98,7 @@ static void holtekff_send(struct holtekff_device *holtekff,
                holtekff->field->value[i] = data[i];
        }
 
-       dbg_hid("sending %*ph\n", 7, data);
+       dbg_hid("sending %7ph\n", data);
 
        hid_hw_request(hid, holtekff->field->report, HID_REQ_SET_REPORT);
 }
index ffe4c7ae3340150cdcfb8c9f3db9c241422cf8eb..9386df57f19587b93e35ca50a0617077420eb007 100644 (file)
 #define USB_VENDOR_ID_KYE              0x0458
 #define USB_DEVICE_ID_KYE_ERGO_525V    0x0087
 #define USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE 0x0138
+#define USB_DEVICE_ID_GENIUS_GX_IMPERATOR      0x4018
 #define USB_DEVICE_ID_KYE_GPEN_560     0x5003
 #define USB_DEVICE_ID_KYE_EASYPEN_I405X        0x5010
 #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X       0x5011
 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16   0x0012
 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17   0x0013
 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18   0x0014
+#define USB_DEVICE_ID_NTRIG_DUOSENSE 0x1500
 
 #define USB_VENDOR_ID_ONTRAK           0x0a07
 #define USB_DEVICE_ID_ONTRAK_ADU100    0x0064
 #define USB_DEVICE_ID_ROCCAT_KONE      0x2ced
 #define USB_DEVICE_ID_ROCCAT_KONEPLUS  0x2d51
 #define USB_DEVICE_ID_ROCCAT_KONEPURE  0x2dbe
+#define USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL  0x2db4
 #define USB_DEVICE_ID_ROCCAT_KONEXTD   0x2e22
 #define USB_DEVICE_ID_ROCCAT_KOVAPLUS  0x2d50
 #define USB_DEVICE_ID_ROCCAT_LUA       0x2c2e
 #define USB_VENDOR_ID_XAT      0x2505
 #define USB_DEVICE_ID_XAT_CSR  0x0220
 
+#define USB_VENDOR_ID_XIN_MO                   0x16c0
+#define USB_DEVICE_ID_XIN_MO_DUAL_ARCADE       0x05e1
+
 #define USB_VENDOR_ID_XIROKU           0x1477
 #define USB_DEVICE_ID_XIROKU_SPX       0x1006
 #define USB_DEVICE_ID_XIROKU_MPX       0x1007
index 7480799e535cb229a8bae89cf3795d1a5e91b738..3fc4034a43678e0282b8e9c4bba42bd3648eeee6 100644 (file)
@@ -340,7 +340,7 @@ static int hidinput_get_battery_property(struct power_supply *psy,
 {
        struct hid_device *dev = container_of(psy, struct hid_device, battery);
        int ret = 0;
-       __u8 buf[2] = {};
+       __u8 *buf;
 
        switch (prop) {
        case POWER_SUPPLY_PROP_PRESENT:
@@ -349,12 +349,19 @@ static int hidinput_get_battery_property(struct power_supply *psy,
                break;
 
        case POWER_SUPPLY_PROP_CAPACITY:
+
+               buf = kmalloc(2 * sizeof(__u8), GFP_KERNEL);
+               if (!buf) {
+                       ret = -ENOMEM;
+                       break;
+               }
                ret = dev->hid_get_raw_report(dev, dev->battery_report_id,
-                                             buf, sizeof(buf),
+                                             buf, 2,
                                              dev->battery_report_type);
 
                if (ret != 2) {
                        ret = -ENODATA;
+                       kfree(buf);
                        break;
                }
                ret = 0;
@@ -364,6 +371,7 @@ static int hidinput_get_battery_property(struct power_supply *psy,
                    buf[1] <= dev->battery_max)
                        val->intval = (100 * (buf[1] - dev->battery_min)) /
                                (dev->battery_max - dev->battery_min);
+               kfree(buf);
                break;
 
        case POWER_SUPPLY_PROP_MODEL_NAME:
index 1e2ee2aa84a023fc5e4412c7fe8c04666a3e6a8e..73845120295eba6f678679715c9ca3f97917a643 100644 (file)
@@ -268,6 +268,26 @@ static __u8 easypen_m610x_rdesc_fixed[] = {
        0xC0                          /*  End Collection                  */
 };
 
+static __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize, int offset, const char *device_name) {
+       /*
+        * the fixup that need to be done:
+        *   - change Usage Maximum in the Comsumer Control
+        *     (report ID 3) to a reasonable value
+        */
+       if (*rsize >= offset + 31 &&
+           /* Usage Page (Consumer Devices) */
+           rdesc[offset] == 0x05 && rdesc[offset + 1] == 0x0c &&
+           /* Usage (Consumer Control) */
+           rdesc[offset + 2] == 0x09 && rdesc[offset + 3] == 0x01 &&
+           /*   Usage Maximum > 12287 */
+           rdesc[offset + 10] == 0x2a && rdesc[offset + 12] > 0x2f) {
+               hid_info(hdev, "fixing up %s report descriptor\n", device_name);
+               rdesc[offset + 12] = 0x2f;
+       }
+       return rdesc;
+}
+
 static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
 {
@@ -315,23 +335,12 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                }
                break;
        case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE:
-               /*
-                * the fixup that need to be done:
-                *   - change Usage Maximum in the Comsumer Control
-                *     (report ID 3) to a reasonable value
-                */
-               if (*rsize >= 135 &&
-                       /* Usage Page (Consumer Devices) */
-                       rdesc[104] == 0x05 && rdesc[105] == 0x0c &&
-                       /* Usage (Consumer Control) */
-                       rdesc[106] == 0x09 && rdesc[107] == 0x01 &&
-                       /*   Usage Maximum > 12287 */
-                       rdesc[114] == 0x2a && rdesc[116] > 0x2f) {
-                       hid_info(hdev,
-                                "fixing up Genius Gila Gaming Mouse "
-                                "report descriptor\n");
-                       rdesc[116] = 0x2f;
-               }
+               rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
+                                       "Genius Gila Gaming Mouse");
+               break;
+       case USB_DEVICE_ID_GENIUS_GX_IMPERATOR:
+               rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83,
+                                       "Genius Gx Imperator Keyboard");
                break;
        }
        return rdesc;
@@ -428,6 +437,8 @@ static const struct hid_device_id kye_devices[] = {
                                USB_DEVICE_ID_KYE_EASYPEN_M610X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
                                USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
+                               USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, kye_devices);
index cd33084c78602146d42efca60e358d08f00da219..d0e5963c1ba189a877ece23123839d8f3a29df8c 100644 (file)
@@ -619,7 +619,7 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
 
        struct hid_field *field;
        struct hid_report *report;
-       unsigned char data[8];
+       unsigned char *data;
        int offset;
 
        dbg_hid("%s: %s, type:%d | code:%d | value:%d\n",
@@ -635,6 +635,13 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
                return -1;
        }
        hid_set_field(field, offset, value);
+
+       data = hid_alloc_report_buf(field->report, GFP_ATOMIC);
+       if (!data) {
+               dev_warn(&dev->dev, "failed to allocate report buf memory\n");
+               return -1;
+       }
+
        hid_output_report(field->report, &data[0]);
 
        output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT];
@@ -645,8 +652,9 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
 
        hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT);
 
-       return 0;
+       kfree(data);
 
+       return 0;
 }
 
 static int logi_dj_ll_start(struct hid_device *hid)
index 5bc37343eb22b3de7f3cca6163c6f1fd9a10dd4b..a32f5a24b27ceadcdfe33e05a8fe9715eed4d38a 100644 (file)
@@ -36,7 +36,7 @@ MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel");
 static unsigned int scroll_speed = 32;
 static int param_set_scroll_speed(const char *val, struct kernel_param *kp) {
        unsigned long speed;
-       if (!val || strict_strtoul(val, 0, &speed) || speed > 63)
+       if (!val || kstrtoul(val, 0, &speed) || speed > 63)
                return -EINVAL;
        scroll_speed = speed;
        return 0;
index ef95102515e4d499143dd02a831481902d674b1e..98d1fdf7d8cd0d2e3d5c7ae6b240e15085a951d7 100644 (file)
@@ -237,7 +237,7 @@ static ssize_t set_min_width(struct device *dev,
 
        unsigned long val;
 
-       if (strict_strtoul(buf, 0, &val))
+       if (kstrtoul(buf, 0, &val))
                return -EINVAL;
 
        if (val > nd->sensor_physical_width)
@@ -272,7 +272,7 @@ static ssize_t set_min_height(struct device *dev,
 
        unsigned long val;
 
-       if (strict_strtoul(buf, 0, &val))
+       if (kstrtoul(buf, 0, &val))
                return -EINVAL;
 
        if (val > nd->sensor_physical_height)
@@ -306,7 +306,7 @@ static ssize_t set_activate_slack(struct device *dev,
 
        unsigned long val;
 
-       if (strict_strtoul(buf, 0, &val))
+       if (kstrtoul(buf, 0, &val))
                return -EINVAL;
 
        if (val > 0x7f)
@@ -341,7 +341,7 @@ static ssize_t set_activation_width(struct device *dev,
 
        unsigned long val;
 
-       if (strict_strtoul(buf, 0, &val))
+       if (kstrtoul(buf, 0, &val))
                return -EINVAL;
 
        if (val > nd->sensor_physical_width)
@@ -377,7 +377,7 @@ static ssize_t set_activation_height(struct device *dev,
 
        unsigned long val;
 
-       if (strict_strtoul(buf, 0, &val))
+       if (kstrtoul(buf, 0, &val))
                return -EINVAL;
 
        if (val > nd->sensor_physical_height)
@@ -411,7 +411,7 @@ static ssize_t set_deactivate_slack(struct device *dev,
 
        unsigned long val;
 
-       if (strict_strtoul(buf, 0, &val))
+       if (kstrtoul(buf, 0, &val))
                return -EINVAL;
 
        /*
index e346038f0f111eaf1b47571552df952d10537760..59d5eb1e742c98b8721f14a100528b587c25e3ef 100644 (file)
@@ -145,6 +145,7 @@ void picolcd_exit_cir(struct picolcd_data *data)
        struct rc_dev *rdev = data->rc_dev;
 
        data->rc_dev = NULL;
-       rc_unregister_device(rdev);
+       if (rdev)
+               rc_unregister_device(rdev);
 }
 
index 59ab8e157e6b249d025ea26d4bd0ba4b2bb7f227..024cdf3c2297f91d6288cd13cf75e3a4c4881991 100644 (file)
@@ -394,7 +394,7 @@ static void dump_buff_as_hex(char *dst, size_t dst_sz, const u8 *data,
 void picolcd_debug_out_report(struct picolcd_data *data,
                struct hid_device *hdev, struct hid_report *report)
 {
-       u8 raw_data[70];
+       u8 *raw_data;
        int raw_size = (report->size >> 3) + 1;
        char *buff;
 #define BUFF_SZ 256
@@ -407,20 +407,20 @@ void picolcd_debug_out_report(struct picolcd_data *data,
        if (!buff)
                return;
 
-       snprintf(buff, BUFF_SZ, "\nout report %d (size %d) =  ",
-                       report->id, raw_size);
-       hid_debug_event(hdev, buff);
-       if (raw_size + 5 > sizeof(raw_data)) {
+       raw_data = hid_alloc_report_buf(report, GFP_ATOMIC);
+       if (!raw_data) {
                kfree(buff);
-               hid_debug_event(hdev, " TOO BIG\n");
                return;
-       } else {
-               raw_data[0] = report->id;
-               hid_output_report(report, raw_data);
-               dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
-               hid_debug_event(hdev, buff);
        }
 
+       snprintf(buff, BUFF_SZ, "\nout report %d (size %d) =  ",
+                       report->id, raw_size);
+       hid_debug_event(hdev, buff);
+       raw_data[0] = report->id;
+       hid_output_report(report, raw_data);
+       dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
+       hid_debug_event(hdev, buff);
+
        switch (report->id) {
        case REPORT_LED_STATE:
                /* 1 data byte with GPO state */
@@ -644,6 +644,7 @@ void picolcd_debug_out_report(struct picolcd_data *data,
                break;
        }
        wake_up_interruptible(&hdev->debug_wait);
+       kfree(raw_data);
        kfree(buff);
 }
 
index 591f6b22aa947190a9e728b650caa40090cc9595..c930ab8554eac830dd8d615e86c01926bb716be0 100644 (file)
@@ -593,10 +593,14 @@ int picolcd_init_framebuffer(struct picolcd_data *data)
 void picolcd_exit_framebuffer(struct picolcd_data *data)
 {
        struct fb_info *info = data->fb_info;
-       struct picolcd_fb_data *fbdata = info->par;
+       struct picolcd_fb_data *fbdata;
        unsigned long flags;
 
+       if (!info)
+               return;
+
        device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate);
+       fbdata = info->par;
 
        /* disconnect framebuffer from HID dev */
        spin_lock_irqsave(&fbdata->lock, flags);
index 327f9b8ed1f4ea3cea3e89166c29570a9539d306..071ee9e2fd9fea5c4d40165e60e6f1b71e5bd7a4 100644 (file)
@@ -59,7 +59,7 @@ static ssize_t arvo_sysfs_set_mode_key(struct device *dev,
        unsigned long state;
        int retval;
 
-       retval = strict_strtoul(buf, 10, &state);
+       retval = kstrtoul(buf, 10, &state);
        if (retval)
                return retval;
 
@@ -107,7 +107,7 @@ static ssize_t arvo_sysfs_set_key_mask(struct device *dev,
        unsigned long key_mask;
        int retval;
 
-       retval = strict_strtoul(buf, 10, &key_mask);
+       retval = kstrtoul(buf, 10, &key_mask);
        if (retval)
                return retval;
 
@@ -159,7 +159,7 @@ static ssize_t arvo_sysfs_set_actual_profile(struct device *dev,
        unsigned long profile;
        int retval;
 
-       retval = strict_strtoul(buf, 10, &profile);
+       retval = kstrtoul(buf, 10, &profile);
        if (retval)
                return retval;
 
index 8023751d525766ae16b32f8a8943f8c5f9b0796e..5dd0ea4eb4f71ec6cfc210b5a71a8b648a709461 100644 (file)
@@ -82,7 +82,7 @@ static ssize_t isku_sysfs_set_actual_profile(struct device *dev,
        isku = hid_get_drvdata(dev_get_drvdata(dev));
        usb_dev = interface_to_usbdev(to_usb_interface(dev));
 
-       retval = strict_strtoul(buf, 10, &profile);
+       retval = kstrtoul(buf, 10, &profile);
        if (retval)
                return retval;
 
index 7fae070788fa2e4b03fb9281e792aaf9e24065a4..00ab287f73849b94d85c3d4bf603733273396fc6 100644 (file)
@@ -456,7 +456,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev,
        kone = hid_get_drvdata(dev_get_drvdata(dev));
        usb_dev = interface_to_usbdev(to_usb_interface(dev));
 
-       retval = strict_strtoul(buf, 10, &state);
+       retval = kstrtoul(buf, 10, &state);
        if (retval)
                return retval;
 
@@ -545,7 +545,7 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
        kone = hid_get_drvdata(dev_get_drvdata(dev));
        usb_dev = interface_to_usbdev(to_usb_interface(dev));
 
-       retval = strict_strtoul(buf, 10, &new_startup_profile);
+       retval = kstrtoul(buf, 10, &new_startup_profile);
        if (retval)
                return retval;
 
index 6a48fa3c7da913e487e5aa0b1538ba5aff19bbb1..26b9663ddf4746ce1590733745d77f512c46d8c0 100644 (file)
@@ -246,7 +246,7 @@ static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
        koneplus = hid_get_drvdata(dev_get_drvdata(dev));
        usb_dev = interface_to_usbdev(to_usb_interface(dev));
 
-       retval = strict_strtoul(buf, 10, &profile);
+       retval = kstrtoul(buf, 10, &profile);
        if (retval)
                return retval;
 
index c79d0b06c143d8aa1a0bd6dfacdad5a9c56b16e0..5850959d48f573f64ff7b4e7d59732df512e82fe 100644 (file)
@@ -262,6 +262,7 @@ static int konepure_raw_event(struct hid_device *hdev,
 
 static const struct hid_device_id konepure_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL) },
        { }
 };
 
@@ -300,5 +301,5 @@ module_init(konepure_init);
 module_exit(konepure_exit);
 
 MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat KonePure driver");
+MODULE_DESCRIPTION("USB Roccat KonePure/Optical driver");
 MODULE_LICENSE("GPL v2");
index b8b37789b864bbeb3c4de24047658172518b25ec..c2a17e45c99cb6fa49443e68c0b37fe9f7839f99 100644 (file)
@@ -282,7 +282,7 @@ static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev,
        kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
        usb_dev = interface_to_usbdev(to_usb_interface(dev));
 
-       retval = strict_strtoul(buf, 10, &profile);
+       retval = kstrtoul(buf, 10, &profile);
        if (retval)
                return retval;
 
index ca74981073271effdddc72ba1f173acea27ebbf9..ffc80cf481b438e68c13992ede4352f6c480870a 100644 (file)
@@ -416,7 +416,7 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
                return 1;
 
        ptr = raw_data;
-       ptr++; /*Skip report id*/
+       ptr++; /* Skip report id */
 
        spin_lock_irqsave(&pdata->lock, flags);
 
index a2f587d004e1e6afccadcd424a2ac5af202a74b6..7112f3e832ee22cd39f725f5f1100bb47f966643 100644 (file)
@@ -3,7 +3,7 @@
  *  Fixes "jumpy" cursor and removes nonexistent keyboard LEDS from
  *  the HID descriptor.
  *
- *  Copyright (c) 2011 Stefan Kriwanek <mail@stefankriwanek.de>
+ *  Copyright (c) 2011, 2013 Stefan Kriwanek <dev@stefankriwanek.de>
  */
 
 /*
@@ -46,8 +46,13 @@ static int speedlink_event(struct hid_device *hdev, struct hid_field *field,
                struct hid_usage *usage, __s32 value)
 {
        /* No other conditions due to usage_table. */
-       /* Fix "jumpy" cursor (invalid events sent by device). */
-       if (value == 256)
+
+       /* This fixes the "jumpy" cursor occuring due to invalid events sent
+        * by the device. Some devices only send them with value==+256, others
+        * don't. However, catching abs(value)>=256 is restrictive enough not
+        * to interfere with devices that were bug-free (has been tested).
+        */
+       if (abs(value) >= 256)
                return 1;
        /* Drop useless distance 0 events (on button clicks etc.) as well */
        if (value == 0)
diff --git a/drivers/hid/hid-xinmo.c b/drivers/hid/hid-xinmo.c
new file mode 100644 (file)
index 0000000..7df5227
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *  HID driver for Xin-Mo devices, currently only the Dual Arcade controller.
+ *  Fixes the negative axis event values (the devices sends -2) to match the
+ *  logical axis minimum of the HID report descriptor (the report announces
+ *  -1). It is needed because hid-input discards out of bounds values.
+ *  (This module is based on "hid-saitek" and "hid-lg".)
+ *
+ *  Copyright (c) 2013 Olivier Scherler
+ */
+
+/*
+ * 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/kernel.h>
+
+#include "hid-ids.h"
+
+/*
+ * Fix negative events that are out of bounds.
+ */
+static int xinmo_event(struct hid_device *hdev, struct hid_field *field,
+               struct hid_usage *usage, __s32 value)
+{
+       switch (usage->code) {
+       case ABS_X:
+       case ABS_Y:
+       case ABS_Z:
+       case ABS_RX:
+               if (value < -1) {
+                       input_event(field->hidinput->input, usage->type,
+                               usage->code, -1);
+                       return 1;
+               }
+               break;
+       }
+
+       return 0;
+}
+
+static const struct hid_device_id xinmo_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE) },
+       { }
+};
+
+MODULE_DEVICE_TABLE(hid, xinmo_devices);
+
+static struct hid_driver xinmo_driver = {
+       .name = "xinmo",
+       .id_table = xinmo_devices,
+       .event = xinmo_event
+};
+
+module_hid_driver(xinmo_driver);
+MODULE_LICENSE("GPL");
index 6f1feb2c2e97b5defb0628d92bfc98a719449685..8918dd12bb6915d08ab588e04b22b64a24d6e827 100644 (file)
@@ -113,7 +113,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
        __u8 *buf;
        int ret = 0;
 
-       if (!hidraw_table[minor]) {
+       if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
                ret = -ENODEV;
                goto out;
        }
@@ -253,6 +253,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
        unsigned int minor = iminor(inode);
        struct hidraw *dev;
        struct hidraw_list *list;
+       unsigned long flags;
        int err = 0;
 
        if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) {
@@ -261,16 +262,11 @@ static int hidraw_open(struct inode *inode, struct file *file)
        }
 
        mutex_lock(&minors_lock);
-       if (!hidraw_table[minor]) {
+       if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
                err = -ENODEV;
                goto out_unlock;
        }
 
-       list->hidraw = hidraw_table[minor];
-       mutex_init(&list->read_mutex);
-       list_add_tail(&list->node, &hidraw_table[minor]->list);
-       file->private_data = list;
-
        dev = hidraw_table[minor];
        if (!dev->open++) {
                err = hid_hw_power(dev->hid, PM_HINT_FULLON);
@@ -283,9 +279,16 @@ static int hidraw_open(struct inode *inode, struct file *file)
                if (err < 0) {
                        hid_hw_power(dev->hid, PM_HINT_NORMAL);
                        dev->open--;
+                       goto out_unlock;
                }
        }
 
+       list->hidraw = hidraw_table[minor];
+       mutex_init(&list->read_mutex);
+       spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
+       list_add_tail(&list->node, &hidraw_table[minor]->list);
+       spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
+       file->private_data = list;
 out_unlock:
        mutex_unlock(&minors_lock);
 out:
@@ -302,39 +305,41 @@ static int hidraw_fasync(int fd, struct file *file, int on)
        return fasync_helper(fd, file, on, &list->fasync);
 }
 
+static void drop_ref(struct hidraw *hidraw, int exists_bit)
+{
+       if (exists_bit) {
+               hid_hw_close(hidraw->hid);
+               hidraw->exist = 0;
+               if (hidraw->open)
+                       wake_up_interruptible(&hidraw->wait);
+       } else {
+               --hidraw->open;
+       }
+
+       if (!hidraw->open && !hidraw->exist) {
+               device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
+               hidraw_table[hidraw->minor] = NULL;
+               kfree(hidraw);
+       }
+}
+
 static int hidraw_release(struct inode * inode, struct file * file)
 {
        unsigned int minor = iminor(inode);
-       struct hidraw *dev;
        struct hidraw_list *list = file->private_data;
-       int ret;
-       int i;
+       unsigned long flags;
 
        mutex_lock(&minors_lock);
-       if (!hidraw_table[minor]) {
-               ret = -ENODEV;
-               goto unlock;
-       }
 
+       spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
        list_del(&list->node);
-       dev = hidraw_table[minor];
-       if (!--dev->open) {
-               if (list->hidraw->exist) {
-                       hid_hw_power(dev->hid, PM_HINT_NORMAL);
-                       hid_hw_close(dev->hid);
-               } else {
-                       kfree(list->hidraw);
-               }
-       }
-
-       for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i)
-               kfree(list->buffer[i].value);
+       spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
        kfree(list);
-       ret = 0;
-unlock:
-       mutex_unlock(&minors_lock);
 
-       return ret;
+       drop_ref(hidraw_table[minor], 0);
+
+       mutex_unlock(&minors_lock);
+       return 0;
 }
 
 static long hidraw_ioctl(struct file *file, unsigned int cmd,
@@ -457,7 +462,9 @@ int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
        struct hidraw *dev = hid->hidraw;
        struct hidraw_list *list;
        int ret = 0;
+       unsigned long flags;
 
+       spin_lock_irqsave(&dev->list_lock, flags);
        list_for_each_entry(list, &dev->list, node) {
                int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
 
@@ -472,6 +479,7 @@ int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
                list->head = new_head;
                kill_fasync(&list->fasync, SIGIO, POLL_IN);
        }
+       spin_unlock_irqrestore(&dev->list_lock, flags);
 
        wake_up_interruptible(&dev->wait);
        return ret;
@@ -519,6 +527,7 @@ int hidraw_connect(struct hid_device *hid)
        }
 
        init_waitqueue_head(&dev->wait);
+       spin_lock_init(&dev->list_lock);
        INIT_LIST_HEAD(&dev->list);
 
        dev->hid = hid;
@@ -539,18 +548,9 @@ void hidraw_disconnect(struct hid_device *hid)
        struct hidraw *hidraw = hid->hidraw;
 
        mutex_lock(&minors_lock);
-       hidraw->exist = 0;
 
-       device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
+       drop_ref(hidraw, 1);
 
-       hidraw_table[hidraw->minor] = NULL;
-
-       if (hidraw->open) {
-               hid_hw_close(hid);
-               wake_up_interruptible(&hidraw->wait);
-       } else {
-               kfree(hidraw);
-       }
        mutex_unlock(&minors_lock);
 }
 EXPORT_SYMBOL_GPL(hidraw_disconnect);
index 879b0ed701a3fb4109243a2642857c16518185b8..3cb7d966da9ee50f38651f3c055a7d8eff7f0189 100644 (file)
@@ -824,8 +824,8 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
         * bytes 2-3 -> bcdVersion (has to be 1.00) */
        ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer, 4);
 
-       i2c_hid_dbg(ihid, "%s, ihid->hdesc_buffer: %*ph\n",
-                       __func__, 4, ihid->hdesc_buffer);
+       i2c_hid_dbg(ihid, "%s, ihid->hdesc_buffer: %4ph\n", __func__,
+                       ihid->hdesc_buffer);
 
        if (ret) {
                dev_err(&client->dev,
index fc307e0422afc92c31bfac65d410244d5859e804..9ab7dfc6c72cf129d5445c7531563d9119c1cf87 100644 (file)
@@ -659,3 +659,4 @@ module_exit(uhid_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
 MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem");
+MODULE_ALIAS("devname:" UHID_NAME);
index 99418285222cf118cbc09e4d9029c80ba3493fcf..ada164e1b3a1fd909c8c6a437dc2cc5cb424a845 100644 (file)
@@ -535,7 +535,6 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
 {
        int head;
        struct usbhid_device *usbhid = hid->driver_data;
-       int len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
 
        if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
                return;
@@ -546,7 +545,7 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
                        return;
                }
 
-               usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC);
+               usbhid->out[usbhid->outhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC);
                if (!usbhid->out[usbhid->outhead].raw_report) {
                        hid_warn(hid, "output queueing failed\n");
                        return;
@@ -595,7 +594,7 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
        }
 
        if (dir == USB_DIR_OUT) {
-               usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC);
+               usbhid->ctrl[usbhid->ctrlhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC);
                if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) {
                        hid_warn(hid, "control queueing failed\n");
                        return;
index 19b8360f2330ddec85856e09605a1ce69e32d880..07345521f4210f4988627cff4421beedc96d1c06 100644 (file)
@@ -109,6 +109,8 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS },
+
        { 0, 0 }
 };
 
index ecefb7311dd61c2310114c71a0e2f54608ce3597..32ba45158d39eaf050adfc411118163f23858b4f 100644 (file)
@@ -172,7 +172,7 @@ struct hid_sensor_common {
        struct hid_sensor_hub_attribute_info sensitivity;
 };
 
-/*Convert from hid unit expo to regular exponent*/
+/* Convert from hid unit expo to regular exponent */
 static inline int hid_sensor_convert_exponent(int unit_expo)
 {
        if (unit_expo < 0x08)
index 6f24446e76699b295eef42e6e8946388766a121e..4f945d3ed49fc7a511affdc307ea84aff60565cb 100644 (file)
@@ -37,7 +37,7 @@
 #define HID_USAGE_SENSOR_ANGL_VELOCITY_Y_AXIS                  0x200458
 #define HID_USAGE_SENSOR_ANGL_VELOCITY_Z_AXIS                  0x200459
 
-/*ORIENTATION: Compass 3D: (200083) */
+/* ORIENTATION: Compass 3D: (200083) */
 #define HID_USAGE_SENSOR_COMPASS_3D                            0x200083
 #define HID_USAGE_SENSOR_ORIENT_MAGN_HEADING                   0x200471
 #define HID_USAGE_SENSOR_ORIENT_MAGN_HEADING_X                 0x200472
index 0c48991b0402d0d93110b8a4fa9cd42d615279c2..acccdf4eb48598240064e00011594cd54a5254a8 100644 (file)
@@ -744,6 +744,7 @@ struct hid_field *hidinput_get_led_field(struct hid_device *hid);
 unsigned int hidinput_count_leds(struct hid_device *hid);
 __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code);
 void hid_output_report(struct hid_report *report, __u8 *data);
+u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags);
 struct hid_device *hid_allocate_device(void);
 struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
 int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
index 2451662c728a7881e5d7d42fe02d17c15ce86914..ddf52612eed85dffed82a0d1993892ba848dc38b 100644 (file)
@@ -23,6 +23,7 @@ struct hidraw {
        wait_queue_head_t wait;
        struct hid_device *hid;
        struct device *dev;
+       spinlock_t list_lock;
        struct list_head list;
 };
 
index 0c699cdc3696edbdf7e7c3d3e213a88979da662e..d38ab152700698baf92f3e7dc128495f3beca713 100644 (file)
@@ -225,17 +225,22 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
 
 static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
 {
-       unsigned char buf[32], hdr;
-       int rsize;
+       unsigned char hdr;
+       u8 *buf;
+       int rsize, ret;
 
-       rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
-       if (rsize > sizeof(buf))
+       buf = hid_alloc_report_buf(report, GFP_ATOMIC);
+       if (!buf)
                return -EIO;
 
        hid_output_report(report, buf);
        hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
 
-       return hidp_send_intr_message(session, hdr, buf, rsize);
+       rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
+       ret = hidp_send_intr_message(session, hdr, buf, rsize);
+
+       kfree(buf);
+       return ret;
 }
 
 static int hidp_get_raw_report(struct hid_device *hid,
diff --git a/samples/hidraw/.gitignore b/samples/hidraw/.gitignore
new file mode 100644 (file)
index 0000000..05e51a6
--- /dev/null
@@ -0,0 +1 @@
+hid-example