HID: rmi: Scan the report descriptor to determine if the device is suitable for the...
authorAndrew Duggan <aduggan@synaptics.com>
Fri, 12 Dec 2014 18:17:26 +0000 (10:17 -0800)
committerJiri Kosina <jkosina@suse.cz>
Wed, 17 Dec 2014 08:13:13 +0000 (09:13 +0100)
On composite HID devices there may be multiple HID devices on separate
interfaces, but hid-rmi should only bind to the touchpad. The previous version
simply checked that the interface protocol was set to mouse. Unfortuately, it
is not always the case that the touchpad has the mouse interface protocol set.
This patch takes a different approach and scans the report descriptor looking
for the Generic Desktop Pointer usage and the Vendor Specific Top Level
Collection needed by the hid-rmi driver to interface with the device.

Signed-off-by: Andrew Duggan <aduggan@synaptics.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
drivers/hid/hid-core.c
include/linux/hid.h

index c3d0ac1a0988096eaacbe8063b354399b6a85e14..81665b4f225827a78863dde889cc6b16e694783b 100644 (file)
@@ -698,6 +698,7 @@ static void hid_scan_feature_usage(struct hid_parser *parser, u32 usage)
 static void hid_scan_collection(struct hid_parser *parser, unsigned type)
 {
        struct hid_device *hid = parser->device;
+       int i;
 
        if (((parser->global.usage_page << 16) == HID_UP_SENSOR) &&
            type == HID_COLLECTION_PHYSICAL)
@@ -707,6 +708,14 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type)
            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 &&
            hid->group == HID_GROUP_MULTITOUCH)
                hid->group = HID_GROUP_GENERIC;
+
+       if ((parser->global.usage_page << 16) == HID_UP_GENDESK)
+               for (i = 0; i < parser->local.usage_index; i++)
+                       if (parser->local.usage[i] == HID_GD_POINTER)
+                               parser->scan_flags |= HID_SCAN_FLAG_GD_POINTER;
+
+       if ((parser->global.usage_page << 16) >= HID_UP_MSVENDOR)
+               parser->scan_flags |= HID_SCAN_FLAG_VENDOR_SPECIFIC;
 }
 
 static int hid_scan_main(struct hid_parser *parser, struct hid_item *item)
@@ -792,11 +801,14 @@ static int hid_scan_report(struct hid_device *hid)
                hid->group = HID_GROUP_WACOM;
                break;
        case USB_VENDOR_ID_SYNAPTICS:
-               if ((hid->group == HID_GROUP_GENERIC) &&
-                   (hid->bus != BUS_USB || hid->type == HID_TYPE_USBMOUSE))
-                       /* hid-rmi should only bind to the mouse interface of
-                        * composite USB devices */
-                       hid->group = HID_GROUP_RMI;
+               if (hid->group == HID_GROUP_GENERIC)
+                       if ((parser->scan_flags & HID_SCAN_FLAG_VENDOR_SPECIFIC)
+                           && (parser->scan_flags & HID_SCAN_FLAG_GD_POINTER))
+                               /*
+                                * hid-rmi should take care of them,
+                                * not hid-generic
+                                */
+                               hid->group = HID_GROUP_RMI;
                break;
        }
 
index 06c4607744f637156d14a667b9b5b55f0a37b693..efc7787a41a8c75db5b89509e8ec4051d019038a 100644 (file)
@@ -574,7 +574,9 @@ static inline void hid_set_drvdata(struct hid_device *hdev, void *data)
 #define HID_GLOBAL_STACK_SIZE 4
 #define HID_COLLECTION_STACK_SIZE 4
 
-#define HID_SCAN_FLAG_MT_WIN_8                 0x00000001
+#define HID_SCAN_FLAG_MT_WIN_8                 BIT(0)
+#define HID_SCAN_FLAG_VENDOR_SPECIFIC          BIT(1)
+#define HID_SCAN_FLAG_GD_POINTER               BIT(2)
 
 struct hid_parser {
        struct hid_global     global;