From 92e0d896ce3087112602449efd87c6d7f4eae8d0 Mon Sep 17 00:00:00 2001 From: Sergey Belyashov Date: Mon, 4 May 2009 13:01:02 +0400 Subject: [PATCH 01/10] HID: autocentering support for Logitech G25 Racing Wheel Some months ago I send patch which adds autocentering for Logitech MOMO Wheel. Now I have access to Logitech G25 Racing Wheel and test autocentering for it. I write patch for current kernel to support autocentering for G25 in legacy mode (this device supports other modes, but after switching device reconnects with ID 0xc299 and FF support comes out) and others Logitech (Driving Force, Formula Force Ex etc) wheels with ID 046d:c294. Signed-off-by: Sergey Belyashov Signed-off-by: Jiri Kosina --- drivers/hid/hid-lgff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c index 51aff08e10ce..9735be6ee4ff 100644 --- a/drivers/hid/hid-lgff.c +++ b/drivers/hid/hid-lgff.c @@ -61,7 +61,7 @@ static const struct dev_type devices[] = { { 0x046d, 0xc219, ff_rumble }, { 0x046d, 0xc283, ff_joystick }, { 0x046d, 0xc286, ff_joystick }, - { 0x046d, 0xc294, ff_joystick }, + { 0x046d, 0xc294, ff_wheel }, { 0x046d, 0xc295, ff_joystick }, { 0x046d, 0xca03, ff_wheel }, }; From ca2dcd40f54c8928b3994712a6cadd2078a087fa Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 11 May 2009 17:18:12 +0200 Subject: [PATCH 02/10] HID: Wacom Graphire Bluetooth driver Based on the work by Andrew Zabolotny, an HID driver for the Bluetooth Wacom tablet. This is required as it uses a slightly different protocols from what's currently support by the drivers/input/wacom* driver, and those only support USB. A user-space patch is required to activate mode 2 of the Wacom tablet, as hidp does not support hid_output_raw_report. Signed-off-by: Bastien Nocera Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 7 ++ drivers/hid/Makefile | 1 + drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + drivers/hid/hid-wacom.c | 259 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 269 insertions(+) create mode 100644 drivers/hid/hid-wacom.c diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 7e67dcb3d4f6..21edf407bbda 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -271,6 +271,13 @@ config THRUSTMASTER_FF Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel. +config HID_WACOM + tristate "Wacom Bluetooth devices support" if EMBEDDED + depends on BT_HIDP + default !EMBEDDED + ---help--- + Support for Wacom Graphire Bluetooth tablet. + config ZEROPLUS_FF tristate "Zeroplus based game controller support" depends on USB_HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 1f7cb0fd4505..39cebcfa898c 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -40,6 +40,7 @@ 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_HID_WACOM) += hid-wacom.o obj-$(CONFIG_USB_HID) += usbhid/ obj-$(CONFIG_USB_MOUSE) += usbhid/ diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 8551693d645f..9f38ab874c93 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1312,6 +1312,7 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) }, { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 4d5ee2bbc62b..b519692732db 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -414,6 +414,7 @@ #define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006 #define USB_VENDOR_ID_WACOM 0x056a +#define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 #define USB_VENDOR_ID_WISEGROUP 0x0925 #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c new file mode 100644 index 000000000000..1f9237f511e3 --- /dev/null +++ b/drivers/hid/hid-wacom.c @@ -0,0 +1,259 @@ +/* + * Bluetooth Wacom Tablet support + * + * Copyright (c) 1999 Andreas Gal + * Copyright (c) 2000-2005 Vojtech Pavlik + * Copyright (c) 2005 Michael Haboustak for Concept2, Inc + * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley + * Copyright (c) 2008 Jiri Slaby + * Copyright (c) 2006 Andrew Zabolotny + * Copyright (c) 2009 Bastien Nocera + */ + +/* + * 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 +#include +#include + +#include "hid-ids.h" + +struct wacom_data { + __u16 tool; + unsigned char butstate; +}; + +static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, + u8 *raw_data, int size) +{ + struct wacom_data *wdata = hid_get_drvdata(hdev); + struct hid_input *hidinput; + struct input_dev *input; + unsigned char *data = (unsigned char *) raw_data; + int tool, x, y, rw; + + if (!(hdev->claimed & HID_CLAIMED_INPUT)) + return 0; + + tool = 0; + hidinput = list_entry(hdev->inputs.next, struct hid_input, list); + input = hidinput->input; + + /* Check if this is a tablet report */ + if (data[0] != 0x03) + return 0; + + /* Get X & Y positions */ + x = le16_to_cpu(*(__le16 *) &data[2]); + y = le16_to_cpu(*(__le16 *) &data[4]); + + /* Get current tool identifier */ + if (data[1] & 0x90) { /* If pen is in the in/active area */ + switch ((data[1] >> 5) & 3) { + case 0: /* Pen */ + tool = BTN_TOOL_PEN; + break; + + case 1: /* Rubber */ + tool = BTN_TOOL_RUBBER; + break; + + case 2: /* Mouse with wheel */ + case 3: /* Mouse without wheel */ + tool = BTN_TOOL_MOUSE; + break; + } + + /* Reset tool if out of active tablet area */ + if (!(data[1] & 0x10)) + tool = 0; + } + + /* If tool changed, notify input subsystem */ + if (wdata->tool != tool) { + if (wdata->tool) { + /* Completely reset old tool state */ + if (wdata->tool == BTN_TOOL_MOUSE) { + input_report_key(input, BTN_LEFT, 0); + input_report_key(input, BTN_RIGHT, 0); + input_report_key(input, BTN_MIDDLE, 0); + input_report_abs(input, ABS_DISTANCE, + input->absmax[ABS_DISTANCE]); + } else { + input_report_key(input, BTN_TOUCH, 0); + input_report_key(input, BTN_STYLUS, 0); + input_report_key(input, BTN_STYLUS2, 0); + input_report_abs(input, ABS_PRESSURE, 0); + } + input_report_key(input, wdata->tool, 0); + input_sync(input); + } + wdata->tool = tool; + if (tool) + input_report_key(input, tool, 1); + } + + if (tool) { + input_report_abs(input, ABS_X, x); + input_report_abs(input, ABS_Y, y); + + switch ((data[1] >> 5) & 3) { + case 2: /* Mouse with wheel */ + input_report_key(input, BTN_MIDDLE, data[1] & 0x04); + rw = (data[6] & 0x01) ? -1 : + (data[6] & 0x02) ? 1 : 0; + input_report_rel(input, REL_WHEEL, rw); + /* fall through */ + + case 3: /* Mouse without wheel */ + input_report_key(input, BTN_LEFT, data[1] & 0x01); + input_report_key(input, BTN_RIGHT, data[1] & 0x02); + /* Compute distance between mouse and tablet */ + rw = 44 - (data[6] >> 2); + if (rw < 0) + rw = 0; + else if (rw > 31) + rw = 31; + input_report_abs(input, ABS_DISTANCE, rw); + break; + + default: + input_report_abs(input, ABS_PRESSURE, + data[6] | (((__u16) (data[1] & 0x08)) << 5)); + input_report_key(input, BTN_TOUCH, data[1] & 0x01); + input_report_key(input, BTN_STYLUS, data[1] & 0x02); + input_report_key(input, BTN_STYLUS2, (tool == BTN_TOOL_PEN) && data[1] & 0x04); + break; + } + + input_sync(input); + } + + /* Report the state of the two buttons at the top of the tablet + * as two extra fingerpad keys (buttons 4 & 5). */ + rw = data[7] & 0x03; + if (rw != wdata->butstate) { + wdata->butstate = rw; + input_report_key(input, BTN_0, rw & 0x02); + input_report_key(input, BTN_1, rw & 0x01); + input_event(input, EV_MSC, MSC_SERIAL, 0xf0); + input_sync(input); + } + + return 1; +} + +static int wacom_probe(struct hid_device *hdev, + const struct hid_device_id *id) +{ + struct hid_input *hidinput; + struct input_dev *input; + struct wacom_data *wdata; + int ret; + + wdata = kzalloc(sizeof(*wdata), GFP_KERNEL); + if (wdata == NULL) { + dev_err(&hdev->dev, "can't alloc wacom descriptor\n"); + return -ENOMEM; + } + + hid_set_drvdata(hdev, wdata); + + 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; + } + + hidinput = list_entry(hdev->inputs.next, struct hid_input, list); + input = hidinput->input; + + /* Basics */ + input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); + input->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | + BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE); + input->relbit[0] |= BIT(REL_WHEEL); + set_bit(BTN_TOOL_PEN, input->keybit); + set_bit(BTN_TOUCH, input->keybit); + set_bit(BTN_STYLUS, input->keybit); + set_bit(BTN_STYLUS2, input->keybit); + set_bit(BTN_LEFT, input->keybit); + set_bit(BTN_RIGHT, input->keybit); + set_bit(BTN_MIDDLE, input->keybit); + + /* Pad */ + input->evbit[0] |= BIT(EV_MSC); + input->mscbit[0] |= BIT(MSC_SERIAL); + + /* Distance, rubber and mouse */ + input->absbit[0] |= BIT(ABS_DISTANCE); + set_bit(BTN_TOOL_RUBBER, input->keybit); + set_bit(BTN_TOOL_MOUSE, input->keybit); + + input->absmax[ABS_PRESSURE] = 511; + input->absmax[ABS_DISTANCE] = 32; + + input->absmax[ABS_X] = 16704; + input->absmax[ABS_Y] = 12064; + input->absfuzz[ABS_X] = 4; + input->absfuzz[ABS_Y] = 4; + + return 0; +err_free: + kfree(wdata); + return ret; +} + +static void wacom_remove(struct hid_device *hdev) +{ + hid_hw_stop(hdev); + kfree(hid_get_drvdata(hdev)); +} + +static const struct hid_device_id wacom_devices[] = { + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, + + { } +}; +MODULE_DEVICE_TABLE(hid, wacom_devices); + +static struct hid_driver wacom_driver = { + .name = "wacom", + .id_table = wacom_devices, + .probe = wacom_probe, + .remove = wacom_remove, + .raw_event = wacom_raw_event, +}; + +static int wacom_init(void) +{ + int ret; + + ret = hid_register_driver(&wacom_driver); + if (ret) + printk(KERN_ERR "can't register wacom driver\n"); + printk(KERN_ERR "wacom driver registered\n"); + return ret; +} + +static void wacom_exit(void) +{ + hid_unregister_driver(&wacom_driver); +} + +module_init(wacom_init); +module_exit(wacom_exit); +MODULE_LICENSE("GPL"); + From fac733f029251a393c42a8313432f2d9fe43bb83 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Wed, 13 May 2009 11:54:38 +0300 Subject: [PATCH 03/10] HID: force feedback support for SmartJoy PLUS PS2/USB adapter This driver adds force feedback support for SmartJoy PLUS PS2/USB adapter. I made this driver one device spesific instead of making generic 'wisegroup-ff' because I have another Wisegroup PS2/USB adapter that doesn't work same way as SmartJoy PLUS. If another device that is compatible pops up, this driver could be then renamed to something more generic. Signed-off-by: Jussi Kivilinna Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 15 ++++ drivers/hid/Makefile | 1 + drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + drivers/hid/hid-sjoy.c | 180 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 198 insertions(+) create mode 100644 drivers/hid/hid-sjoy.c diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 21edf407bbda..4cdf846da62c 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -256,6 +256,21 @@ config GREENASIA_FF (like MANTA Warrior MM816 and SpeedLink Strike2 SL-6635) or adapter and want to enable force feedback support for it. +config HID_SMARTJOYPLUS + tristate "SmartJoy PLUS PS2/USB adapter support" if EMBEDDED + depends on USB_HID + default !EMBEDDED + ---help--- + Support for SmartJoy PLUS PS2/USB adapter. + +config SMARTJOYPLUS_FF + bool "SmartJoy PLUS PS2/USB adapter force feedback support" + depends on HID_SMARTJOYPLUS + select INPUT_FF_MEMLESS + ---help--- + Say Y here if you have a SmartJoy PLUS PS2/USB 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 diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 39cebcfa898c..eddd5b633b63 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -34,6 +34,7 @@ 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 +obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o obj-$(CONFIG_HID_SONY) += hid-sony.o obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o obj-$(CONFIG_GREENASIA_FF) += hid-gaff.o diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 9f38ab874c93..f2c21d5d24e8 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1312,6 +1312,7 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) }, { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b519692732db..630101037921 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -417,6 +417,7 @@ #define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 #define USB_VENDOR_ID_WISEGROUP 0x0925 +#define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005 #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 #define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104 #define USB_DEVICE_ID_8_8_4_IF_KIT 0x8201 diff --git a/drivers/hid/hid-sjoy.c b/drivers/hid/hid-sjoy.c new file mode 100644 index 000000000000..eab169e5c371 --- /dev/null +++ b/drivers/hid/hid-sjoy.c @@ -0,0 +1,180 @@ +/* + * Force feedback support for SmartJoy PLUS PS2->USB adapter + * + * Copyright (c) 2009 Jussi Kivilinna + * + * Based of hid-pl.c and hid-gaff.c + * Copyright (c) 2007, 2009 Anssi Hannula + * Copyright (c) 2008 Lukasz Lubojanski + */ + +/* + * 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 + */ + +/* #define DEBUG */ + +#include +#include +#include +#include "hid-ids.h" + +#ifdef CONFIG_SMARTJOYPLUS_FF +#include "usbhid/usbhid.h" + +struct sjoyff_device { + struct hid_report *report; +}; + +static int hid_sjoyff_play(struct input_dev *dev, void *data, + struct ff_effect *effect) +{ + struct hid_device *hid = input_get_drvdata(dev); + struct sjoyff_device *sjoyff = data; + u32 left, right; + + left = effect->u.rumble.strong_magnitude; + right = effect->u.rumble.weak_magnitude; + dev_dbg(&dev->dev, "called with 0x%08x 0x%08x\n", left, right); + + left = left * 0xff / 0xffff; + right = (right != 0); /* on/off only */ + + sjoyff->report->field[0]->value[1] = right; + sjoyff->report->field[0]->value[2] = left; + dev_dbg(&dev->dev, "running with 0x%02x 0x%02x\n", left, right); + usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); + + return 0; +} + +static int sjoyff_init(struct hid_device *hid) +{ + struct sjoyff_device *sjoyff; + 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; + int error; + + if (list_empty(report_list)) { + dev_err(&hid->dev, "no output reports found\n"); + return -ENODEV; + } + + report_ptr = report_ptr->next; + + if (report_ptr == report_list) { + dev_err(&hid->dev, "required output report is " + "missing\n"); + return -ENODEV; + } + + 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 < 3) { + dev_err(&hid->dev, "not enough values in the field\n"); + return -ENODEV; + } + + sjoyff = kzalloc(sizeof(struct sjoyff_device), GFP_KERNEL); + if (!sjoyff) + return -ENOMEM; + + dev = hidinput->input; + + set_bit(FF_RUMBLE, dev->ffbit); + + error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play); + if (error) { + kfree(sjoyff); + return error; + } + + sjoyff->report = report; + sjoyff->report->field[0]->value[0] = 0x01; + sjoyff->report->field[0]->value[1] = 0x00; + sjoyff->report->field[0]->value[2] = 0x00; + usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); + + dev_info(&hid->dev, + "Force feedback for SmartJoy PLUS PS2/USB adapter\n"); + + return 0; +} +#else +static inline int sjoyff_init(struct hid_device *hid) +{ + return 0; +} +#endif + +static int sjoy_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; + } + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); + if (ret) { + dev_err(&hdev->dev, "hw start failed\n"); + goto err; + } + + sjoyff_init(hdev); + + return 0; +err: + return ret; +} + +static const struct hid_device_id sjoy_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, + { } +}; +MODULE_DEVICE_TABLE(hid, sjoy_devices); + +static struct hid_driver sjoy_driver = { + .name = "smartjoyplus", + .id_table = sjoy_devices, + .probe = sjoy_probe, +}; + +static int sjoy_init(void) +{ + return hid_register_driver(&sjoy_driver); +} + +static void sjoy_exit(void) +{ + hid_unregister_driver(&sjoy_driver); +} + +module_init(sjoy_init); +module_exit(sjoy_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jussi Kivilinna"); + From 0f6f4319a72a2b32d19643ff811f25633d8b0207 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Fri, 15 May 2009 15:46:44 +0200 Subject: [PATCH 04/10] HID: fix hid-ff drivers so that devices work even without ff support Currently, the hid-*ff force feedback drivers, which claim the blacklisted device on a HID bus, are only compiled in if the user selects force feedback support. However we want the device to be supported even when the kernel is configured without force feedback. This patch fixes the drivers in a way that they get compiled even if force feedback is turned off; all the force feedback support code is compiled out in such case, and the driver works as a usual driver on HID bus, claiming and initializing the device, making it operational without FF effects. Reported-by: Jussi Kivilinna Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 72 ++++++++++++++++++++++++++++++++---------- drivers/hid/Makefile | 8 ++--- drivers/hid/hid-drff.c | 8 +++++ drivers/hid/hid-gaff.c | 8 +++++ drivers/hid/hid-tmff.c | 17 +++++++--- drivers/hid/hid-zpff.c | 7 ++++ 6 files changed, 95 insertions(+), 25 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 4cdf846da62c..7831a0318d3c 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -116,9 +116,16 @@ config HID_CYPRESS ---help--- Support for cypress mouse and barcode readers. -config DRAGONRISE_FF - tristate "DragonRise Inc. force feedback support" +config HID_DRAGONRISE + tristate "DragonRise Inc. support" if EMBEDDED depends on USB_HID + default !EMBEDDED + ---help--- + Say Y here if you have DragonRise Inc.game controllers. + +config DRAGONRISE_FF + bool "DragonRise Inc. force feedback support" + depends on HID_DRAGONRISE select INPUT_FF_MEMLESS ---help--- Say Y here if you want to enable force feedback support for DragonRise Inc. @@ -160,7 +167,7 @@ config HID_LOGITECH Support for Logitech devices that are not fully compliant with HID standard. config LOGITECH_FF - bool "Logitech force feedback" + bool "Logitech force feedback support" depends on HID_LOGITECH select INPUT_FF_MEMLESS help @@ -176,7 +183,7 @@ config LOGITECH_FF force feedback. config LOGIRUMBLEPAD2_FF - bool "Logitech Rumblepad 2 force feedback" + bool "Logitech Rumblepad 2 force feedback support" depends on HID_LOGITECH select INPUT_FF_MEMLESS help @@ -211,11 +218,19 @@ config HID_PANTHERLORD ---help--- Support for PantherLord/GreenAsia based device support. +config HID_PANTHERLORD + tristate "Pantherlord support" if EMBEDDED + depends on USB_HID + default !EMBEDDED + ---help--- + Say Y here if you have a PantherLord/GreenAsia based game controller + or adapter. + config PANTHERLORD_FF bool "Pantherlord force feedback support" depends on HID_PANTHERLORD select INPUT_FF_MEMLESS - help + ---help--- Say Y here if you have a PantherLord/GreenAsia based game controller or adapter and want to enable force feedback support for it. @@ -247,9 +262,17 @@ config HID_SUNPLUS ---help--- Support for Sunplus wireless desktop. -config GREENASIA_FF - tristate "GreenAsia (Product ID 0x12) force feedback support" +config HID_GREENASIA + tristate "GreenAsia (Product ID 0x12) support" if EMBEDDED depends on USB_HID + default !EMBEDDED + ---help--- + Say Y here if you have a GreenAsia (Product ID 0x12) based game + controller or adapter. + +config GREENASIA_FF + bool "GreenAsia (Product ID 0x12) force feedback support" + depends on HID_GREENASIA select INPUT_FF_MEMLESS ---help--- Say Y here if you have a GreenAsia (Product ID 0x12) based game controller @@ -278,13 +301,22 @@ config HID_TOPSEED ---help--- Say Y if you have a TopSeed Cyberlink remote control. -config THRUSTMASTER_FF - tristate "ThrustMaster devices support" +config HID_THRUSTMASTER + tristate "ThrustMaster devices support" if EMBEDDED depends on USB_HID - select INPUT_FF_MEMLESS - help + default !EMBEDDED + ---help--- Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or - a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel. + a THRUSTMASTER Ferrari GT Rumble Wheel. + +config THRUSTMASTER_FF + bool "ThrustMaster devices force feedback support" + depends on HID_THRUSTMASTER + select INPUT_FF_MEMLESS + ---help--- + Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or + a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel and + want to enable force feedback support for it. config HID_WACOM tristate "Wacom Bluetooth devices support" if EMBEDDED @@ -293,13 +325,21 @@ config HID_WACOM ---help--- Support for Wacom Graphire Bluetooth tablet. -config ZEROPLUS_FF - tristate "Zeroplus based game controller support" +config HID_ZEROPLUS + tristate "Zeroplus based game controller support" if EMBEDDED depends on USB_HID - select INPUT_FF_MEMLESS - help + default !EMBEDDED + ---help--- Say Y here if you have a Zeroplus based game controller. +config ZEROPLUS_FF + bool "Zeroplus based game controller force feedback support" + depends on HID_ZEROPLUS + select INPUT_FF_MEMLESS + ---help--- + Say Y here if you have a Zeroplus based game controller and want + to have force feedback support for it. + endmenu endif # HID_SUPPORT diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index eddd5b633b63..db35151673b1 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_HID_BELKIN) += hid-belkin.o obj-$(CONFIG_HID_CHERRY) += hid-cherry.o obj-$(CONFIG_HID_CHICONY) += hid-chicony.o obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o -obj-$(CONFIG_DRAGONRISE_FF) += hid-drff.o +obj-$(CONFIG_HID_DRAGONRISE) += hid-drff.o obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o obj-$(CONFIG_HID_GYRATION) += hid-gyration.o obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o @@ -37,10 +37,10 @@ obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.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_HID_GREENASIA) += hid-gaff.o +obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o -obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o +obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o obj-$(CONFIG_HID_WACOM) += hid-wacom.o obj-$(CONFIG_USB_HID) += usbhid/ diff --git a/drivers/hid/hid-drff.c b/drivers/hid/hid-drff.c index 34f3eb65100b..a239d20ad7a5 100644 --- a/drivers/hid/hid-drff.c +++ b/drivers/hid/hid-drff.c @@ -32,6 +32,8 @@ #include #include "hid-ids.h" + +#ifdef CONFIG_DRAGONRISE_FF #include "usbhid/usbhid.h" struct drff_device { @@ -135,6 +137,12 @@ static int drff_init(struct hid_device *hid) return 0; } +#else +static inline int drff_init(struct hid_device *hid) +{ + return 0; +} +#endif static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id) { diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c index 510ad3ab8d33..8a11ccddaf2e 100644 --- a/drivers/hid/hid-gaff.c +++ b/drivers/hid/hid-gaff.c @@ -31,6 +31,8 @@ #include #include #include "hid-ids.h" + +#ifdef CONFIG_GREENASIA_FF #include "usbhid/usbhid.h" struct gaff_device { @@ -130,6 +132,12 @@ static int gaff_init(struct hid_device *hid) return 0; } +#else +static inline int gaff_init(struct hid_device *hdev) +{ + return 0; +} +#endif static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id) { diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c index 7c1f7b50330c..fcd6ccd02fee 100644 --- a/drivers/hid/hid-tmff.c +++ b/drivers/hid/hid-tmff.c @@ -33,11 +33,6 @@ #include "hid-ids.h" -#include "usbhid/usbhid.h" - -/* Usages for thrustmaster devices I know about */ -#define THRUSTMASTER_USAGE_FF (HID_UP_GENDESK | 0xbb) - static const signed short ff_rumble[] = { FF_RUMBLE, -1 @@ -48,6 +43,12 @@ static const signed short ff_joystick[] = { -1 }; +#ifdef CONFIG_THRUSTMASTER_FF +#include "usbhid/usbhid.h" + +/* Usages for thrustmaster devices I know about */ +#define THRUSTMASTER_USAGE_FF (HID_UP_GENDESK | 0xbb) + struct tmff_device { struct hid_report *report; struct hid_field *ff_field; @@ -209,6 +210,12 @@ fail: kfree(tmff); return error; } +#else +static inline int tmff_init(struct hid_device *hid, const signed short *ff_bits) +{ + return 0; +} +#endif static int tm_probe(struct hid_device *hdev, const struct hid_device_id *id) { diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c index 85a198a18537..57f710757bf4 100644 --- a/drivers/hid/hid-zpff.c +++ b/drivers/hid/hid-zpff.c @@ -27,6 +27,7 @@ #include "hid-ids.h" +#ifdef CONFIG_ZEROPLUS_FF #include "usbhid/usbhid.h" struct zpff_device { @@ -108,6 +109,12 @@ static int zpff_init(struct hid_device *hid) return 0; } +#else +static inline int zpff_init(struct hid_device *hid) +{ + return 0; +} +#endif static int zp_probe(struct hid_device *hdev, const struct hid_device_id *id) { From f0bca459829fd33d659c8cd0369ac86a3924a9bc Mon Sep 17 00:00:00 2001 From: Sergey Belyashov Date: Fri, 15 May 2009 16:05:57 +0200 Subject: [PATCH 05/10] HID: autocentering support for Logitech Force 3D Pro This patch adds autocentering support for Logitech Force 3D Pro. Signed-off-by: Sergey Belyashov Signed-off-by: Jiri Kosina --- drivers/hid/hid-lgff.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c index 9735be6ee4ff..56099709581c 100644 --- a/drivers/hid/hid-lgff.c +++ b/drivers/hid/hid-lgff.c @@ -50,6 +50,12 @@ static const signed short ff_joystick[] = { -1 }; +static const signed short ff_joystick_ac[] = { + FF_CONSTANT, + FF_AUTOCENTER, + -1 +}; + static const signed short ff_wheel[] = { FF_CONSTANT, FF_AUTOCENTER, @@ -60,7 +66,7 @@ static const struct dev_type devices[] = { { 0x046d, 0xc211, ff_rumble }, { 0x046d, 0xc219, ff_rumble }, { 0x046d, 0xc283, ff_joystick }, - { 0x046d, 0xc286, ff_joystick }, + { 0x046d, 0xc286, ff_joystick_ac }, { 0x046d, 0xc294, ff_wheel }, { 0x046d, 0xc295, ff_joystick }, { 0x046d, 0xca03, ff_wheel }, From 89f536ccfa8b370ff4d054f4061858ca9322c25a Mon Sep 17 00:00:00 2001 From: Stephane Chatty Date: Wed, 20 May 2009 15:41:24 +0200 Subject: [PATCH 06/10] HID: add new multitouch and digitizer contants Added constants to hid.h for all digitizer usages (including the new multitouch ones that are not yet in the official USB spec but are being pushed by Microsft as described in their paper "Digitizer Drivers for Windows Touch and Pen-Based Computers"). Updated hid-debug.c to support the new MT input constants such as ABS_MT_POSITION_X. Signed-off-by: Stephane Chatty Signed-off-by: Jiri Kosina --- drivers/hid/hid-debug.c | 23 +++++++++++++++++++++-- include/linux/hid.h | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 47ac1a7d66e1..04359ed64b87 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -137,6 +137,14 @@ static const struct hid_usage_entry hid_usage_table[] = { {0, 0x44, "BarrelSwitch"}, {0, 0x45, "Eraser"}, {0, 0x46, "TabletPick"}, + {0, 0x47, "Confidence"}, + {0, 0x48, "Width"}, + {0, 0x49, "Height"}, + {0, 0x51, "ContactID"}, + {0, 0x52, "InputMode"}, + {0, 0x53, "DeviceIndex"}, + {0, 0x54, "ContactCount"}, + {0, 0x55, "ContactMaximumNumber"}, { 15, 0, "PhysicalInterfaceDevice" }, {0, 0x00, "Undefined"}, {0, 0x01, "Physical_Interface_Device"}, @@ -514,9 +522,11 @@ static const char *events[EV_MAX + 1] = { [EV_FF_STATUS] = "ForceFeedbackStatus", }; -static const char *syncs[2] = { +static const char *syncs[3] = { [SYN_REPORT] = "Report", [SYN_CONFIG] = "Config", + [SYN_MT_REPORT] = "MT Report", }; + static const char *keys[KEY_MAX + 1] = { [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc", [KEY_1] = "1", [KEY_2] = "2", @@ -734,8 +744,17 @@ static const char *absolutes[ABS_MAX + 1] = { [ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X", [ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure", [ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt", - [ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "Tool Width", + [ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "ToolWidth", [ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc", + [ABS_MT_TOUCH_MAJOR] = "MTMajor", + [ABS_MT_TOUCH_MINOR] = "MTMinor", + [ABS_MT_WIDTH_MAJOR] = "MTMajorW", + [ABS_MT_WIDTH_MINOR] = "MTMinorW", + [ABS_MT_ORIENTATION] = "MTOrientation", + [ABS_MT_POSITION_X] = "MTPositionX", + [ABS_MT_POSITION_Y] = "MTPositionY", + [ABS_MT_TOOL_TYPE] = "MTToolType", + [ABS_MT_BLOB_ID] = "MTBlobID", }; static const char *misc[MSC_MAX + 1] = { diff --git a/include/linux/hid.h b/include/linux/hid.h index a72876e43589..53489fd4d700 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -238,6 +238,42 @@ struct hid_item { #define HID_GD_RIGHT 0x00010092 #define HID_GD_LEFT 0x00010093 +#define HID_DG_DIGITIZER 0x000d0001 +#define HID_DG_PEN 0x000d0002 +#define HID_DG_LIGHTPEN 0x000d0003 +#define HID_DG_TOUCHSCREEN 0x000d0004 +#define HID_DG_TOUCHPAD 0x000d0005 +#define HID_DG_STYLUS 0x000d0020 +#define HID_DG_PUCK 0x000d0021 +#define HID_DG_FINGER 0x000d0022 +#define HID_DG_TIPPRESSURE 0x000d0030 +#define HID_DG_BARRELPRESSURE 0x000d0031 +#define HID_DG_INRANGE 0x000d0032 +#define HID_DG_TOUCH 0x000d0033 +#define HID_DG_UNTOUCH 0x000d0034 +#define HID_DG_TAP 0x000d0035 +#define HID_DG_TABLETFUNCTIONKEY 0x000d0039 +#define HID_DG_PROGRAMCHANGEKEY 0x000d003a +#define HID_DG_INVERT 0x000d003c +#define HID_DG_TIPSWITCH 0x000d0042 +#define HID_DG_TIPSWITCH2 0x000d0043 +#define HID_DG_BARRELSWITCH 0x000d0044 +#define HID_DG_ERASER 0x000d0045 +#define HID_DG_TABLETPICK 0x000d0046 +/* + * as of May 20, 2009 the usages below are not yet in the official USB spec + * but are being pushed by Microsft as described in their paper "Digitizer + * Drivers for Windows Touch and Pen-Based Computers" + */ +#define HID_DG_CONFIDENCE 0x000d0047 +#define HID_DG_WIDTH 0x000d0048 +#define HID_DG_HEIGHT 0x000d0049 +#define HID_DG_CONTACTID 0x000d0051 +#define HID_DG_INPUTMODE 0x000d0052 +#define HID_DG_DEVICEINDEX 0x000d0053 +#define HID_DG_CONTACTCOUNT 0x000d0054 +#define HID_DG_CONTACTMAX 0x000d0055 + /* * HID report types --- Ouch! HID spec says 1 2 3! */ From 57fd637ad9ac6b13c1c47b9a0ced4ee99bb26e76 Mon Sep 17 00:00:00 2001 From: Stephane Chatty Date: Wed, 20 May 2009 15:49:35 +0200 Subject: [PATCH 07/10] HID: Multitouch support for the N-Trig touchscreen Adds support for multitouch interaction on the N-Trig touchscreen, using the new ABS_MT_* input constants. Single touch support works as previously. This code was tested against two versions of the N- Trig firmware: one that supports dual pen/finger single touch, and one that supports finger multitouch but no pen at all. Copyright notices that looked wrong were removed, as it seems that there is only code written in 2009 by Rafin Rubin and Stephane Chatty in this file. Signed-off-by: Stephane Chatty Signed-off-by: Jiri Kosina --- drivers/hid/hid-ntrig.c | 222 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 211 insertions(+), 11 deletions(-) diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index c5b252be9c21..75ed9d2c1a36 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -1,13 +1,8 @@ /* - * HID driver for some ntrig "special" devices + * HID driver for N-Trig touchscreens * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik - * Copyright (c) 2005 Michael Haboustak for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby * Copyright (c) 2008 Rafi Rubin + * Copyright (c) 2009 Stephane Chatty * */ @@ -29,15 +24,79 @@ #define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ EV_KEY, (c)) +struct ntrig_data { + __s32 x, y, id, w, h; + char reading_a_point, found_contact_id; +}; + +/* + * this driver is aimed at two firmware versions in circulation: + * - dual pen/finger single touch + * - finger multitouch, pen not working + */ + 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; + switch (usage->hid & HID_USAGE_PAGE) { + + case HID_UP_GENDESK: + switch (usage->hid) { + case HID_GD_X: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_POSITION_X); + input_set_abs_params(hi->input, ABS_X, + field->logical_minimum, + field->logical_maximum, 0, 0); + return 1; + case HID_GD_Y: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_POSITION_Y); + input_set_abs_params(hi->input, ABS_Y, + field->logical_minimum, + field->logical_maximum, 0, 0); + return 1; + } + return 0; + + case HID_UP_DIGITIZER: + switch (usage->hid) { + /* we do not want to map these for now */ + case HID_DG_INVERT: /* value is always 0 */ + case HID_DG_ERASER: /* value is always 0 */ + case HID_DG_CONTACTID: /* value is useless */ + case HID_DG_BARRELSWITCH: /* doubtful */ + case HID_DG_INPUTMODE: + case HID_DG_DEVICEINDEX: + case HID_DG_CONTACTCOUNT: + case HID_DG_CONTACTMAX: + return -1; + + /* original mapping by Rafi Rubin */ + case HID_DG_CONFIDENCE: + nt_map_key_clear(BTN_TOOL_DOUBLETAP); + return 1; + + /* width/height mapped on TouchMajor/TouchMinor/Orientation */ + case HID_DG_WIDTH: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_TOUCH_MAJOR); + return 1; + case HID_DG_HEIGHT: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_TOUCH_MINOR); + input_set_abs_params(hi->input, ABS_MT_ORIENTATION, + 0, 1, 0, 0); + return 1; + } + return 0; + + case 0xff000000: + /* we do not want to map these: no input-oriented meaning */ + return -1; } + return 0; } @@ -51,6 +110,138 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, return 0; } + +/* + * this function is called upon all reports + * so that we can filter contact point information, + * decide whether we are in multi or single touch mode + * and call input_mt_sync after each point if necessary + */ +static int ntrig_event (struct hid_device *hid, struct hid_field *field, + struct hid_usage *usage, __s32 value) +{ + struct input_dev *input = field->hidinput->input; + struct ntrig_data *nd = hid_get_drvdata(hid); + + if (hid->claimed & HID_CLAIMED_INPUT) { + switch (usage->hid) { + case HID_GD_X: + nd->x = value; + nd->reading_a_point = 1; + break; + case HID_GD_Y: + nd->y = value; + break; + case HID_DG_CONTACTID: + nd->id = value; + /* we receive this only when in multitouch mode */ + nd->found_contact_id = 1; + break; + case HID_DG_WIDTH: + nd->w = value; + break; + case HID_DG_HEIGHT: + nd->h = value; + /* + * when in single touch mode, this is the last + * report received in a finger event. We want + * to emit a normal (X, Y) position + */ + if (! nd->found_contact_id) { + input_event(input, EV_ABS, ABS_X, nd->x); + input_event(input, EV_ABS, ABS_Y, nd->y); + } + break; + case HID_DG_TIPPRESSURE: + /* + * when in single touch mode, this is the last + * report received in a pen event. We want + * to emit a normal (X, Y) position + */ + if (! nd->found_contact_id) { + input_event(input, EV_ABS, ABS_X, nd->x); + input_event(input, EV_ABS, ABS_Y, nd->y); + input_event(input, EV_ABS, ABS_PRESSURE, value); + } + break; + case 0xff000002: + /* + * we receive this when the device is in multitouch + * mode. The first of the three values tagged with + * this usage tells if the contact point is real + * or a placeholder + */ + if (!nd->reading_a_point || value != 1) + break; + /* emit a normal (X, Y) for the first point only */ + if (nd->id == 0) { + input_event(input, EV_ABS, ABS_X, nd->x); + input_event(input, EV_ABS, ABS_Y, nd->y); + } + input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x); + input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y); + if (nd->w > nd->h) { + input_event(input, EV_ABS, + ABS_MT_ORIENTATION, 1); + input_event(input, EV_ABS, + ABS_MT_TOUCH_MAJOR, nd->w); + input_event(input, EV_ABS, + ABS_MT_TOUCH_MINOR, nd->h); + } else { + input_event(input, EV_ABS, + ABS_MT_ORIENTATION, 0); + input_event(input, EV_ABS, + ABS_MT_TOUCH_MAJOR, nd->h); + input_event(input, EV_ABS, + ABS_MT_TOUCH_MINOR, nd->w); + } + input_mt_sync(field->hidinput->input); + nd->reading_a_point = 0; + nd->found_contact_id = 0; + break; + + default: + /* fallback to the generic hidinput handling */ + return 0; + } + } + + /* we have handled the hidinput part, now remains hiddev */ + if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) + hid->hiddev_hid_event(hid, field, usage, value); + + return 1; +} + +static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) +{ + int ret; + struct ntrig_data *nd; + + nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL); + if (!nd) { + dev_err(&hdev->dev, "cannot allocate N-Trig data\n"); + return -ENOMEM; + } + nd->reading_a_point = 0; + nd->found_contact_id = 0; + hid_set_drvdata(hdev, nd); + + ret = hid_parse(hdev); + if (!ret) + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + + if (ret) + kfree (nd); + return ret; +} + +static void ntrig_remove(struct hid_device *hdev) +{ + hid_hw_stop(hdev); + kfree(hid_get_drvdata(hdev)); +} + 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 }, @@ -58,11 +249,20 @@ static const struct hid_device_id ntrig_devices[] = { }; MODULE_DEVICE_TABLE(hid, ntrig_devices); +static const struct hid_usage_id ntrig_grabbed_usages[] = { + { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, + { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} +}; + static struct hid_driver ntrig_driver = { .name = "ntrig", .id_table = ntrig_devices, + .probe = ntrig_probe, + .remove = ntrig_remove, .input_mapping = ntrig_input_mapping, .input_mapped = ntrig_input_mapped, + .usage_table = ntrig_grabbed_usages, + .event = ntrig_event, }; static int ntrig_init(void) From bbe281fad65f2eda1792d70763663a1b729fc03c Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 4 Jun 2009 15:44:25 +0200 Subject: [PATCH 08/10] HID: hidraw -- fix comment about accepted devices hidraw accepts any devices, no matter if the device has already been claimed by other HID driver (hid-input, hidraw), and this is intended to stay. Fix up the comment to reflect reality. Signed-off-by: Jiri Kosina --- drivers/hid/hidraw.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 00ccf4b1985d..0c6639ea03dd 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -349,10 +349,7 @@ int hidraw_connect(struct hid_device *hid) int minor, result; struct hidraw *dev; - /* TODO currently we accept any HID device. This should later - * probably be fixed to accept only those devices which provide - * non-input applications - */ + /* we accept any HID device, no matter the applications */ dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL); if (!dev) From 70fa9f2eadea7ca35bdcd89b20d555934593b40c Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 4 Jun 2009 15:48:38 +0200 Subject: [PATCH 09/10] HID: no more reinitializtion is needed in post_reset No more reinitialization is needed in the post reset hook, remove the FIXME comment. While at it, clean up whitespaces in the immediate surrounding. Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index ac8049b5f1e9..76c4bbe9dccb 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1234,12 +1234,11 @@ static int hid_post_reset(struct usb_interface *intf) struct hid_device *hid = usb_get_intfdata(intf); struct usbhid_device *usbhid = hid->driver_data; int status; - + spin_lock_irq(&usbhid->lock); clear_bit(HID_RESET_PENDING, &usbhid->iofl); spin_unlock_irq(&usbhid->lock); hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); - /* FIXME: Any more reinitialization needed? */ status = hid_start_in(hid); if (status < 0) hid_io_error(hid); @@ -1251,14 +1250,14 @@ static int hid_post_reset(struct usb_interface *intf) int usbhid_get_power(struct hid_device *hid) { struct usbhid_device *usbhid = hid->driver_data; - + return usb_autopm_get_interface(usbhid->intf); } void usbhid_put_power(struct hid_device *hid) { struct usbhid_device *usbhid = hid->driver_data; - + usb_autopm_put_interface(usbhid->intf); } From fa047e4f6fa63a6e9d0ae4d7749538830d14a343 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Wed, 10 Jun 2009 10:25:56 +0200 Subject: [PATCH 10/10] HID: fix inverted wheel for bluetooth version of apple mighty mouse Bluetooth version of Apple Mighty mouse (0x05ac/0x030c) doesn't, according to multiple reports on linux-input@, need the same quirk as the USB version of this mouse (0x05ac/0x0304) does. Signed-off-by: Jiri Kosina --- drivers/hid/hid-apple.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index acbce5745b0c..303ccce05bb3 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -436,10 +436,6 @@ static const struct hid_device_id apple_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - /* Apple wireless Mighty Mouse */ - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c), - .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL }, - { } }; MODULE_DEVICE_TABLE(hid, apple_devices);