summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOliver Neukum <oneukum@suse.de>2013-09-25 09:42:55 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-12-08 07:29:16 -0800
commit30699c9661d6ecf0fb31804723f5d870865a617a (patch)
treebed2a34e03297e34efa1b92db05b3d5e5d525d16
parentfef8c18a3f38d5446328997aaf7c8a56534df8c6 (diff)
HID: hid-elo: some systems cannot stomach work around
commit 403cfb53fb450d53751fdc7ee0cd6652419612cf upstream. Some systems although they have firmware class 'M', which usually needs a work around to not crash, must not be subjected to the work around because the work around crashes them. They cannot be told apart by their own device descriptor, but as they are part of compound devices, can be identified by looking at their siblings. Signed-off-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Jiri Kosina <jkosina@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/hid/hid-elo.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c
index f042a6cf8b18..55e4920f967b 100644
--- a/drivers/hid/hid-elo.c
+++ b/drivers/hid/hid-elo.c
@@ -181,7 +181,40 @@ fail:
*/
static bool elo_broken_firmware(struct usb_device *dev)
{
- return use_fw_quirk && le16_to_cpu(dev->descriptor.bcdDevice) == 0x10d;
+ struct usb_device *hub = dev->parent;
+ struct usb_device *child = NULL;
+ u16 fw_lvl = le16_to_cpu(dev->descriptor.bcdDevice);
+ u16 child_vid, child_pid;
+ int i;
+
+ if (!use_fw_quirk)
+ return false;
+ if (fw_lvl != 0x10d)
+ return false;
+
+ /* iterate sibling devices of the touch controller */
+ usb_hub_for_each_child(hub, i, child) {
+ child_vid = le16_to_cpu(child->descriptor.idVendor);
+ child_pid = le16_to_cpu(child->descriptor.idProduct);
+
+ /*
+ * If one of the devices below is present attached as a sibling of
+ * the touch controller then this is a newer IBM 4820 monitor that
+ * does not need the IBM-requested workaround if fw level is
+ * 0x010d - aka 'M'.
+ * No other HW can have this combination.
+ */
+ if (child_vid==0x04b3) {
+ switch (child_pid) {
+ case 0x4676: /* 4820 21x Video */
+ case 0x4677: /* 4820 51x Video */
+ case 0x4678: /* 4820 2Lx Video */
+ case 0x4679: /* 4820 5Lx Video */
+ return false;
+ }
+ }
+ }
+ return true;
}
static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id)