summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/Kconfig7
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-a4tech.c162
-rw-r--r--drivers/hid/hid-core.c2
-rw-r--r--drivers/hid/hid-dummy.c3
-rw-r--r--drivers/hid/hid-input-quirks.c25
-rw-r--r--drivers/hid/hid-input.c9
-rw-r--r--drivers/hid/usbhid/hid-quirks.c4
-rw-r--r--include/linux/hid.h5
9 files changed, 175 insertions, 43 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 69f3420882a6..01456b1d3833 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -82,6 +82,13 @@ config HID_COMPAT
If unsure, say Y.
+config HID_A4TECH
+ tristate "A4 tech"
+ default m
+ depends on USB_HID
+ ---help---
+ Support for A4 tech X5 and WOP-35 / Trust 450L mice.
+
config HID_APPLE
tristate "Apple"
default m
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 061066201186..ceede11eed7c 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -12,6 +12,7 @@ ifdef CONFIG_HID_COMPAT
obj-m += hid-dummy.o
endif
+obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
obj-$(CONFIG_HID_APPLE) += hid-apple.o
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
diff --git a/drivers/hid/hid-a4tech.c b/drivers/hid/hid-a4tech.c
new file mode 100644
index 000000000000..26e16083a1f1
--- /dev/null
+++ b/drivers/hid/hid-a4tech.c
@@ -0,0 +1,162 @@
+/*
+ * HID driver for some a4tech "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/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define A4_2WHEEL_MOUSE_HACK_7 0x01
+#define A4_2WHEEL_MOUSE_HACK_B8 0x02
+
+struct a4tech_sc {
+ unsigned long quirks;
+ unsigned int hw_wheel;
+ __s32 delayed_value;
+};
+
+static int a4_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ struct a4tech_sc *a4 = hid_get_drvdata(hdev);
+
+ if (usage->type == EV_REL && usage->code == REL_WHEEL)
+ set_bit(REL_HWHEEL, *bit);
+
+ if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007)
+ return -1;
+
+ return 0;
+}
+
+static int a4_event(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ struct a4tech_sc *a4 = hid_get_drvdata(hdev);
+ struct input_dev *input;
+
+ if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+ !usage->type)
+ return 0;
+
+ input = field->hidinput->input;
+
+ if (a4->quirks & A4_2WHEEL_MOUSE_HACK_B8) {
+ if (usage->type == EV_REL && usage->code == REL_WHEEL) {
+ a4->delayed_value = value;
+ return 1;
+ }
+
+ if (usage->hid == 0x000100b8) {
+ input_event(input, EV_REL, value ? REL_HWHEEL :
+ REL_WHEEL, a4->delayed_value);
+ return 1;
+ }
+ }
+
+ if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007) {
+ a4->hw_wheel = !!value;
+ return 1;
+ }
+
+ if (usage->code == REL_WHEEL && a4->hw_wheel) {
+ input_event(input, usage->type, REL_HWHEEL, value);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ struct a4tech_sc *a4;
+ int ret;
+
+ a4 = kzalloc(sizeof(*a4), GFP_KERNEL);
+ if (a4 == NULL) {
+ dev_err(&hdev->dev, "can't alloc device descriptor\n");
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ a4->quirks = id->driver_data;
+
+ hid_set_drvdata(hdev, a4);
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ ret = hid_hw_start(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+ return 0;
+err_free:
+ kfree(a4);
+ return ret;
+}
+
+static void a4_remove(struct hid_device *hdev)
+{
+ struct a4tech_sc *a4 = hid_get_drvdata(hdev);
+
+ hid_hw_stop(hdev);
+ kfree(a4);
+}
+
+static const struct hid_device_id a4_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU),
+ .driver_data = A4_2WHEEL_MOUSE_HACK_7 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D),
+ .driver_data = A4_2WHEEL_MOUSE_HACK_B8 },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, a4_devices);
+
+static struct hid_driver a4_driver = {
+ .name = "a4tech",
+ .id_table = a4_devices,
+ .input_mapped = a4_input_mapped,
+ .event = a4_event,
+ .probe = a4_probe,
+ .remove = a4_remove,
+};
+
+static int a4_init(void)
+{
+ return hid_register_driver(&a4_driver);
+}
+
+static void a4_exit(void)
+{
+ hid_unregister_driver(&a4_driver);
+}
+
+module_init(a4_init);
+module_exit(a4_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(a4tech);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 331670b32e68..be582976db2c 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1132,6 +1132,8 @@ static const struct hid_device_id *hid_match_id(struct hid_device *hdev,
}
static const struct hid_device_id hid_blacklist[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) },
diff --git a/drivers/hid/hid-dummy.c b/drivers/hid/hid-dummy.c
index 27cffe3586f5..123f1c71cdf2 100644
--- a/drivers/hid/hid-dummy.c
+++ b/drivers/hid/hid-dummy.c
@@ -4,6 +4,9 @@
static int __init hid_dummy_init(void)
{
+#ifdef CONFIG_HID_A4TECH_MODULE
+ HID_COMPAT_CALL_DRIVER(a4tech);
+#endif
#ifdef CONFIG_HID_APPLE_MODULE
HID_COMPAT_CALL_DRIVER(apple);
#endif
diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c
index 6e7314f7b998..5bacf181a8ca 100644
--- a/drivers/hid/hid-input-quirks.c
+++ b/drivers/hid/hid-input-quirks.c
@@ -236,31 +236,6 @@ int hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struc
input = field->hidinput->input;
- if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) &&
- (usage->hid == 0x00090007)) {
- if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
- else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
- return 1;
- }
-
- if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) &&
- (usage->type == EV_REL) &&
- (usage->code == REL_WHEEL)) {
- hid->delayed_value = value;
- return 1;
- }
-
- if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) &&
- (usage->hid == 0x000100b8)) {
- input_event(input, EV_REL, value ? REL_HWHEEL : REL_WHEEL, hid->delayed_value);
- return 1;
- }
-
- if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) {
- input_event(input, usage->type, REL_HWHEEL, value);
- return 1;
- }
-
/* handle the temporary quirky mapping to HWHEEL */
if (hid->quirks & HID_QUIRK_HWHEEL_WHEEL_INVERT &&
usage->type == EV_REL && usage->code == REL_HWHEEL) {
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index f1df25ab0baa..1d2d0827820c 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -515,15 +515,6 @@ mapped:
hidinput, field, usage, &bit, &max) < 0)
goto ignore;
- if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 |
- HID_QUIRK_2WHEEL_MOUSE_HACK_B8)) && (usage->type == EV_REL) &&
- (usage->code == REL_WHEEL))
- set_bit(REL_HWHEEL, bit);
-
- if ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) &&
- (usage->hid == 0x00090007))
- goto ignore;
-
set_bit(usage->type, input->evbit);
while (usage->code <= max && test_and_set_bit(usage->code, bit))
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index da80c64fb25c..1d12fb24829c 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -28,10 +28,6 @@ static const struct hid_blacklist {
__u16 idProduct;
__u32 quirks;
} hid_blacklist[] = {
-
- { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
- { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D, HID_QUIRK_2WHEEL_MOUSE_HACK_B8 },
-
{ USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 27bfbcc1ef81..a7cc4af2e467 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -261,14 +261,11 @@ struct hid_item {
#define HID_QUIRK_HIDDEV 0x00000010
#define HID_QUIRK_BADPAD 0x00000020
#define HID_QUIRK_MULTI_INPUT 0x00000040
-#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080
-#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200
#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00040000
#define HID_QUIRK_RESET_LEDS 0x00100000
#define HID_QUIRK_HIDINPUT 0x00200000
#define HID_QUIRK_IGNORE_HIDINPUT 0x01000000
-#define HID_QUIRK_2WHEEL_MOUSE_HACK_B8 0x02000000
#define HID_QUIRK_HWHEEL_WHEEL_INVERT 0x04000000
#define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000
@@ -453,8 +450,6 @@ struct hid_device { /* device report descriptor */
void *driver_data;
- __s32 delayed_value; /* For A4 Tech mice hwheel quirk */
-
/* hiddev event handler */
void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field,
struct hid_usage *, __s32);