From ac26fca3e14c8882e382daa7e96ab73e0186cf03 Mon Sep 17 00:00:00 2001
From: Jiri Kosina <jkosina@suse.cz>
Date: Thu, 20 Nov 2008 11:27:02 +0100
Subject: HID: ignore mouse interface for unibody macbooks

The mouse interface on unibody macbooks is going to be handled by
bcm59743 driver in 2.6.29.

Reported-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/hid-core.c | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'drivers')

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 40df3e1b4bd1..839de38a43c7 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1577,6 +1577,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
 	{ }
-- 
cgit v1.2.3


From efc7ce18d9037aa947c1aad5eb712ecc47520126 Mon Sep 17 00:00:00 2001
From: Jiri Kosina <jkosina@suse.cz>
Date: Fri, 17 Oct 2008 15:01:15 +0200
Subject: HID: non-input reports can also be numbered

When computing the maximal buffer size needed, we must take into
account that not only input reports can be numbered.

Pointed out in bugzilla #10467

Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/usbhid/hid-core.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

(limited to 'drivers')

diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 606369ea24ca..2afc8617f591 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -4,7 +4,7 @@
  *  Copyright (c) 1999 Andreas Gal
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2006-2008 Jiri Kosina
  */
 
 /*
@@ -641,9 +641,7 @@ static void hid_find_max_report(struct hid_device *hid, unsigned int type,
 	unsigned int size;
 
 	list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
-		size = ((report->size - 1) >> 3) + 1;
-		if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered)
-			size++;
+		size = ((report->size - 1) >> 3) + 1 + hid->report_enum[type].numbered;
 		if (*max < size)
 			*max = size;
 	}
-- 
cgit v1.2.3


From 08ef08ee8c5a8d538ca9a3c433d4213c128af863 Mon Sep 17 00:00:00 2001
From: Alan Stern <stern@rowland.harvard.edu>
Date: Thu, 30 Oct 2008 23:58:51 +0100
Subject: HID: automatically call usbhid_set_leds in usbhid driver

This patch (as1146c) makes usbhid automatically call usbhid_set_leds()
for any device that supports the keyboard boot protocol.

In theory this should be perfectly safe.  BIOSes send the LED output
report as part of their normal device initialization, so any keyboard
device supporting the boot protocol has to be able to handle it.

As a side effect, the hid-dell and hid-bright drivers are no longer
needed, and the Logitech keyboard driver can be removed from hid-lg.

CC: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/Kconfig           | 15 ---------
 drivers/hid/Makefile          |  2 --
 drivers/hid/hid-bright.c      | 71 ----------------------------------------
 drivers/hid/hid-core.c        |  5 ---
 drivers/hid/hid-dell.c        | 76 -------------------------------------------
 drivers/hid/hid-ids.h         | 11 -------
 drivers/hid/hid-lg.c          |  7 ----
 drivers/hid/usbhid/hid-core.c |  9 +++++
 8 files changed, 9 insertions(+), 187 deletions(-)
 delete mode 100644 drivers/hid/hid-bright.c
 delete mode 100644 drivers/hid/hid-dell.c

(limited to 'drivers')

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index b4fd8ca701a4..65b577eaf823 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -107,13 +107,6 @@ config HID_BELKIN
 	---help---
 	Support for Belkin Flip KVM and Wireless keyboard.
 
-config HID_BRIGHT
-	tristate "Bright" if EMBEDDED
-	depends on USB_HID
-	default y
-	---help---
-	Support for Bright ABNT-2 keyboard.
-
 config HID_CHERRY
 	tristate "Cherry" if EMBEDDED
 	depends on USB_HID
@@ -135,14 +128,6 @@ config HID_CYPRESS
 	---help---
 	Support for cypress mouse and barcode readers.
 
-config HID_DELL
-	tristate "Dell" if EMBEDDED
-	depends on USB_HID
-	default y
-	---help---
-	Support for quirky Dell HID hardware that require
-	special LED handling (W7658 and SK8115 models)
-
 config HID_EZKEY
 	tristate "Ezkey" if EMBEDDED
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index b09e43e7413e..e2294a8b2a68 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -23,11 +23,9 @@ endif
 obj-$(CONFIG_HID_A4TECH)	+= hid-a4tech.o
 obj-$(CONFIG_HID_APPLE)		+= hid-apple.o
 obj-$(CONFIG_HID_BELKIN)	+= hid-belkin.o
-obj-$(CONFIG_HID_BRIGHT)	+= hid-bright.o
 obj-$(CONFIG_HID_CHERRY)	+= hid-cherry.o
 obj-$(CONFIG_HID_CHICONY)	+= hid-chicony.o
 obj-$(CONFIG_HID_CYPRESS)	+= hid-cypress.o
-obj-$(CONFIG_HID_DELL)		+= hid-dell.o
 obj-$(CONFIG_HID_EZKEY)		+= hid-ezkey.o
 obj-$(CONFIG_HID_GYRATION)	+= hid-gyration.o
 obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
diff --git a/drivers/hid/hid-bright.c b/drivers/hid/hid-bright.c
deleted file mode 100644
index 38517a117dfd..000000000000
--- a/drivers/hid/hid-bright.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *  HID driver for some bright "special" devices
- *
- *  Copyright (c) 2008 Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- * Based on hid-dell driver
- */
-
-/*
- * 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 "hid-ids.h"
-
-static int bright_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-	int ret;
-
-	ret = hid_parse(hdev);
-	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
-		goto err_free;
-	}
-
-	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
-		goto err_free;
-	}
-
-	usbhid_set_leds(hdev);
-
-	return 0;
-err_free:
-	return ret;
-}
-
-static const struct hid_device_id bright_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, bright_devices);
-
-static struct hid_driver bright_driver = {
-	.name = "bright",
-	.id_table = bright_devices,
-	.probe = bright_probe,
-};
-
-static int bright_init(void)
-{
-	return hid_register_driver(&bright_driver);
-}
-
-static void bright_exit(void)
-{
-	hid_unregister_driver(&bright_driver);
-}
-
-module_init(bright_init);
-module_exit(bright_exit);
-MODULE_LICENSE("GPL");
-
-HID_COMPAT_LOAD_DRIVER(bright);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 839de38a43c7..8be30037cffe 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1256,16 +1256,12 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
 	{ 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_MOUSE) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
 	{ 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_GREENASIA, 0x0003) },
@@ -1279,7 +1275,6 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
diff --git a/drivers/hid/hid-dell.c b/drivers/hid/hid-dell.c
deleted file mode 100644
index f5474300b83a..000000000000
--- a/drivers/hid/hid-dell.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *  HID driver for some dell "special" devices
- *
- *  Copyright (c) 1999 Andreas Gal
- *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
- *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
- *  Copyright (c) 2008 Jiri Slaby
- */
-
-/*
- * 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 "hid-ids.h"
-
-static int dell_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-	int ret;
-
-	ret = hid_parse(hdev);
-	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
-		goto err_free;
-	}
-
-	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
-		goto err_free;
-	}
-
-	usbhid_set_leds(hdev);
-
-	return 0;
-err_free:
-	return ret;
-}
-
-static const struct hid_device_id dell_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, dell_devices);
-
-static struct hid_driver dell_driver = {
-	.name = "dell",
-	.id_table = dell_devices,
-	.probe = dell_probe,
-};
-
-static int dell_init(void)
-{
-	return hid_register_driver(&dell_driver);
-}
-
-static void dell_exit(void)
-{
-	hid_unregister_driver(&dell_driver);
-}
-
-module_init(dell_init);
-module_exit(dell_exit);
-MODULE_LICENSE("GPL");
-
-HID_COMPAT_LOAD_DRIVER(dell);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 39289699c32f..aae2ceca0bce 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -107,9 +107,6 @@
 #define USB_VENDOR_ID_BELKIN           0x050d
 #define USB_DEVICE_ID_FLIP_KVM         0x3201
 
-#define USB_VENDOR_ID_BRIGHT		0x1241
-#define USB_DEVICE_ID_BRIGHT_ABNT2	0x1503
-
 #define USB_VENDOR_ID_BERKSHIRE		0x0c98
 #define USB_DEVICE_ID_BERKSHIRE_PCWD	0x1140
 
@@ -141,10 +138,6 @@
 #define USB_DEVICE_ID_CYPRESS_BARCODE_1	0xde61
 #define USB_DEVICE_ID_CYPRESS_BARCODE_2	0xde64
 
-#define USB_VENDOR_ID_DELL		0x413c
-#define USB_DEVICE_ID_DELL_W7658	0x2005
-#define USB_DEVICE_ID_DELL_SK8115	0x2105
-
 #define USB_VENDOR_ID_DELORME		0x1163
 #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
 #define USB_DEVICE_ID_DELORME_EM_LT20	0x0200
@@ -167,9 +160,6 @@
 
 #define USB_VENDOR_ID_GENERAL_TOUCH	0x0dfc
 
-#define USB_VENDOR_ID_GENERIC_13BA	0x13ba
-#define USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE	0x0017
-
 #define USB_VENDOR_ID_GLAB		0x06c2
 #define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038
 #define USB_DEVICE_ID_1_PHIDGETSERVO_30	0x0039
@@ -292,7 +282,6 @@
 #define USB_DEVICE_ID_LOGITECH_WHEEL	0xc294
 #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL	0xc295
 #define USB_DEVICE_ID_LOGITECH_ELITE_KBD	0xc30a
-#define USB_DEVICE_ID_LOGITECH_KBD	0xc311
 #define USB_DEVICE_ID_S510_RECEIVER	0xc50c
 #define USB_DEVICE_ID_S510_RECEIVER_2	0xc517
 #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500	0xc512
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 2bae340eafe2..83e07c9f4144 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -26,7 +26,6 @@
 #define LG_RDESC		0x001
 #define LG_BAD_RELATIVE_KEYS	0x002
 #define LG_DUPLICATE_USAGES	0x004
-#define LG_RESET_LEDS		0x008
 #define LG_EXPANDED_KEYMAP	0x010
 #define LG_IGNORE_DOUBLED_WHEEL	0x020
 #define LG_WIRELESS		0x040
@@ -248,9 +247,6 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 		goto err_free;
 	}
 
-	if (quirks & LG_RESET_LEDS)
-		usbhid_set_leds(hdev);
-
 	if (quirks & LG_FF)
 		lgff_init(hdev);
 	if (quirks & LG_FF2)
@@ -279,9 +275,6 @@ static const struct hid_device_id lg_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
 		.driver_data = LG_DUPLICATE_USAGES },
 
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD),
-		.driver_data = LG_RESET_LEDS },
-
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
 		.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 2afc8617f591..6383145b5840 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -874,6 +874,15 @@ static int usbhid_start(struct hid_device *hid)
 
 	set_bit(HID_STARTED, &usbhid->iofl);
 
+	/* Some keyboards don't work until their LEDs have been set.
+	 * Since BIOSes do set the LEDs, it must be safe for any device
+	 * that supports the keyboard boot protocol.
+	 */
+	if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT &&
+			interface->desc.bInterfaceProtocol ==
+				USB_INTERFACE_PROTOCOL_KEYBOARD)
+		usbhid_set_leds(hid);
+
 	return 0;
 
 fail:
-- 
cgit v1.2.3


From 6bbe586fd4d94439f3960e200056ff057f7db5c6 Mon Sep 17 00:00:00 2001
From: Kay Sievers <kay.sievers@vrfy.org>
Date: Fri, 31 Oct 2008 00:12:32 +0100
Subject: HID: struct device - replace bus_id with dev_name(), dev_set_name()

This patch is part of a larger patch series which will remove
the "char bus_id[20]" name string from struct device. The device
name is managed in the kobject anyway, and without any size
limitation, and just needlessly copied into "struct device".

To set and read the device name dev_name(dev) and dev_set_name(dev)
must be used. If your code uses static kobjects, which it shouldn't
do, "const char *init_name" can be used to statically provide the
name the registered device should have. At registration time, the
init_name field is cleared, to enforce the use of dev_name(dev) to
access the device name at a later time.

We need to get rid of all occurrences of bus_id in the entire tree
to be able to enable the new interface. Please apply this patch,
and possibly convert any remaining remaining occurrences of bus_id.

We want to submit a patch to -next, which will remove bus_id from
"struct device", to find the remaining pieces to convert, and finally
switch over to the new api, which will remove the 20 bytes array
and does no longer have a size limitation.

CC: Jiri Kosina <jkosina@suse.cz>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/hid-core.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

(limited to 'drivers')

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 8be30037cffe..8624a8fe085b 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1616,9 +1616,10 @@ int hid_add_device(struct hid_device *hdev)
 	if (hid_ignore(hdev))
 		return -ENODEV;
 
-	/* XXX hack, any other cleaner solution < 20 bus_id bytes? */
-	sprintf(hdev->dev.bus_id, "%04X:%04X:%04X.%04X", hdev->bus,
-			hdev->vendor, hdev->product, atomic_inc_return(&id));
+	/* XXX hack, any other cleaner solution after the driver core
+	 * is converted to allow more than 20 bytes as the device name? */
+	dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
+		     hdev->vendor, hdev->product, atomic_inc_return(&id));
 
 	ret = device_add(&hdev->dev);
 	if (!ret)
-- 
cgit v1.2.3


From 9188e79ec3fd43a0a605274324aecfb731baa88b Mon Sep 17 00:00:00 2001
From: Jiri Kosina <jkosina@suse.cz>
Date: Wed, 12 Nov 2008 16:14:08 +0100
Subject: HID: add phys and name ioctls to hidraw

The hiddev interface provides ioctl() calls which can be used
to obtain phys and raw name of the underlying device.

Add the corresponding support also into hidraw.

Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/hidraw.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

(limited to 'drivers')

diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 7685ae6808c4..975edd88a3db 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -265,6 +265,34 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
 				break;
 			}
 		default:
+			{
+				struct hid_device *hid = dev->hid;
+				if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
+					return -EINVAL;
+
+				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
+					int len;
+					if (!hid->name)
+						return 0;
+					len = strlen(hid->name) + 1;
+					if (len > _IOC_SIZE(cmd))
+						len = _IOC_SIZE(cmd);
+					return copy_to_user(user_arg, hid->name, len) ?
+						-EFAULT : len;
+				}
+
+				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
+					int len;
+					if (!hid->phys)
+						return 0;
+					len = strlen(hid->phys) + 1;
+					if (len > _IOC_SIZE(cmd))
+						len = _IOC_SIZE(cmd);
+					return copy_to_user(user_arg, hid->phys, len) ?
+						-EFAULT : len;
+				}
+                }
+
 			ret = -ENOTTY;
 	}
 	unlock_kernel();
-- 
cgit v1.2.3


From 94011f93f2cd7410401e22390cf7a14fe5495a22 Mon Sep 17 00:00:00 2001
From: Rafi Rubin <rafi@seas.upenn.edu>
Date: Wed, 19 Nov 2008 15:54:46 +0100
Subject: HID: add n-trig digitizer support

Added quirks for the N-Trig digitizer.

Signed-off-by: Rafi Rubin <rafi@seas.upenn.edu>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/Kconfig     |  7 +++++
 drivers/hid/Makefile    |  1 +
 drivers/hid/hid-core.c  |  1 +
 drivers/hid/hid-dummy.c |  3 ++
 drivers/hid/hid-ids.h   |  3 ++
 drivers/hid/hid-ntrig.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 97 insertions(+)
 create mode 100644 drivers/hid/hid-ntrig.c

(limited to 'drivers')

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 65b577eaf823..aadef9abc05d 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -187,6 +187,13 @@ config HID_MONTEREY
 	---help---
 	Support for Monterey Genius KB29E.
 
+config HID_NTRIG
+	tristate "NTrig" if EMBEDDED
+	depends on USB_HID
+	default y
+	---help---
+	Support for N-Trig touch screen.
+
 config HID_PANTHERLORD
 	tristate "Pantherlord devices support" if EMBEDDED
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index e2294a8b2a68..7d34e8bf3de5 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_HID_GYRATION)	+= hid-gyration.o
 obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
 obj-$(CONFIG_HID_MICROSOFT)	+= hid-microsoft.o
 obj-$(CONFIG_HID_MONTEREY)	+= hid-monterey.o
+obj-$(CONFIG_HID_NTRIG)		+= hid-ntrig.o
 obj-$(CONFIG_HID_PANTHERLORD)	+= hid-pl.o
 obj-$(CONFIG_HID_PETALYNX)	+= hid-petalynx.o
 obj-$(CONFIG_HID_SAMSUNG)	+= hid-samsung.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 8624a8fe085b..344f8fdb2824 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1292,6 +1292,7 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
diff --git a/drivers/hid/hid-dummy.c b/drivers/hid/hid-dummy.c
index e148f86fb58e..4a6af3cf192d 100644
--- a/drivers/hid/hid-dummy.c
+++ b/drivers/hid/hid-dummy.c
@@ -43,6 +43,9 @@ static int __init hid_dummy_init(void)
 #ifdef CONFIG_HID_MONTEREY_MODULE
 	HID_COMPAT_CALL_DRIVER(monterey);
 #endif
+#ifdef CONFIG_HID_NTRIG_MODULE
+	HID_COMPAT_CALL_DRIVER(ntrig);
+#endif
 #ifdef CONFIG_HID_PANTHERLORD_MODULE
 	HID_COMPAT_CALL_DRIVER(pantherlord);
 #endif
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index aae2ceca0bce..2b7b6eeae8c6 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -328,6 +328,9 @@
 #define USB_VENDOR_ID_NEC		0x073e
 #define USB_DEVICE_ID_NEC_USB_GAME_PAD	0x0301
 
+#define USB_VENDOR_ID_NTRIG                0x1b96
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN   0x0001
+
 #define USB_VENDOR_ID_ONTRAK		0x0a07
 #define USB_DEVICE_ID_ONTRAK_ADU100	0x0064
 
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
new file mode 100644
index 000000000000..db44fbd7bdf6
--- /dev/null
+++ b/drivers/hid/hid-ntrig.c
@@ -0,0 +1,82 @@
+/*
+ *  HID driver for some ntrig "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ *  Copyright (c) 2008 Rafi Rubin
+ *
+ */
+
+/*
+ * 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 "hid-ids.h"
+
+#define NTRIG_DUPLICATE_USAGES	0x001
+
+#define nt_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, max, \
+					EV_KEY, (c))
+
+static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_DIGITIZER &&
+			(usage->hid & 0xff) == 0x47) {
+		nt_map_key_clear(BTN_TOOL_DOUBLETAP);
+		return 1;
+	}
+	return 0;
+}
+
+static int ntrig_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_REL
+			|| usage->type == EV_ABS)
+		clear_bit(usage->code, *bit);
+
+	return 0;
+}
+static const struct hid_device_id ntrig_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
+		.driver_data = NTRIG_DUPLICATE_USAGES },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, ntrig_devices);
+
+static struct hid_driver ntrig_driver = {
+	.name = "ntrig",
+	.id_table = ntrig_devices,
+	.input_mapping = ntrig_input_mapping,
+	.input_mapped = ntrig_input_mapped,
+};
+
+static int ntrig_init(void)
+{
+	return hid_register_driver(&ntrig_driver);
+}
+
+static void ntrig_exit(void)
+{
+	hid_unregister_driver(&ntrig_driver);
+}
+
+module_init(ntrig_init);
+module_exit(ntrig_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(ntrig);
-- 
cgit v1.2.3


From 0ed94b334265b6ee3e3336b4fedacfa9cb2ccaba Mon Sep 17 00:00:00 2001
From: Jiri Slaby <jirislaby@gmail.com>
Date: Mon, 24 Nov 2008 16:20:07 +0100
Subject: HID: move usbhid flags to usbhid.h

Move usbhid specific flags from global hid.h into local usbhid.h.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/usbhid/usbhid.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

(limited to 'drivers')

diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index 332abcdf9956..9eb30564be9c 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -40,6 +40,16 @@ int usbhid_open(struct hid_device *hid);
 void usbhid_init_reports(struct hid_device *hid);
 void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir);
 
+/* iofl flags */
+#define HID_CTRL_RUNNING	1
+#define HID_OUT_RUNNING		2
+#define HID_IN_RUNNING		3
+#define HID_RESET_PENDING	4
+#define HID_SUSPENDED		5
+#define HID_CLEAR_HALT		6
+#define HID_DISCONNECTED	7
+#define HID_STARTED		8
+
 /*
  * USB-specific HID struct, to be pointed to
  * from struct hid_device->driver_data
-- 
cgit v1.2.3


From 581a2739607b5fdfb6b22d6083fc7f83c441077f Mon Sep 17 00:00:00 2001
From: Jiri Slaby <jirislaby@gmail.com>
Date: Mon, 24 Nov 2008 16:20:08 +0100
Subject: HID: usbhid, use usb_endpoint_xfer_int

Use usb_endpoint_xfer_int() instead of direct use of constants.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/usbhid/hid-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 6383145b5840..832e469265ee 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -805,7 +805,7 @@ static int usbhid_start(struct hid_device *hid)
 		int interval;
 
 		endpoint = &interface->endpoint[n].desc;
-		if ((endpoint->bmAttributes & 3) != 3)		/* Not an interrupt endpoint */
+		if (!usb_endpoint_xfer_int(endpoint))
 			continue;
 
 		interval = endpoint->bInterval;
-- 
cgit v1.2.3


From 898089d08f983ef0fdb176267620543a7929826a Mon Sep 17 00:00:00 2001
From: Jiri Slaby <jirislaby@gmail.com>
Date: Mon, 24 Nov 2008 16:20:06 +0100
Subject: HID: use GFP_KERNEL in hid_alloc_buffers

We might sleep, so no problem to use GFP_KERNEL.

While at it bring the function to coding style.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/usbhid/hid-core.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

(limited to 'drivers')

diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 832e469265ee..03cb494af1c5 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -651,13 +651,16 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
 {
 	struct usbhid_device *usbhid = hid->driver_data;
 
-	if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma)))
-		return -1;
-	if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma)))
-		return -1;
-	if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma)))
-		return -1;
-	if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma)))
+	usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
+			&usbhid->inbuf_dma);
+	usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
+			&usbhid->outbuf_dma);
+	usbhid->cr = usb_buffer_alloc(dev, sizeof(*usbhid->cr), GFP_KERNEL,
+			&usbhid->cr_dma);
+	usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
+			&usbhid->ctrlbuf_dma);
+	if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr ||
+			!usbhid->ctrlbuf)
 		return -1;
 
 	return 0;
-- 
cgit v1.2.3


From 3a6f82f7a22cf19687f556997c6978b31c109360 Mon Sep 17 00:00:00 2001
From: Jiri Slaby <jirislaby@gmail.com>
Date: Mon, 24 Nov 2008 16:20:09 +0100
Subject: HID: add dynids facility

Allow adding new devices to the hid drivers on the fly without
a need of kernel recompilation.

Now, one can test a driver e.g. by:
echo 0003:045E:00F0.0003 > ../generic-usb/unbind
echo 0003 045E 00F0 > new_id
from some driver subdir.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/hid-core.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 98 insertions(+), 3 deletions(-)

(limited to 'drivers')

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 344f8fdb2824..34cc3b0d01f6 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1304,12 +1304,92 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ }
 };
 
+struct hid_dynid {
+	struct list_head list;
+	struct hid_device_id id;
+};
+
+/**
+ * store_new_id - add a new HID device ID to this driver and re-probe devices
+ * @driver: target device driver
+ * @buf: buffer for scanning device ID data
+ * @count: input size
+ *
+ * Adds a new dynamic hid device ID to this driver,
+ * and causes the driver to probe for all devices again.
+ */
+static ssize_t store_new_id(struct device_driver *drv, const char *buf,
+		size_t count)
+{
+	struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
+	struct hid_dynid *dynid;
+	__u32 bus, vendor, product;
+	unsigned long driver_data = 0;
+	int ret;
+
+	ret = sscanf(buf, "%x %x %x %lx",
+			&bus, &vendor, &product, &driver_data);
+	if (ret < 3)
+		return -EINVAL;
+
+	dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
+	if (!dynid)
+		return -ENOMEM;
+
+	dynid->id.bus = bus;
+	dynid->id.vendor = vendor;
+	dynid->id.product = product;
+	dynid->id.driver_data = driver_data;
+
+	spin_lock(&hdrv->dyn_lock);
+	list_add_tail(&dynid->list, &hdrv->dyn_list);
+	spin_unlock(&hdrv->dyn_lock);
+
+	ret = 0;
+	if (get_driver(&hdrv->driver)) {
+		ret = driver_attach(&hdrv->driver);
+		put_driver(&hdrv->driver);
+	}
+
+	return ret ? : count;
+}
+static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
+
+static void hid_free_dynids(struct hid_driver *hdrv)
+{
+	struct hid_dynid *dynid, *n;
+
+	spin_lock(&hdrv->dyn_lock);
+	list_for_each_entry_safe(dynid, n, &hdrv->dyn_list, list) {
+		list_del(&dynid->list);
+		kfree(dynid);
+	}
+	spin_unlock(&hdrv->dyn_lock);
+}
+
+static const struct hid_device_id *hid_match_device(struct hid_device *hdev,
+		struct hid_driver *hdrv)
+{
+	struct hid_dynid *dynid;
+
+	spin_lock(&hdrv->dyn_lock);
+	list_for_each_entry(dynid, &hdrv->dyn_list, list) {
+		if (hid_match_one_id(hdev, &dynid->id)) {
+			spin_unlock(&hdrv->dyn_lock);
+			return &dynid->id;
+		}
+	}
+	spin_unlock(&hdrv->dyn_lock);
+
+	return hid_match_id(hdev, hdrv->id_table);
+}
+
 static int hid_bus_match(struct device *dev, struct device_driver *drv)
 {
 	struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
 
-	if (!hid_match_id(hdev, hdrv->id_table))
+	if (!hid_match_device(hdev, hdrv))
 		return 0;
 
 	/* generic wants all non-blacklisted */
@@ -1328,7 +1408,7 @@ static int hid_device_probe(struct device *dev)
 	int ret = 0;
 
 	if (!hdev->driver) {
-		id = hid_match_id(hdev, hdrv->id_table);
+		id = hid_match_device(hdev, hdrv);
 		if (id == NULL)
 			return -ENODEV;
 
@@ -1695,18 +1775,33 @@ EXPORT_SYMBOL_GPL(hid_destroy_device);
 int __hid_register_driver(struct hid_driver *hdrv, struct module *owner,
 		const char *mod_name)
 {
+	int ret;
+
 	hdrv->driver.name = hdrv->name;
 	hdrv->driver.bus = &hid_bus_type;
 	hdrv->driver.owner = owner;
 	hdrv->driver.mod_name = mod_name;
 
-	return driver_register(&hdrv->driver);
+	INIT_LIST_HEAD(&hdrv->dyn_list);
+	spin_lock_init(&hdrv->dyn_lock);
+
+	ret = driver_register(&hdrv->driver);
+	if (ret)
+		return ret;
+
+	ret = driver_create_file(&hdrv->driver, &driver_attr_new_id);
+	if (ret)
+		driver_unregister(&hdrv->driver);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(__hid_register_driver);
 
 void hid_unregister_driver(struct hid_driver *hdrv)
 {
+	driver_remove_file(&hdrv->driver, &driver_attr_new_id);
 	driver_unregister(&hdrv->driver);
+	hid_free_dynids(hdrv);
 }
 EXPORT_SYMBOL_GPL(hid_unregister_driver);
 
-- 
cgit v1.2.3


From aae6c286dad33c7f2c6992b9e310a371f2ae377e Mon Sep 17 00:00:00 2001
From: Jiri Kosina <jkosina@suse.cz>
Date: Thu, 4 Dec 2008 16:16:46 +0100
Subject: HID: set proper dev.parent in hidraw

We need to properly set parent of the hidraw device (which is the
corresponding physical device itself) in order to hidraw devices not
end up under virtual device tree.

Reported-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/hidraw.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 975edd88a3db..aab5911c4e33 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -357,7 +357,7 @@ int hidraw_connect(struct hid_device *hid)
 		goto out;
 	}
 
-	dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor),
+	dev->dev = device_create(hidraw_class, &hid->dev, MKDEV(hidraw_major, minor),
 				 NULL, "%s%d", "hidraw", minor);
 
 	if (IS_ERR(dev->dev)) {
-- 
cgit v1.2.3


From d04b431e3d769fbbf26c4f4072002375c8cc4ed9 Mon Sep 17 00:00:00 2001
From: David Brownell <dbrownell@users.sourceforge.net>
Date: Thu, 11 Dec 2008 14:54:07 +0100
Subject: HID: switch specialized drivers from "default y" to !EMBEDDED

Fix the obnoxious "default y" for all the "special" HID code, which forces folk
with EMBEDDED defined to manually override that inappropriate default for
almost 20 choices.  The general policy is against "default y"; it should apply
here too.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/Kconfig | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

(limited to 'drivers')

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index aadef9abc05d..1033129d4767 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -85,14 +85,14 @@ config HID_COMPAT
 config HID_A4TECH
 	tristate "A4 tech" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for A4 tech X5 and WOP-35 / Trust 450L mice.
 
 config HID_APPLE
 	tristate "Apple" if EMBEDDED
 	depends on (USB_HID || BT_HIDP)
-	default y
+	default !EMBEDDED
 	---help---
 	Support for some Apple devices which less or more break
 	HID specification.
@@ -103,49 +103,49 @@ config HID_APPLE
 config HID_BELKIN
 	tristate "Belkin" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for Belkin Flip KVM and Wireless keyboard.
 
 config HID_CHERRY
 	tristate "Cherry" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for Cherry Cymotion keyboard.
 
 config HID_CHICONY
 	tristate "Chicony" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for Chicony Tactical pad.
 
 config HID_CYPRESS
 	tristate "Cypress" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for cypress mouse and barcode readers.
 
 config HID_EZKEY
 	tristate "Ezkey" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for Ezkey BTC 8193 keyboard.
 
 config HID_GYRATION
 	tristate "Gyration" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for Gyration remote control.
 
 config HID_LOGITECH
 	tristate "Logitech" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for Logitech devices that are not fully compliant with HID standard.
 
@@ -176,28 +176,28 @@ config LOGIRUMBLEPAD2_FF
 config HID_MICROSOFT
 	tristate "Microsoft" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for Microsoft devices that are not fully compliant with HID standard.
 
 config HID_MONTEREY
 	tristate "Monterey" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for Monterey Genius KB29E.
 
 config HID_NTRIG
 	tristate "NTrig" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for N-Trig touch screen.
 
 config HID_PANTHERLORD
 	tristate "Pantherlord devices support" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for PantherLord/GreenAsia based device support.
 
@@ -212,28 +212,28 @@ config PANTHERLORD_FF
 config HID_PETALYNX
 	tristate "Petalynx" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for Petalynx Maxter remote control.
 
 config HID_SAMSUNG
 	tristate "Samsung" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for Samsung InfraRed remote control.
 
 config HID_SONY
 	tristate "Sony" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for Sony PS3 controller.
 
 config HID_SUNPLUS
 	tristate "Sunplus" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Support for Sunplus wireless desktop.
 
-- 
cgit v1.2.3


From 42859e0bd21daba9974757fcfe4a4dde265fe28d Mon Sep 17 00:00:00 2001
From: Lukasz Lubojanski <lukasz@lubojanski.info>
Date: Thu, 11 Dec 2008 22:07:59 +0100
Subject: HID: force feedback driver for GreenAsia 0x12 PID

I have implemented Force Feedback driver for another "GreeAsia" based device
(0e8f:0012 "GreenAsia Inc. USB Joystick"). The functionality was tested with
MANTA Warior MM816 and SpeedLink Strike2 SL-6635 and fftest software -
everything seems to work right.

Signed-off-by: Lukasz Lubojanski <lukasz@lubojanski.info>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/Kconfig     |   9 +++
 drivers/hid/Makefile    |   1 +
 drivers/hid/hid-core.c  |   1 +
 drivers/hid/hid-dummy.c |   3 +
 drivers/hid/hid-gaff.c  | 185 ++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 199 insertions(+)
 create mode 100644 drivers/hid/hid-gaff.c

(limited to 'drivers')

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 1033129d4767..81dd9b8eeeaa 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -237,6 +237,15 @@ config HID_SUNPLUS
 	---help---
 	Support for Sunplus wireless desktop.
 
+config GREENASIA_FF
+	tristate "GreenAsia (Product ID 0x12) force feedback support"
+	depends on USB_HID
+	select INPUT_FF_MEMLESS
+	---help---
+	Say Y here if you have a GreenAsia (Product ID 0x12) based game controller
+	(like MANTA Warior MM816 and SpeedLink Strike2 SL-6635) or adapter
+	and want to enable force feedback support for it.
+
 config THRUSTMASTER_FF
 	tristate "ThrustMaster devices support"
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 7d34e8bf3de5..3354eacffa49 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_HID_PETALYNX)	+= hid-petalynx.o
 obj-$(CONFIG_HID_SAMSUNG)	+= hid-samsung.o
 obj-$(CONFIG_HID_SONY)		+= hid-sony.o
 obj-$(CONFIG_HID_SUNPLUS)	+= hid-sunplus.o
+obj-$(CONFIG_GREENASIA_FF)	+= hid-gaff.o
 obj-$(CONFIG_THRUSTMASTER_FF)	+= hid-tmff.o
 obj-$(CONFIG_ZEROPLUS_FF)	+= hid-zpff.o
 
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 34cc3b0d01f6..8fd35a697c5b 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1265,6 +1265,7 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ 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_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_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
diff --git a/drivers/hid/hid-dummy.c b/drivers/hid/hid-dummy.c
index 4a6af3cf192d..b4cc0f743d63 100644
--- a/drivers/hid/hid-dummy.c
+++ b/drivers/hid/hid-dummy.c
@@ -61,6 +61,9 @@ static int __init hid_dummy_init(void)
 #ifdef CONFIG_HID_SUNPLUS_MODULE
 	HID_COMPAT_CALL_DRIVER(sunplus);
 #endif
+#ifdef CONFIG_GREENASIA_FF_MODULE
+	HID_COMPAT_CALL_DRIVER(greenasia);
+#endif
 #ifdef CONFIG_THRUSTMASTER_FF_MODULE
 	HID_COMPAT_CALL_DRIVER(thrustmaster);
 #endif
diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c
new file mode 100644
index 000000000000..71211f6a4f02
--- /dev/null
+++ b/drivers/hid/hid-gaff.c
@@ -0,0 +1,185 @@
+/*
+ *  Force feedback support for GreenAsia (Product ID 0x12) based devices
+ *
+ *  The devices are distributed under various names and the same USB device ID
+ *  can be used in many game controllers.
+ *
+ *
+ *  0e8f:0012 "GreenAsia Inc.    USB Joystick     "
+ *   - tested with MANTA Warior MM816 and SpeedLink Strike2 SL-6635.
+ *
+ *  Copyright (c) 2008 Lukasz Lubojanski <lukasz@lubojanski.info>
+ */
+
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+#include "hid-ids.h"
+#include "usbhid/usbhid.h"
+
+struct gaff_device {
+	struct hid_report *report;
+};
+
+static int hid_gaff_play(struct input_dev *dev, void *data,
+			 struct ff_effect *effect)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct gaff_device *gaff = data;
+	int left, right;
+
+	left = effect->u.rumble.strong_magnitude;
+	right = effect->u.rumble.weak_magnitude;
+
+	dbg_hid("called with 0x%04x 0x%04x", left, right);
+
+	left = left * 0xfe / 0xffff;
+	right = right * 0xfe / 0xffff;
+
+	gaff->report->field[0]->value[0] = 0x51;
+	gaff->report->field[0]->value[1] = 0x0;
+	gaff->report->field[0]->value[2] = right;
+	gaff->report->field[0]->value[3] = 0;
+	gaff->report->field[0]->value[4] = left;
+	gaff->report->field[0]->value[5] = 0;
+	dbg_hid("running with 0x%02x 0x%02x", left, right);
+	usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+
+	gaff->report->field[0]->value[0] = 0xfa;
+	gaff->report->field[0]->value[1] = 0xfe;
+	gaff->report->field[0]->value[2] = 0x0;
+	gaff->report->field[0]->value[4] = 0x0;
+
+	usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+
+	return 0;
+}
+
+static int gaff_init(struct hid_device *hid)
+{
+	struct gaff_device *gaff;
+	struct hid_report *report;
+	struct hid_input *hidinput = list_entry(hid->inputs.next,
+						struct hid_input, list);
+	struct list_head *report_list =
+			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct list_head *report_ptr = report_list;
+	struct input_dev *dev = hidinput->input;
+	int error;
+
+	if (list_empty(report_list)) {
+		dev_err(&hid->dev, "no output reports found\n");
+		return -ENODEV;
+	}
+
+	report_ptr = report_ptr->next;
+
+	report = list_entry(report_ptr, struct hid_report, list);
+	if (report->maxfield < 1) {
+		dev_err(&hid->dev, "no fields in the report\n");
+		return -ENODEV;
+	}
+
+	if (report->field[0]->report_count < 6) {
+		dev_err(&hid->dev, "not enough values in the field\n");
+		return -ENODEV;
+	}
+
+	gaff = kzalloc(sizeof(struct gaff_device), GFP_KERNEL);
+	if (!gaff)
+		return -ENOMEM;
+
+	set_bit(FF_RUMBLE, dev->ffbit);
+
+	error = input_ff_create_memless(dev, gaff, hid_gaff_play);
+	if (error) {
+		kfree(gaff);
+		return error;
+	}
+
+	gaff->report = report;
+	gaff->report->field[0]->value[0] = 0x51;
+	gaff->report->field[0]->value[1] = 0x00;
+	gaff->report->field[0]->value[2] = 0x00;
+	gaff->report->field[0]->value[3] = 0x00;
+	usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+
+	gaff->report->field[0]->value[0] = 0xfa;
+	gaff->report->field[0]->value[1] = 0xfe;
+
+	usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+
+	dev_info(&hid->dev, "Force Feedback for GreenAsia 0x12"
+	       " devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n");
+
+	return 0;
+}
+
+static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+
+	dev_dbg(&hdev->dev, "Greenasia HID hardware probe...");
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		dev_err(&hdev->dev, "parse failed\n");
+		goto err;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+	if (ret) {
+		dev_err(&hdev->dev, "hw start failed\n");
+		goto err;
+	}
+
+	gaff_init(hdev);
+
+	return 0;
+err:
+	return ret;
+}
+
+static const struct hid_device_id ga_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012),  },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, ga_devices);
+
+static struct hid_driver ga_driver = {
+	.name = "greenasia",
+	.id_table = ga_devices,
+	.probe = ga_probe,
+};
+
+static int __init ga_init(void)
+{
+	return hid_register_driver(&ga_driver);
+}
+
+static void __exit ga_exit(void)
+{
+	hid_unregister_driver(&ga_driver);
+}
+
+module_init(ga_init);
+module_exit(ga_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(greenasia);
-- 
cgit v1.2.3


From 079034073faf974973baa0256b029451f6e768ad Mon Sep 17 00:00:00 2001
From: Oliver Neukum <oliver@neukum.org>
Date: Tue, 16 Dec 2008 10:55:15 +0100
Subject: HID: hiddev cleanup -- handle all error conditions properly

This is a cleanup of hiddev and fixes the following issues:

- thread safety by locking in read & ioctl, introducing a per device mutex
- race between ioctl and disconnect, introducing a flag and locking
  in form of a per low level device mutex
- race between open and other methods, making sure only successfully
  opened devices are put on the list, changing order of events
- range checking both upper and lower limits of the minor range
- make sure further calls to open fail for unplugged devices even if
  the device still has opened files
- error checking for low level open
- possible loss of wakeup events, using standard waiting macros
- race in initialisation by moving registration after full initialisation

Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/usbhid/hiddev.c | 135 ++++++++++++++++++++++++++++++++------------
 1 file changed, 99 insertions(+), 36 deletions(-)

(limited to 'drivers')

diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 83e851a5ed30..6a98f9f572b0 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -49,6 +49,7 @@
 struct hiddev {
 	int exist;
 	int open;
+	struct mutex existancelock;
 	wait_queue_head_t wait;
 	struct hid_device *hid;
 	struct list_head list;
@@ -63,6 +64,7 @@ struct hiddev_list {
 	struct fasync_struct *fasync;
 	struct hiddev *hiddev;
 	struct list_head node;
+	struct mutex thread_lock;
 };
 
 static struct hiddev *hiddev_table[HIDDEV_MINORS];
@@ -264,29 +266,48 @@ static int hiddev_release(struct inode * inode, struct file * file)
 static int hiddev_open(struct inode *inode, struct file *file)
 {
 	struct hiddev_list *list;
-	unsigned long flags;
+	int res;
 
 	int i = iminor(inode) - HIDDEV_MINOR_BASE;
 
-	if (i >= HIDDEV_MINORS || !hiddev_table[i])
+	if (i >= HIDDEV_MINORS || i < 0 || !hiddev_table[i])
 		return -ENODEV;
 
 	if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
 		return -ENOMEM;
+	mutex_init(&list->thread_lock);
 
 	list->hiddev = hiddev_table[i];
 
-	spin_lock_irqsave(&list->hiddev->list_lock, flags);
-	list_add_tail(&list->node, &hiddev_table[i]->list);
-	spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
 
 	file->private_data = list;
 
-	if (!list->hiddev->open++)
-		if (list->hiddev->exist)
-			usbhid_open(hiddev_table[i]->hid);
+	/*
+	 * no need for locking because the USB major number
+	 * is shared which usbcore guards against disconnect
+	 */
+	if (list->hiddev->exist) {
+		if (!list->hiddev->open++) {
+			res = usbhid_open(hiddev_table[i]->hid);
+			if (res < 0) {
+				res = -EIO;
+				goto bail;
+			}
+		}
+	} else {
+		res = -ENODEV;
+		goto bail;
+	}
+
+	spin_lock_irq(&list->hiddev->list_lock);
+	list_add_tail(&list->node, &hiddev_table[i]->list);
+	spin_unlock_irq(&list->hiddev->list_lock);
 
 	return 0;
+bail:
+	file->private_data = NULL;
+	kfree(list->hiddev);
+	return res;
 }
 
 /*
@@ -305,7 +326,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
 	DECLARE_WAITQUEUE(wait, current);
 	struct hiddev_list *list = file->private_data;
 	int event_size;
-	int retval = 0;
+	int retval;
 
 	event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
 		sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event);
@@ -313,10 +334,14 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
 	if (count < event_size)
 		return 0;
 
+	/* lock against other threads */
+	retval = mutex_lock_interruptible(&list->thread_lock);
+	if (retval)
+		return -ERESTARTSYS;
+
 	while (retval == 0) {
 		if (list->head == list->tail) {
-			add_wait_queue(&list->hiddev->wait, &wait);
-			set_current_state(TASK_INTERRUPTIBLE);
+			prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE);
 
 			while (list->head == list->tail) {
 				if (file->f_flags & O_NONBLOCK) {
@@ -332,35 +357,45 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
 					break;
 				}
 
+				/* let O_NONBLOCK tasks run */
+				mutex_unlock(&list->thread_lock);
 				schedule();
+				if (mutex_lock_interruptible(&list->thread_lock))
+					return -EINTR;
 				set_current_state(TASK_INTERRUPTIBLE);
 			}
+			finish_wait(&list->hiddev->wait, &wait);
 
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&list->hiddev->wait, &wait);
 		}
 
-		if (retval)
+		if (retval) {
+			mutex_unlock(&list->thread_lock);
 			return retval;
+		}
 
 
 		while (list->head != list->tail &&
 		       retval + event_size <= count) {
 			if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
-				if (list->buffer[list->tail].field_index !=
-				    HID_FIELD_INDEX_NONE) {
+				if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE) {
 					struct hiddev_event event;
+
 					event.hid = list->buffer[list->tail].usage_code;
 					event.value = list->buffer[list->tail].value;
-					if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event)))
+					if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) {
+						mutex_unlock(&list->thread_lock);
 						return -EFAULT;
+					}
 					retval += sizeof(struct hiddev_event);
 				}
 			} else {
 				if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
 				    (list->flags & HIDDEV_FLAG_REPORT) != 0) {
-					if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref)))
+
+					if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) {
+						mutex_unlock(&list->thread_lock);
 						return -EFAULT;
+					}
 					retval += sizeof(struct hiddev_usage_ref);
 				}
 			}
@@ -368,6 +403,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
 		}
 
 	}
+	mutex_unlock(&list->thread_lock);
 
 	return retval;
 }
@@ -555,7 +591,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	struct hid_field *field;
 	struct usbhid_device *usbhid = hid->driver_data;
 	void __user *user_arg = (void __user *)arg;
-	int i;
+	int i, r;
 	
 	/* Called without BKL by compat methods so no BKL taken */
 
@@ -619,10 +655,22 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		}
 
 	case HIDIOCGSTRING:
-		return hiddev_ioctl_string(hiddev, cmd, user_arg);
+		mutex_lock(&hiddev->existancelock);
+		if (!hiddev->exist)
+			r = hiddev_ioctl_string(hiddev, cmd, user_arg);
+		else
+			r = -ENODEV;
+		mutex_unlock(&hiddev->existancelock);
+		return r;
 
 	case HIDIOCINITREPORT:
+		mutex_lock(&hiddev->existancelock);
+		if (!hiddev->exist) {
+			mutex_unlock(&hiddev->existancelock);
+			return -ENODEV;
+		}
 		usbhid_init_reports(hid);
+		mutex_unlock(&hiddev->existancelock);
 
 		return 0;
 
@@ -636,8 +684,12 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
 			return -EINVAL;
 
-		usbhid_submit_report(hid, report, USB_DIR_IN);
-		usbhid_wait_io(hid);
+		mutex_lock(&hiddev->existancelock);
+		if (hiddev->exist) {
+			usbhid_submit_report(hid, report, USB_DIR_IN);
+			usbhid_wait_io(hid);
+		}
+		mutex_unlock(&hiddev->existancelock);
 
 		return 0;
 
@@ -651,8 +703,12 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
 			return -EINVAL;
 
-		usbhid_submit_report(hid, report, USB_DIR_OUT);
-		usbhid_wait_io(hid);
+		mutex_lock(&hiddev->existancelock);
+		if (hiddev->exist) {
+			usbhid_submit_report(hid, report, USB_DIR_OUT);
+			usbhid_wait_io(hid);
+		}
+		mutex_unlock(&hiddev->existancelock);
 
 		return 0;
 
@@ -710,7 +766,13 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	case HIDIOCGUSAGES:
 	case HIDIOCSUSAGES:
 	case HIDIOCGCOLLECTIONINDEX:
-		return hiddev_ioctl_usage(hiddev, cmd, user_arg);
+		mutex_lock(&hiddev->existancelock);
+		if (hiddev->exist)
+			r = hiddev_ioctl_usage(hiddev, cmd, user_arg);
+		else
+			r = -ENODEV;
+		mutex_unlock(&hiddev->existancelock);
+		return r;
 
 	case HIDIOCGCOLLECTIONINFO:
 		if (copy_from_user(&cinfo, user_arg, sizeof(cinfo)))
@@ -808,23 +870,22 @@ int hiddev_connect(struct hid_device *hid, unsigned int force)
 	if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL)))
 		return -1;
 
-	retval = usb_register_dev(usbhid->intf, &hiddev_class);
-	if (retval) {
-		err_hid("Not able to get a minor for this device.");
-		kfree(hiddev);
-		return -1;
-	}
-
 	init_waitqueue_head(&hiddev->wait);
 	INIT_LIST_HEAD(&hiddev->list);
 	spin_lock_init(&hiddev->list_lock);
+	mutex_init(&hiddev->existancelock);
 	hiddev->hid = hid;
 	hiddev->exist = 1;
 
-	hid->minor = usbhid->intf->minor;
-	hid->hiddev = hiddev;
-
-	hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
+	retval = usb_register_dev(usbhid->intf, &hiddev_class);
+	if (retval) {
+		err_hid("Not able to get a minor for this device.");
+		kfree(hiddev);
+		return -1;
+	} else {
+		hid->minor = usbhid->intf->minor;
+		hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
+	}
 
 	return 0;
 }
@@ -839,7 +900,9 @@ void hiddev_disconnect(struct hid_device *hid)
 	struct hiddev *hiddev = hid->hiddev;
 	struct usbhid_device *usbhid = hid->driver_data;
 
+	mutex_lock(&hiddev->existancelock);
 	hiddev->exist = 0;
+	mutex_unlock(&hiddev->existancelock);
 
 	hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
 	usb_deregister_dev(usbhid->intf, &hiddev_class);
-- 
cgit v1.2.3


From ac09952babed8e2ac6999127b7f95d7a2bbfd7af Mon Sep 17 00:00:00 2001
From: Parag Warudkar <parag.lkml@gmail.com>
Date: Mon, 22 Dec 2008 22:50:52 +0100
Subject: HID: make boot protocol drivers depend on EMBEDDED

The usbmouse and usbkbd modules are not supposed to be used with regular USB
mice and keyboards. Make them depend on EMBEDDED to prevent them from being
built and loaded on non-EMBEDDED configs.

Signed-off-by: Parag Warudkar <parag.lkml@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/usbhid/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig
index 5d9aa95fc3ef..4edb3bef94a6 100644
--- a/drivers/hid/usbhid/Kconfig
+++ b/drivers/hid/usbhid/Kconfig
@@ -45,7 +45,7 @@ config USB_HIDDEV
 	  If unsure, say Y.
 
 menu "USB HID Boot Protocol drivers"
-	depends on USB!=n && USB_HID!=y
+	depends on USB!=n && USB_HID!=y && EMBEDDED
 
 config USB_KBD
 	tristate "USB HIDBP Keyboard (simple Boot) support"
-- 
cgit v1.2.3


From f14f526d02b14fd0b8c1ac4ec413e4577ad5f62e Mon Sep 17 00:00:00 2001
From: Lev Babiev <harley@hosers.org>
Date: Sun, 4 Jan 2009 00:36:56 +0100
Subject: HID: driver for TopSeed Cyberlink quirky remote

I recently picked up a Cyberlink branded remote control produced
by TopSeed Tech Corp. Alas, it appears that this device is using
non-standard mappings for some of it's keys (Usage page 0xffbc).

Signed-off-by: Lev Babiev <harley@hosers.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/Kconfig       |  7 +++++
 drivers/hid/Makefile      |  1 +
 drivers/hid/hid-core.c    |  1 +
 drivers/hid/hid-ids.h     |  3 ++
 drivers/hid/hid-topseed.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 89 insertions(+)
 create mode 100644 drivers/hid/hid-topseed.c

(limited to 'drivers')

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 81dd9b8eeeaa..4c65e75d5b8d 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -246,6 +246,13 @@ config GREENASIA_FF
 	(like MANTA Warior MM816 and SpeedLink Strike2 SL-6635) or adapter
 	and want to enable force feedback support for it.
 
+config HID_TOPSEED
+	tristate "TopSeed Cyberlink remote control support" if EMBEDDED
+	depends on USB_HID
+	default y
+	---help---
+	Say Y if you have a TopSeed Cyberlink remote control.
+
 config THRUSTMASTER_FF
 	tristate "ThrustMaster devices support"
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 3354eacffa49..fbd021f153f1 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_HID_SONY)		+= hid-sony.o
 obj-$(CONFIG_HID_SUNPLUS)	+= hid-sunplus.o
 obj-$(CONFIG_GREENASIA_FF)	+= hid-gaff.o
 obj-$(CONFIG_THRUSTMASTER_FF)	+= hid-tmff.o
+obj-$(CONFIG_HID_TOPSEED)	+= hid-topseed.o
 obj-$(CONFIG_ZEROPLUS_FF)	+= hid-zpff.o
 
 obj-$(CONFIG_USB_HID)		+= usbhid/
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 8fd35a697c5b..58a706dc7496 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1299,6 +1299,7 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_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_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
 
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 2b7b6eeae8c6..daced0bf9d49 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -375,6 +375,9 @@
 #define USB_VENDOR_ID_TOPMAX		0x0663
 #define USB_DEVICE_ID_TOPMAX_COBRAPAD	0x0103
 
+#define USB_VENDOR_ID_TOPSEED		0x0766
+#define USB_DEVICE_ID_TOPSEED_CYBERLINK	0x0204
+
 #define USB_VENDOR_ID_TURBOX		0x062a
 #define USB_DEVICE_ID_TURBOX_KEYBOARD	0x0201
 
diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c
new file mode 100644
index 000000000000..cca64a0564a9
--- /dev/null
+++ b/drivers/hid/hid-topseed.c
@@ -0,0 +1,77 @@
+/*
+ *  HID driver for TopSeed Cyberlink remote
+ *
+ *  Copyright (c) 2008 Lev Babiev
+ *  based on hid-cherry driver
+ */
+
+/*
+ * 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 "hid-ids.h"
+
+#define ts_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, max, \
+					EV_KEY, (c))
+static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	if ((usage->hid & HID_USAGE_PAGE) != 0x0ffbc0000)
+		return 0;
+
+	switch (usage->hid & HID_USAGE) {
+        case 0x00d: ts_map_key_clear(KEY_HOME);           break;
+        case 0x024: ts_map_key_clear(KEY_MENU);           break;
+        case 0x025: ts_map_key_clear(KEY_TV);             break;
+        case 0x048: ts_map_key_clear(KEY_RED);            break;
+        case 0x047: ts_map_key_clear(KEY_GREEN);          break;
+        case 0x049: ts_map_key_clear(KEY_YELLOW);         break;
+        case 0x04a: ts_map_key_clear(KEY_BLUE);           break;
+        case 0x04b: ts_map_key_clear(KEY_ANGLE);          break;
+        case 0x04c: ts_map_key_clear(KEY_LANGUAGE);       break;
+        case 0x04d: ts_map_key_clear(KEY_SUBTITLE);       break;
+        case 0x031: ts_map_key_clear(KEY_AUDIO);          break;
+        case 0x032: ts_map_key_clear(KEY_TEXT);           break;
+        case 0x033: ts_map_key_clear(KEY_CHANNEL);        break;
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+
+static const struct hid_device_id ts_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, ts_devices);
+
+static struct hid_driver ts_driver = {
+	.name = "topseed",
+	.id_table = ts_devices,
+	.input_mapping = ts_input_mapping,
+};
+
+static int ts_init(void)
+{
+	return hid_register_driver(&ts_driver);
+}
+
+static void ts_exit(void)
+{
+	hid_unregister_driver(&ts_driver);
+}
+
+module_init(ts_init);
+module_exit(ts_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(topseed);
-- 
cgit v1.2.3


From 1db489b2953799d41098a891c85dea02e3c4721a Mon Sep 17 00:00:00 2001
From: Jiri Kosina <jkosina@suse.cz>
Date: Sun, 4 Jan 2009 00:39:08 +0100
Subject: HID: fix default Kconfig setting for TopSpeed driver

Make default setting for TopSpeed driver compliant with the defaults
of the other specialized HID drivers.

Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 4c65e75d5b8d..e85c8fe9ffcf 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -249,7 +249,7 @@ config GREENASIA_FF
 config HID_TOPSEED
 	tristate "TopSeed Cyberlink remote control support" if EMBEDDED
 	depends on USB_HID
-	default y
+	default !EMBEDDED
 	---help---
 	Say Y if you have a TopSeed Cyberlink remote control.
 
-- 
cgit v1.2.3


From 5f6108cf9be4a77d6bee96750aa4fe18b6b97dee Mon Sep 17 00:00:00 2001
From: Alexey Klimov <klimov.linux@gmail.com>
Date: Mon, 8 Dec 2008 12:40:14 +0100
Subject: HID: don't allow DealExtreme usb-radio be handled by usb hid driver

This device is already handled by radio-si470x driver, and we therefore
want usbhid to ignore it.  Patch places usb ids of that device in
ignore section of hid-core.c

Signed-off-by: Alexey Klimov <klimov.linux@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/hid-core.c | 1 +
 drivers/hid/hid-ids.h  | 3 +++
 2 files changed, 4 insertions(+)

(limited to 'drivers')

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 40df3e1b4bd1..0ac2b668616b 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1420,6 +1420,7 @@ static const struct hid_device_id hid_ignore_list[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 39289699c32f..1fe0b8bae1b7 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -141,6 +141,9 @@
 #define USB_DEVICE_ID_CYPRESS_BARCODE_1	0xde61
 #define USB_DEVICE_ID_CYPRESS_BARCODE_2	0xde64
 
+#define USB_VENDOR_ID_DEALEXTREAME	0x10c5
+#define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701	0x819a
+
 #define USB_VENDOR_ID_DELL		0x413c
 #define USB_DEVICE_ID_DELL_W7658	0x2005
 #define USB_DEVICE_ID_DELL_SK8115	0x2105
-- 
cgit v1.2.3


From 25e61613cf3ca7f6d5f89a707b20c9eed6b74455 Mon Sep 17 00:00:00 2001
From: Matt Helsley <matt.helsley@gmail.com>
Date: Sat, 13 Dec 2008 14:28:54 +0100
Subject: HID: add proper support for pensketch 12x9 tablet

The Genius PenSketch 12x9 tablet has a puck (labeled a
"Tablet Mouse") in addition to a pen. Without registering a quirk
the tablet appears to be a single input device that reports the
wrong axis information in /proc/bus/input/devices, and sends
incorrect events (e.g. ABS_Z instead of ABS_Y). This information
confuses the X evdev driver and makes the device impossible to
use.

The quirk fixes events and splits the device into multiple input
event devices so that at least the puck is useful.

Signed-off-by: Matt Helsley <matt.helsley@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/hid-ids.h           | 3 +++
 drivers/hid/usbhid/hid-quirks.c | 1 +
 2 files changed, 4 insertions(+)

(limited to 'drivers')

diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 1fe0b8bae1b7..63aaa0ff3971 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -389,6 +389,9 @@
 #define USB_VENDOR_ID_TURBOX		0x062a
 #define USB_DEVICE_ID_TURBOX_KEYBOARD	0x0201
 
+#define USB_VENDOR_ID_UCLOGIC		0x5543
+#define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209	0x0042
+
 #define USB_VENDOR_ID_VERNIER		0x08f7
 #define USB_DEVICE_ID_VERNIER_LABPRO	0x0001
 #define USB_DEVICE_ID_VERNIER_GOTEMP	0x0002
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 47ebe045f9b5..4391717d2519 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -54,6 +54,7 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, 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_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 
-- 
cgit v1.2.3


From b8a832b1c0a70531b4bd69a67aa0bf72f6f2dc34 Mon Sep 17 00:00:00 2001
From: Oliver Neukum <oliver@neukum.org>
Date: Mon, 15 Dec 2008 13:12:08 +0100
Subject: HID: fix reference count leak hidraw

The hidraw subsystem has a bug that prevents the close syscall from ever
reaching the low level driver, leading to a resource leak. Fix by replacing
postdecrement with predecrement.

Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/hidraw.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 7685ae6808c4..96ec1bacbbf3 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -208,7 +208,7 @@ static int hidraw_release(struct inode * inode, struct file * file)
 
 	list_del(&list->node);
 	dev = hidraw_table[minor];
-	if (!dev->open--) {
+	if (!--dev->open) {
 		if (list->hidraw->exist)
 			dev->hid->ll_driver->close(dev->hid);
 		else
-- 
cgit v1.2.3


From 4dfdc46468a142216b284eea66040f49df3f7191 Mon Sep 17 00:00:00 2001
From: Jiri Kosina <jkosina@suse.cz>
Date: Tue, 30 Dec 2008 00:49:59 +0100
Subject: HID: fix error condition propagation in hid-sony driver

sony_set_operational() only propagates return value from
usb_control_msg(), which returns negative on error and number
of transferred bytes otherwise.

Reported-by: Marcin Tolysz <tolysz@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
 drivers/hid/hid-sony.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 86e563b8d644..dd5a3979a4de 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -102,7 +102,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	}
 
 	ret = sony_set_operational(hdev);
-	if (ret)
+	if (ret < 0)
 		goto err_stop;
 
 	return 0;
-- 
cgit v1.2.3