HID: move logitech FF processing

Merge the logitech force feedback processing directly into logitech
driver from the usbhid core.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 1ab067e..4319af3 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -160,6 +160,30 @@
 	Support for some Logitech devices which breaks less or more
 	HID specification.
 
+config LOGITECH_FF
+	bool "Logitech force feedback"
+	depends on HID_LOGITECH
+	select INPUT_FF_MEMLESS
+	help
+	  Say Y here if you have one of these devices:
+	  - Logitech WingMan Cordless RumblePad
+	  - Logitech WingMan Cordless RumblePad 2
+	  - Logitech WingMan Force 3D
+	  - Logitech Formula Force EX
+	  - Logitech MOMO Force wheel
+
+	  and if you want to enable force feedback for them.
+	  Note: if you say N here, this device will still be supported, but without
+	  force feedback.
+
+config LOGIRUMBLEPAD2_FF
+	bool "Logitech Rumblepad 2 force feedback"
+	depends on HID_LOGITECH
+	select INPUT_FF_MEMLESS
+	help
+	  Say Y here if you want to enable force feedback support for Logitech
+	  Rumblepad 2 devices.
+
 config HID_MICROSOFT
 	tristate "Microsoft"
 	default m
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 4a756c6..300ee00 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -12,6 +12,14 @@
 obj-m				+= hid-dummy.o
 endif
 
+hid-logitech-objs		:= hid-lg.o
+ifdef CONFIG_LOGITECH_FF
+	hid-logitech-objs	+= hid-lgff.o
+endif
+ifdef CONFIG_LOGIRUMBLEPAD2_FF
+	hid-logitech-objs	+= hid-lg2ff.o
+endif
+
 obj-$(CONFIG_HID_A4TECH)	+= hid-a4tech.o
 obj-$(CONFIG_HID_APPLE)		+= hid-apple.o
 obj-$(CONFIG_HID_BELKIN)	+= hid-belkin.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 699547c..6a730df 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1262,6 +1262,13 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 678f7c3..e2fd52c 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -263,8 +263,14 @@
 #define USB_DEVICE_ID_LOGITECH_RECEIVER	0xc101
 #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST  0xc110
 #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
+#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD	0xc211
 #define USB_DEVICE_ID_LOGITECH_EXTREME_3D	0xc215
+#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2	0xc218
+#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2	0xc219
+#define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D	0xc283
+#define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO	0xc286
 #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
@@ -274,6 +280,7 @@
 #define USB_DEVICE_ID_DINOVO_DESKTOP	0xc704
 #define USB_DEVICE_ID_DINOVO_EDGE	0xc714
 #define USB_DEVICE_ID_DINOVO_MINI	0xc71f
+#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2	0xca03
 
 #define USB_VENDOR_ID_MCC		0x09db
 #define USB_DEVICE_ID_MCC_PMD1024LS	0x0076
diff --git a/drivers/hid/hid-logitech.c b/drivers/hid/hid-lg.c
similarity index 89%
rename from drivers/hid/hid-logitech.c
rename to drivers/hid/hid-lg.c
index df27f9a..406d8c8 100644
--- a/drivers/hid/hid-logitech.c
+++ b/drivers/hid/hid-lg.c
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 
 #include "hid-ids.h"
+#include "hid-lg.h"
 
 #define LG_RDESC		0x001
 #define LG_BAD_RELATIVE_KEYS	0x002
@@ -31,6 +32,8 @@
 #define LG_WIRELESS		0x040
 #define LG_INVERT_HWHEEL	0x080
 #define LG_NOGET		0x100
+#define LG_FF			0x200
+#define LG_FF2			0x400
 
 /*
  * Certain Logitech keyboards send in report #3 keys which are far
@@ -222,6 +225,7 @@
 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
 	unsigned long quirks = id->driver_data;
+	unsigned int connect_mask = HID_CONNECT_DEFAULT;
 	int ret;
 
 	hid_set_drvdata(hdev, (void *)quirks);
@@ -235,7 +239,10 @@
 		goto err_free;
 	}
 
-	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (quirks & (LG_FF | LG_FF2))
+		connect_mask &= ~HID_CONNECT_FF;
+
+	ret = hid_hw_start(hdev, connect_mask);
 	if (ret) {
 		dev_err(&hdev->dev, "hw start failed\n");
 		goto err_free;
@@ -244,6 +251,11 @@
 	if (quirks & LG_RESET_LEDS)
 		usbhid_set_leds(hdev);
 
+	if (quirks & LG_FF)
+		lgff_init(hdev);
+	if (quirks & LG_FF2)
+		lg2ff_init(hdev);
+
 	return 0;
 err_free:
 	return ret;
@@ -283,7 +295,22 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
 		.driver_data = LG_NOGET },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
-		.driver_data = LG_NOGET },
+		.driver_data = LG_NOGET | LG_FF },
+
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD),
+		.driver_data = LG_FF },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
+		.driver_data = LG_FF },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D),
+		.driver_data = LG_FF },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
+		.driver_data = LG_FF },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
+		.driver_data = LG_FF },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
+		.driver_data = LG_FF },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
+		.driver_data = LG_FF2 },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, lg_devices);
diff --git a/drivers/hid/hid-lg.h b/drivers/hid/hid-lg.h
new file mode 100644
index 0000000..27ae750
--- /dev/null
+++ b/drivers/hid/hid-lg.h
@@ -0,0 +1,18 @@
+#ifndef __HID_LG_H
+#define __HID_LG_H
+
+#include <linux/autoconf.h>
+
+#ifdef CONFIG_LOGITECH_FF
+int lgff_init(struct hid_device *hdev);
+#else
+static inline int lgff_init(struct hid_device *hdev) { return -1; }
+#endif
+
+#ifdef CONFIG_LOGIRUMBLEPAD2_FF
+int lg2ff_init(struct hid_device *hdev);
+#else
+static inline int lg2ff_init(struct hid_device *hdev) { return -1; }
+#endif
+
+#endif
diff --git a/drivers/hid/usbhid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c
similarity index 96%
rename from drivers/hid/usbhid/hid-lg2ff.c
rename to drivers/hid/hid-lg2ff.c
index d469bd0..b2e9a67 100644
--- a/drivers/hid/usbhid/hid-lg2ff.c
+++ b/drivers/hid/hid-lg2ff.c
@@ -24,7 +24,9 @@
 #include <linux/input.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
-#include "usbhid.h"
+
+#include "usbhid/usbhid.h"
+#include "hid-lg.h"
 
 struct lg2ff_device {
 	struct hid_report *report;
@@ -57,7 +59,7 @@
 	return 0;
 }
 
-int hid_lg2ff_init(struct hid_device *hid)
+int lg2ff_init(struct hid_device *hid)
 {
 	struct lg2ff_device *lg2ff;
 	struct hid_report *report;
diff --git a/drivers/hid/usbhid/hid-lgff.c b/drivers/hid/hid-lgff.c
similarity index 97%
rename from drivers/hid/usbhid/hid-lgff.c
rename to drivers/hid/hid-lgff.c
index 4b7ab6a..e379c16 100644
--- a/drivers/hid/usbhid/hid-lgff.c
+++ b/drivers/hid/hid-lgff.c
@@ -30,7 +30,9 @@
 #include <linux/input.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
-#include "usbhid.h"
+
+#include "usbhid/usbhid.h"
+#include "hid-lg.h"
 
 struct dev_type {
 	u16 idVendor;
@@ -100,7 +102,7 @@
 	return 0;
 }
 
-int hid_lgff_init(struct hid_device* hid)
+int lgff_init(struct hid_device* hid)
 {
 	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;
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig
index 177bfa1..0e7e2e6 100644
--- a/drivers/hid/usbhid/Kconfig
+++ b/drivers/hid/usbhid/Kconfig
@@ -44,30 +44,6 @@
 	  feedback for it. Microsoft Sidewinder Force Feedback 2 is one of such
 	  devices.
 
-config LOGITECH_FF
-	bool "Logitech devices support"
-	depends on HID_FF
-	select INPUT_FF_MEMLESS if USB_HID
-	help
-	  Say Y here if you have one of these devices:
-	  - Logitech WingMan Cordless RumblePad
-	  - Logitech WingMan Cordless RumblePad 2
-	  - Logitech WingMan Force 3D
-	  - Logitech Formula Force EX
-	  - Logitech MOMO Force wheel
-
-	  and if you want to enable force feedback for them.
-	  Note: if you say N here, this device will still be supported, but without
-	  force feedback.
-
-config LOGIRUMBLEPAD2_FF
-	bool "Logitech Rumblepad 2 support"
-	depends on HID_FF
-	select INPUT_FF_MEMLESS if USB_HID
-	help
-	  Say Y here if you want to enable force feedback support for Logitech
-	  Rumblepad 2 devices.
-
 config PANTHERLORD_FF
 	bool "PantherLord/GreenAsia based device support"
 	depends on HID_FF
diff --git a/drivers/hid/usbhid/Makefile b/drivers/hid/usbhid/Makefile
index 00a7b70..224c62d 100644
--- a/drivers/hid/usbhid/Makefile
+++ b/drivers/hid/usbhid/Makefile
@@ -13,12 +13,6 @@
 ifeq ($(CONFIG_HID_PID),y)
 	usbhid-objs	+= hid-pidff.o
 endif
-ifeq ($(CONFIG_LOGITECH_FF),y)
-	usbhid-objs	+= hid-lgff.o
-endif
-ifeq ($(CONFIG_LOGIRUMBLEPAD2_FF),y)
-	usbhid-objs	+= hid-lg2ff.o
-endif
 ifeq ($(CONFIG_PANTHERLORD_FF),y)
 	usbhid-objs	+= hid-plff.o
 endif
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 402ace7..4ec10aa 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -444,6 +444,7 @@
 
 	spin_unlock_irqrestore(&usbhid->ctrllock, flags);
 }
+EXPORT_SYMBOL_GPL(usbhid_submit_report);
 
 static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
diff --git a/drivers/hid/usbhid/hid-ff.c b/drivers/hid/usbhid/hid-ff.c
index 1d0dac5..8891f60 100644
--- a/drivers/hid/usbhid/hid-ff.c
+++ b/drivers/hid/usbhid/hid-ff.c
@@ -50,18 +50,6 @@
  * be a PID device
  */
 static struct hid_ff_initializer inits[] = {
-#ifdef CONFIG_LOGITECH_FF
-	{ 0x46d, 0xc211, hid_lgff_init }, /* Logitech Cordless rumble pad */
-	{ 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */
-	{ 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */
-	{ 0x46d, 0xc286, hid_lgff_init }, /* Logitech Force 3D Pro Joystick */
-	{ 0x46d, 0xc294, hid_lgff_init }, /* Logitech Formula Force EX */
-	{ 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
-	{ 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */
-#endif
-#ifdef CONFIG_LOGIRUMBLEPAD2_FF
-	{ 0x46d, 0xc218, hid_lg2ff_init }, /* Logitech Rumblepad 2 */
-#endif
 #ifdef CONFIG_PANTHERLORD_FF
 	{ 0x810, 0x0001, hid_plff_init }, /* "Twin USB Joystick" */
 	{ 0xe8f, 0x0003, hid_plff_init }, /* "GreenAsia Inc.    USB Joystick     " */