diff options
author | Jiri Kosina <jkosina@suse.cz> | 2007-03-08 10:47:49 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2007-04-11 04:36:02 -0400 |
commit | 6db3dfefa28739e7c9c60809c3a5aef7cc088b97 (patch) | |
tree | 9f88649e7a53af36a94db34ff8f1a0f47316260e /drivers/hid | |
parent | a21bd69e1509b43823c317c3bf3f7ffa99884356 (diff) |
USB HID: move usbhid code from drivers/usb/input to drivers/hid/usbhid
Separate usbhid code into dedicated drivers/hid/usbhid directory as
discussed previously with Greg, so that it eases maintaineance process.
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/Kconfig | 2 | ||||
-rw-r--r-- | drivers/hid/Makefile | 4 | ||||
-rw-r--r-- | drivers/hid/usbhid/Kconfig | 149 | ||||
-rw-r--r-- | drivers/hid/usbhid/Makefile | 35 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 1477 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-ff.c | 89 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-lgff.c | 150 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-pidff.c | 1331 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-plff.c | 129 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-tmff.c | 147 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-zpff.c | 111 | ||||
-rw-r--r-- | drivers/hid/usbhid/hiddev.c | 847 | ||||
-rw-r--r-- | drivers/hid/usbhid/usbhid.h | 87 | ||||
-rw-r--r-- | drivers/hid/usbhid/usbkbd.c | 362 | ||||
-rw-r--r-- | drivers/hid/usbhid/usbmouse.c | 245 |
15 files changed, 5165 insertions, 0 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 850788f4dd2e..8fbe9fdac128 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -36,5 +36,7 @@ config HID_DEBUG | |||
36 | 36 | ||
37 | If unsure, say N | 37 | If unsure, say N |
38 | 38 | ||
39 | source "drivers/hid/usbhid/Kconfig" | ||
40 | |||
39 | endmenu | 41 | endmenu |
40 | 42 | ||
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 52e97d8f3c95..68d1376a53fb 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -6,3 +6,7 @@ hid-objs := hid-core.o hid-input.o | |||
6 | obj-$(CONFIG_HID) += hid.o | 6 | obj-$(CONFIG_HID) += hid.o |
7 | hid-$(CONFIG_HID_DEBUG) += hid-debug.o | 7 | hid-$(CONFIG_HID_DEBUG) += hid-debug.o |
8 | 8 | ||
9 | obj-$(CONFIG_USB_HID) += usbhid/ | ||
10 | obj-$(CONFIG_USB_MOUSE) += usbhid/ | ||
11 | obj-$(CONFIG_USB_KBD) += usbhid/ | ||
12 | |||
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig new file mode 100644 index 000000000000..7c87bdc538bc --- /dev/null +++ b/drivers/hid/usbhid/Kconfig | |||
@@ -0,0 +1,149 @@ | |||
1 | comment "USB Input Devices" | ||
2 | depends on USB | ||
3 | |||
4 | config USB_HID | ||
5 | tristate "USB Human Interface Device (full HID) support" | ||
6 | default y | ||
7 | depends on USB && INPUT | ||
8 | select HID | ||
9 | ---help--- | ||
10 | Say Y here if you want full HID support to connect USB keyboards, | ||
11 | mice, joysticks, graphic tablets, or any other HID based devices | ||
12 | to your computer via USB, as well as Uninterruptible Power Supply | ||
13 | (UPS) and monitor control devices. | ||
14 | |||
15 | You can't use this driver and the HIDBP (Boot Protocol) keyboard | ||
16 | and mouse drivers at the same time. More information is available: | ||
17 | <file:Documentation/input/input.txt>. | ||
18 | |||
19 | If unsure, say Y. | ||
20 | |||
21 | To compile this driver as a module, choose M here: the | ||
22 | module will be called usbhid. | ||
23 | |||
24 | comment "Input core support is needed for USB HID input layer or HIDBP support" | ||
25 | depends on USB_HID && INPUT=n | ||
26 | |||
27 | config USB_HIDINPUT_POWERBOOK | ||
28 | bool "Enable support for iBook/PowerBook special keys" | ||
29 | default n | ||
30 | depends on USB_HID | ||
31 | help | ||
32 | Say Y here if you want support for the special keys (Fn, Numlock) on | ||
33 | Apple iBooks and PowerBooks. | ||
34 | |||
35 | If unsure, say N. | ||
36 | |||
37 | config HID_FF | ||
38 | bool "Force feedback support (EXPERIMENTAL)" | ||
39 | depends on USB_HID && EXPERIMENTAL | ||
40 | help | ||
41 | Say Y here is you want force feedback support for a few HID devices. | ||
42 | See below for a list of supported devices. | ||
43 | |||
44 | See <file:Documentation/input/ff.txt> for a description of the force | ||
45 | feedback API. | ||
46 | |||
47 | If unsure, say N. | ||
48 | |||
49 | config HID_PID | ||
50 | bool "PID device support" | ||
51 | depends on HID_FF | ||
52 | help | ||
53 | Say Y here if you have a PID-compliant device and wish to enable force | ||
54 | feedback for it. Microsoft Sidewinder Force Feedback 2 is one of such | ||
55 | devices. | ||
56 | |||
57 | config LOGITECH_FF | ||
58 | bool "Logitech devices support" | ||
59 | depends on HID_FF | ||
60 | select INPUT_FF_MEMLESS if USB_HID | ||
61 | help | ||
62 | Say Y here if you have one of these devices: | ||
63 | - Logitech WingMan Cordless RumblePad | ||
64 | - Logitech WingMan Cordless RumblePad 2 | ||
65 | - Logitech WingMan Force 3D | ||
66 | - Logitech Formula Force EX | ||
67 | - Logitech MOMO Force wheel | ||
68 | |||
69 | and if you want to enable force feedback for them. | ||
70 | Note: if you say N here, this device will still be supported, but without | ||
71 | force feedback. | ||
72 | |||
73 | config PANTHERLORD_FF | ||
74 | bool "PantherLord USB/PS2 2in1 Adapter support" | ||
75 | depends on HID_FF | ||
76 | select INPUT_FF_MEMLESS if USB_HID | ||
77 | help | ||
78 | Say Y here if you have a PantherLord USB/PS2 2in1 Adapter and want | ||
79 | to enable force feedback support for it. | ||
80 | |||
81 | config THRUSTMASTER_FF | ||
82 | bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)" | ||
83 | depends on HID_FF && EXPERIMENTAL | ||
84 | select INPUT_FF_MEMLESS if USB_HID | ||
85 | help | ||
86 | Say Y here if you have a THRUSTMASTER FireStore Dual Power 2, | ||
87 | and want to enable force feedback support for it. | ||
88 | Note: if you say N here, this device will still be supported, but without | ||
89 | force feedback. | ||
90 | |||
91 | config ZEROPLUS_FF | ||
92 | bool "Zeroplus based game controller support" | ||
93 | depends on HID_FF | ||
94 | select INPUT_FF_MEMLESS if USB_HID | ||
95 | help | ||
96 | Say Y here if you have a Zeroplus based game controller and want to | ||
97 | enable force feedback for it. | ||
98 | |||
99 | config USB_HIDDEV | ||
100 | bool "/dev/hiddev raw HID device support" | ||
101 | depends on USB_HID | ||
102 | help | ||
103 | Say Y here if you want to support HID devices (from the USB | ||
104 | specification standpoint) that aren't strictly user interface | ||
105 | devices, like monitor controls and Uninterruptable Power Supplies. | ||
106 | |||
107 | This module supports these devices separately using a separate | ||
108 | event interface on /dev/usb/hiddevX (char 180:96 to 180:111). | ||
109 | |||
110 | If unsure, say Y. | ||
111 | |||
112 | menu "USB HID Boot Protocol drivers" | ||
113 | depends on USB!=n && USB_HID!=y | ||
114 | |||
115 | config USB_KBD | ||
116 | tristate "USB HIDBP Keyboard (simple Boot) support" | ||
117 | depends on USB && INPUT | ||
118 | ---help--- | ||
119 | Say Y here only if you are absolutely sure that you don't want | ||
120 | to use the generic HID driver for your USB keyboard and prefer | ||
121 | to use the keyboard in its limited Boot Protocol mode instead. | ||
122 | |||
123 | This is almost certainly not what you want. This is mostly | ||
124 | useful for embedded applications or simple keyboards. | ||
125 | |||
126 | To compile this driver as a module, choose M here: the | ||
127 | module will be called usbkbd. | ||
128 | |||
129 | If even remotely unsure, say N. | ||
130 | |||
131 | config USB_MOUSE | ||
132 | tristate "USB HIDBP Mouse (simple Boot) support" | ||
133 | depends on USB && INPUT | ||
134 | ---help--- | ||
135 | Say Y here only if you are absolutely sure that you don't want | ||
136 | to use the generic HID driver for your USB mouse and prefer | ||
137 | to use the mouse in its limited Boot Protocol mode instead. | ||
138 | |||
139 | This is almost certainly not what you want. This is mostly | ||
140 | useful for embedded applications or simple mice. | ||
141 | |||
142 | To compile this driver as a module, choose M here: the | ||
143 | module will be called usbmouse. | ||
144 | |||
145 | If even remotely unsure, say N. | ||
146 | |||
147 | endmenu | ||
148 | |||
149 | |||
diff --git a/drivers/hid/usbhid/Makefile b/drivers/hid/usbhid/Makefile new file mode 100644 index 000000000000..de9bc1fe3eaa --- /dev/null +++ b/drivers/hid/usbhid/Makefile | |||
@@ -0,0 +1,35 @@ | |||
1 | # | ||
2 | # Makefile for the USB input drivers | ||
3 | # | ||
4 | |||
5 | # Multipart objects. | ||
6 | usbhid-objs := hid-core.o | ||
7 | |||
8 | # Optional parts of multipart objects. | ||
9 | |||
10 | ifeq ($(CONFIG_USB_HIDDEV),y) | ||
11 | usbhid-objs += hiddev.o | ||
12 | endif | ||
13 | ifeq ($(CONFIG_HID_PID),y) | ||
14 | usbhid-objs += hid-pidff.o | ||
15 | endif | ||
16 | ifeq ($(CONFIG_LOGITECH_FF),y) | ||
17 | usbhid-objs += hid-lgff.o | ||
18 | endif | ||
19 | ifeq ($(CONFIG_PANTHERLORD_FF),y) | ||
20 | usbhid-objs += hid-plff.o | ||
21 | endif | ||
22 | ifeq ($(CONFIG_THRUSTMASTER_FF),y) | ||
23 | usbhid-objs += hid-tmff.o | ||
24 | endif | ||
25 | ifeq ($(CONFIG_ZEROPLUS_FF),y) | ||
26 | usbhid-objs += hid-zpff.o | ||
27 | endif | ||
28 | ifeq ($(CONFIG_HID_FF),y) | ||
29 | usbhid-objs += hid-ff.o | ||
30 | endif | ||
31 | |||
32 | obj-$(CONFIG_USB_HID) += usbhid.o | ||
33 | obj-$(CONFIG_USB_KBD) += usbkbd.o | ||
34 | obj-$(CONFIG_USB_MOUSE) += usbmouse.o | ||
35 | |||
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c new file mode 100644 index 000000000000..827a75a186ba --- /dev/null +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -0,0 +1,1477 @@ | |||
1 | /* | ||
2 | * USB HID support for Linux | ||
3 | * | ||
4 | * Copyright (c) 1999 Andreas Gal | ||
5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> | ||
6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc | ||
7 | * Copyright (c) 2006-2007 Jiri Kosina | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the Free | ||
13 | * Software Foundation; either version 2 of the License, or (at your option) | ||
14 | * any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/list.h> | ||
22 | #include <linux/mm.h> | ||
23 | #include <linux/smp_lock.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <asm/unaligned.h> | ||
26 | #include <asm/byteorder.h> | ||
27 | #include <linux/input.h> | ||
28 | #include <linux/wait.h> | ||
29 | |||
30 | #include <linux/usb.h> | ||
31 | |||
32 | #include <linux/hid.h> | ||
33 | #include <linux/hiddev.h> | ||
34 | #include <linux/hid-debug.h> | ||
35 | #include "usbhid.h" | ||
36 | |||
37 | /* | ||
38 | * Version Information | ||
39 | */ | ||
40 | |||
41 | #define DRIVER_VERSION "v2.6" | ||
42 | #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik" | ||
43 | #define DRIVER_DESC "USB HID core driver" | ||
44 | #define DRIVER_LICENSE "GPL" | ||
45 | |||
46 | static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick", | ||
47 | "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"}; | ||
48 | /* | ||
49 | * Module parameters. | ||
50 | */ | ||
51 | |||
52 | static unsigned int hid_mousepoll_interval; | ||
53 | module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); | ||
54 | MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); | ||
55 | |||
56 | /* | ||
57 | * Input submission and I/O error handler. | ||
58 | */ | ||
59 | |||
60 | static void hid_io_error(struct hid_device *hid); | ||
61 | |||
62 | /* Start up the input URB */ | ||
63 | static int hid_start_in(struct hid_device *hid) | ||
64 | { | ||
65 | unsigned long flags; | ||
66 | int rc = 0; | ||
67 | struct usbhid_device *usbhid = hid->driver_data; | ||
68 | |||
69 | spin_lock_irqsave(&usbhid->inlock, flags); | ||
70 | if (hid->open > 0 && !test_bit(HID_SUSPENDED, &usbhid->iofl) && | ||
71 | !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { | ||
72 | rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); | ||
73 | if (rc != 0) | ||
74 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
75 | } | ||
76 | spin_unlock_irqrestore(&usbhid->inlock, flags); | ||
77 | return rc; | ||
78 | } | ||
79 | |||
80 | /* I/O retry timer routine */ | ||
81 | static void hid_retry_timeout(unsigned long _hid) | ||
82 | { | ||
83 | struct hid_device *hid = (struct hid_device *) _hid; | ||
84 | struct usbhid_device *usbhid = hid->driver_data; | ||
85 | |||
86 | dev_dbg(&usbhid->intf->dev, "retrying intr urb\n"); | ||
87 | if (hid_start_in(hid)) | ||
88 | hid_io_error(hid); | ||
89 | } | ||
90 | |||
91 | /* Workqueue routine to reset the device or clear a halt */ | ||
92 | static void hid_reset(struct work_struct *work) | ||
93 | { | ||
94 | struct usbhid_device *usbhid = | ||
95 | container_of(work, struct usbhid_device, reset_work); | ||
96 | struct hid_device *hid = usbhid->hid; | ||
97 | int rc_lock, rc = 0; | ||
98 | |||
99 | if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) { | ||
100 | dev_dbg(&usbhid->intf->dev, "clear halt\n"); | ||
101 | rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid->urbin->pipe); | ||
102 | clear_bit(HID_CLEAR_HALT, &usbhid->iofl); | ||
103 | hid_start_in(hid); | ||
104 | } | ||
105 | |||
106 | else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) { | ||
107 | dev_dbg(&usbhid->intf->dev, "resetting device\n"); | ||
108 | rc = rc_lock = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf); | ||
109 | if (rc_lock >= 0) { | ||
110 | rc = usb_reset_composite_device(hid_to_usb_dev(hid), usbhid->intf); | ||
111 | if (rc_lock) | ||
112 | usb_unlock_device(hid_to_usb_dev(hid)); | ||
113 | } | ||
114 | clear_bit(HID_RESET_PENDING, &usbhid->iofl); | ||
115 | } | ||
116 | |||
117 | switch (rc) { | ||
118 | case 0: | ||
119 | if (!test_bit(HID_IN_RUNNING, &usbhid->iofl)) | ||
120 | hid_io_error(hid); | ||
121 | break; | ||
122 | default: | ||
123 | err("can't reset device, %s-%s/input%d, status %d", | ||
124 | hid_to_usb_dev(hid)->bus->bus_name, | ||
125 | hid_to_usb_dev(hid)->devpath, | ||
126 | usbhid->ifnum, rc); | ||
127 | /* FALLTHROUGH */ | ||
128 | case -EHOSTUNREACH: | ||
129 | case -ENODEV: | ||
130 | case -EINTR: | ||
131 | break; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | /* Main I/O error handler */ | ||
136 | static void hid_io_error(struct hid_device *hid) | ||
137 | { | ||
138 | unsigned long flags; | ||
139 | struct usbhid_device *usbhid = hid->driver_data; | ||
140 | |||
141 | spin_lock_irqsave(&usbhid->inlock, flags); | ||
142 | |||
143 | /* Stop when disconnected */ | ||
144 | if (usb_get_intfdata(usbhid->intf) == NULL) | ||
145 | goto done; | ||
146 | |||
147 | /* When an error occurs, retry at increasing intervals */ | ||
148 | if (usbhid->retry_delay == 0) { | ||
149 | usbhid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */ | ||
150 | usbhid->stop_retry = jiffies + msecs_to_jiffies(1000); | ||
151 | } else if (usbhid->retry_delay < 100) | ||
152 | usbhid->retry_delay *= 2; | ||
153 | |||
154 | if (time_after(jiffies, usbhid->stop_retry)) { | ||
155 | |||
156 | /* Retries failed, so do a port reset */ | ||
157 | if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) { | ||
158 | schedule_work(&usbhid->reset_work); | ||
159 | goto done; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | mod_timer(&usbhid->io_retry, | ||
164 | jiffies + msecs_to_jiffies(usbhid->retry_delay)); | ||
165 | done: | ||
166 | spin_unlock_irqrestore(&usbhid->inlock, flags); | ||
167 | } | ||
168 | |||
169 | /* | ||
170 | * Input interrupt completion handler. | ||
171 | */ | ||
172 | |||
173 | static void hid_irq_in(struct urb *urb) | ||
174 | { | ||
175 | struct hid_device *hid = urb->context; | ||
176 | struct usbhid_device *usbhid = hid->driver_data; | ||
177 | int status; | ||
178 | |||
179 | switch (urb->status) { | ||
180 | case 0: /* success */ | ||
181 | usbhid->retry_delay = 0; | ||
182 | hid_input_report(urb->context, HID_INPUT_REPORT, | ||
183 | urb->transfer_buffer, | ||
184 | urb->actual_length, 1); | ||
185 | break; | ||
186 | case -EPIPE: /* stall */ | ||
187 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
188 | set_bit(HID_CLEAR_HALT, &usbhid->iofl); | ||
189 | schedule_work(&usbhid->reset_work); | ||
190 | return; | ||
191 | case -ECONNRESET: /* unlink */ | ||
192 | case -ENOENT: | ||
193 | case -ESHUTDOWN: /* unplug */ | ||
194 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
195 | return; | ||
196 | case -EILSEQ: /* protocol error or unplug */ | ||
197 | case -EPROTO: /* protocol error or unplug */ | ||
198 | case -ETIME: /* protocol error or unplug */ | ||
199 | case -ETIMEDOUT: /* Should never happen, but... */ | ||
200 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
201 | hid_io_error(hid); | ||
202 | return; | ||
203 | default: /* error */ | ||
204 | warn("input irq status %d received", urb->status); | ||
205 | } | ||
206 | |||
207 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
208 | if (status) { | ||
209 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
210 | if (status != -EPERM) { | ||
211 | err("can't resubmit intr, %s-%s/input%d, status %d", | ||
212 | hid_to_usb_dev(hid)->bus->bus_name, | ||
213 | hid_to_usb_dev(hid)->devpath, | ||
214 | usbhid->ifnum, status); | ||
215 | hid_io_error(hid); | ||
216 | } | ||
217 | } | ||
218 | } | ||
219 | |||
220 | static int hid_submit_out(struct hid_device *hid) | ||
221 | { | ||
222 | struct hid_report *report; | ||
223 | struct usbhid_device *usbhid = hid->driver_data; | ||
224 | |||
225 | report = usbhid->out[usbhid->outtail]; | ||
226 | |||
227 | hid_output_report(report, usbhid->outbuf); | ||
228 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); | ||
229 | usbhid->urbout->dev = hid_to_usb_dev(hid); | ||
230 | |||
231 | dbg("submitting out urb"); | ||
232 | |||
233 | if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { | ||
234 | err("usb_submit_urb(out) failed"); | ||
235 | return -1; | ||
236 | } | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int hid_submit_ctrl(struct hid_device *hid) | ||
242 | { | ||
243 | struct hid_report *report; | ||
244 | unsigned char dir; | ||
245 | int len; | ||
246 | struct usbhid_device *usbhid = hid->driver_data; | ||
247 | |||
248 | report = usbhid->ctrl[usbhid->ctrltail].report; | ||
249 | dir = usbhid->ctrl[usbhid->ctrltail].dir; | ||
250 | |||
251 | len = ((report->size - 1) >> 3) + 1 + (report->id > 0); | ||
252 | if (dir == USB_DIR_OUT) { | ||
253 | hid_output_report(report, usbhid->ctrlbuf); | ||
254 | usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); | ||
255 | usbhid->urbctrl->transfer_buffer_length = len; | ||
256 | } else { | ||
257 | int maxpacket, padlen; | ||
258 | |||
259 | usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0); | ||
260 | maxpacket = usb_maxpacket(hid_to_usb_dev(hid), usbhid->urbctrl->pipe, 0); | ||
261 | if (maxpacket > 0) { | ||
262 | padlen = (len + maxpacket - 1) / maxpacket; | ||
263 | padlen *= maxpacket; | ||
264 | if (padlen > usbhid->bufsize) | ||
265 | padlen = usbhid->bufsize; | ||
266 | } else | ||
267 | padlen = 0; | ||
268 | usbhid->urbctrl->transfer_buffer_length = padlen; | ||
269 | } | ||
270 | usbhid->urbctrl->dev = hid_to_usb_dev(hid); | ||
271 | |||
272 | usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; | ||
273 | usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT; | ||
274 | usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); | ||
275 | usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum); | ||
276 | usbhid->cr->wLength = cpu_to_le16(len); | ||
277 | |||
278 | dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u", | ||
279 | usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", | ||
280 | usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); | ||
281 | |||
282 | if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { | ||
283 | err("usb_submit_urb(ctrl) failed"); | ||
284 | return -1; | ||
285 | } | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | /* | ||
291 | * Output interrupt completion handler. | ||
292 | */ | ||
293 | |||
294 | static void hid_irq_out(struct urb *urb) | ||
295 | { | ||
296 | struct hid_device *hid = urb->context; | ||
297 | struct usbhid_device *usbhid = hid->driver_data; | ||
298 | unsigned long flags; | ||
299 | int unplug = 0; | ||
300 | |||
301 | switch (urb->status) { | ||
302 | case 0: /* success */ | ||
303 | break; | ||
304 | case -ESHUTDOWN: /* unplug */ | ||
305 | unplug = 1; | ||
306 | case -EILSEQ: /* protocol error or unplug */ | ||
307 | case -EPROTO: /* protocol error or unplug */ | ||
308 | case -ECONNRESET: /* unlink */ | ||
309 | case -ENOENT: | ||
310 | break; | ||
311 | default: /* error */ | ||
312 | warn("output irq status %d received", urb->status); | ||
313 | } | ||
314 | |||
315 | spin_lock_irqsave(&usbhid->outlock, flags); | ||
316 | |||
317 | if (unplug) | ||
318 | usbhid->outtail = usbhid->outhead; | ||
319 | else | ||
320 | usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); | ||
321 | |||
322 | if (usbhid->outhead != usbhid->outtail) { | ||
323 | if (hid_submit_out(hid)) { | ||
324 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
325 | wake_up(&hid->wait); | ||
326 | } | ||
327 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
328 | return; | ||
329 | } | ||
330 | |||
331 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
332 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
333 | wake_up(&hid->wait); | ||
334 | } | ||
335 | |||
336 | /* | ||
337 | * Control pipe completion handler. | ||
338 | */ | ||
339 | |||
340 | static void hid_ctrl(struct urb *urb) | ||
341 | { | ||
342 | struct hid_device *hid = urb->context; | ||
343 | struct usbhid_device *usbhid = hid->driver_data; | ||
344 | unsigned long flags; | ||
345 | int unplug = 0; | ||
346 | |||
347 | spin_lock_irqsave(&usbhid->ctrllock, flags); | ||
348 | |||
349 | switch (urb->status) { | ||
350 | case 0: /* success */ | ||
351 | if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN) | ||
352 | hid_input_report(urb->context, usbhid->ctrl[usbhid->ctrltail].report->type, | ||
353 | urb->transfer_buffer, urb->actual_length, 0); | ||
354 | break; | ||
355 | case -ESHUTDOWN: /* unplug */ | ||
356 | unplug = 1; | ||
357 | case -EILSEQ: /* protocol error or unplug */ | ||
358 | case -EPROTO: /* protocol error or unplug */ | ||
359 | case -ECONNRESET: /* unlink */ | ||
360 | case -ENOENT: | ||
361 | case -EPIPE: /* report not available */ | ||
362 | break; | ||
363 | default: /* error */ | ||
364 | warn("ctrl urb status %d received", urb->status); | ||
365 | } | ||
366 | |||
367 | if (unplug) | ||
368 | usbhid->ctrltail = usbhid->ctrlhead; | ||
369 | else | ||
370 | usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); | ||
371 | |||
372 | if (usbhid->ctrlhead != usbhid->ctrltail) { | ||
373 | if (hid_submit_ctrl(hid)) { | ||
374 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
375 | wake_up(&hid->wait); | ||
376 | } | ||
377 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | ||
378 | return; | ||
379 | } | ||
380 | |||
381 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
382 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | ||
383 | wake_up(&hid->wait); | ||
384 | } | ||
385 | |||
386 | void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) | ||
387 | { | ||
388 | int head; | ||
389 | unsigned long flags; | ||
390 | struct usbhid_device *usbhid = hid->driver_data; | ||
391 | |||
392 | if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) | ||
393 | return; | ||
394 | |||
395 | if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { | ||
396 | |||
397 | spin_lock_irqsave(&usbhid->outlock, flags); | ||
398 | |||
399 | if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) { | ||
400 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
401 | warn("output queue full"); | ||
402 | return; | ||
403 | } | ||
404 | |||
405 | usbhid->out[usbhid->outhead] = report; | ||
406 | usbhid->outhead = head; | ||
407 | |||
408 | if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) | ||
409 | if (hid_submit_out(hid)) | ||
410 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
411 | |||
412 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
413 | return; | ||
414 | } | ||
415 | |||
416 | spin_lock_irqsave(&usbhid->ctrllock, flags); | ||
417 | |||
418 | if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) { | ||
419 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | ||
420 | warn("control queue full"); | ||
421 | return; | ||
422 | } | ||
423 | |||
424 | usbhid->ctrl[usbhid->ctrlhead].report = report; | ||
425 | usbhid->ctrl[usbhid->ctrlhead].dir = dir; | ||
426 | usbhid->ctrlhead = head; | ||
427 | |||
428 | if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) | ||
429 | if (hid_submit_ctrl(hid)) | ||
430 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
431 | |||
432 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | ||
433 | } | ||
434 | |||
435 | static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | ||
436 | { | ||
437 | struct hid_device *hid = dev->private; | ||
438 | struct hid_field *field; | ||
439 | int offset; | ||
440 | |||
441 | if (type == EV_FF) | ||
442 | return input_ff_event(dev, type, code, value); | ||
443 | |||
444 | if (type != EV_LED) | ||
445 | return -1; | ||
446 | |||
447 | if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) { | ||
448 | warn("event field not found"); | ||
449 | return -1; | ||
450 | } | ||
451 | |||
452 | hid_set_field(field, offset, value); | ||
453 | usbhid_submit_report(hid, field->report, USB_DIR_OUT); | ||
454 | |||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | int usbhid_wait_io(struct hid_device *hid) | ||
459 | { | ||
460 | struct usbhid_device *usbhid = hid->driver_data; | ||
461 | |||
462 | if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) && | ||
463 | !test_bit(HID_OUT_RUNNING, &usbhid->iofl)), | ||
464 | 10*HZ)) { | ||
465 | dbg("timeout waiting for ctrl or out queue to clear"); | ||
466 | return -1; | ||
467 | } | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) | ||
473 | { | ||
474 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
475 | HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report, | ||
476 | ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
477 | } | ||
478 | |||
479 | static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, | ||
480 | unsigned char type, void *buf, int size) | ||
481 | { | ||
482 | int result, retries = 4; | ||
483 | |||
484 | memset(buf, 0, size); | ||
485 | |||
486 | do { | ||
487 | result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
488 | USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, | ||
489 | (type << 8), ifnum, buf, size, USB_CTRL_GET_TIMEOUT); | ||
490 | retries--; | ||
491 | } while (result < size && retries); | ||
492 | return result; | ||
493 | } | ||
494 | |||
495 | int usbhid_open(struct hid_device *hid) | ||
496 | { | ||
497 | ++hid->open; | ||
498 | if (hid_start_in(hid)) | ||
499 | hid_io_error(hid); | ||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | void usbhid_close(struct hid_device *hid) | ||
504 | { | ||
505 | struct usbhid_device *usbhid = hid->driver_data; | ||
506 | |||
507 | if (!--hid->open) | ||
508 | usb_kill_urb(usbhid->urbin); | ||
509 | } | ||
510 | |||
511 | #define USB_VENDOR_ID_PANJIT 0x134c | ||
512 | |||
513 | #define USB_VENDOR_ID_TURBOX 0x062a | ||
514 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 | ||
515 | #define USB_VENDOR_ID_CIDC 0x1677 | ||
516 | |||
517 | /* | ||
518 | * Initialize all reports | ||
519 | */ | ||
520 | |||
521 | void usbhid_init_reports(struct hid_device *hid) | ||
522 | { | ||
523 | struct hid_report *report; | ||
524 | struct usbhid_device *usbhid = hid->driver_data; | ||
525 | int err, ret; | ||
526 | |||
527 | list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) | ||
528 | usbhid_submit_report(hid, report, USB_DIR_IN); | ||
529 | |||
530 | list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) | ||
531 | usbhid_submit_report(hid, report, USB_DIR_IN); | ||
532 | |||
533 | err = 0; | ||
534 | ret = usbhid_wait_io(hid); | ||
535 | while (ret) { | ||
536 | err |= ret; | ||
537 | if (test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) | ||
538 | usb_kill_urb(usbhid->urbctrl); | ||
539 | if (test_bit(HID_OUT_RUNNING, &usbhid->iofl)) | ||
540 | usb_kill_urb(usbhid->urbout); | ||
541 | ret = usbhid_wait_io(hid); | ||
542 | } | ||
543 | |||
544 | if (err) | ||
545 | warn("timeout initializing reports"); | ||
546 | } | ||
547 | |||
548 | #define USB_VENDOR_ID_GTCO 0x078c | ||
549 | #define USB_DEVICE_ID_GTCO_90 0x0090 | ||
550 | #define USB_DEVICE_ID_GTCO_100 0x0100 | ||
551 | #define USB_DEVICE_ID_GTCO_101 0x0101 | ||
552 | #define USB_DEVICE_ID_GTCO_103 0x0103 | ||
553 | #define USB_DEVICE_ID_GTCO_104 0x0104 | ||
554 | #define USB_DEVICE_ID_GTCO_105 0x0105 | ||
555 | #define USB_DEVICE_ID_GTCO_106 0x0106 | ||
556 | #define USB_DEVICE_ID_GTCO_107 0x0107 | ||
557 | #define USB_DEVICE_ID_GTCO_108 0x0108 | ||
558 | #define USB_DEVICE_ID_GTCO_200 0x0200 | ||
559 | #define USB_DEVICE_ID_GTCO_201 0x0201 | ||
560 | #define USB_DEVICE_ID_GTCO_202 0x0202 | ||
561 | #define USB_DEVICE_ID_GTCO_203 0x0203 | ||
562 | #define USB_DEVICE_ID_GTCO_204 0x0204 | ||
563 | #define USB_DEVICE_ID_GTCO_205 0x0205 | ||
564 | #define USB_DEVICE_ID_GTCO_206 0x0206 | ||
565 | #define USB_DEVICE_ID_GTCO_207 0x0207 | ||
566 | #define USB_DEVICE_ID_GTCO_300 0x0300 | ||
567 | #define USB_DEVICE_ID_GTCO_301 0x0301 | ||
568 | #define USB_DEVICE_ID_GTCO_302 0x0302 | ||
569 | #define USB_DEVICE_ID_GTCO_303 0x0303 | ||
570 | #define USB_DEVICE_ID_GTCO_304 0x0304 | ||
571 | #define USB_DEVICE_ID_GTCO_305 0x0305 | ||
572 | #define USB_DEVICE_ID_GTCO_306 0x0306 | ||
573 | #define USB_DEVICE_ID_GTCO_307 0x0307 | ||
574 | #define USB_DEVICE_ID_GTCO_308 0x0308 | ||
575 | #define USB_DEVICE_ID_GTCO_309 0x0309 | ||
576 | #define USB_DEVICE_ID_GTCO_400 0x0400 | ||
577 | #define USB_DEVICE_ID_GTCO_401 0x0401 | ||
578 | #define USB_DEVICE_ID_GTCO_402 0x0402 | ||
579 | #define USB_DEVICE_ID_GTCO_403 0x0403 | ||
580 | #define USB_DEVICE_ID_GTCO_404 0x0404 | ||
581 | #define USB_DEVICE_ID_GTCO_405 0x0405 | ||
582 | #define USB_DEVICE_ID_GTCO_500 0x0500 | ||
583 | #define USB_DEVICE_ID_GTCO_501 0x0501 | ||
584 | #define USB_DEVICE_ID_GTCO_502 0x0502 | ||
585 | #define USB_DEVICE_ID_GTCO_503 0x0503 | ||
586 | #define USB_DEVICE_ID_GTCO_504 0x0504 | ||
587 | #define USB_DEVICE_ID_GTCO_1000 0x1000 | ||
588 | #define USB_DEVICE_ID_GTCO_1001 0x1001 | ||
589 | #define USB_DEVICE_ID_GTCO_1002 0x1002 | ||
590 | #define USB_DEVICE_ID_GTCO_1003 0x1003 | ||
591 | #define USB_DEVICE_ID_GTCO_1004 0x1004 | ||
592 | #define USB_DEVICE_ID_GTCO_1005 0x1005 | ||
593 | #define USB_DEVICE_ID_GTCO_1006 0x1006 | ||
594 | |||
595 | #define USB_VENDOR_ID_WACOM 0x056a | ||
596 | |||
597 | #define USB_VENDOR_ID_ACECAD 0x0460 | ||
598 | #define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 | ||
599 | #define USB_DEVICE_ID_ACECAD_302 0x0008 | ||
600 | |||
601 | #define USB_VENDOR_ID_KBGEAR 0x084e | ||
602 | #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 | ||
603 | |||
604 | #define USB_VENDOR_ID_AIPTEK 0x08ca | ||
605 | #define USB_DEVICE_ID_AIPTEK_01 0x0001 | ||
606 | #define USB_DEVICE_ID_AIPTEK_10 0x0010 | ||
607 | #define USB_DEVICE_ID_AIPTEK_20 0x0020 | ||
608 | #define USB_DEVICE_ID_AIPTEK_21 0x0021 | ||
609 | #define USB_DEVICE_ID_AIPTEK_22 0x0022 | ||
610 | #define USB_DEVICE_ID_AIPTEK_23 0x0023 | ||
611 | #define USB_DEVICE_ID_AIPTEK_24 0x0024 | ||
612 | |||
613 | #define USB_VENDOR_ID_GRIFFIN 0x077d | ||
614 | #define USB_DEVICE_ID_POWERMATE 0x0410 | ||
615 | #define USB_DEVICE_ID_SOUNDKNOB 0x04AA | ||
616 | |||
617 | #define USB_VENDOR_ID_ATEN 0x0557 | ||
618 | #define USB_DEVICE_ID_ATEN_UC100KM 0x2004 | ||
619 | #define USB_DEVICE_ID_ATEN_CS124U 0x2202 | ||
620 | #define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204 | ||
621 | #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 | ||
622 | #define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 | ||
623 | |||
624 | #define USB_VENDOR_ID_TOPMAX 0x0663 | ||
625 | #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 | ||
626 | |||
627 | #define USB_VENDOR_ID_HAPP 0x078b | ||
628 | #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 | ||
629 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 | ||
630 | #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 | ||
631 | |||
632 | #define USB_VENDOR_ID_MGE 0x0463 | ||
633 | #define USB_DEVICE_ID_MGE_UPS 0xffff | ||
634 | #define USB_DEVICE_ID_MGE_UPS1 0x0001 | ||
635 | |||
636 | #define USB_VENDOR_ID_ONTRAK 0x0a07 | ||
637 | #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 | ||
638 | |||
639 | #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f | ||
640 | #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 | ||
641 | |||
642 | #define USB_VENDOR_ID_A4TECH 0x09da | ||
643 | #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 | ||
644 | |||
645 | #define USB_VENDOR_ID_AASHIMA 0x06d6 | ||
646 | #define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025 | ||
647 | #define USB_DEVICE_ID_AASHIMA_PREDATOR 0x0026 | ||
648 | |||
649 | #define USB_VENDOR_ID_CYPRESS 0x04b4 | ||
650 | #define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 | ||
651 | #define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500 | ||
652 | #define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417 | ||
653 | |||
654 | #define USB_VENDOR_ID_BERKSHIRE 0x0c98 | ||
655 | #define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 | ||
656 | |||
657 | #define USB_VENDOR_ID_ALPS 0x0433 | ||
658 | #define USB_DEVICE_ID_IBM_GAMEPAD 0x1101 | ||
659 | |||
660 | #define USB_VENDOR_ID_SAITEK 0x06a3 | ||
661 | #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 | ||
662 | |||
663 | #define USB_VENDOR_ID_NEC 0x073e | ||
664 | #define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 | ||
665 | |||
666 | #define USB_VENDOR_ID_CHIC 0x05fe | ||
667 | #define USB_DEVICE_ID_CHIC_GAMEPAD 0x0014 | ||
668 | |||
669 | #define USB_VENDOR_ID_GLAB 0x06c2 | ||
670 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 | ||
671 | #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 | ||
672 | #define USB_DEVICE_ID_0_0_4_IF_KIT 0x0040 | ||
673 | #define USB_DEVICE_ID_0_16_16_IF_KIT 0x0044 | ||
674 | #define USB_DEVICE_ID_8_8_8_IF_KIT 0x0045 | ||
675 | #define USB_DEVICE_ID_0_8_7_IF_KIT 0x0051 | ||
676 | #define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053 | ||
677 | #define USB_DEVICE_ID_PHIDGET_MOTORCONTROL 0x0058 | ||
678 | |||
679 | #define USB_VENDOR_ID_WISEGROUP 0x0925 | ||
680 | #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 | ||
681 | #define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104 | ||
682 | #define USB_DEVICE_ID_8_8_4_IF_KIT 0x8201 | ||
683 | #define USB_DEVICE_ID_DUAL_USB_JOYPAD 0x8866 | ||
684 | |||
685 | #define USB_VENDOR_ID_WISEGROUP_LTD 0x6677 | ||
686 | #define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802 | ||
687 | |||
688 | #define USB_VENDOR_ID_CODEMERCS 0x07c0 | ||
689 | #define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500 | ||
690 | #define USB_DEVICE_ID_CODEMERCS_IOW_LAST 0x15ff | ||
691 | |||
692 | #define USB_VENDOR_ID_DELORME 0x1163 | ||
693 | #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 | ||
694 | #define USB_DEVICE_ID_DELORME_EM_LT20 0x0200 | ||
695 | |||
696 | #define USB_VENDOR_ID_MCC 0x09db | ||
697 | #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 | ||
698 | #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a | ||
699 | |||
700 | #define USB_VENDOR_ID_VERNIER 0x08f7 | ||
701 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 | ||
702 | #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 | ||
703 | #define USB_DEVICE_ID_VERNIER_SKIP 0x0003 | ||
704 | #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 | ||
705 | |||
706 | #define USB_VENDOR_ID_LD 0x0f11 | ||
707 | #define USB_DEVICE_ID_LD_CASSY 0x1000 | ||
708 | #define USB_DEVICE_ID_LD_POCKETCASSY 0x1010 | ||
709 | #define USB_DEVICE_ID_LD_MOBILECASSY 0x1020 | ||
710 | #define USB_DEVICE_ID_LD_JWM 0x1080 | ||
711 | #define USB_DEVICE_ID_LD_DMMP 0x1081 | ||
712 | #define USB_DEVICE_ID_LD_UMIP 0x1090 | ||
713 | #define USB_DEVICE_ID_LD_XRAY1 0x1100 | ||
714 | #define USB_DEVICE_ID_LD_XRAY2 0x1101 | ||
715 | #define USB_DEVICE_ID_LD_VIDEOCOM 0x1200 | ||
716 | #define USB_DEVICE_ID_LD_COM3LAB 0x2000 | ||
717 | #define USB_DEVICE_ID_LD_TELEPORT 0x2010 | ||
718 | #define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020 | ||
719 | #define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 | ||
720 | #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 | ||
721 | |||
722 | #define USB_VENDOR_ID_APPLE 0x05ac | ||
723 | #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 | ||
724 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e | ||
725 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f | ||
726 | #define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214 | ||
727 | #define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215 | ||
728 | #define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216 | ||
729 | #define USB_DEVICE_ID_APPLE_GEYSER3_ANSI 0x0217 | ||
730 | #define USB_DEVICE_ID_APPLE_GEYSER3_ISO 0x0218 | ||
731 | #define USB_DEVICE_ID_APPLE_GEYSER3_JIS 0x0219 | ||
732 | #define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a | ||
733 | #define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b | ||
734 | #define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c | ||
735 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a | ||
736 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b | ||
737 | #define USB_DEVICE_ID_APPLE_IR 0x8240 | ||
738 | |||
739 | #define USB_VENDOR_ID_CHERRY 0x046a | ||
740 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 | ||
741 | |||
742 | #define USB_VENDOR_ID_YEALINK 0x6993 | ||
743 | #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 | ||
744 | |||
745 | #define USB_VENDOR_ID_ALCOR 0x058f | ||
746 | #define USB_DEVICE_ID_ALCOR_USBRS232 0x9720 | ||
747 | |||
748 | #define USB_VENDOR_ID_SUN 0x0430 | ||
749 | #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab | ||
750 | |||
751 | #define USB_VENDOR_ID_AIRCABLE 0x16CA | ||
752 | #define USB_DEVICE_ID_AIRCABLE1 0x1502 | ||
753 | |||
754 | #define USB_VENDOR_ID_LOGITECH 0x046d | ||
755 | #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER 0xc101 | ||
756 | #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2 0xc517 | ||
757 | #define USB_DEVICE_ID_DINOVO_EDGE 0xc714 | ||
758 | |||
759 | #define USB_VENDOR_ID_IMATION 0x0718 | ||
760 | #define USB_DEVICE_ID_DISC_STAKKA 0xd000 | ||
761 | |||
762 | #define USB_VENDOR_ID_PANTHERLORD 0x0810 | ||
763 | #define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001 | ||
764 | |||
765 | #define USB_VENDOR_ID_SONY 0x054c | ||
766 | #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 | ||
767 | |||
768 | /* | ||
769 | * Alphabetically sorted blacklist by quirk type. | ||
770 | */ | ||
771 | |||
772 | static const struct hid_blacklist { | ||
773 | __u16 idVendor; | ||
774 | __u16 idProduct; | ||
775 | unsigned quirks; | ||
776 | } hid_blacklist[] = { | ||
777 | |||
778 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES }, | ||
779 | |||
780 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, | ||
781 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE }, | ||
782 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE }, | ||
783 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21, HID_QUIRK_IGNORE }, | ||
784 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE }, | ||
785 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE }, | ||
786 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE }, | ||
787 | { USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1, HID_QUIRK_IGNORE }, | ||
788 | { USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE }, | ||
789 | { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, | ||
790 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE }, | ||
791 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE }, | ||
792 | { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE }, | ||
793 | { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE }, | ||
794 | { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, | ||
795 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, | ||
796 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, | ||
797 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE }, | ||
798 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT, HID_QUIRK_IGNORE }, | ||
799 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE }, | ||
800 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT, HID_QUIRK_IGNORE }, | ||
801 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE }, | ||
802 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL, HID_QUIRK_IGNORE }, | ||
803 | { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, | ||
804 | { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, | ||
805 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE }, | ||
806 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100, HID_QUIRK_IGNORE }, | ||
807 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101, HID_QUIRK_IGNORE }, | ||
808 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103, HID_QUIRK_IGNORE }, | ||
809 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104, HID_QUIRK_IGNORE }, | ||
810 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105, HID_QUIRK_IGNORE }, | ||
811 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106, HID_QUIRK_IGNORE }, | ||
812 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107, HID_QUIRK_IGNORE }, | ||
813 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108, HID_QUIRK_IGNORE }, | ||
814 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200, HID_QUIRK_IGNORE }, | ||
815 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201, HID_QUIRK_IGNORE }, | ||
816 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202, HID_QUIRK_IGNORE }, | ||
817 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203, HID_QUIRK_IGNORE }, | ||
818 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204, HID_QUIRK_IGNORE }, | ||
819 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205, HID_QUIRK_IGNORE }, | ||
820 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206, HID_QUIRK_IGNORE }, | ||
821 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207, HID_QUIRK_IGNORE }, | ||
822 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300, HID_QUIRK_IGNORE }, | ||
823 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301, HID_QUIRK_IGNORE }, | ||
824 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302, HID_QUIRK_IGNORE }, | ||
825 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303, HID_QUIRK_IGNORE }, | ||
826 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304, HID_QUIRK_IGNORE }, | ||
827 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305, HID_QUIRK_IGNORE }, | ||
828 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306, HID_QUIRK_IGNORE }, | ||
829 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307, HID_QUIRK_IGNORE }, | ||
830 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308, HID_QUIRK_IGNORE }, | ||
831 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309, HID_QUIRK_IGNORE }, | ||
832 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400, HID_QUIRK_IGNORE }, | ||
833 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401, HID_QUIRK_IGNORE }, | ||
834 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402, HID_QUIRK_IGNORE }, | ||
835 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403, HID_QUIRK_IGNORE }, | ||
836 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404, HID_QUIRK_IGNORE }, | ||
837 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405, HID_QUIRK_IGNORE }, | ||
838 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500, HID_QUIRK_IGNORE }, | ||
839 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501, HID_QUIRK_IGNORE }, | ||
840 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE }, | ||
841 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE }, | ||
842 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE }, | ||
843 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE }, | ||
844 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE }, | ||
845 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE }, | ||
846 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003, HID_QUIRK_IGNORE }, | ||
847 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE }, | ||
848 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE }, | ||
849 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE }, | ||
850 | { USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE }, | ||
851 | { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, | ||
852 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE }, | ||
853 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE }, | ||
854 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY, HID_QUIRK_IGNORE }, | ||
855 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM, HID_QUIRK_IGNORE }, | ||
856 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP, HID_QUIRK_IGNORE }, | ||
857 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP, HID_QUIRK_IGNORE }, | ||
858 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1, HID_QUIRK_IGNORE }, | ||
859 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2, HID_QUIRK_IGNORE }, | ||
860 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM, HID_QUIRK_IGNORE }, | ||
861 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB, HID_QUIRK_IGNORE }, | ||
862 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT, HID_QUIRK_IGNORE }, | ||
863 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER, HID_QUIRK_IGNORE }, | ||
864 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL, HID_QUIRK_IGNORE }, | ||
865 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST, HID_QUIRK_IGNORE }, | ||
866 | { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE }, | ||
867 | { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE }, | ||
868 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE }, | ||
869 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE }, | ||
870 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE }, | ||
871 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20, HID_QUIRK_IGNORE }, | ||
872 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30, HID_QUIRK_IGNORE }, | ||
873 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE }, | ||
874 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108, HID_QUIRK_IGNORE }, | ||
875 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118, HID_QUIRK_IGNORE }, | ||
876 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE }, | ||
877 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE }, | ||
878 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE }, | ||
879 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE }, | ||
880 | { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO, HID_QUIRK_IGNORE }, | ||
881 | { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE }, | ||
882 | { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE }, | ||
883 | { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE }, | ||
884 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | ||
885 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | ||
886 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT, HID_QUIRK_IGNORE }, | ||
887 | { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE }, | ||
888 | |||
889 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, | ||
890 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE }, | ||
891 | |||
892 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, | ||
893 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, | ||
894 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, | ||
895 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, | ||
896 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, | ||
897 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, | ||
898 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | ||
899 | { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | ||
900 | |||
901 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, | ||
902 | { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, | ||
903 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, | ||
904 | |||
905 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD }, | ||
906 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, | ||
907 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, | ||
908 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, | ||
909 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | ||
910 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | ||
911 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | ||
912 | { USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD }, | ||
913 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, | ||
914 | { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, | ||
915 | |||
916 | { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, | ||
917 | |||
918 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
919 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
920 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
921 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, | ||
922 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
923 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
924 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, | ||
925 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
926 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
927 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, | ||
928 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
929 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
930 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
931 | |||
932 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IR, HID_QUIRK_IGNORE }, | ||
933 | |||
934 | { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE }, | ||
935 | { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE }, | ||
936 | { USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE }, | ||
937 | { USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE }, | ||
938 | |||
939 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, | ||
940 | |||
941 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS }, | ||
942 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2, HID_QUIRK_LOGITECH_S510_DESCRIPTOR }, | ||
943 | |||
944 | { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | ||
945 | |||
946 | { USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER }, | ||
947 | |||
948 | { USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE }, | ||
949 | |||
950 | { 0, 0 } | ||
951 | }; | ||
952 | |||
953 | /* | ||
954 | * Traverse the supplied list of reports and find the longest | ||
955 | */ | ||
956 | static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max) | ||
957 | { | ||
958 | struct hid_report *report; | ||
959 | int size; | ||
960 | |||
961 | list_for_each_entry(report, &hid->report_enum[type].report_list, list) { | ||
962 | size = ((report->size - 1) >> 3) + 1; | ||
963 | if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered) | ||
964 | size++; | ||
965 | if (*max < size) | ||
966 | *max = size; | ||
967 | } | ||
968 | } | ||
969 | |||
970 | static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) | ||
971 | { | ||
972 | struct usbhid_device *usbhid = hid->driver_data; | ||
973 | |||
974 | if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma))) | ||
975 | return -1; | ||
976 | if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma))) | ||
977 | return -1; | ||
978 | if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma))) | ||
979 | return -1; | ||
980 | if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma))) | ||
981 | return -1; | ||
982 | |||
983 | return 0; | ||
984 | } | ||
985 | |||
986 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) | ||
987 | { | ||
988 | struct usbhid_device *usbhid = hid->driver_data; | ||
989 | |||
990 | if (usbhid->inbuf) | ||
991 | usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma); | ||
992 | if (usbhid->outbuf) | ||
993 | usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma); | ||
994 | if (usbhid->cr) | ||
995 | usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma); | ||
996 | if (usbhid->ctrlbuf) | ||
997 | usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma); | ||
998 | } | ||
999 | |||
1000 | /* | ||
1001 | * Cherry Cymotion keyboard have an invalid HID report descriptor, | ||
1002 | * that needs fixing before we can parse it. | ||
1003 | */ | ||
1004 | |||
1005 | static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize) | ||
1006 | { | ||
1007 | if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { | ||
1008 | info("Fixing up Cherry Cymotion report descriptor"); | ||
1009 | rdesc[11] = rdesc[16] = 0xff; | ||
1010 | rdesc[12] = rdesc[17] = 0x03; | ||
1011 | } | ||
1012 | } | ||
1013 | |||
1014 | /* | ||
1015 | * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller | ||
1016 | * to "operational". Without this, the ps3 controller will not report any | ||
1017 | * events. | ||
1018 | */ | ||
1019 | static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum) | ||
1020 | { | ||
1021 | int result; | ||
1022 | char *buf = kmalloc(18, GFP_KERNEL); | ||
1023 | |||
1024 | if (!buf) | ||
1025 | return; | ||
1026 | |||
1027 | result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
1028 | HID_REQ_GET_REPORT, | ||
1029 | USB_DIR_IN | USB_TYPE_CLASS | | ||
1030 | USB_RECIP_INTERFACE, | ||
1031 | (3 << 8) | 0xf2, ifnum, buf, 17, | ||
1032 | USB_CTRL_GET_TIMEOUT); | ||
1033 | |||
1034 | if (result < 0) | ||
1035 | err("%s failed: %d\n", __func__, result); | ||
1036 | |||
1037 | kfree(buf); | ||
1038 | } | ||
1039 | |||
1040 | /* | ||
1041 | * Logitech S510 keyboard sends in report #3 keys which are far | ||
1042 | * above the logical maximum described in descriptor. This extends | ||
1043 | * the original value of 0x28c of logical maximum to 0x104d | ||
1044 | */ | ||
1045 | static void hid_fixup_s510_descriptor(unsigned char *rdesc, int rsize) | ||
1046 | { | ||
1047 | if (rsize >= 90 && rdesc[83] == 0x26 | ||
1048 | && rdesc[84] == 0x8c | ||
1049 | && rdesc[85] == 0x02) { | ||
1050 | info("Fixing up Logitech S510 report descriptor"); | ||
1051 | rdesc[84] = rdesc[89] = 0x4d; | ||
1052 | rdesc[85] = rdesc[90] = 0x10; | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1056 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) | ||
1057 | { | ||
1058 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
1059 | struct usb_device *dev = interface_to_usbdev (intf); | ||
1060 | struct hid_descriptor *hdesc; | ||
1061 | struct hid_device *hid; | ||
1062 | unsigned quirks = 0, rsize = 0; | ||
1063 | char *rdesc; | ||
1064 | int n, len, insize = 0; | ||
1065 | struct usbhid_device *usbhid; | ||
1066 | |||
1067 | /* Ignore all Wacom devices */ | ||
1068 | if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_WACOM) | ||
1069 | return NULL; | ||
1070 | /* ignore all Code Mercenaries IOWarrior devices */ | ||
1071 | if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_CODEMERCS) | ||
1072 | if (le16_to_cpu(dev->descriptor.idProduct) >= USB_DEVICE_ID_CODEMERCS_IOW_FIRST && | ||
1073 | le16_to_cpu(dev->descriptor.idProduct) <= USB_DEVICE_ID_CODEMERCS_IOW_LAST) | ||
1074 | return NULL; | ||
1075 | |||
1076 | for (n = 0; hid_blacklist[n].idVendor; n++) | ||
1077 | if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) && | ||
1078 | (hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct))) | ||
1079 | quirks = hid_blacklist[n].quirks; | ||
1080 | |||
1081 | /* Many keyboards and mice don't like to be polled for reports, | ||
1082 | * so we will always set the HID_QUIRK_NOGET flag for them. */ | ||
1083 | if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { | ||
1084 | if (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD || | ||
1085 | interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) | ||
1086 | quirks |= HID_QUIRK_NOGET; | ||
1087 | } | ||
1088 | |||
1089 | if (quirks & HID_QUIRK_IGNORE) | ||
1090 | return NULL; | ||
1091 | |||
1092 | if ((quirks & HID_QUIRK_IGNORE_MOUSE) && | ||
1093 | (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)) | ||
1094 | return NULL; | ||
1095 | |||
1096 | |||
1097 | if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && | ||
1098 | (!interface->desc.bNumEndpoints || | ||
1099 | usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { | ||
1100 | dbg("class descriptor not present\n"); | ||
1101 | return NULL; | ||
1102 | } | ||
1103 | |||
1104 | for (n = 0; n < hdesc->bNumDescriptors; n++) | ||
1105 | if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) | ||
1106 | rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); | ||
1107 | |||
1108 | if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { | ||
1109 | dbg("weird size of report descriptor (%u)", rsize); | ||
1110 | return NULL; | ||
1111 | } | ||
1112 | |||
1113 | if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) { | ||
1114 | dbg("couldn't allocate rdesc memory"); | ||
1115 | return NULL; | ||
1116 | } | ||
1117 | |||
1118 | hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0); | ||
1119 | |||
1120 | if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) { | ||
1121 | dbg("reading report descriptor failed"); | ||
1122 | kfree(rdesc); | ||
1123 | return NULL; | ||
1124 | } | ||
1125 | |||
1126 | if ((quirks & HID_QUIRK_CYMOTION)) | ||
1127 | hid_fixup_cymotion_descriptor(rdesc, rsize); | ||
1128 | |||
1129 | if (quirks & HID_QUIRK_LOGITECH_S510_DESCRIPTOR) | ||
1130 | hid_fixup_s510_descriptor(rdesc, rsize); | ||
1131 | |||
1132 | #ifdef CONFIG_HID_DEBUG | ||
1133 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); | ||
1134 | for (n = 0; n < rsize; n++) | ||
1135 | printk(" %02x", (unsigned char) rdesc[n]); | ||
1136 | printk("\n"); | ||
1137 | #endif | ||
1138 | |||
1139 | if (!(hid = hid_parse_report(rdesc, n))) { | ||
1140 | dbg("parsing report descriptor failed"); | ||
1141 | kfree(rdesc); | ||
1142 | return NULL; | ||
1143 | } | ||
1144 | |||
1145 | kfree(rdesc); | ||
1146 | hid->quirks = quirks; | ||
1147 | |||
1148 | if (!(usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL))) | ||
1149 | goto fail; | ||
1150 | |||
1151 | hid->driver_data = usbhid; | ||
1152 | usbhid->hid = hid; | ||
1153 | |||
1154 | usbhid->bufsize = HID_MIN_BUFFER_SIZE; | ||
1155 | hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); | ||
1156 | hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); | ||
1157 | hid_find_max_report(hid, HID_FEATURE_REPORT, &usbhid->bufsize); | ||
1158 | |||
1159 | if (usbhid->bufsize > HID_MAX_BUFFER_SIZE) | ||
1160 | usbhid->bufsize = HID_MAX_BUFFER_SIZE; | ||
1161 | |||
1162 | hid_find_max_report(hid, HID_INPUT_REPORT, &insize); | ||
1163 | |||
1164 | if (insize > HID_MAX_BUFFER_SIZE) | ||
1165 | insize = HID_MAX_BUFFER_SIZE; | ||
1166 | |||
1167 | if (hid_alloc_buffers(dev, hid)) { | ||
1168 | hid_free_buffers(dev, hid); | ||
1169 | goto fail; | ||
1170 | } | ||
1171 | |||
1172 | for (n = 0; n < interface->desc.bNumEndpoints; n++) { | ||
1173 | |||
1174 | struct usb_endpoint_descriptor *endpoint; | ||
1175 | int pipe; | ||
1176 | int interval; | ||
1177 | |||
1178 | endpoint = &interface->endpoint[n].desc; | ||
1179 | if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */ | ||
1180 | continue; | ||
1181 | |||
1182 | interval = endpoint->bInterval; | ||
1183 | |||
1184 | /* Change the polling interval of mice. */ | ||
1185 | if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) | ||
1186 | interval = hid_mousepoll_interval; | ||
1187 | |||
1188 | if (usb_endpoint_dir_in(endpoint)) { | ||
1189 | if (usbhid->urbin) | ||
1190 | continue; | ||
1191 | if (!(usbhid->urbin = usb_alloc_urb(0, GFP_KERNEL))) | ||
1192 | goto fail; | ||
1193 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
1194 | usb_fill_int_urb(usbhid->urbin, dev, pipe, usbhid->inbuf, insize, | ||
1195 | hid_irq_in, hid, interval); | ||
1196 | usbhid->urbin->transfer_dma = usbhid->inbuf_dma; | ||
1197 | usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
1198 | } else { | ||
1199 | if (usbhid->urbout) | ||
1200 | continue; | ||
1201 | if (!(usbhid->urbout = usb_alloc_urb(0, GFP_KERNEL))) | ||
1202 | goto fail; | ||
1203 | pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress); | ||
1204 | usb_fill_int_urb(usbhid->urbout, dev, pipe, usbhid->outbuf, 0, | ||
1205 | hid_irq_out, hid, interval); | ||
1206 | usbhid->urbout->transfer_dma = usbhid->outbuf_dma; | ||
1207 | usbhid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
1208 | } | ||
1209 | } | ||
1210 | |||
1211 | if (!usbhid->urbin) { | ||
1212 | err("couldn't find an input interrupt endpoint"); | ||
1213 | goto fail; | ||
1214 | } | ||
1215 | |||
1216 | init_waitqueue_head(&hid->wait); | ||
1217 | |||
1218 | INIT_WORK(&usbhid->reset_work, hid_reset); | ||
1219 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); | ||
1220 | |||
1221 | spin_lock_init(&usbhid->inlock); | ||
1222 | spin_lock_init(&usbhid->outlock); | ||
1223 | spin_lock_init(&usbhid->ctrllock); | ||
1224 | |||
1225 | hid->version = le16_to_cpu(hdesc->bcdHID); | ||
1226 | hid->country = hdesc->bCountryCode; | ||
1227 | hid->dev = &intf->dev; | ||
1228 | usbhid->intf = intf; | ||
1229 | usbhid->ifnum = interface->desc.bInterfaceNumber; | ||
1230 | |||
1231 | hid->name[0] = 0; | ||
1232 | |||
1233 | if (dev->manufacturer) | ||
1234 | strlcpy(hid->name, dev->manufacturer, sizeof(hid->name)); | ||
1235 | |||
1236 | if (dev->product) { | ||
1237 | if (dev->manufacturer) | ||
1238 | strlcat(hid->name, " ", sizeof(hid->name)); | ||
1239 | strlcat(hid->name, dev->product, sizeof(hid->name)); | ||
1240 | } | ||
1241 | |||
1242 | if (!strlen(hid->name)) | ||
1243 | snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x", | ||
1244 | le16_to_cpu(dev->descriptor.idVendor), | ||
1245 | le16_to_cpu(dev->descriptor.idProduct)); | ||
1246 | |||
1247 | hid->bus = BUS_USB; | ||
1248 | hid->vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
1249 | hid->product = le16_to_cpu(dev->descriptor.idProduct); | ||
1250 | |||
1251 | usb_make_path(dev, hid->phys, sizeof(hid->phys)); | ||
1252 | strlcat(hid->phys, "/input", sizeof(hid->phys)); | ||
1253 | len = strlen(hid->phys); | ||
1254 | if (len < sizeof(hid->phys) - 1) | ||
1255 | snprintf(hid->phys + len, sizeof(hid->phys) - len, | ||
1256 | "%d", intf->altsetting[0].desc.bInterfaceNumber); | ||
1257 | |||
1258 | if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) | ||
1259 | hid->uniq[0] = 0; | ||
1260 | |||
1261 | usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); | ||
1262 | if (!usbhid->urbctrl) | ||
1263 | goto fail; | ||
1264 | |||
1265 | usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr, | ||
1266 | usbhid->ctrlbuf, 1, hid_ctrl, hid); | ||
1267 | usbhid->urbctrl->setup_dma = usbhid->cr_dma; | ||
1268 | usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma; | ||
1269 | usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); | ||
1270 | hid->hidinput_input_event = usb_hidinput_input_event; | ||
1271 | hid->hid_open = usbhid_open; | ||
1272 | hid->hid_close = usbhid_close; | ||
1273 | #ifdef CONFIG_USB_HIDDEV | ||
1274 | hid->hiddev_hid_event = hiddev_hid_event; | ||
1275 | hid->hiddev_report_event = hiddev_report_event; | ||
1276 | #endif | ||
1277 | return hid; | ||
1278 | |||
1279 | fail: | ||
1280 | usb_free_urb(usbhid->urbin); | ||
1281 | usb_free_urb(usbhid->urbout); | ||
1282 | usb_free_urb(usbhid->urbctrl); | ||
1283 | hid_free_buffers(dev, hid); | ||
1284 | hid_free_device(hid); | ||
1285 | |||
1286 | return NULL; | ||
1287 | } | ||
1288 | |||
1289 | static void hid_disconnect(struct usb_interface *intf) | ||
1290 | { | ||
1291 | struct hid_device *hid = usb_get_intfdata (intf); | ||
1292 | struct usbhid_device *usbhid; | ||
1293 | |||
1294 | if (!hid) | ||
1295 | return; | ||
1296 | |||
1297 | usbhid = hid->driver_data; | ||
1298 | |||
1299 | spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ | ||
1300 | usb_set_intfdata(intf, NULL); | ||
1301 | spin_unlock_irq(&usbhid->inlock); | ||
1302 | usb_kill_urb(usbhid->urbin); | ||
1303 | usb_kill_urb(usbhid->urbout); | ||
1304 | usb_kill_urb(usbhid->urbctrl); | ||
1305 | |||
1306 | del_timer_sync(&usbhid->io_retry); | ||
1307 | flush_scheduled_work(); | ||
1308 | |||
1309 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
1310 | hidinput_disconnect(hid); | ||
1311 | if (hid->claimed & HID_CLAIMED_HIDDEV) | ||
1312 | hiddev_disconnect(hid); | ||
1313 | |||
1314 | usb_free_urb(usbhid->urbin); | ||
1315 | usb_free_urb(usbhid->urbctrl); | ||
1316 | usb_free_urb(usbhid->urbout); | ||
1317 | |||
1318 | hid_free_buffers(hid_to_usb_dev(hid), hid); | ||
1319 | hid_free_device(hid); | ||
1320 | } | ||
1321 | |||
1322 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
1323 | { | ||
1324 | struct hid_device *hid; | ||
1325 | char path[64]; | ||
1326 | int i; | ||
1327 | char *c; | ||
1328 | |||
1329 | dbg("HID probe called for ifnum %d", | ||
1330 | intf->altsetting->desc.bInterfaceNumber); | ||
1331 | |||
1332 | if (!(hid = usb_hid_configure(intf))) | ||
1333 | return -ENODEV; | ||
1334 | |||
1335 | usbhid_init_reports(hid); | ||
1336 | hid_dump_device(hid); | ||
1337 | |||
1338 | if (!hidinput_connect(hid)) | ||
1339 | hid->claimed |= HID_CLAIMED_INPUT; | ||
1340 | if (!hiddev_connect(hid)) | ||
1341 | hid->claimed |= HID_CLAIMED_HIDDEV; | ||
1342 | |||
1343 | usb_set_intfdata(intf, hid); | ||
1344 | |||
1345 | if (!hid->claimed) { | ||
1346 | printk ("HID device not claimed by input or hiddev\n"); | ||
1347 | hid_disconnect(intf); | ||
1348 | return -ENODEV; | ||
1349 | } | ||
1350 | |||
1351 | if ((hid->claimed & HID_CLAIMED_INPUT)) | ||
1352 | hid_ff_init(hid); | ||
1353 | |||
1354 | if (hid->quirks & HID_QUIRK_SONY_PS3_CONTROLLER) | ||
1355 | hid_fixup_sony_ps3_controller(interface_to_usbdev(intf), | ||
1356 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
1357 | |||
1358 | printk(KERN_INFO); | ||
1359 | |||
1360 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
1361 | printk("input"); | ||
1362 | if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV)) | ||
1363 | printk(","); | ||
1364 | if (hid->claimed & HID_CLAIMED_HIDDEV) | ||
1365 | printk("hiddev%d", hid->minor); | ||
1366 | |||
1367 | c = "Device"; | ||
1368 | for (i = 0; i < hid->maxcollection; i++) { | ||
1369 | if (hid->collection[i].type == HID_COLLECTION_APPLICATION && | ||
1370 | (hid->collection[i].usage & HID_USAGE_PAGE) == HID_UP_GENDESK && | ||
1371 | (hid->collection[i].usage & 0xffff) < ARRAY_SIZE(hid_types)) { | ||
1372 | c = hid_types[hid->collection[i].usage & 0xffff]; | ||
1373 | break; | ||
1374 | } | ||
1375 | } | ||
1376 | |||
1377 | usb_make_path(interface_to_usbdev(intf), path, 63); | ||
1378 | |||
1379 | printk(": USB HID v%x.%02x %s [%s] on %s\n", | ||
1380 | hid->version >> 8, hid->version & 0xff, c, hid->name, path); | ||
1381 | |||
1382 | return 0; | ||
1383 | } | ||
1384 | |||
1385 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) | ||
1386 | { | ||
1387 | struct hid_device *hid = usb_get_intfdata (intf); | ||
1388 | struct usbhid_device *usbhid = hid->driver_data; | ||
1389 | |||
1390 | spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ | ||
1391 | set_bit(HID_SUSPENDED, &usbhid->iofl); | ||
1392 | spin_unlock_irq(&usbhid->inlock); | ||
1393 | del_timer(&usbhid->io_retry); | ||
1394 | usb_kill_urb(usbhid->urbin); | ||
1395 | dev_dbg(&intf->dev, "suspend\n"); | ||
1396 | return 0; | ||
1397 | } | ||
1398 | |||
1399 | static int hid_resume(struct usb_interface *intf) | ||
1400 | { | ||
1401 | struct hid_device *hid = usb_get_intfdata (intf); | ||
1402 | struct usbhid_device *usbhid = hid->driver_data; | ||
1403 | int status; | ||
1404 | |||
1405 | clear_bit(HID_SUSPENDED, &usbhid->iofl); | ||
1406 | usbhid->retry_delay = 0; | ||
1407 | status = hid_start_in(hid); | ||
1408 | dev_dbg(&intf->dev, "resume status %d\n", status); | ||
1409 | return status; | ||
1410 | } | ||
1411 | |||
1412 | /* Treat USB reset pretty much the same as suspend/resume */ | ||
1413 | static void hid_pre_reset(struct usb_interface *intf) | ||
1414 | { | ||
1415 | /* FIXME: What if the interface is already suspended? */ | ||
1416 | hid_suspend(intf, PMSG_ON); | ||
1417 | } | ||
1418 | |||
1419 | static void hid_post_reset(struct usb_interface *intf) | ||
1420 | { | ||
1421 | struct usb_device *dev = interface_to_usbdev (intf); | ||
1422 | |||
1423 | hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); | ||
1424 | /* FIXME: Any more reinitialization needed? */ | ||
1425 | |||
1426 | hid_resume(intf); | ||
1427 | } | ||
1428 | |||
1429 | static struct usb_device_id hid_usb_ids [] = { | ||
1430 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, | ||
1431 | .bInterfaceClass = USB_INTERFACE_CLASS_HID }, | ||
1432 | { } /* Terminating entry */ | ||
1433 | }; | ||
1434 | |||
1435 | MODULE_DEVICE_TABLE (usb, hid_usb_ids); | ||
1436 | |||
1437 | static struct usb_driver hid_driver = { | ||
1438 | .name = "usbhid", | ||
1439 | .probe = hid_probe, | ||
1440 | .disconnect = hid_disconnect, | ||
1441 | .suspend = hid_suspend, | ||
1442 | .resume = hid_resume, | ||
1443 | .pre_reset = hid_pre_reset, | ||
1444 | .post_reset = hid_post_reset, | ||
1445 | .id_table = hid_usb_ids, | ||
1446 | }; | ||
1447 | |||
1448 | static int __init hid_init(void) | ||
1449 | { | ||
1450 | int retval; | ||
1451 | retval = hiddev_init(); | ||
1452 | if (retval) | ||
1453 | goto hiddev_init_fail; | ||
1454 | retval = usb_register(&hid_driver); | ||
1455 | if (retval) | ||
1456 | goto usb_register_fail; | ||
1457 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
1458 | |||
1459 | return 0; | ||
1460 | usb_register_fail: | ||
1461 | hiddev_exit(); | ||
1462 | hiddev_init_fail: | ||
1463 | return retval; | ||
1464 | } | ||
1465 | |||
1466 | static void __exit hid_exit(void) | ||
1467 | { | ||
1468 | usb_deregister(&hid_driver); | ||
1469 | hiddev_exit(); | ||
1470 | } | ||
1471 | |||
1472 | module_init(hid_init); | ||
1473 | module_exit(hid_exit); | ||
1474 | |||
1475 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
1476 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
1477 | MODULE_LICENSE(DRIVER_LICENSE); | ||
diff --git a/drivers/hid/usbhid/hid-ff.c b/drivers/hid/usbhid/hid-ff.c new file mode 100644 index 000000000000..e431faaa6abc --- /dev/null +++ b/drivers/hid/usbhid/hid-ff.c | |||
@@ -0,0 +1,89 @@ | |||
1 | /* | ||
2 | * $Id: hid-ff.c,v 1.2 2002/04/18 22:02:47 jdeneux Exp $ | ||
3 | * | ||
4 | * Force feedback support for hid devices. | ||
5 | * Not all hid devices use the same protocol. For example, some use PID, | ||
6 | * other use their own proprietary procotol. | ||
7 | * | ||
8 | * Copyright (c) 2002-2004 Johann Deneux | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | * Should you need to contact me, the author, you can do so by | ||
27 | * e-mail - mail your message to <johann.deneux@it.uu.se> | ||
28 | */ | ||
29 | |||
30 | #include <linux/input.h> | ||
31 | |||
32 | #undef DEBUG | ||
33 | #include <linux/usb.h> | ||
34 | |||
35 | #include <linux/hid.h> | ||
36 | #include "usbhid.h" | ||
37 | |||
38 | /* | ||
39 | * This table contains pointers to initializers. To add support for new | ||
40 | * devices, you need to add the USB vendor and product ids here. | ||
41 | */ | ||
42 | struct hid_ff_initializer { | ||
43 | u16 idVendor; | ||
44 | u16 idProduct; | ||
45 | int (*init)(struct hid_device*); | ||
46 | }; | ||
47 | |||
48 | /* | ||
49 | * We try pidff when no other driver is found because PID is the | ||
50 | * standards compliant way of implementing force feedback in HID. | ||
51 | * pidff_init() will quickly abort if the device doesn't appear to | ||
52 | * be a PID device | ||
53 | */ | ||
54 | static struct hid_ff_initializer inits[] = { | ||
55 | #ifdef CONFIG_LOGITECH_FF | ||
56 | { 0x46d, 0xc211, hid_lgff_init }, /* Logitech Cordless rumble pad */ | ||
57 | { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */ | ||
58 | { 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */ | ||
59 | { 0x46d, 0xc294, hid_lgff_init }, /* Logitech Formula Force EX */ | ||
60 | { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */ | ||
61 | { 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */ | ||
62 | #endif | ||
63 | #ifdef CONFIG_PANTHERLORD_FF | ||
64 | { 0x810, 0x0001, hid_plff_init }, | ||
65 | #endif | ||
66 | #ifdef CONFIG_THRUSTMASTER_FF | ||
67 | { 0x44f, 0xb304, hid_tmff_init }, | ||
68 | #endif | ||
69 | #ifdef CONFIG_ZEROPLUS_FF | ||
70 | { 0xc12, 0x0005, hid_zpff_init }, | ||
71 | { 0xc12, 0x0030, hid_zpff_init }, | ||
72 | #endif | ||
73 | { 0, 0, hid_pidff_init} /* Matches anything */ | ||
74 | }; | ||
75 | |||
76 | int hid_ff_init(struct hid_device* hid) | ||
77 | { | ||
78 | struct hid_ff_initializer *init; | ||
79 | int vendor = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idVendor); | ||
80 | int product = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idProduct); | ||
81 | |||
82 | for (init = inits; init->idVendor; init++) | ||
83 | if (init->idVendor == vendor && init->idProduct == product) | ||
84 | break; | ||
85 | |||
86 | return init->init(hid); | ||
87 | } | ||
88 | EXPORT_SYMBOL_GPL(hid_ff_init); | ||
89 | |||
diff --git a/drivers/hid/usbhid/hid-lgff.c b/drivers/hid/usbhid/hid-lgff.c new file mode 100644 index 000000000000..e6f3af3e66d1 --- /dev/null +++ b/drivers/hid/usbhid/hid-lgff.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | * Force feedback support for hid-compliant for some of the devices from | ||
3 | * Logitech, namely: | ||
4 | * - WingMan Cordless RumblePad | ||
5 | * - WingMan Force 3D | ||
6 | * | ||
7 | * Copyright (c) 2002-2004 Johann Deneux | ||
8 | * Copyright (c) 2006 Anssi Hannula <anssi.hannula@gmail.com> | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | * Should you need to contact me, the author, you can do so by | ||
27 | * e-mail - mail your message to <johann.deneux@it.uu.se> | ||
28 | */ | ||
29 | |||
30 | #include <linux/input.h> | ||
31 | #include <linux/usb.h> | ||
32 | #include <linux/hid.h> | ||
33 | #include "usbhid.h" | ||
34 | |||
35 | struct dev_type { | ||
36 | u16 idVendor; | ||
37 | u16 idProduct; | ||
38 | const signed short *ff; | ||
39 | }; | ||
40 | |||
41 | static const signed short ff_rumble[] = { | ||
42 | FF_RUMBLE, | ||
43 | -1 | ||
44 | }; | ||
45 | |||
46 | static const signed short ff_joystick[] = { | ||
47 | FF_CONSTANT, | ||
48 | -1 | ||
49 | }; | ||
50 | |||
51 | static const struct dev_type devices[] = { | ||
52 | { 0x046d, 0xc211, ff_rumble }, | ||
53 | { 0x046d, 0xc219, ff_rumble }, | ||
54 | { 0x046d, 0xc283, ff_joystick }, | ||
55 | { 0x046d, 0xc294, ff_joystick }, | ||
56 | { 0x046d, 0xc295, ff_joystick }, | ||
57 | { 0x046d, 0xca03, ff_joystick }, | ||
58 | }; | ||
59 | |||
60 | static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect) | ||
61 | { | ||
62 | struct hid_device *hid = dev->private; | ||
63 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
64 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); | ||
65 | int x, y; | ||
66 | unsigned int left, right; | ||
67 | |||
68 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff | ||
69 | |||
70 | switch (effect->type) { | ||
71 | case FF_CONSTANT: | ||
72 | x = effect->u.ramp.start_level + 0x7f; /* 0x7f is center */ | ||
73 | y = effect->u.ramp.end_level + 0x7f; | ||
74 | CLAMP(x); | ||
75 | CLAMP(y); | ||
76 | report->field[0]->value[0] = 0x51; | ||
77 | report->field[0]->value[1] = 0x08; | ||
78 | report->field[0]->value[2] = x; | ||
79 | report->field[0]->value[3] = y; | ||
80 | dbg("(x, y)=(%04x, %04x)", x, y); | ||
81 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
82 | break; | ||
83 | |||
84 | case FF_RUMBLE: | ||
85 | right = effect->u.rumble.strong_magnitude; | ||
86 | left = effect->u.rumble.weak_magnitude; | ||
87 | right = right * 0xff / 0xffff; | ||
88 | left = left * 0xff / 0xffff; | ||
89 | CLAMP(left); | ||
90 | CLAMP(right); | ||
91 | report->field[0]->value[0] = 0x42; | ||
92 | report->field[0]->value[1] = 0x00; | ||
93 | report->field[0]->value[2] = left; | ||
94 | report->field[0]->value[3] = right; | ||
95 | dbg("(left, right)=(%04x, %04x)", left, right); | ||
96 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
97 | break; | ||
98 | } | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | int hid_lgff_init(struct hid_device* hid) | ||
103 | { | ||
104 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
105 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
106 | struct input_dev *dev = hidinput->input; | ||
107 | struct hid_report *report; | ||
108 | struct hid_field *field; | ||
109 | const signed short *ff_bits = ff_joystick; | ||
110 | int error; | ||
111 | int i; | ||
112 | |||
113 | /* Find the report to use */ | ||
114 | if (list_empty(report_list)) { | ||
115 | err("No output report found"); | ||
116 | return -1; | ||
117 | } | ||
118 | |||
119 | /* Check that the report looks ok */ | ||
120 | report = list_entry(report_list->next, struct hid_report, list); | ||
121 | if (!report) { | ||
122 | err("NULL output report"); | ||
123 | return -1; | ||
124 | } | ||
125 | |||
126 | field = report->field[0]; | ||
127 | if (!field) { | ||
128 | err("NULL field"); | ||
129 | return -1; | ||
130 | } | ||
131 | |||
132 | for (i = 0; i < ARRAY_SIZE(devices); i++) { | ||
133 | if (dev->id.vendor == devices[i].idVendor && | ||
134 | dev->id.product == devices[i].idProduct) { | ||
135 | ff_bits = devices[i].ff; | ||
136 | break; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | for (i = 0; ff_bits[i] >= 0; i++) | ||
141 | set_bit(ff_bits[i], dev->ffbit); | ||
142 | |||
143 | error = input_ff_create_memless(dev, NULL, hid_lgff_play); | ||
144 | if (error) | ||
145 | return error; | ||
146 | |||
147 | printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n"); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c new file mode 100644 index 000000000000..f5a90e950e6b --- /dev/null +++ b/drivers/hid/usbhid/hid-pidff.c | |||
@@ -0,0 +1,1331 @@ | |||
1 | /* | ||
2 | * Force feedback driver for USB HID PID compliant devices | ||
3 | * | ||
4 | * Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com> | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | /* #define DEBUG */ | ||
24 | |||
25 | #define debug(format, arg...) pr_debug("hid-pidff: " format "\n" , ## arg) | ||
26 | |||
27 | #include <linux/input.h> | ||
28 | #include <linux/usb.h> | ||
29 | |||
30 | #include <linux/hid.h> | ||
31 | |||
32 | #include "usbhid.h" | ||
33 | |||
34 | #define PID_EFFECTS_MAX 64 | ||
35 | |||
36 | /* Report usage table used to put reports into an array */ | ||
37 | |||
38 | #define PID_SET_EFFECT 0 | ||
39 | #define PID_EFFECT_OPERATION 1 | ||
40 | #define PID_DEVICE_GAIN 2 | ||
41 | #define PID_POOL 3 | ||
42 | #define PID_BLOCK_LOAD 4 | ||
43 | #define PID_BLOCK_FREE 5 | ||
44 | #define PID_DEVICE_CONTROL 6 | ||
45 | #define PID_CREATE_NEW_EFFECT 7 | ||
46 | |||
47 | #define PID_REQUIRED_REPORTS 7 | ||
48 | |||
49 | #define PID_SET_ENVELOPE 8 | ||
50 | #define PID_SET_CONDITION 9 | ||
51 | #define PID_SET_PERIODIC 10 | ||
52 | #define PID_SET_CONSTANT 11 | ||
53 | #define PID_SET_RAMP 12 | ||
54 | static const u8 pidff_reports[] = { | ||
55 | 0x21, 0x77, 0x7d, 0x7f, 0x89, 0x90, 0x96, 0xab, | ||
56 | 0x5a, 0x5f, 0x6e, 0x73, 0x74 | ||
57 | }; | ||
58 | |||
59 | /* device_control is really 0x95, but 0x96 specified as it is the usage of | ||
60 | the only field in that report */ | ||
61 | |||
62 | /* Value usage tables used to put fields and values into arrays */ | ||
63 | |||
64 | #define PID_EFFECT_BLOCK_INDEX 0 | ||
65 | |||
66 | #define PID_DURATION 1 | ||
67 | #define PID_GAIN 2 | ||
68 | #define PID_TRIGGER_BUTTON 3 | ||
69 | #define PID_TRIGGER_REPEAT_INT 4 | ||
70 | #define PID_DIRECTION_ENABLE 5 | ||
71 | #define PID_START_DELAY 6 | ||
72 | static const u8 pidff_set_effect[] = { | ||
73 | 0x22, 0x50, 0x52, 0x53, 0x54, 0x56, 0xa7 | ||
74 | }; | ||
75 | |||
76 | #define PID_ATTACK_LEVEL 1 | ||
77 | #define PID_ATTACK_TIME 2 | ||
78 | #define PID_FADE_LEVEL 3 | ||
79 | #define PID_FADE_TIME 4 | ||
80 | static const u8 pidff_set_envelope[] = { 0x22, 0x5b, 0x5c, 0x5d, 0x5e }; | ||
81 | |||
82 | #define PID_PARAM_BLOCK_OFFSET 1 | ||
83 | #define PID_CP_OFFSET 2 | ||
84 | #define PID_POS_COEFFICIENT 3 | ||
85 | #define PID_NEG_COEFFICIENT 4 | ||
86 | #define PID_POS_SATURATION 5 | ||
87 | #define PID_NEG_SATURATION 6 | ||
88 | #define PID_DEAD_BAND 7 | ||
89 | static const u8 pidff_set_condition[] = { | ||
90 | 0x22, 0x23, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65 | ||
91 | }; | ||
92 | |||
93 | #define PID_MAGNITUDE 1 | ||
94 | #define PID_OFFSET 2 | ||
95 | #define PID_PHASE 3 | ||
96 | #define PID_PERIOD 4 | ||
97 | static const u8 pidff_set_periodic[] = { 0x22, 0x70, 0x6f, 0x71, 0x72 }; | ||
98 | static const u8 pidff_set_constant[] = { 0x22, 0x70 }; | ||
99 | |||
100 | #define PID_RAMP_START 1 | ||
101 | #define PID_RAMP_END 2 | ||
102 | static const u8 pidff_set_ramp[] = { 0x22, 0x75, 0x76 }; | ||
103 | |||
104 | #define PID_RAM_POOL_AVAILABLE 1 | ||
105 | static const u8 pidff_block_load[] = { 0x22, 0xac }; | ||
106 | |||
107 | #define PID_LOOP_COUNT 1 | ||
108 | static const u8 pidff_effect_operation[] = { 0x22, 0x7c }; | ||
109 | |||
110 | static const u8 pidff_block_free[] = { 0x22 }; | ||
111 | |||
112 | #define PID_DEVICE_GAIN_FIELD 0 | ||
113 | static const u8 pidff_device_gain[] = { 0x7e }; | ||
114 | |||
115 | #define PID_RAM_POOL_SIZE 0 | ||
116 | #define PID_SIMULTANEOUS_MAX 1 | ||
117 | #define PID_DEVICE_MANAGED_POOL 2 | ||
118 | static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 }; | ||
119 | |||
120 | /* Special field key tables used to put special field keys into arrays */ | ||
121 | |||
122 | #define PID_ENABLE_ACTUATORS 0 | ||
123 | #define PID_RESET 1 | ||
124 | static const u8 pidff_device_control[] = { 0x97, 0x9a }; | ||
125 | |||
126 | #define PID_CONSTANT 0 | ||
127 | #define PID_RAMP 1 | ||
128 | #define PID_SQUARE 2 | ||
129 | #define PID_SINE 3 | ||
130 | #define PID_TRIANGLE 4 | ||
131 | #define PID_SAW_UP 5 | ||
132 | #define PID_SAW_DOWN 6 | ||
133 | #define PID_SPRING 7 | ||
134 | #define PID_DAMPER 8 | ||
135 | #define PID_INERTIA 9 | ||
136 | #define PID_FRICTION 10 | ||
137 | static const u8 pidff_effect_types[] = { | ||
138 | 0x26, 0x27, 0x30, 0x31, 0x32, 0x33, 0x34, | ||
139 | 0x40, 0x41, 0x42, 0x43 | ||
140 | }; | ||
141 | |||
142 | #define PID_BLOCK_LOAD_SUCCESS 0 | ||
143 | #define PID_BLOCK_LOAD_FULL 1 | ||
144 | static const u8 pidff_block_load_status[] = { 0x8c, 0x8d }; | ||
145 | |||
146 | #define PID_EFFECT_START 0 | ||
147 | #define PID_EFFECT_STOP 1 | ||
148 | static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b }; | ||
149 | |||
150 | struct pidff_usage { | ||
151 | struct hid_field *field; | ||
152 | s32 *value; | ||
153 | }; | ||
154 | |||
155 | struct pidff_device { | ||
156 | struct hid_device *hid; | ||
157 | |||
158 | struct hid_report *reports[sizeof(pidff_reports)]; | ||
159 | |||
160 | struct pidff_usage set_effect[sizeof(pidff_set_effect)]; | ||
161 | struct pidff_usage set_envelope[sizeof(pidff_set_envelope)]; | ||
162 | struct pidff_usage set_condition[sizeof(pidff_set_condition)]; | ||
163 | struct pidff_usage set_periodic[sizeof(pidff_set_periodic)]; | ||
164 | struct pidff_usage set_constant[sizeof(pidff_set_constant)]; | ||
165 | struct pidff_usage set_ramp[sizeof(pidff_set_ramp)]; | ||
166 | |||
167 | struct pidff_usage device_gain[sizeof(pidff_device_gain)]; | ||
168 | struct pidff_usage block_load[sizeof(pidff_block_load)]; | ||
169 | struct pidff_usage pool[sizeof(pidff_pool)]; | ||
170 | struct pidff_usage effect_operation[sizeof(pidff_effect_operation)]; | ||
171 | struct pidff_usage block_free[sizeof(pidff_block_free)]; | ||
172 | |||
173 | /* Special field is a field that is not composed of | ||
174 | usage<->value pairs that pidff_usage values are */ | ||
175 | |||
176 | /* Special field in create_new_effect */ | ||
177 | struct hid_field *create_new_effect_type; | ||
178 | |||
179 | /* Special fields in set_effect */ | ||
180 | struct hid_field *set_effect_type; | ||
181 | struct hid_field *effect_direction; | ||
182 | |||
183 | /* Special field in device_control */ | ||
184 | struct hid_field *device_control; | ||
185 | |||
186 | /* Special field in block_load */ | ||
187 | struct hid_field *block_load_status; | ||
188 | |||
189 | /* Special field in effect_operation */ | ||
190 | struct hid_field *effect_operation_status; | ||
191 | |||
192 | int control_id[sizeof(pidff_device_control)]; | ||
193 | int type_id[sizeof(pidff_effect_types)]; | ||
194 | int status_id[sizeof(pidff_block_load_status)]; | ||
195 | int operation_id[sizeof(pidff_effect_operation_status)]; | ||
196 | |||
197 | int pid_id[PID_EFFECTS_MAX]; | ||
198 | }; | ||
199 | |||
200 | /* | ||
201 | * Scale an unsigned value with range 0..max for the given field | ||
202 | */ | ||
203 | static int pidff_rescale(int i, int max, struct hid_field *field) | ||
204 | { | ||
205 | return i * (field->logical_maximum - field->logical_minimum) / max + | ||
206 | field->logical_minimum; | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | * Scale a signed value in range -0x8000..0x7fff for the given field | ||
211 | */ | ||
212 | static int pidff_rescale_signed(int i, struct hid_field *field) | ||
213 | { | ||
214 | return i == 0 ? 0 : i > | ||
215 | 0 ? i * field->logical_maximum / 0x7fff : i * | ||
216 | field->logical_minimum / -0x8000; | ||
217 | } | ||
218 | |||
219 | static void pidff_set(struct pidff_usage *usage, u16 value) | ||
220 | { | ||
221 | usage->value[0] = pidff_rescale(value, 0xffff, usage->field); | ||
222 | debug("calculated from %d to %d", value, usage->value[0]); | ||
223 | } | ||
224 | |||
225 | static void pidff_set_signed(struct pidff_usage *usage, s16 value) | ||
226 | { | ||
227 | if (usage->field->logical_minimum < 0) | ||
228 | usage->value[0] = pidff_rescale_signed(value, usage->field); | ||
229 | else { | ||
230 | if (value < 0) | ||
231 | usage->value[0] = | ||
232 | pidff_rescale(-value, 0x8000, usage->field); | ||
233 | else | ||
234 | usage->value[0] = | ||
235 | pidff_rescale(value, 0x7fff, usage->field); | ||
236 | } | ||
237 | debug("calculated from %d to %d", value, usage->value[0]); | ||
238 | } | ||
239 | |||
240 | /* | ||
241 | * Send envelope report to the device | ||
242 | */ | ||
243 | static void pidff_set_envelope_report(struct pidff_device *pidff, | ||
244 | struct ff_envelope *envelope) | ||
245 | { | ||
246 | pidff->set_envelope[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
247 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
248 | |||
249 | pidff->set_envelope[PID_ATTACK_LEVEL].value[0] = | ||
250 | pidff_rescale(envelope->attack_level > | ||
251 | 0x7fff ? 0x7fff : envelope->attack_level, 0x7fff, | ||
252 | pidff->set_envelope[PID_ATTACK_LEVEL].field); | ||
253 | pidff->set_envelope[PID_FADE_LEVEL].value[0] = | ||
254 | pidff_rescale(envelope->fade_level > | ||
255 | 0x7fff ? 0x7fff : envelope->fade_level, 0x7fff, | ||
256 | pidff->set_envelope[PID_FADE_LEVEL].field); | ||
257 | |||
258 | pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length; | ||
259 | pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length; | ||
260 | |||
261 | debug("attack %u => %d", envelope->attack_level, | ||
262 | pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); | ||
263 | |||
264 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE], | ||
265 | USB_DIR_OUT); | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | * Test if the new envelope differs from old one | ||
270 | */ | ||
271 | static int pidff_needs_set_envelope(struct ff_envelope *envelope, | ||
272 | struct ff_envelope *old) | ||
273 | { | ||
274 | return envelope->attack_level != old->attack_level || | ||
275 | envelope->fade_level != old->fade_level || | ||
276 | envelope->attack_length != old->attack_length || | ||
277 | envelope->fade_length != old->fade_length; | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * Send constant force report to the device | ||
282 | */ | ||
283 | static void pidff_set_constant_force_report(struct pidff_device *pidff, | ||
284 | struct ff_effect *effect) | ||
285 | { | ||
286 | pidff->set_constant[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
287 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
288 | pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE], | ||
289 | effect->u.constant.level); | ||
290 | |||
291 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT], | ||
292 | USB_DIR_OUT); | ||
293 | } | ||
294 | |||
295 | /* | ||
296 | * Test if the constant parameters have changed between effects | ||
297 | */ | ||
298 | static int pidff_needs_set_constant(struct ff_effect *effect, | ||
299 | struct ff_effect *old) | ||
300 | { | ||
301 | return effect->u.constant.level != old->u.constant.level; | ||
302 | } | ||
303 | |||
304 | /* | ||
305 | * Send set effect report to the device | ||
306 | */ | ||
307 | static void pidff_set_effect_report(struct pidff_device *pidff, | ||
308 | struct ff_effect *effect) | ||
309 | { | ||
310 | pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
311 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
312 | pidff->set_effect_type->value[0] = | ||
313 | pidff->create_new_effect_type->value[0]; | ||
314 | pidff->set_effect[PID_DURATION].value[0] = effect->replay.length; | ||
315 | pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button; | ||
316 | pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = | ||
317 | effect->trigger.interval; | ||
318 | pidff->set_effect[PID_GAIN].value[0] = | ||
319 | pidff->set_effect[PID_GAIN].field->logical_maximum; | ||
320 | pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1; | ||
321 | pidff->effect_direction->value[0] = | ||
322 | pidff_rescale(effect->direction, 0xffff, | ||
323 | pidff->effect_direction); | ||
324 | pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay; | ||
325 | |||
326 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], | ||
327 | USB_DIR_OUT); | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * Test if the values used in set_effect have changed | ||
332 | */ | ||
333 | static int pidff_needs_set_effect(struct ff_effect *effect, | ||
334 | struct ff_effect *old) | ||
335 | { | ||
336 | return effect->replay.length != old->replay.length || | ||
337 | effect->trigger.interval != old->trigger.interval || | ||
338 | effect->trigger.button != old->trigger.button || | ||
339 | effect->direction != old->direction || | ||
340 | effect->replay.delay != old->replay.delay; | ||
341 | } | ||
342 | |||
343 | /* | ||
344 | * Send periodic effect report to the device | ||
345 | */ | ||
346 | static void pidff_set_periodic_report(struct pidff_device *pidff, | ||
347 | struct ff_effect *effect) | ||
348 | { | ||
349 | pidff->set_periodic[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
350 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
351 | pidff_set_signed(&pidff->set_periodic[PID_MAGNITUDE], | ||
352 | effect->u.periodic.magnitude); | ||
353 | pidff_set_signed(&pidff->set_periodic[PID_OFFSET], | ||
354 | effect->u.periodic.offset); | ||
355 | pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase); | ||
356 | pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period; | ||
357 | |||
358 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC], | ||
359 | USB_DIR_OUT); | ||
360 | |||
361 | } | ||
362 | |||
363 | /* | ||
364 | * Test if periodic effect parameters have changed | ||
365 | */ | ||
366 | static int pidff_needs_set_periodic(struct ff_effect *effect, | ||
367 | struct ff_effect *old) | ||
368 | { | ||
369 | return effect->u.periodic.magnitude != old->u.periodic.magnitude || | ||
370 | effect->u.periodic.offset != old->u.periodic.offset || | ||
371 | effect->u.periodic.phase != old->u.periodic.phase || | ||
372 | effect->u.periodic.period != old->u.periodic.period; | ||
373 | } | ||
374 | |||
375 | /* | ||
376 | * Send condition effect reports to the device | ||
377 | */ | ||
378 | static void pidff_set_condition_report(struct pidff_device *pidff, | ||
379 | struct ff_effect *effect) | ||
380 | { | ||
381 | int i; | ||
382 | |||
383 | pidff->set_condition[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
384 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
385 | |||
386 | for (i = 0; i < 2; i++) { | ||
387 | pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i; | ||
388 | pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET], | ||
389 | effect->u.condition[i].center); | ||
390 | pidff_set_signed(&pidff->set_condition[PID_POS_COEFFICIENT], | ||
391 | effect->u.condition[i].right_coeff); | ||
392 | pidff_set_signed(&pidff->set_condition[PID_NEG_COEFFICIENT], | ||
393 | effect->u.condition[i].left_coeff); | ||
394 | pidff_set(&pidff->set_condition[PID_POS_SATURATION], | ||
395 | effect->u.condition[i].right_saturation); | ||
396 | pidff_set(&pidff->set_condition[PID_NEG_SATURATION], | ||
397 | effect->u.condition[i].left_saturation); | ||
398 | pidff_set(&pidff->set_condition[PID_DEAD_BAND], | ||
399 | effect->u.condition[i].deadband); | ||
400 | usbhid_wait_io(pidff->hid); | ||
401 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION], | ||
402 | USB_DIR_OUT); | ||
403 | } | ||
404 | } | ||
405 | |||
406 | /* | ||
407 | * Test if condition effect parameters have changed | ||
408 | */ | ||
409 | static int pidff_needs_set_condition(struct ff_effect *effect, | ||
410 | struct ff_effect *old) | ||
411 | { | ||
412 | int i; | ||
413 | int ret = 0; | ||
414 | |||
415 | for (i = 0; i < 2; i++) { | ||
416 | struct ff_condition_effect *cond = &effect->u.condition[i]; | ||
417 | struct ff_condition_effect *old_cond = &old->u.condition[i]; | ||
418 | |||
419 | ret |= cond->center != old_cond->center || | ||
420 | cond->right_coeff != old_cond->right_coeff || | ||
421 | cond->left_coeff != old_cond->left_coeff || | ||
422 | cond->right_saturation != old_cond->right_saturation || | ||
423 | cond->left_saturation != old_cond->left_saturation || | ||
424 | cond->deadband != old_cond->deadband; | ||
425 | } | ||
426 | |||
427 | return ret; | ||
428 | } | ||
429 | |||
430 | /* | ||
431 | * Send ramp force report to the device | ||
432 | */ | ||
433 | static void pidff_set_ramp_force_report(struct pidff_device *pidff, | ||
434 | struct ff_effect *effect) | ||
435 | { | ||
436 | pidff->set_ramp[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
437 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
438 | pidff_set_signed(&pidff->set_ramp[PID_RAMP_START], | ||
439 | effect->u.ramp.start_level); | ||
440 | pidff_set_signed(&pidff->set_ramp[PID_RAMP_END], | ||
441 | effect->u.ramp.end_level); | ||
442 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP], | ||
443 | USB_DIR_OUT); | ||
444 | } | ||
445 | |||
446 | /* | ||
447 | * Test if ramp force parameters have changed | ||
448 | */ | ||
449 | static int pidff_needs_set_ramp(struct ff_effect *effect, struct ff_effect *old) | ||
450 | { | ||
451 | return effect->u.ramp.start_level != old->u.ramp.start_level || | ||
452 | effect->u.ramp.end_level != old->u.ramp.end_level; | ||
453 | } | ||
454 | |||
455 | /* | ||
456 | * Send a request for effect upload to the device | ||
457 | * | ||
458 | * Returns 0 if device reported success, -ENOSPC if the device reported memory | ||
459 | * is full. Upon unknown response the function will retry for 60 times, if | ||
460 | * still unsuccessful -EIO is returned. | ||
461 | */ | ||
462 | static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) | ||
463 | { | ||
464 | int j; | ||
465 | |||
466 | pidff->create_new_effect_type->value[0] = efnum; | ||
467 | usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], | ||
468 | USB_DIR_OUT); | ||
469 | debug("create_new_effect sent, type: %d", efnum); | ||
470 | |||
471 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0; | ||
472 | pidff->block_load_status->value[0] = 0; | ||
473 | usbhid_wait_io(pidff->hid); | ||
474 | |||
475 | for (j = 0; j < 60; j++) { | ||
476 | debug("pid_block_load requested"); | ||
477 | usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD], | ||
478 | USB_DIR_IN); | ||
479 | usbhid_wait_io(pidff->hid); | ||
480 | if (pidff->block_load_status->value[0] == | ||
481 | pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) { | ||
482 | debug("device reported free memory: %d bytes", | ||
483 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? | ||
484 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); | ||
485 | return 0; | ||
486 | } | ||
487 | if (pidff->block_load_status->value[0] == | ||
488 | pidff->status_id[PID_BLOCK_LOAD_FULL]) { | ||
489 | debug("not enough memory free: %d bytes", | ||
490 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? | ||
491 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); | ||
492 | return -ENOSPC; | ||
493 | } | ||
494 | } | ||
495 | printk(KERN_ERR "hid-pidff: pid_block_load failed 60 times\n"); | ||
496 | return -EIO; | ||
497 | } | ||
498 | |||
499 | /* | ||
500 | * Play the effect with PID id n times | ||
501 | */ | ||
502 | static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n) | ||
503 | { | ||
504 | pidff->effect_operation[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; | ||
505 | |||
506 | if (n == 0) { | ||
507 | pidff->effect_operation_status->value[0] = | ||
508 | pidff->operation_id[PID_EFFECT_STOP]; | ||
509 | } else { | ||
510 | pidff->effect_operation_status->value[0] = | ||
511 | pidff->operation_id[PID_EFFECT_START]; | ||
512 | pidff->effect_operation[PID_LOOP_COUNT].value[0] = n; | ||
513 | } | ||
514 | |||
515 | usbhid_wait_io(pidff->hid); | ||
516 | usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION], | ||
517 | USB_DIR_OUT); | ||
518 | } | ||
519 | |||
520 | /** | ||
521 | * Play the effect with effect id @effect_id for @value times | ||
522 | */ | ||
523 | static int pidff_playback(struct input_dev *dev, int effect_id, int value) | ||
524 | { | ||
525 | struct pidff_device *pidff = dev->ff->private; | ||
526 | |||
527 | pidff_playback_pid(pidff, pidff->pid_id[effect_id], value); | ||
528 | |||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | /* | ||
533 | * Erase effect with PID id | ||
534 | */ | ||
535 | static void pidff_erase_pid(struct pidff_device *pidff, int pid_id) | ||
536 | { | ||
537 | pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; | ||
538 | usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE], | ||
539 | USB_DIR_OUT); | ||
540 | } | ||
541 | |||
542 | /* | ||
543 | * Stop and erase effect with effect_id | ||
544 | */ | ||
545 | static int pidff_erase_effect(struct input_dev *dev, int effect_id) | ||
546 | { | ||
547 | struct pidff_device *pidff = dev->ff->private; | ||
548 | int pid_id = pidff->pid_id[effect_id]; | ||
549 | |||
550 | debug("starting to erase %d/%d", effect_id, pidff->pid_id[effect_id]); | ||
551 | pidff_playback_pid(pidff, pid_id, 0); | ||
552 | pidff_erase_pid(pidff, pid_id); | ||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | /* | ||
558 | * Effect upload handler | ||
559 | */ | ||
560 | static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, | ||
561 | struct ff_effect *old) | ||
562 | { | ||
563 | struct pidff_device *pidff = dev->ff->private; | ||
564 | int type_id; | ||
565 | int error; | ||
566 | |||
567 | switch (effect->type) { | ||
568 | case FF_CONSTANT: | ||
569 | if (!old) { | ||
570 | error = pidff_request_effect_upload(pidff, | ||
571 | pidff->type_id[PID_CONSTANT]); | ||
572 | if (error) | ||
573 | return error; | ||
574 | } | ||
575 | if (!old || pidff_needs_set_effect(effect, old)) | ||
576 | pidff_set_effect_report(pidff, effect); | ||
577 | if (!old || pidff_needs_set_constant(effect, old)) | ||
578 | pidff_set_constant_force_report(pidff, effect); | ||
579 | if (!old || | ||
580 | pidff_needs_set_envelope(&effect->u.constant.envelope, | ||
581 | &old->u.constant.envelope)) | ||
582 | pidff_set_envelope_report(pidff, | ||
583 | &effect->u.constant.envelope); | ||
584 | break; | ||
585 | |||
586 | case FF_PERIODIC: | ||
587 | if (!old) { | ||
588 | switch (effect->u.periodic.waveform) { | ||
589 | case FF_SQUARE: | ||
590 | type_id = PID_SQUARE; | ||
591 | break; | ||
592 | case FF_TRIANGLE: | ||
593 | type_id = PID_TRIANGLE; | ||
594 | break; | ||
595 | case FF_SINE: | ||
596 | type_id = PID_SINE; | ||
597 | break; | ||
598 | case FF_SAW_UP: | ||
599 | type_id = PID_SAW_UP; | ||
600 | break; | ||
601 | case FF_SAW_DOWN: | ||
602 | type_id = PID_SAW_DOWN; | ||
603 | break; | ||
604 | default: | ||
605 | printk(KERN_ERR | ||
606 | "hid-pidff: invalid waveform\n"); | ||
607 | return -EINVAL; | ||
608 | } | ||
609 | |||
610 | error = pidff_request_effect_upload(pidff, | ||
611 | pidff->type_id[type_id]); | ||
612 | if (error) | ||
613 | return error; | ||
614 | } | ||
615 | if (!old || pidff_needs_set_effect(effect, old)) | ||
616 | pidff_set_effect_report(pidff, effect); | ||
617 | if (!old || pidff_needs_set_periodic(effect, old)) | ||
618 | pidff_set_periodic_report(pidff, effect); | ||
619 | if (!old || | ||
620 | pidff_needs_set_envelope(&effect->u.periodic.envelope, | ||
621 | &old->u.periodic.envelope)) | ||
622 | pidff_set_envelope_report(pidff, | ||
623 | &effect->u.periodic.envelope); | ||
624 | break; | ||
625 | |||
626 | case FF_RAMP: | ||
627 | if (!old) { | ||
628 | error = pidff_request_effect_upload(pidff, | ||
629 | pidff->type_id[PID_RAMP]); | ||
630 | if (error) | ||
631 | return error; | ||
632 | } | ||
633 | if (!old || pidff_needs_set_effect(effect, old)) | ||
634 | pidff_set_effect_report(pidff, effect); | ||
635 | if (!old || pidff_needs_set_ramp(effect, old)) | ||
636 | pidff_set_ramp_force_report(pidff, effect); | ||
637 | if (!old || | ||
638 | pidff_needs_set_envelope(&effect->u.ramp.envelope, | ||
639 | &old->u.ramp.envelope)) | ||
640 | pidff_set_envelope_report(pidff, | ||
641 | &effect->u.ramp.envelope); | ||
642 | break; | ||
643 | |||
644 | case FF_SPRING: | ||
645 | if (!old) { | ||
646 | error = pidff_request_effect_upload(pidff, | ||
647 | pidff->type_id[PID_SPRING]); | ||
648 | if (error) | ||
649 | return error; | ||
650 | } | ||
651 | if (!old || pidff_needs_set_effect(effect, old)) | ||
652 | pidff_set_effect_report(pidff, effect); | ||
653 | if (!old || pidff_needs_set_condition(effect, old)) | ||
654 | pidff_set_condition_report(pidff, effect); | ||
655 | break; | ||
656 | |||
657 | case FF_FRICTION: | ||
658 | if (!old) { | ||
659 | error = pidff_request_effect_upload(pidff, | ||
660 | pidff->type_id[PID_FRICTION]); | ||
661 | if (error) | ||
662 | return error; | ||
663 | } | ||
664 | if (!old || pidff_needs_set_effect(effect, old)) | ||
665 | pidff_set_effect_report(pidff, effect); | ||
666 | if (!old || pidff_needs_set_condition(effect, old)) | ||
667 | pidff_set_condition_report(pidff, effect); | ||
668 | break; | ||
669 | |||
670 | case FF_DAMPER: | ||
671 | if (!old) { | ||
672 | error = pidff_request_effect_upload(pidff, | ||
673 | pidff->type_id[PID_DAMPER]); | ||
674 | if (error) | ||
675 | return error; | ||
676 | } | ||
677 | if (!old || pidff_needs_set_effect(effect, old)) | ||
678 | pidff_set_effect_report(pidff, effect); | ||
679 | if (!old || pidff_needs_set_condition(effect, old)) | ||
680 | pidff_set_condition_report(pidff, effect); | ||
681 | break; | ||
682 | |||
683 | case FF_INERTIA: | ||
684 | if (!old) { | ||
685 | error = pidff_request_effect_upload(pidff, | ||
686 | pidff->type_id[PID_INERTIA]); | ||
687 | if (error) | ||
688 | return error; | ||
689 | } | ||
690 | if (!old || pidff_needs_set_effect(effect, old)) | ||
691 | pidff_set_effect_report(pidff, effect); | ||
692 | if (!old || pidff_needs_set_condition(effect, old)) | ||
693 | pidff_set_condition_report(pidff, effect); | ||
694 | break; | ||
695 | |||
696 | default: | ||
697 | printk(KERN_ERR "hid-pidff: invalid type\n"); | ||
698 | return -EINVAL; | ||
699 | } | ||
700 | |||
701 | if (!old) | ||
702 | pidff->pid_id[effect->id] = | ||
703 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
704 | |||
705 | debug("uploaded"); | ||
706 | |||
707 | return 0; | ||
708 | } | ||
709 | |||
710 | /* | ||
711 | * set_gain() handler | ||
712 | */ | ||
713 | static void pidff_set_gain(struct input_dev *dev, u16 gain) | ||
714 | { | ||
715 | struct pidff_device *pidff = dev->ff->private; | ||
716 | |||
717 | pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain); | ||
718 | usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], | ||
719 | USB_DIR_OUT); | ||
720 | } | ||
721 | |||
722 | static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) | ||
723 | { | ||
724 | struct hid_field *field = | ||
725 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field; | ||
726 | |||
727 | if (!magnitude) { | ||
728 | pidff_playback_pid(pidff, field->logical_minimum, 0); | ||
729 | return; | ||
730 | } | ||
731 | |||
732 | pidff_playback_pid(pidff, field->logical_minimum, 1); | ||
733 | |||
734 | pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
735 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum; | ||
736 | pidff->set_effect_type->value[0] = pidff->type_id[PID_SPRING]; | ||
737 | pidff->set_effect[PID_DURATION].value[0] = 0; | ||
738 | pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0; | ||
739 | pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0; | ||
740 | pidff_set(&pidff->set_effect[PID_GAIN], magnitude); | ||
741 | pidff->set_effect[PID_START_DELAY].value[0] = 0; | ||
742 | |||
743 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], | ||
744 | USB_DIR_OUT); | ||
745 | } | ||
746 | |||
747 | /* | ||
748 | * pidff_set_autocenter() handler | ||
749 | */ | ||
750 | static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude) | ||
751 | { | ||
752 | struct pidff_device *pidff = dev->ff->private; | ||
753 | |||
754 | pidff_autocenter(pidff, magnitude); | ||
755 | } | ||
756 | |||
757 | /* | ||
758 | * Find fields from a report and fill a pidff_usage | ||
759 | */ | ||
760 | static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, | ||
761 | struct hid_report *report, int count, int strict) | ||
762 | { | ||
763 | int i, j, k, found; | ||
764 | |||
765 | for (k = 0; k < count; k++) { | ||
766 | found = 0; | ||
767 | for (i = 0; i < report->maxfield; i++) { | ||
768 | if (report->field[i]->maxusage != | ||
769 | report->field[i]->report_count) { | ||
770 | debug("maxusage and report_count do not match, " | ||
771 | "skipping"); | ||
772 | continue; | ||
773 | } | ||
774 | for (j = 0; j < report->field[i]->maxusage; j++) { | ||
775 | if (report->field[i]->usage[j].hid == | ||
776 | (HID_UP_PID | table[k])) { | ||
777 | debug("found %d at %d->%d", k, i, j); | ||
778 | usage[k].field = report->field[i]; | ||
779 | usage[k].value = | ||
780 | &report->field[i]->value[j]; | ||
781 | found = 1; | ||
782 | break; | ||
783 | } | ||
784 | } | ||
785 | if (found) | ||
786 | break; | ||
787 | } | ||
788 | if (!found && strict) { | ||
789 | debug("failed to locate %d", k); | ||
790 | return -1; | ||
791 | } | ||
792 | } | ||
793 | return 0; | ||
794 | } | ||
795 | |||
796 | /* | ||
797 | * Return index into pidff_reports for the given usage | ||
798 | */ | ||
799 | static int pidff_check_usage(int usage) | ||
800 | { | ||
801 | int i; | ||
802 | |||
803 | for (i = 0; i < sizeof(pidff_reports); i++) | ||
804 | if (usage == (HID_UP_PID | pidff_reports[i])) | ||
805 | return i; | ||
806 | |||
807 | return -1; | ||
808 | } | ||
809 | |||
810 | /* | ||
811 | * Find the reports and fill pidff->reports[] | ||
812 | * report_type specifies either OUTPUT or FEATURE reports | ||
813 | */ | ||
814 | static void pidff_find_reports(struct hid_device *hid, int report_type, | ||
815 | struct pidff_device *pidff) | ||
816 | { | ||
817 | struct hid_report *report; | ||
818 | int i, ret; | ||
819 | |||
820 | list_for_each_entry(report, | ||
821 | &hid->report_enum[report_type].report_list, list) { | ||
822 | if (report->maxfield < 1) | ||
823 | continue; | ||
824 | ret = pidff_check_usage(report->field[0]->logical); | ||
825 | if (ret != -1) { | ||
826 | debug("found usage 0x%02x from field->logical", | ||
827 | pidff_reports[ret]); | ||
828 | pidff->reports[ret] = report; | ||
829 | continue; | ||
830 | } | ||
831 | |||
832 | /* | ||
833 | * Sometimes logical collections are stacked to indicate | ||
834 | * different usages for the report and the field, in which | ||
835 | * case we want the usage of the parent. However, Linux HID | ||
836 | * implementation hides this fact, so we have to dig it up | ||
837 | * ourselves | ||
838 | */ | ||
839 | i = report->field[0]->usage[0].collection_index; | ||
840 | if (i <= 0 || | ||
841 | hid->collection[i - 1].type != HID_COLLECTION_LOGICAL) | ||
842 | continue; | ||
843 | ret = pidff_check_usage(hid->collection[i - 1].usage); | ||
844 | if (ret != -1 && !pidff->reports[ret]) { | ||
845 | debug("found usage 0x%02x from collection array", | ||
846 | pidff_reports[ret]); | ||
847 | pidff->reports[ret] = report; | ||
848 | } | ||
849 | } | ||
850 | } | ||
851 | |||
852 | /* | ||
853 | * Test if the required reports have been found | ||
854 | */ | ||
855 | static int pidff_reports_ok(struct pidff_device *pidff) | ||
856 | { | ||
857 | int i; | ||
858 | |||
859 | for (i = 0; i <= PID_REQUIRED_REPORTS; i++) { | ||
860 | if (!pidff->reports[i]) { | ||
861 | debug("%d missing", i); | ||
862 | return 0; | ||
863 | } | ||
864 | } | ||
865 | |||
866 | return 1; | ||
867 | } | ||
868 | |||
869 | /* | ||
870 | * Find a field with a specific usage within a report | ||
871 | */ | ||
872 | static struct hid_field *pidff_find_special_field(struct hid_report *report, | ||
873 | int usage, int enforce_min) | ||
874 | { | ||
875 | int i; | ||
876 | |||
877 | for (i = 0; i < report->maxfield; i++) { | ||
878 | if (report->field[i]->logical == (HID_UP_PID | usage) && | ||
879 | report->field[i]->report_count > 0) { | ||
880 | if (!enforce_min || | ||
881 | report->field[i]->logical_minimum == 1) | ||
882 | return report->field[i]; | ||
883 | else { | ||
884 | printk(KERN_ERR "hid-pidff: logical_minimum " | ||
885 | "is not 1 as it should be\n"); | ||
886 | return NULL; | ||
887 | } | ||
888 | } | ||
889 | } | ||
890 | return NULL; | ||
891 | } | ||
892 | |||
893 | /* | ||
894 | * Fill a pidff->*_id struct table | ||
895 | */ | ||
896 | static int pidff_find_special_keys(int *keys, struct hid_field *fld, | ||
897 | const u8 *usagetable, int count) | ||
898 | { | ||
899 | |||
900 | int i, j; | ||
901 | int found = 0; | ||
902 | |||
903 | for (i = 0; i < count; i++) { | ||
904 | for (j = 0; j < fld->maxusage; j++) { | ||
905 | if (fld->usage[j].hid == (HID_UP_PID | usagetable[i])) { | ||
906 | keys[i] = j + 1; | ||
907 | found++; | ||
908 | break; | ||
909 | } | ||
910 | } | ||
911 | } | ||
912 | return found; | ||
913 | } | ||
914 | |||
915 | #define PIDFF_FIND_SPECIAL_KEYS(keys, field, name) \ | ||
916 | pidff_find_special_keys(pidff->keys, pidff->field, pidff_ ## name, \ | ||
917 | sizeof(pidff_ ## name)) | ||
918 | |||
919 | /* | ||
920 | * Find and check the special fields | ||
921 | */ | ||
922 | static int pidff_find_special_fields(struct pidff_device *pidff) | ||
923 | { | ||
924 | debug("finding special fields"); | ||
925 | |||
926 | pidff->create_new_effect_type = | ||
927 | pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT], | ||
928 | 0x25, 1); | ||
929 | pidff->set_effect_type = | ||
930 | pidff_find_special_field(pidff->reports[PID_SET_EFFECT], | ||
931 | 0x25, 1); | ||
932 | pidff->effect_direction = | ||
933 | pidff_find_special_field(pidff->reports[PID_SET_EFFECT], | ||
934 | 0x57, 0); | ||
935 | pidff->device_control = | ||
936 | pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL], | ||
937 | 0x96, 1); | ||
938 | pidff->block_load_status = | ||
939 | pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD], | ||
940 | 0x8b, 1); | ||
941 | pidff->effect_operation_status = | ||
942 | pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION], | ||
943 | 0x78, 1); | ||
944 | |||
945 | debug("search done"); | ||
946 | |||
947 | if (!pidff->create_new_effect_type || !pidff->set_effect_type) { | ||
948 | printk(KERN_ERR "hid-pidff: effect lists not found\n"); | ||
949 | return -1; | ||
950 | } | ||
951 | |||
952 | if (!pidff->effect_direction) { | ||
953 | printk(KERN_ERR "hid-pidff: direction field not found\n"); | ||
954 | return -1; | ||
955 | } | ||
956 | |||
957 | if (!pidff->device_control) { | ||
958 | printk(KERN_ERR "hid-pidff: device control field not found\n"); | ||
959 | return -1; | ||
960 | } | ||
961 | |||
962 | if (!pidff->block_load_status) { | ||
963 | printk(KERN_ERR | ||
964 | "hid-pidff: block load status field not found\n"); | ||
965 | return -1; | ||
966 | } | ||
967 | |||
968 | if (!pidff->effect_operation_status) { | ||
969 | printk(KERN_ERR | ||
970 | "hid-pidff: effect operation field not found\n"); | ||
971 | return -1; | ||
972 | } | ||
973 | |||
974 | pidff_find_special_keys(pidff->control_id, pidff->device_control, | ||
975 | pidff_device_control, | ||
976 | sizeof(pidff_device_control)); | ||
977 | |||
978 | PIDFF_FIND_SPECIAL_KEYS(control_id, device_control, device_control); | ||
979 | |||
980 | if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type, | ||
981 | effect_types)) { | ||
982 | printk(KERN_ERR "hid-pidff: no effect types found\n"); | ||
983 | return -1; | ||
984 | } | ||
985 | |||
986 | if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status, | ||
987 | block_load_status) != | ||
988 | sizeof(pidff_block_load_status)) { | ||
989 | printk(KERN_ERR | ||
990 | "hidpidff: block load status identifiers not found\n"); | ||
991 | return -1; | ||
992 | } | ||
993 | |||
994 | if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status, | ||
995 | effect_operation_status) != | ||
996 | sizeof(pidff_effect_operation_status)) { | ||
997 | printk(KERN_ERR | ||
998 | "hidpidff: effect operation identifiers not found\n"); | ||
999 | return -1; | ||
1000 | } | ||
1001 | |||
1002 | return 0; | ||
1003 | } | ||
1004 | |||
1005 | /** | ||
1006 | * Find the implemented effect types | ||
1007 | */ | ||
1008 | static int pidff_find_effects(struct pidff_device *pidff, | ||
1009 | struct input_dev *dev) | ||
1010 | { | ||
1011 | int i; | ||
1012 | |||
1013 | for (i = 0; i < sizeof(pidff_effect_types); i++) { | ||
1014 | int pidff_type = pidff->type_id[i]; | ||
1015 | if (pidff->set_effect_type->usage[pidff_type].hid != | ||
1016 | pidff->create_new_effect_type->usage[pidff_type].hid) { | ||
1017 | printk(KERN_ERR "hid-pidff: " | ||
1018 | "effect type number %d is invalid\n", i); | ||
1019 | return -1; | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | if (pidff->type_id[PID_CONSTANT]) | ||
1024 | set_bit(FF_CONSTANT, dev->ffbit); | ||
1025 | if (pidff->type_id[PID_RAMP]) | ||
1026 | set_bit(FF_RAMP, dev->ffbit); | ||
1027 | if (pidff->type_id[PID_SQUARE]) { | ||
1028 | set_bit(FF_SQUARE, dev->ffbit); | ||
1029 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1030 | } | ||
1031 | if (pidff->type_id[PID_SINE]) { | ||
1032 | set_bit(FF_SINE, dev->ffbit); | ||
1033 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1034 | } | ||
1035 | if (pidff->type_id[PID_TRIANGLE]) { | ||
1036 | set_bit(FF_TRIANGLE, dev->ffbit); | ||
1037 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1038 | } | ||
1039 | if (pidff->type_id[PID_SAW_UP]) { | ||
1040 | set_bit(FF_SAW_UP, dev->ffbit); | ||
1041 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1042 | } | ||
1043 | if (pidff->type_id[PID_SAW_DOWN]) { | ||
1044 | set_bit(FF_SAW_DOWN, dev->ffbit); | ||
1045 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1046 | } | ||
1047 | if (pidff->type_id[PID_SPRING]) | ||
1048 | set_bit(FF_SPRING, dev->ffbit); | ||
1049 | if (pidff->type_id[PID_DAMPER]) | ||
1050 | set_bit(FF_DAMPER, dev->ffbit); | ||
1051 | if (pidff->type_id[PID_INERTIA]) | ||
1052 | set_bit(FF_INERTIA, dev->ffbit); | ||
1053 | if (pidff->type_id[PID_FRICTION]) | ||
1054 | set_bit(FF_FRICTION, dev->ffbit); | ||
1055 | |||
1056 | return 0; | ||
1057 | |||
1058 | } | ||
1059 | |||
1060 | #define PIDFF_FIND_FIELDS(name, report, strict) \ | ||
1061 | pidff_find_fields(pidff->name, pidff_ ## name, \ | ||
1062 | pidff->reports[report], \ | ||
1063 | sizeof(pidff_ ## name), strict) | ||
1064 | |||
1065 | /* | ||
1066 | * Fill and check the pidff_usages | ||
1067 | */ | ||
1068 | static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) | ||
1069 | { | ||
1070 | int envelope_ok = 0; | ||
1071 | |||
1072 | if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) { | ||
1073 | printk(KERN_ERR | ||
1074 | "hid-pidff: unknown set_effect report layout\n"); | ||
1075 | return -ENODEV; | ||
1076 | } | ||
1077 | |||
1078 | PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0); | ||
1079 | if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) { | ||
1080 | printk(KERN_ERR | ||
1081 | "hid-pidff: unknown pid_block_load report layout\n"); | ||
1082 | return -ENODEV; | ||
1083 | } | ||
1084 | |||
1085 | if (PIDFF_FIND_FIELDS(effect_operation, PID_EFFECT_OPERATION, 1)) { | ||
1086 | printk(KERN_ERR | ||
1087 | "hid-pidff: unknown effect_operation report layout\n"); | ||
1088 | return -ENODEV; | ||
1089 | } | ||
1090 | |||
1091 | if (PIDFF_FIND_FIELDS(block_free, PID_BLOCK_FREE, 1)) { | ||
1092 | printk(KERN_ERR | ||
1093 | "hid-pidff: unknown pid_block_free report layout\n"); | ||
1094 | return -ENODEV; | ||
1095 | } | ||
1096 | |||
1097 | if (!PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1)) | ||
1098 | envelope_ok = 1; | ||
1099 | |||
1100 | if (pidff_find_special_fields(pidff) || pidff_find_effects(pidff, dev)) | ||
1101 | return -ENODEV; | ||
1102 | |||
1103 | if (!envelope_ok) { | ||
1104 | if (test_and_clear_bit(FF_CONSTANT, dev->ffbit)) | ||
1105 | printk(KERN_WARNING "hid-pidff: " | ||
1106 | "has constant effect but no envelope\n"); | ||
1107 | if (test_and_clear_bit(FF_RAMP, dev->ffbit)) | ||
1108 | printk(KERN_WARNING "hid-pidff: " | ||
1109 | "has ramp effect but no envelope\n"); | ||
1110 | |||
1111 | if (test_and_clear_bit(FF_PERIODIC, dev->ffbit)) | ||
1112 | printk(KERN_WARNING "hid-pidff: " | ||
1113 | "has periodic effect but no envelope\n"); | ||
1114 | } | ||
1115 | |||
1116 | if (test_bit(FF_CONSTANT, dev->ffbit) && | ||
1117 | PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) { | ||
1118 | printk(KERN_WARNING | ||
1119 | "hid-pidff: unknown constant effect layout\n"); | ||
1120 | clear_bit(FF_CONSTANT, dev->ffbit); | ||
1121 | } | ||
1122 | |||
1123 | if (test_bit(FF_RAMP, dev->ffbit) && | ||
1124 | PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) { | ||
1125 | printk(KERN_WARNING "hid-pidff: unknown ramp effect layout\n"); | ||
1126 | clear_bit(FF_RAMP, dev->ffbit); | ||
1127 | } | ||
1128 | |||
1129 | if ((test_bit(FF_SPRING, dev->ffbit) || | ||
1130 | test_bit(FF_DAMPER, dev->ffbit) || | ||
1131 | test_bit(FF_FRICTION, dev->ffbit) || | ||
1132 | test_bit(FF_INERTIA, dev->ffbit)) && | ||
1133 | PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) { | ||
1134 | printk(KERN_WARNING | ||
1135 | "hid-pidff: unknown condition effect layout\n"); | ||
1136 | clear_bit(FF_SPRING, dev->ffbit); | ||
1137 | clear_bit(FF_DAMPER, dev->ffbit); | ||
1138 | clear_bit(FF_FRICTION, dev->ffbit); | ||
1139 | clear_bit(FF_INERTIA, dev->ffbit); | ||
1140 | } | ||
1141 | |||
1142 | if (test_bit(FF_PERIODIC, dev->ffbit) && | ||
1143 | PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) { | ||
1144 | printk(KERN_WARNING | ||
1145 | "hid-pidff: unknown periodic effect layout\n"); | ||
1146 | clear_bit(FF_PERIODIC, dev->ffbit); | ||
1147 | } | ||
1148 | |||
1149 | PIDFF_FIND_FIELDS(pool, PID_POOL, 0); | ||
1150 | |||
1151 | if (!PIDFF_FIND_FIELDS(device_gain, PID_DEVICE_GAIN, 1)) | ||
1152 | set_bit(FF_GAIN, dev->ffbit); | ||
1153 | |||
1154 | return 0; | ||
1155 | } | ||
1156 | |||
1157 | /* | ||
1158 | * Reset the device | ||
1159 | */ | ||
1160 | static void pidff_reset(struct pidff_device *pidff) | ||
1161 | { | ||
1162 | struct hid_device *hid = pidff->hid; | ||
1163 | int i = 0; | ||
1164 | |||
1165 | pidff->device_control->value[0] = pidff->control_id[PID_RESET]; | ||
1166 | /* We reset twice as sometimes hid_wait_io isn't waiting long enough */ | ||
1167 | usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | ||
1168 | usbhid_wait_io(hid); | ||
1169 | usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | ||
1170 | usbhid_wait_io(hid); | ||
1171 | |||
1172 | pidff->device_control->value[0] = | ||
1173 | pidff->control_id[PID_ENABLE_ACTUATORS]; | ||
1174 | usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | ||
1175 | usbhid_wait_io(hid); | ||
1176 | |||
1177 | /* pool report is sometimes messed up, refetch it */ | ||
1178 | usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN); | ||
1179 | usbhid_wait_io(hid); | ||
1180 | |||
1181 | if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { | ||
1182 | int sim_effects = pidff->pool[PID_SIMULTANEOUS_MAX].value[0]; | ||
1183 | while (sim_effects < 2) { | ||
1184 | if (i++ > 20) { | ||
1185 | printk(KERN_WARNING "hid-pidff: device reports " | ||
1186 | "%d simultaneous effects\n", | ||
1187 | sim_effects); | ||
1188 | break; | ||
1189 | } | ||
1190 | debug("pid_pool requested again"); | ||
1191 | usbhid_submit_report(hid, pidff->reports[PID_POOL], | ||
1192 | USB_DIR_IN); | ||
1193 | usbhid_wait_io(hid); | ||
1194 | } | ||
1195 | } | ||
1196 | } | ||
1197 | |||
1198 | /* | ||
1199 | * Test if autocenter modification is using the supported method | ||
1200 | */ | ||
1201 | static int pidff_check_autocenter(struct pidff_device *pidff, | ||
1202 | struct input_dev *dev) | ||
1203 | { | ||
1204 | int error; | ||
1205 | |||
1206 | /* | ||
1207 | * Let's find out if autocenter modification is supported | ||
1208 | * Specification doesn't specify anything, so we request an | ||
1209 | * effect upload and cancel it immediately. If the approved | ||
1210 | * effect id was one above the minimum, then we assume the first | ||
1211 | * effect id is a built-in spring type effect used for autocenter | ||
1212 | */ | ||
1213 | |||
1214 | error = pidff_request_effect_upload(pidff, 1); | ||
1215 | if (error) { | ||
1216 | printk(KERN_ERR "hid-pidff: upload request failed\n"); | ||
1217 | return error; | ||
1218 | } | ||
1219 | |||
1220 | if (pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] == | ||
1221 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + 1) { | ||
1222 | pidff_autocenter(pidff, 0xffff); | ||
1223 | set_bit(FF_AUTOCENTER, dev->ffbit); | ||
1224 | } else { | ||
1225 | printk(KERN_NOTICE "hid-pidff: " | ||
1226 | "device has unknown autocenter control method\n"); | ||
1227 | } | ||
1228 | |||
1229 | pidff_erase_pid(pidff, | ||
1230 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]); | ||
1231 | |||
1232 | return 0; | ||
1233 | |||
1234 | } | ||
1235 | |||
1236 | /* | ||
1237 | * Check if the device is PID and initialize it | ||
1238 | */ | ||
1239 | int hid_pidff_init(struct hid_device *hid) | ||
1240 | { | ||
1241 | struct pidff_device *pidff; | ||
1242 | struct hid_input *hidinput = list_entry(hid->inputs.next, | ||
1243 | struct hid_input, list); | ||
1244 | struct input_dev *dev = hidinput->input; | ||
1245 | struct ff_device *ff; | ||
1246 | int max_effects; | ||
1247 | int error; | ||
1248 | |||
1249 | debug("starting pid init"); | ||
1250 | |||
1251 | if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) { | ||
1252 | debug("not a PID device, no output report"); | ||
1253 | return -ENODEV; | ||
1254 | } | ||
1255 | |||
1256 | pidff = kzalloc(sizeof(*pidff), GFP_KERNEL); | ||
1257 | if (!pidff) | ||
1258 | return -ENOMEM; | ||
1259 | |||
1260 | pidff->hid = hid; | ||
1261 | |||
1262 | pidff_find_reports(hid, HID_OUTPUT_REPORT, pidff); | ||
1263 | pidff_find_reports(hid, HID_FEATURE_REPORT, pidff); | ||
1264 | |||
1265 | if (!pidff_reports_ok(pidff)) { | ||
1266 | debug("reports not ok, aborting"); | ||
1267 | error = -ENODEV; | ||
1268 | goto fail; | ||
1269 | } | ||
1270 | |||
1271 | error = pidff_init_fields(pidff, dev); | ||
1272 | if (error) | ||
1273 | goto fail; | ||
1274 | |||
1275 | pidff_reset(pidff); | ||
1276 | |||
1277 | if (test_bit(FF_GAIN, dev->ffbit)) { | ||
1278 | pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); | ||
1279 | usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], | ||
1280 | USB_DIR_OUT); | ||
1281 | } | ||
1282 | |||
1283 | error = pidff_check_autocenter(pidff, dev); | ||
1284 | if (error) | ||
1285 | goto fail; | ||
1286 | |||
1287 | max_effects = | ||
1288 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_maximum - | ||
1289 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + | ||
1290 | 1; | ||
1291 | debug("max effects is %d", max_effects); | ||
1292 | |||
1293 | if (max_effects > PID_EFFECTS_MAX) | ||
1294 | max_effects = PID_EFFECTS_MAX; | ||
1295 | |||
1296 | if (pidff->pool[PID_SIMULTANEOUS_MAX].value) | ||
1297 | debug("max simultaneous effects is %d", | ||
1298 | pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); | ||
1299 | |||
1300 | if (pidff->pool[PID_RAM_POOL_SIZE].value) | ||
1301 | debug("device memory size is %d bytes", | ||
1302 | pidff->pool[PID_RAM_POOL_SIZE].value[0]); | ||
1303 | |||
1304 | if (pidff->pool[PID_DEVICE_MANAGED_POOL].value && | ||
1305 | pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) { | ||
1306 | printk(KERN_NOTICE "hid-pidff: " | ||
1307 | "device does not support device managed pool\n"); | ||
1308 | goto fail; | ||
1309 | } | ||
1310 | |||
1311 | error = input_ff_create(dev, max_effects); | ||
1312 | if (error) | ||
1313 | goto fail; | ||
1314 | |||
1315 | ff = dev->ff; | ||
1316 | ff->private = pidff; | ||
1317 | ff->upload = pidff_upload_effect; | ||
1318 | ff->erase = pidff_erase_effect; | ||
1319 | ff->set_gain = pidff_set_gain; | ||
1320 | ff->set_autocenter = pidff_set_autocenter; | ||
1321 | ff->playback = pidff_playback; | ||
1322 | |||
1323 | printk(KERN_INFO "Force feedback for USB HID PID devices by " | ||
1324 | "Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
1325 | |||
1326 | return 0; | ||
1327 | |||
1328 | fail: | ||
1329 | kfree(pidff); | ||
1330 | return error; | ||
1331 | } | ||
diff --git a/drivers/hid/usbhid/hid-plff.c b/drivers/hid/usbhid/hid-plff.c new file mode 100644 index 000000000000..76d2e6e14db4 --- /dev/null +++ b/drivers/hid/usbhid/hid-plff.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Force feedback support for PantherLord USB/PS2 2in1 Adapter devices | ||
3 | * | ||
4 | * Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com> | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | |||
24 | /* #define DEBUG */ | ||
25 | |||
26 | #define debug(format, arg...) pr_debug("hid-plff: " format "\n" , ## arg) | ||
27 | |||
28 | #include <linux/input.h> | ||
29 | #include <linux/usb.h> | ||
30 | #include <linux/hid.h> | ||
31 | #include "usbhid.h" | ||
32 | |||
33 | struct plff_device { | ||
34 | struct hid_report *report; | ||
35 | }; | ||
36 | |||
37 | static int hid_plff_play(struct input_dev *dev, void *data, | ||
38 | struct ff_effect *effect) | ||
39 | { | ||
40 | struct hid_device *hid = dev->private; | ||
41 | struct plff_device *plff = data; | ||
42 | int left, right; | ||
43 | |||
44 | left = effect->u.rumble.strong_magnitude; | ||
45 | right = effect->u.rumble.weak_magnitude; | ||
46 | debug("called with 0x%04x 0x%04x", left, right); | ||
47 | |||
48 | left = left * 0x7f / 0xffff; | ||
49 | right = right * 0x7f / 0xffff; | ||
50 | |||
51 | plff->report->field[0]->value[2] = left; | ||
52 | plff->report->field[0]->value[3] = right; | ||
53 | debug("running with 0x%02x 0x%02x", left, right); | ||
54 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | int hid_plff_init(struct hid_device *hid) | ||
60 | { | ||
61 | struct plff_device *plff; | ||
62 | struct hid_report *report; | ||
63 | struct hid_input *hidinput; | ||
64 | struct list_head *report_list = | ||
65 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
66 | struct list_head *report_ptr = report_list; | ||
67 | struct input_dev *dev; | ||
68 | int error; | ||
69 | |||
70 | /* The device contains 2 output reports (one for each | ||
71 | HID_QUIRK_MULTI_INPUT device), both containing 1 field, which | ||
72 | contains 4 ff00.0002 usages and 4 16bit absolute values. | ||
73 | |||
74 | The 2 input reports also contain a field which contains | ||
75 | 8 ff00.0001 usages and 8 boolean values. Their meaning is | ||
76 | currently unknown. */ | ||
77 | |||
78 | if (list_empty(report_list)) { | ||
79 | printk(KERN_ERR "hid-plff: no output reports found\n"); | ||
80 | return -ENODEV; | ||
81 | } | ||
82 | |||
83 | list_for_each_entry(hidinput, &hid->inputs, list) { | ||
84 | |||
85 | report_ptr = report_ptr->next; | ||
86 | |||
87 | if (report_ptr == report_list) { | ||
88 | printk(KERN_ERR "hid-plff: required output report is missing\n"); | ||
89 | return -ENODEV; | ||
90 | } | ||
91 | |||
92 | report = list_entry(report_ptr, struct hid_report, list); | ||
93 | if (report->maxfield < 1) { | ||
94 | printk(KERN_ERR "hid-plff: no fields in the report\n"); | ||
95 | return -ENODEV; | ||
96 | } | ||
97 | |||
98 | if (report->field[0]->report_count < 4) { | ||
99 | printk(KERN_ERR "hid-plff: not enough values in the field\n"); | ||
100 | return -ENODEV; | ||
101 | } | ||
102 | |||
103 | plff = kzalloc(sizeof(struct plff_device), GFP_KERNEL); | ||
104 | if (!plff) | ||
105 | return -ENOMEM; | ||
106 | |||
107 | dev = hidinput->input; | ||
108 | |||
109 | set_bit(FF_RUMBLE, dev->ffbit); | ||
110 | |||
111 | error = input_ff_create_memless(dev, plff, hid_plff_play); | ||
112 | if (error) { | ||
113 | kfree(plff); | ||
114 | return error; | ||
115 | } | ||
116 | |||
117 | plff->report = report; | ||
118 | plff->report->field[0]->value[0] = 0x00; | ||
119 | plff->report->field[0]->value[1] = 0x00; | ||
120 | plff->report->field[0]->value[2] = 0x00; | ||
121 | plff->report->field[0]->value[3] = 0x00; | ||
122 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); | ||
123 | } | ||
124 | |||
125 | printk(KERN_INFO "hid-plff: Force feedback for PantherLord USB/PS2 " | ||
126 | "2in1 Adapters by Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c new file mode 100644 index 000000000000..ab67331620d0 --- /dev/null +++ b/drivers/hid/usbhid/hid-tmff.c | |||
@@ -0,0 +1,147 @@ | |||
1 | /* | ||
2 | * Force feedback support for various HID compliant devices by ThrustMaster: | ||
3 | * ThrustMaster FireStorm Dual Power 2 | ||
4 | * and possibly others whose device ids haven't been added. | ||
5 | * | ||
6 | * Modified to support ThrustMaster devices by Zinx Verituse | ||
7 | * on 2003-01-25 from the Logitech force feedback driver, | ||
8 | * which is by Johann Deneux. | ||
9 | * | ||
10 | * Copyright (c) 2003 Zinx Verituse <zinx@epicsol.org> | ||
11 | * Copyright (c) 2002 Johann Deneux | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
28 | */ | ||
29 | |||
30 | #include <linux/input.h> | ||
31 | |||
32 | #undef DEBUG | ||
33 | #include <linux/usb.h> | ||
34 | |||
35 | #include <linux/hid.h> | ||
36 | #include "usbhid.h" | ||
37 | |||
38 | /* Usages for thrustmaster devices I know about */ | ||
39 | #define THRUSTMASTER_USAGE_RUMBLE_LR (HID_UP_GENDESK | 0xbb) | ||
40 | |||
41 | |||
42 | struct tmff_device { | ||
43 | struct hid_report *report; | ||
44 | struct hid_field *rumble; | ||
45 | }; | ||
46 | |||
47 | /* Changes values from 0 to 0xffff into values from minimum to maximum */ | ||
48 | static inline int hid_tmff_scale(unsigned int in, int minimum, int maximum) | ||
49 | { | ||
50 | int ret; | ||
51 | |||
52 | ret = (in * (maximum - minimum) / 0xffff) + minimum; | ||
53 | if (ret < minimum) | ||
54 | return minimum; | ||
55 | if (ret > maximum) | ||
56 | return maximum; | ||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect) | ||
61 | { | ||
62 | struct hid_device *hid = dev->private; | ||
63 | struct tmff_device *tmff = data; | ||
64 | int left, right; /* Rumbling */ | ||
65 | |||
66 | left = hid_tmff_scale(effect->u.rumble.weak_magnitude, | ||
67 | tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); | ||
68 | right = hid_tmff_scale(effect->u.rumble.strong_magnitude, | ||
69 | tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); | ||
70 | |||
71 | tmff->rumble->value[0] = left; | ||
72 | tmff->rumble->value[1] = right; | ||
73 | dbg("(left,right)=(%08x, %08x)", left, right); | ||
74 | usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | int hid_tmff_init(struct hid_device *hid) | ||
80 | { | ||
81 | struct tmff_device *tmff; | ||
82 | struct list_head *pos; | ||
83 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
84 | struct input_dev *input_dev = hidinput->input; | ||
85 | int error; | ||
86 | |||
87 | tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); | ||
88 | if (!tmff) | ||
89 | return -ENOMEM; | ||
90 | |||
91 | /* Find the report to use */ | ||
92 | __list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) { | ||
93 | struct hid_report *report = (struct hid_report *)pos; | ||
94 | int fieldnum; | ||
95 | |||
96 | for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) { | ||
97 | struct hid_field *field = report->field[fieldnum]; | ||
98 | |||
99 | if (field->maxusage <= 0) | ||
100 | continue; | ||
101 | |||
102 | switch (field->usage[0].hid) { | ||
103 | case THRUSTMASTER_USAGE_RUMBLE_LR: | ||
104 | if (field->report_count < 2) { | ||
105 | warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with report_count < 2"); | ||
106 | continue; | ||
107 | } | ||
108 | |||
109 | if (field->logical_maximum == field->logical_minimum) { | ||
110 | warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with logical_maximum == logical_minimum"); | ||
111 | continue; | ||
112 | } | ||
113 | |||
114 | if (tmff->report && tmff->report != report) { | ||
115 | warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR in other report"); | ||
116 | continue; | ||
117 | } | ||
118 | |||
119 | if (tmff->rumble && tmff->rumble != field) { | ||
120 | warn("ignoring duplicate THRUSTMASTER_USAGE_RUMBLE_LR"); | ||
121 | continue; | ||
122 | } | ||
123 | |||
124 | tmff->report = report; | ||
125 | tmff->rumble = field; | ||
126 | |||
127 | set_bit(FF_RUMBLE, input_dev->ffbit); | ||
128 | break; | ||
129 | |||
130 | default: | ||
131 | warn("ignoring unknown output usage %08x", field->usage[0].hid); | ||
132 | continue; | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | |||
137 | error = input_ff_create_memless(input_dev, tmff, hid_tmff_play); | ||
138 | if (error) { | ||
139 | kfree(tmff); | ||
140 | return error; | ||
141 | } | ||
142 | |||
143 | info("Force feedback for ThrustMaster rumble pad devices by Zinx Verituse <zinx@epicsol.org>"); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
diff --git a/drivers/hid/usbhid/hid-zpff.c b/drivers/hid/usbhid/hid-zpff.c new file mode 100644 index 000000000000..7bd8238ca212 --- /dev/null +++ b/drivers/hid/usbhid/hid-zpff.c | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * Force feedback support for Zeroplus based devices | ||
3 | * | ||
4 | * Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com> | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | |||
24 | /* #define DEBUG */ | ||
25 | |||
26 | #define debug(format, arg...) pr_debug("hid-zpff: " format "\n" , ## arg) | ||
27 | |||
28 | #include <linux/input.h> | ||
29 | #include <linux/usb.h> | ||
30 | #include <linux/hid.h> | ||
31 | #include "usbhid.h" | ||
32 | |||
33 | struct zpff_device { | ||
34 | struct hid_report *report; | ||
35 | }; | ||
36 | |||
37 | static int hid_zpff_play(struct input_dev *dev, void *data, | ||
38 | struct ff_effect *effect) | ||
39 | { | ||
40 | struct hid_device *hid = dev->private; | ||
41 | struct zpff_device *zpff = data; | ||
42 | int left, right; | ||
43 | |||
44 | /* | ||
45 | * The following is specified the other way around in the Zeroplus | ||
46 | * datasheet but the order below is correct for the XFX Executioner; | ||
47 | * however it is possible that the XFX Executioner is an exception | ||
48 | */ | ||
49 | |||
50 | left = effect->u.rumble.strong_magnitude; | ||
51 | right = effect->u.rumble.weak_magnitude; | ||
52 | debug("called with 0x%04x 0x%04x", left, right); | ||
53 | |||
54 | left = left * 0x7f / 0xffff; | ||
55 | right = right * 0x7f / 0xffff; | ||
56 | |||
57 | zpff->report->field[2]->value[0] = left; | ||
58 | zpff->report->field[3]->value[0] = right; | ||
59 | debug("running with 0x%02x 0x%02x", left, right); | ||
60 | usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | int hid_zpff_init(struct hid_device *hid) | ||
66 | { | ||
67 | struct zpff_device *zpff; | ||
68 | struct hid_report *report; | ||
69 | struct hid_input *hidinput = list_entry(hid->inputs.next, | ||
70 | struct hid_input, list); | ||
71 | struct list_head *report_list = | ||
72 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
73 | struct input_dev *dev = hidinput->input; | ||
74 | int error; | ||
75 | |||
76 | if (list_empty(report_list)) { | ||
77 | printk(KERN_ERR "hid-zpff: no output report found\n"); | ||
78 | return -ENODEV; | ||
79 | } | ||
80 | |||
81 | report = list_entry(report_list->next, struct hid_report, list); | ||
82 | |||
83 | if (report->maxfield < 4) { | ||
84 | printk(KERN_ERR "hid-zpff: not enough fields in report\n"); | ||
85 | return -ENODEV; | ||
86 | } | ||
87 | |||
88 | zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); | ||
89 | if (!zpff) | ||
90 | return -ENOMEM; | ||
91 | |||
92 | set_bit(FF_RUMBLE, dev->ffbit); | ||
93 | |||
94 | error = input_ff_create_memless(dev, zpff, hid_zpff_play); | ||
95 | if (error) { | ||
96 | kfree(zpff); | ||
97 | return error; | ||
98 | } | ||
99 | |||
100 | zpff->report = report; | ||
101 | zpff->report->field[0]->value[0] = 0x00; | ||
102 | zpff->report->field[1]->value[0] = 0x02; | ||
103 | zpff->report->field[2]->value[0] = 0x00; | ||
104 | zpff->report->field[3]->value[0] = 0x00; | ||
105 | usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); | ||
106 | |||
107 | printk(KERN_INFO "Force feedback for Zeroplus based devices by " | ||
108 | "Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
109 | |||
110 | return 0; | ||
111 | } | ||
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c new file mode 100644 index 000000000000..a8b3d66cd498 --- /dev/null +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -0,0 +1,847 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2001 Paul Stewart | ||
3 | * Copyright (c) 2001 Vojtech Pavlik | ||
4 | * | ||
5 | * HID char devices, giving access to raw HID device events. | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | * Should you need to contact me, the author, you can do so either by | ||
25 | * e-mail - mail your message to Paul Stewart <stewart@wetlogic.net> | ||
26 | */ | ||
27 | |||
28 | #include <linux/poll.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/smp_lock.h> | ||
33 | #include <linux/input.h> | ||
34 | #include <linux/usb.h> | ||
35 | #include <linux/hid.h> | ||
36 | #include <linux/hiddev.h> | ||
37 | #include "usbhid.h" | ||
38 | |||
39 | #ifdef CONFIG_USB_DYNAMIC_MINORS | ||
40 | #define HIDDEV_MINOR_BASE 0 | ||
41 | #define HIDDEV_MINORS 256 | ||
42 | #else | ||
43 | #define HIDDEV_MINOR_BASE 96 | ||
44 | #define HIDDEV_MINORS 16 | ||
45 | #endif | ||
46 | #define HIDDEV_BUFFER_SIZE 64 | ||
47 | |||
48 | struct hiddev { | ||
49 | int exist; | ||
50 | int open; | ||
51 | wait_queue_head_t wait; | ||
52 | struct hid_device *hid; | ||
53 | struct list_head list; | ||
54 | }; | ||
55 | |||
56 | struct hiddev_list { | ||
57 | struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE]; | ||
58 | int head; | ||
59 | int tail; | ||
60 | unsigned flags; | ||
61 | struct fasync_struct *fasync; | ||
62 | struct hiddev *hiddev; | ||
63 | struct list_head node; | ||
64 | }; | ||
65 | |||
66 | static struct hiddev *hiddev_table[HIDDEV_MINORS]; | ||
67 | |||
68 | /* | ||
69 | * Find a report, given the report's type and ID. The ID can be specified | ||
70 | * indirectly by REPORT_ID_FIRST (which returns the first report of the given | ||
71 | * type) or by (REPORT_ID_NEXT | old_id), which returns the next report of the | ||
72 | * given type which follows old_id. | ||
73 | */ | ||
74 | static struct hid_report * | ||
75 | hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) | ||
76 | { | ||
77 | unsigned int flags = rinfo->report_id & ~HID_REPORT_ID_MASK; | ||
78 | unsigned int rid = rinfo->report_id & HID_REPORT_ID_MASK; | ||
79 | struct hid_report_enum *report_enum; | ||
80 | struct hid_report *report; | ||
81 | struct list_head *list; | ||
82 | |||
83 | if (rinfo->report_type < HID_REPORT_TYPE_MIN || | ||
84 | rinfo->report_type > HID_REPORT_TYPE_MAX) | ||
85 | return NULL; | ||
86 | |||
87 | report_enum = hid->report_enum + | ||
88 | (rinfo->report_type - HID_REPORT_TYPE_MIN); | ||
89 | |||
90 | switch (flags) { | ||
91 | case 0: /* Nothing to do -- report_id is already set correctly */ | ||
92 | break; | ||
93 | |||
94 | case HID_REPORT_ID_FIRST: | ||
95 | if (list_empty(&report_enum->report_list)) | ||
96 | return NULL; | ||
97 | |||
98 | list = report_enum->report_list.next; | ||
99 | report = list_entry(list, struct hid_report, list); | ||
100 | rinfo->report_id = report->id; | ||
101 | break; | ||
102 | |||
103 | case HID_REPORT_ID_NEXT: | ||
104 | report = report_enum->report_id_hash[rid]; | ||
105 | if (!report) | ||
106 | return NULL; | ||
107 | |||
108 | list = report->list.next; | ||
109 | if (list == &report_enum->report_list) | ||
110 | return NULL; | ||
111 | |||
112 | report = list_entry(list, struct hid_report, list); | ||
113 | rinfo->report_id = report->id; | ||
114 | break; | ||
115 | |||
116 | default: | ||
117 | return NULL; | ||
118 | } | ||
119 | |||
120 | return report_enum->report_id_hash[rinfo->report_id]; | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Perform an exhaustive search of the report table for a usage, given its | ||
125 | * type and usage id. | ||
126 | */ | ||
127 | static struct hid_field * | ||
128 | hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) | ||
129 | { | ||
130 | int i, j; | ||
131 | struct hid_report *report; | ||
132 | struct hid_report_enum *report_enum; | ||
133 | struct hid_field *field; | ||
134 | |||
135 | if (uref->report_type < HID_REPORT_TYPE_MIN || | ||
136 | uref->report_type > HID_REPORT_TYPE_MAX) | ||
137 | return NULL; | ||
138 | |||
139 | report_enum = hid->report_enum + | ||
140 | (uref->report_type - HID_REPORT_TYPE_MIN); | ||
141 | |||
142 | list_for_each_entry(report, &report_enum->report_list, list) { | ||
143 | for (i = 0; i < report->maxfield; i++) { | ||
144 | field = report->field[i]; | ||
145 | for (j = 0; j < field->maxusage; j++) { | ||
146 | if (field->usage[j].hid == uref->usage_code) { | ||
147 | uref->report_id = report->id; | ||
148 | uref->field_index = i; | ||
149 | uref->usage_index = j; | ||
150 | return field; | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | } | ||
155 | |||
156 | return NULL; | ||
157 | } | ||
158 | |||
159 | static void hiddev_send_event(struct hid_device *hid, | ||
160 | struct hiddev_usage_ref *uref) | ||
161 | { | ||
162 | struct hiddev *hiddev = hid->hiddev; | ||
163 | struct hiddev_list *list; | ||
164 | |||
165 | list_for_each_entry(list, &hiddev->list, node) { | ||
166 | if (uref->field_index != HID_FIELD_INDEX_NONE || | ||
167 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { | ||
168 | list->buffer[list->head] = *uref; | ||
169 | list->head = (list->head + 1) & | ||
170 | (HIDDEV_BUFFER_SIZE - 1); | ||
171 | kill_fasync(&list->fasync, SIGIO, POLL_IN); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | wake_up_interruptible(&hiddev->wait); | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * This is where hid.c calls into hiddev to pass an event that occurred over | ||
180 | * the interrupt pipe | ||
181 | */ | ||
182 | void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, | ||
183 | struct hid_usage *usage, __s32 value) | ||
184 | { | ||
185 | unsigned type = field->report_type; | ||
186 | struct hiddev_usage_ref uref; | ||
187 | |||
188 | uref.report_type = | ||
189 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | ||
190 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | ||
191 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); | ||
192 | uref.report_id = field->report->id; | ||
193 | uref.field_index = field->index; | ||
194 | uref.usage_index = (usage - field->usage); | ||
195 | uref.usage_code = usage->hid; | ||
196 | uref.value = value; | ||
197 | |||
198 | hiddev_send_event(hid, &uref); | ||
199 | } | ||
200 | EXPORT_SYMBOL_GPL(hiddev_hid_event); | ||
201 | |||
202 | void hiddev_report_event(struct hid_device *hid, struct hid_report *report) | ||
203 | { | ||
204 | unsigned type = report->type; | ||
205 | struct hiddev_usage_ref uref; | ||
206 | |||
207 | memset(&uref, 0, sizeof(uref)); | ||
208 | uref.report_type = | ||
209 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | ||
210 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | ||
211 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); | ||
212 | uref.report_id = report->id; | ||
213 | uref.field_index = HID_FIELD_INDEX_NONE; | ||
214 | |||
215 | hiddev_send_event(hid, &uref); | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * fasync file op | ||
220 | */ | ||
221 | static int hiddev_fasync(int fd, struct file *file, int on) | ||
222 | { | ||
223 | int retval; | ||
224 | struct hiddev_list *list = file->private_data; | ||
225 | |||
226 | retval = fasync_helper(fd, file, on, &list->fasync); | ||
227 | |||
228 | return retval < 0 ? retval : 0; | ||
229 | } | ||
230 | |||
231 | |||
232 | /* | ||
233 | * release file op | ||
234 | */ | ||
235 | static int hiddev_release(struct inode * inode, struct file * file) | ||
236 | { | ||
237 | struct hiddev_list *list = file->private_data; | ||
238 | |||
239 | hiddev_fasync(-1, file, 0); | ||
240 | list_del(&list->node); | ||
241 | |||
242 | if (!--list->hiddev->open) { | ||
243 | if (list->hiddev->exist) | ||
244 | usbhid_close(list->hiddev->hid); | ||
245 | else | ||
246 | kfree(list->hiddev); | ||
247 | } | ||
248 | |||
249 | kfree(list); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | /* | ||
255 | * open file op | ||
256 | */ | ||
257 | static int hiddev_open(struct inode *inode, struct file *file) | ||
258 | { | ||
259 | struct hiddev_list *list; | ||
260 | |||
261 | int i = iminor(inode) - HIDDEV_MINOR_BASE; | ||
262 | |||
263 | if (i >= HIDDEV_MINORS || !hiddev_table[i]) | ||
264 | return -ENODEV; | ||
265 | |||
266 | if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) | ||
267 | return -ENOMEM; | ||
268 | |||
269 | list->hiddev = hiddev_table[i]; | ||
270 | list_add_tail(&list->node, &hiddev_table[i]->list); | ||
271 | file->private_data = list; | ||
272 | |||
273 | if (!list->hiddev->open++) | ||
274 | if (list->hiddev->exist) | ||
275 | usbhid_open(hiddev_table[i]->hid); | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * "write" file op | ||
282 | */ | ||
283 | static ssize_t hiddev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) | ||
284 | { | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | |||
288 | /* | ||
289 | * "read" file op | ||
290 | */ | ||
291 | static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) | ||
292 | { | ||
293 | DECLARE_WAITQUEUE(wait, current); | ||
294 | struct hiddev_list *list = file->private_data; | ||
295 | int event_size; | ||
296 | int retval = 0; | ||
297 | |||
298 | event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ? | ||
299 | sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event); | ||
300 | |||
301 | if (count < event_size) | ||
302 | return 0; | ||
303 | |||
304 | while (retval == 0) { | ||
305 | if (list->head == list->tail) { | ||
306 | add_wait_queue(&list->hiddev->wait, &wait); | ||
307 | set_current_state(TASK_INTERRUPTIBLE); | ||
308 | |||
309 | while (list->head == list->tail) { | ||
310 | if (file->f_flags & O_NONBLOCK) { | ||
311 | retval = -EAGAIN; | ||
312 | break; | ||
313 | } | ||
314 | if (signal_pending(current)) { | ||
315 | retval = -ERESTARTSYS; | ||
316 | break; | ||
317 | } | ||
318 | if (!list->hiddev->exist) { | ||
319 | retval = -EIO; | ||
320 | break; | ||
321 | } | ||
322 | |||
323 | schedule(); | ||
324 | set_current_state(TASK_INTERRUPTIBLE); | ||
325 | } | ||
326 | |||
327 | set_current_state(TASK_RUNNING); | ||
328 | remove_wait_queue(&list->hiddev->wait, &wait); | ||
329 | } | ||
330 | |||
331 | if (retval) | ||
332 | return retval; | ||
333 | |||
334 | |||
335 | while (list->head != list->tail && | ||
336 | retval + event_size <= count) { | ||
337 | if ((list->flags & HIDDEV_FLAG_UREF) == 0) { | ||
338 | if (list->buffer[list->tail].field_index != | ||
339 | HID_FIELD_INDEX_NONE) { | ||
340 | struct hiddev_event event; | ||
341 | event.hid = list->buffer[list->tail].usage_code; | ||
342 | event.value = list->buffer[list->tail].value; | ||
343 | if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) | ||
344 | return -EFAULT; | ||
345 | retval += sizeof(struct hiddev_event); | ||
346 | } | ||
347 | } else { | ||
348 | if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE || | ||
349 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { | ||
350 | if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) | ||
351 | return -EFAULT; | ||
352 | retval += sizeof(struct hiddev_usage_ref); | ||
353 | } | ||
354 | } | ||
355 | list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1); | ||
356 | } | ||
357 | |||
358 | } | ||
359 | |||
360 | return retval; | ||
361 | } | ||
362 | |||
363 | /* | ||
364 | * "poll" file op | ||
365 | * No kernel lock - fine | ||
366 | */ | ||
367 | static unsigned int hiddev_poll(struct file *file, poll_table *wait) | ||
368 | { | ||
369 | struct hiddev_list *list = file->private_data; | ||
370 | |||
371 | poll_wait(file, &list->hiddev->wait, wait); | ||
372 | if (list->head != list->tail) | ||
373 | return POLLIN | POLLRDNORM; | ||
374 | if (!list->hiddev->exist) | ||
375 | return POLLERR | POLLHUP; | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | /* | ||
380 | * "ioctl" file op | ||
381 | */ | ||
382 | static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | ||
383 | { | ||
384 | struct hiddev_list *list = file->private_data; | ||
385 | struct hiddev *hiddev = list->hiddev; | ||
386 | struct hid_device *hid = hiddev->hid; | ||
387 | struct usb_device *dev = hid_to_usb_dev(hid); | ||
388 | struct hiddev_collection_info cinfo; | ||
389 | struct hiddev_report_info rinfo; | ||
390 | struct hiddev_field_info finfo; | ||
391 | struct hiddev_usage_ref_multi *uref_multi = NULL; | ||
392 | struct hiddev_usage_ref *uref; | ||
393 | struct hiddev_devinfo dinfo; | ||
394 | struct hid_report *report; | ||
395 | struct hid_field *field; | ||
396 | struct usbhid_device *usbhid = hid->driver_data; | ||
397 | void __user *user_arg = (void __user *)arg; | ||
398 | int i; | ||
399 | |||
400 | if (!hiddev->exist) | ||
401 | return -EIO; | ||
402 | |||
403 | switch (cmd) { | ||
404 | |||
405 | case HIDIOCGVERSION: | ||
406 | return put_user(HID_VERSION, (int __user *)arg); | ||
407 | |||
408 | case HIDIOCAPPLICATION: | ||
409 | if (arg < 0 || arg >= hid->maxapplication) | ||
410 | return -EINVAL; | ||
411 | |||
412 | for (i = 0; i < hid->maxcollection; i++) | ||
413 | if (hid->collection[i].type == | ||
414 | HID_COLLECTION_APPLICATION && arg-- == 0) | ||
415 | break; | ||
416 | |||
417 | if (i == hid->maxcollection) | ||
418 | return -EINVAL; | ||
419 | |||
420 | return hid->collection[i].usage; | ||
421 | |||
422 | case HIDIOCGDEVINFO: | ||
423 | dinfo.bustype = BUS_USB; | ||
424 | dinfo.busnum = dev->bus->busnum; | ||
425 | dinfo.devnum = dev->devnum; | ||
426 | dinfo.ifnum = usbhid->ifnum; | ||
427 | dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
428 | dinfo.product = le16_to_cpu(dev->descriptor.idProduct); | ||
429 | dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice); | ||
430 | dinfo.num_applications = hid->maxapplication; | ||
431 | if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) | ||
432 | return -EFAULT; | ||
433 | |||
434 | return 0; | ||
435 | |||
436 | case HIDIOCGFLAG: | ||
437 | if (put_user(list->flags, (int __user *)arg)) | ||
438 | return -EFAULT; | ||
439 | |||
440 | return 0; | ||
441 | |||
442 | case HIDIOCSFLAG: | ||
443 | { | ||
444 | int newflags; | ||
445 | if (get_user(newflags, (int __user *)arg)) | ||
446 | return -EFAULT; | ||
447 | |||
448 | if ((newflags & ~HIDDEV_FLAGS) != 0 || | ||
449 | ((newflags & HIDDEV_FLAG_REPORT) != 0 && | ||
450 | (newflags & HIDDEV_FLAG_UREF) == 0)) | ||
451 | return -EINVAL; | ||
452 | |||
453 | list->flags = newflags; | ||
454 | |||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | case HIDIOCGSTRING: | ||
459 | { | ||
460 | int idx, len; | ||
461 | char *buf; | ||
462 | |||
463 | if (get_user(idx, (int __user *)arg)) | ||
464 | return -EFAULT; | ||
465 | |||
466 | if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL) | ||
467 | return -ENOMEM; | ||
468 | |||
469 | if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) { | ||
470 | kfree(buf); | ||
471 | return -EINVAL; | ||
472 | } | ||
473 | |||
474 | if (copy_to_user(user_arg+sizeof(int), buf, len+1)) { | ||
475 | kfree(buf); | ||
476 | return -EFAULT; | ||
477 | } | ||
478 | |||
479 | kfree(buf); | ||
480 | |||
481 | return len; | ||
482 | } | ||
483 | |||
484 | case HIDIOCINITREPORT: | ||
485 | usbhid_init_reports(hid); | ||
486 | |||
487 | return 0; | ||
488 | |||
489 | case HIDIOCGREPORT: | ||
490 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | ||
491 | return -EFAULT; | ||
492 | |||
493 | if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT) | ||
494 | return -EINVAL; | ||
495 | |||
496 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
497 | return -EINVAL; | ||
498 | |||
499 | usbhid_submit_report(hid, report, USB_DIR_IN); | ||
500 | usbhid_wait_io(hid); | ||
501 | |||
502 | return 0; | ||
503 | |||
504 | case HIDIOCSREPORT: | ||
505 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | ||
506 | return -EFAULT; | ||
507 | |||
508 | if (rinfo.report_type == HID_REPORT_TYPE_INPUT) | ||
509 | return -EINVAL; | ||
510 | |||
511 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
512 | return -EINVAL; | ||
513 | |||
514 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
515 | usbhid_wait_io(hid); | ||
516 | |||
517 | return 0; | ||
518 | |||
519 | case HIDIOCGREPORTINFO: | ||
520 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | ||
521 | return -EFAULT; | ||
522 | |||
523 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
524 | return -EINVAL; | ||
525 | |||
526 | rinfo.num_fields = report->maxfield; | ||
527 | |||
528 | if (copy_to_user(user_arg, &rinfo, sizeof(rinfo))) | ||
529 | return -EFAULT; | ||
530 | |||
531 | return 0; | ||
532 | |||
533 | case HIDIOCGFIELDINFO: | ||
534 | if (copy_from_user(&finfo, user_arg, sizeof(finfo))) | ||
535 | return -EFAULT; | ||
536 | rinfo.report_type = finfo.report_type; | ||
537 | rinfo.report_id = finfo.report_id; | ||
538 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
539 | return -EINVAL; | ||
540 | |||
541 | if (finfo.field_index >= report->maxfield) | ||
542 | return -EINVAL; | ||
543 | |||
544 | field = report->field[finfo.field_index]; | ||
545 | memset(&finfo, 0, sizeof(finfo)); | ||
546 | finfo.report_type = rinfo.report_type; | ||
547 | finfo.report_id = rinfo.report_id; | ||
548 | finfo.field_index = field->report_count - 1; | ||
549 | finfo.maxusage = field->maxusage; | ||
550 | finfo.flags = field->flags; | ||
551 | finfo.physical = field->physical; | ||
552 | finfo.logical = field->logical; | ||
553 | finfo.application = field->application; | ||
554 | finfo.logical_minimum = field->logical_minimum; | ||
555 | finfo.logical_maximum = field->logical_maximum; | ||
556 | finfo.physical_minimum = field->physical_minimum; | ||
557 | finfo.physical_maximum = field->physical_maximum; | ||
558 | finfo.unit_exponent = field->unit_exponent; | ||
559 | finfo.unit = field->unit; | ||
560 | |||
561 | if (copy_to_user(user_arg, &finfo, sizeof(finfo))) | ||
562 | return -EFAULT; | ||
563 | |||
564 | return 0; | ||
565 | |||
566 | case HIDIOCGUCODE: | ||
567 | uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL); | ||
568 | if (!uref_multi) | ||
569 | return -ENOMEM; | ||
570 | uref = &uref_multi->uref; | ||
571 | if (copy_from_user(uref, user_arg, sizeof(*uref))) | ||
572 | goto fault; | ||
573 | |||
574 | rinfo.report_type = uref->report_type; | ||
575 | rinfo.report_id = uref->report_id; | ||
576 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
577 | goto inval; | ||
578 | |||
579 | if (uref->field_index >= report->maxfield) | ||
580 | goto inval; | ||
581 | |||
582 | field = report->field[uref->field_index]; | ||
583 | if (uref->usage_index >= field->maxusage) | ||
584 | goto inval; | ||
585 | |||
586 | uref->usage_code = field->usage[uref->usage_index].hid; | ||
587 | |||
588 | if (copy_to_user(user_arg, uref, sizeof(*uref))) | ||
589 | goto fault; | ||
590 | |||
591 | kfree(uref_multi); | ||
592 | return 0; | ||
593 | |||
594 | case HIDIOCGUSAGE: | ||
595 | case HIDIOCSUSAGE: | ||
596 | case HIDIOCGUSAGES: | ||
597 | case HIDIOCSUSAGES: | ||
598 | case HIDIOCGCOLLECTIONINDEX: | ||
599 | uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL); | ||
600 | if (!uref_multi) | ||
601 | return -ENOMEM; | ||
602 | uref = &uref_multi->uref; | ||
603 | if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { | ||
604 | if (copy_from_user(uref_multi, user_arg, | ||
605 | sizeof(*uref_multi))) | ||
606 | goto fault; | ||
607 | } else { | ||
608 | if (copy_from_user(uref, user_arg, sizeof(*uref))) | ||
609 | goto fault; | ||
610 | } | ||
611 | |||
612 | if (cmd != HIDIOCGUSAGE && | ||
613 | cmd != HIDIOCGUSAGES && | ||
614 | uref->report_type == HID_REPORT_TYPE_INPUT) | ||
615 | goto inval; | ||
616 | |||
617 | if (uref->report_id == HID_REPORT_ID_UNKNOWN) { | ||
618 | field = hiddev_lookup_usage(hid, uref); | ||
619 | if (field == NULL) | ||
620 | goto inval; | ||
621 | } else { | ||
622 | rinfo.report_type = uref->report_type; | ||
623 | rinfo.report_id = uref->report_id; | ||
624 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
625 | goto inval; | ||
626 | |||
627 | if (uref->field_index >= report->maxfield) | ||
628 | goto inval; | ||
629 | |||
630 | field = report->field[uref->field_index]; | ||
631 | |||
632 | if (cmd == HIDIOCGCOLLECTIONINDEX) { | ||
633 | if (uref->usage_index >= field->maxusage) | ||
634 | goto inval; | ||
635 | } else if (uref->usage_index >= field->report_count) | ||
636 | goto inval; | ||
637 | |||
638 | else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && | ||
639 | (uref_multi->num_values > HID_MAX_MULTI_USAGES || | ||
640 | uref->usage_index + uref_multi->num_values > field->report_count)) | ||
641 | goto inval; | ||
642 | } | ||
643 | |||
644 | switch (cmd) { | ||
645 | case HIDIOCGUSAGE: | ||
646 | uref->value = field->value[uref->usage_index]; | ||
647 | if (copy_to_user(user_arg, uref, sizeof(*uref))) | ||
648 | goto fault; | ||
649 | goto goodreturn; | ||
650 | |||
651 | case HIDIOCSUSAGE: | ||
652 | field->value[uref->usage_index] = uref->value; | ||
653 | goto goodreturn; | ||
654 | |||
655 | case HIDIOCGCOLLECTIONINDEX: | ||
656 | kfree(uref_multi); | ||
657 | return field->usage[uref->usage_index].collection_index; | ||
658 | case HIDIOCGUSAGES: | ||
659 | for (i = 0; i < uref_multi->num_values; i++) | ||
660 | uref_multi->values[i] = | ||
661 | field->value[uref->usage_index + i]; | ||
662 | if (copy_to_user(user_arg, uref_multi, | ||
663 | sizeof(*uref_multi))) | ||
664 | goto fault; | ||
665 | goto goodreturn; | ||
666 | case HIDIOCSUSAGES: | ||
667 | for (i = 0; i < uref_multi->num_values; i++) | ||
668 | field->value[uref->usage_index + i] = | ||
669 | uref_multi->values[i]; | ||
670 | goto goodreturn; | ||
671 | } | ||
672 | |||
673 | goodreturn: | ||
674 | kfree(uref_multi); | ||
675 | return 0; | ||
676 | fault: | ||
677 | kfree(uref_multi); | ||
678 | return -EFAULT; | ||
679 | inval: | ||
680 | kfree(uref_multi); | ||
681 | return -EINVAL; | ||
682 | |||
683 | case HIDIOCGCOLLECTIONINFO: | ||
684 | if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) | ||
685 | return -EFAULT; | ||
686 | |||
687 | if (cinfo.index >= hid->maxcollection) | ||
688 | return -EINVAL; | ||
689 | |||
690 | cinfo.type = hid->collection[cinfo.index].type; | ||
691 | cinfo.usage = hid->collection[cinfo.index].usage; | ||
692 | cinfo.level = hid->collection[cinfo.index].level; | ||
693 | |||
694 | if (copy_to_user(user_arg, &cinfo, sizeof(cinfo))) | ||
695 | return -EFAULT; | ||
696 | return 0; | ||
697 | |||
698 | default: | ||
699 | |||
700 | if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) | ||
701 | return -EINVAL; | ||
702 | |||
703 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) { | ||
704 | int len; | ||
705 | if (!hid->name) | ||
706 | return 0; | ||
707 | len = strlen(hid->name) + 1; | ||
708 | if (len > _IOC_SIZE(cmd)) | ||
709 | len = _IOC_SIZE(cmd); | ||
710 | return copy_to_user(user_arg, hid->name, len) ? | ||
711 | -EFAULT : len; | ||
712 | } | ||
713 | |||
714 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) { | ||
715 | int len; | ||
716 | if (!hid->phys) | ||
717 | return 0; | ||
718 | len = strlen(hid->phys) + 1; | ||
719 | if (len > _IOC_SIZE(cmd)) | ||
720 | len = _IOC_SIZE(cmd); | ||
721 | return copy_to_user(user_arg, hid->phys, len) ? | ||
722 | -EFAULT : len; | ||
723 | } | ||
724 | } | ||
725 | return -EINVAL; | ||
726 | } | ||
727 | |||
728 | static const struct file_operations hiddev_fops = { | ||
729 | .owner = THIS_MODULE, | ||
730 | .read = hiddev_read, | ||
731 | .write = hiddev_write, | ||
732 | .poll = hiddev_poll, | ||
733 | .open = hiddev_open, | ||
734 | .release = hiddev_release, | ||
735 | .ioctl = hiddev_ioctl, | ||
736 | .fasync = hiddev_fasync, | ||
737 | }; | ||
738 | |||
739 | static struct usb_class_driver hiddev_class = { | ||
740 | .name = "hiddev%d", | ||
741 | .fops = &hiddev_fops, | ||
742 | .minor_base = HIDDEV_MINOR_BASE, | ||
743 | }; | ||
744 | |||
745 | /* | ||
746 | * This is where hid.c calls us to connect a hid device to the hiddev driver | ||
747 | */ | ||
748 | int hiddev_connect(struct hid_device *hid) | ||
749 | { | ||
750 | struct hiddev *hiddev; | ||
751 | struct usbhid_device *usbhid = hid->driver_data; | ||
752 | int i; | ||
753 | int retval; | ||
754 | |||
755 | for (i = 0; i < hid->maxcollection; i++) | ||
756 | if (hid->collection[i].type == | ||
757 | HID_COLLECTION_APPLICATION && | ||
758 | !IS_INPUT_APPLICATION(hid->collection[i].usage)) | ||
759 | break; | ||
760 | |||
761 | if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) | ||
762 | return -1; | ||
763 | |||
764 | if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL))) | ||
765 | return -1; | ||
766 | |||
767 | retval = usb_register_dev(usbhid->intf, &hiddev_class); | ||
768 | if (retval) { | ||
769 | err("Not able to get a minor for this device."); | ||
770 | kfree(hiddev); | ||
771 | return -1; | ||
772 | } | ||
773 | |||
774 | init_waitqueue_head(&hiddev->wait); | ||
775 | INIT_LIST_HEAD(&hiddev->list); | ||
776 | hiddev->hid = hid; | ||
777 | hiddev->exist = 1; | ||
778 | |||
779 | hid->minor = usbhid->intf->minor; | ||
780 | hid->hiddev = hiddev; | ||
781 | |||
782 | hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | ||
783 | |||
784 | return 0; | ||
785 | } | ||
786 | |||
787 | /* | ||
788 | * This is where hid.c calls us to disconnect a hiddev device from the | ||
789 | * corresponding hid device (usually because the usb device has disconnected) | ||
790 | */ | ||
791 | static struct usb_class_driver hiddev_class; | ||
792 | void hiddev_disconnect(struct hid_device *hid) | ||
793 | { | ||
794 | struct hiddev *hiddev = hid->hiddev; | ||
795 | struct usbhid_device *usbhid = hid->driver_data; | ||
796 | |||
797 | hiddev->exist = 0; | ||
798 | |||
799 | hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; | ||
800 | usb_deregister_dev(usbhid->intf, &hiddev_class); | ||
801 | |||
802 | if (hiddev->open) { | ||
803 | usbhid_close(hiddev->hid); | ||
804 | wake_up_interruptible(&hiddev->wait); | ||
805 | } else { | ||
806 | kfree(hiddev); | ||
807 | } | ||
808 | } | ||
809 | |||
810 | /* Currently this driver is a USB driver. It's not a conventional one in | ||
811 | * the sense that it doesn't probe at the USB level. Instead it waits to | ||
812 | * be connected by HID through the hiddev_connect / hiddev_disconnect | ||
813 | * routines. The reason to register as a USB device is to gain part of the | ||
814 | * minor number space from the USB major. | ||
815 | * | ||
816 | * In theory, should the HID code be generalized to more than one physical | ||
817 | * medium (say, IEEE 1384), this driver will probably need to register its | ||
818 | * own major number, and in doing so, no longer need to register with USB. | ||
819 | * At that point the probe routine and hiddev_driver struct below will no | ||
820 | * longer be useful. | ||
821 | */ | ||
822 | |||
823 | |||
824 | /* We never attach in this manner, and rely on HID to connect us. This | ||
825 | * is why there is no disconnect routine defined in the usb_driver either. | ||
826 | */ | ||
827 | static int hiddev_usbd_probe(struct usb_interface *intf, | ||
828 | const struct usb_device_id *hiddev_info) | ||
829 | { | ||
830 | return -ENODEV; | ||
831 | } | ||
832 | |||
833 | |||
834 | static /* const */ struct usb_driver hiddev_driver = { | ||
835 | .name = "hiddev", | ||
836 | .probe = hiddev_usbd_probe, | ||
837 | }; | ||
838 | |||
839 | int __init hiddev_init(void) | ||
840 | { | ||
841 | return usb_register(&hiddev_driver); | ||
842 | } | ||
843 | |||
844 | void hiddev_exit(void) | ||
845 | { | ||
846 | usb_deregister(&hiddev_driver); | ||
847 | } | ||
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h new file mode 100644 index 000000000000..0023f96d4294 --- /dev/null +++ b/drivers/hid/usbhid/usbhid.h | |||
@@ -0,0 +1,87 @@ | |||
1 | #ifndef __USBHID_H | ||
2 | #define __USBHID_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (c) 1999 Andreas Gal | ||
6 | * Copyright (c) 2000-2001 Vojtech Pavlik | ||
7 | * Copyright (c) 2006 Jiri Kosina | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/types.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/list.h> | ||
30 | #include <linux/timer.h> | ||
31 | #include <linux/workqueue.h> | ||
32 | #include <linux/input.h> | ||
33 | |||
34 | /* API provided by hid-core.c for USB HID drivers */ | ||
35 | int usbhid_wait_io(struct hid_device* hid); | ||
36 | void usbhid_close(struct hid_device *hid); | ||
37 | int usbhid_open(struct hid_device *hid); | ||
38 | void usbhid_init_reports(struct hid_device *hid); | ||
39 | void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir); | ||
40 | |||
41 | /* | ||
42 | * USB-specific HID struct, to be pointed to | ||
43 | * from struct hid_device->driver_data | ||
44 | */ | ||
45 | |||
46 | struct usbhid_device { | ||
47 | struct hid_device *hid; /* pointer to corresponding HID dev */ | ||
48 | |||
49 | struct usb_interface *intf; /* USB interface */ | ||
50 | int ifnum; /* USB interface number */ | ||
51 | |||
52 | unsigned int bufsize; /* URB buffer size */ | ||
53 | |||
54 | struct urb *urbin; /* Input URB */ | ||
55 | char *inbuf; /* Input buffer */ | ||
56 | dma_addr_t inbuf_dma; /* Input buffer dma */ | ||
57 | spinlock_t inlock; /* Input fifo spinlock */ | ||
58 | |||
59 | struct urb *urbctrl; /* Control URB */ | ||
60 | struct usb_ctrlrequest *cr; /* Control request struct */ | ||
61 | dma_addr_t cr_dma; /* Control request struct dma */ | ||
62 | struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */ | ||
63 | unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */ | ||
64 | char *ctrlbuf; /* Control buffer */ | ||
65 | dma_addr_t ctrlbuf_dma; /* Control buffer dma */ | ||
66 | spinlock_t ctrllock; /* Control fifo spinlock */ | ||
67 | |||
68 | struct urb *urbout; /* Output URB */ | ||
69 | struct hid_report *out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */ | ||
70 | unsigned char outhead, outtail; /* Output pipe fifo head & tail */ | ||
71 | char *outbuf; /* Output buffer */ | ||
72 | dma_addr_t outbuf_dma; /* Output buffer dma */ | ||
73 | spinlock_t outlock; /* Output fifo spinlock */ | ||
74 | |||
75 | unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ | ||
76 | struct timer_list io_retry; /* Retry timer */ | ||
77 | unsigned long stop_retry; /* Time to give up, in jiffies */ | ||
78 | unsigned int retry_delay; /* Delay length in ms */ | ||
79 | struct work_struct reset_work; /* Task context for resets */ | ||
80 | |||
81 | }; | ||
82 | |||
83 | #define hid_to_usb_dev(hid_dev) \ | ||
84 | container_of(hid_dev->dev->parent, struct usb_device, dev) | ||
85 | |||
86 | #endif | ||
87 | |||
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c new file mode 100644 index 000000000000..3749f4a235f9 --- /dev/null +++ b/drivers/hid/usbhid/usbkbd.c | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | * $Id: usbkbd.c,v 1.27 2001/12/27 10:37:41 vojtech Exp $ | ||
3 | * | ||
4 | * Copyright (c) 1999-2001 Vojtech Pavlik | ||
5 | * | ||
6 | * USB HIDBP Keyboard support | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | * Should you need to contact me, the author, you can do so either by | ||
25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
27 | */ | ||
28 | |||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/usb/input.h> | ||
34 | #include <linux/hid.h> | ||
35 | |||
36 | /* | ||
37 | * Version Information | ||
38 | */ | ||
39 | #define DRIVER_VERSION "" | ||
40 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | ||
41 | #define DRIVER_DESC "USB HID Boot Protocol keyboard driver" | ||
42 | #define DRIVER_LICENSE "GPL" | ||
43 | |||
44 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
45 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
46 | MODULE_LICENSE(DRIVER_LICENSE); | ||
47 | |||
48 | static unsigned char usb_kbd_keycode[256] = { | ||
49 | 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, | ||
50 | 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, | ||
51 | 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, | ||
52 | 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, | ||
53 | 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, | ||
54 | 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, | ||
55 | 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, | ||
56 | 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, | ||
57 | 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, | ||
58 | 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
59 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
60 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
61 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
62 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
63 | 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, | ||
64 | 150,158,159,128,136,177,178,176,142,152,173,140 | ||
65 | }; | ||
66 | |||
67 | struct usb_kbd { | ||
68 | struct input_dev *dev; | ||
69 | struct usb_device *usbdev; | ||
70 | unsigned char old[8]; | ||
71 | struct urb *irq, *led; | ||
72 | unsigned char newleds; | ||
73 | char name[128]; | ||
74 | char phys[64]; | ||
75 | |||
76 | unsigned char *new; | ||
77 | struct usb_ctrlrequest *cr; | ||
78 | unsigned char *leds; | ||
79 | dma_addr_t cr_dma; | ||
80 | dma_addr_t new_dma; | ||
81 | dma_addr_t leds_dma; | ||
82 | }; | ||
83 | |||
84 | static void usb_kbd_irq(struct urb *urb) | ||
85 | { | ||
86 | struct usb_kbd *kbd = urb->context; | ||
87 | int i; | ||
88 | |||
89 | switch (urb->status) { | ||
90 | case 0: /* success */ | ||
91 | break; | ||
92 | case -ECONNRESET: /* unlink */ | ||
93 | case -ENOENT: | ||
94 | case -ESHUTDOWN: | ||
95 | return; | ||
96 | /* -EPIPE: should clear the halt */ | ||
97 | default: /* error */ | ||
98 | goto resubmit; | ||
99 | } | ||
100 | |||
101 | for (i = 0; i < 8; i++) | ||
102 | input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1); | ||
103 | |||
104 | for (i = 2; i < 8; i++) { | ||
105 | |||
106 | if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) { | ||
107 | if (usb_kbd_keycode[kbd->old[i]]) | ||
108 | input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0); | ||
109 | else | ||
110 | info("Unknown key (scancode %#x) released.", kbd->old[i]); | ||
111 | } | ||
112 | |||
113 | if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) { | ||
114 | if (usb_kbd_keycode[kbd->new[i]]) | ||
115 | input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); | ||
116 | else | ||
117 | info("Unknown key (scancode %#x) pressed.", kbd->new[i]); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | input_sync(kbd->dev); | ||
122 | |||
123 | memcpy(kbd->old, kbd->new, 8); | ||
124 | |||
125 | resubmit: | ||
126 | i = usb_submit_urb (urb, GFP_ATOMIC); | ||
127 | if (i) | ||
128 | err ("can't resubmit intr, %s-%s/input0, status %d", | ||
129 | kbd->usbdev->bus->bus_name, | ||
130 | kbd->usbdev->devpath, i); | ||
131 | } | ||
132 | |||
133 | static int usb_kbd_event(struct input_dev *dev, unsigned int type, | ||
134 | unsigned int code, int value) | ||
135 | { | ||
136 | struct usb_kbd *kbd = dev->private; | ||
137 | |||
138 | if (type != EV_LED) | ||
139 | return -1; | ||
140 | |||
141 | |||
142 | kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | | ||
143 | (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | | ||
144 | (!!test_bit(LED_NUML, dev->led)); | ||
145 | |||
146 | if (kbd->led->status == -EINPROGRESS) | ||
147 | return 0; | ||
148 | |||
149 | if (*(kbd->leds) == kbd->newleds) | ||
150 | return 0; | ||
151 | |||
152 | *(kbd->leds) = kbd->newleds; | ||
153 | kbd->led->dev = kbd->usbdev; | ||
154 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) | ||
155 | err("usb_submit_urb(leds) failed"); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static void usb_kbd_led(struct urb *urb) | ||
161 | { | ||
162 | struct usb_kbd *kbd = urb->context; | ||
163 | |||
164 | if (urb->status) | ||
165 | warn("led urb status %d received", urb->status); | ||
166 | |||
167 | if (*(kbd->leds) == kbd->newleds) | ||
168 | return; | ||
169 | |||
170 | *(kbd->leds) = kbd->newleds; | ||
171 | kbd->led->dev = kbd->usbdev; | ||
172 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) | ||
173 | err("usb_submit_urb(leds) failed"); | ||
174 | } | ||
175 | |||
176 | static int usb_kbd_open(struct input_dev *dev) | ||
177 | { | ||
178 | struct usb_kbd *kbd = dev->private; | ||
179 | |||
180 | kbd->irq->dev = kbd->usbdev; | ||
181 | if (usb_submit_urb(kbd->irq, GFP_KERNEL)) | ||
182 | return -EIO; | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static void usb_kbd_close(struct input_dev *dev) | ||
188 | { | ||
189 | struct usb_kbd *kbd = dev->private; | ||
190 | |||
191 | usb_kill_urb(kbd->irq); | ||
192 | } | ||
193 | |||
194 | static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) | ||
195 | { | ||
196 | if (!(kbd->irq = usb_alloc_urb(0, GFP_KERNEL))) | ||
197 | return -1; | ||
198 | if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL))) | ||
199 | return -1; | ||
200 | if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma))) | ||
201 | return -1; | ||
202 | if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), GFP_ATOMIC, &kbd->cr_dma))) | ||
203 | return -1; | ||
204 | if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma))) | ||
205 | return -1; | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) | ||
211 | { | ||
212 | usb_free_urb(kbd->irq); | ||
213 | usb_free_urb(kbd->led); | ||
214 | if (kbd->new) | ||
215 | usb_buffer_free(dev, 8, kbd->new, kbd->new_dma); | ||
216 | if (kbd->cr) | ||
217 | usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma); | ||
218 | if (kbd->leds) | ||
219 | usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); | ||
220 | } | ||
221 | |||
222 | static int usb_kbd_probe(struct usb_interface *iface, | ||
223 | const struct usb_device_id *id) | ||
224 | { | ||
225 | struct usb_device *dev = interface_to_usbdev(iface); | ||
226 | struct usb_host_interface *interface; | ||
227 | struct usb_endpoint_descriptor *endpoint; | ||
228 | struct usb_kbd *kbd; | ||
229 | struct input_dev *input_dev; | ||
230 | int i, pipe, maxp; | ||
231 | |||
232 | interface = iface->cur_altsetting; | ||
233 | |||
234 | if (interface->desc.bNumEndpoints != 1) | ||
235 | return -ENODEV; | ||
236 | |||
237 | endpoint = &interface->endpoint[0].desc; | ||
238 | if (!usb_endpoint_is_int_in(endpoint)) | ||
239 | return -ENODEV; | ||
240 | |||
241 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
242 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | ||
243 | |||
244 | kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL); | ||
245 | input_dev = input_allocate_device(); | ||
246 | if (!kbd || !input_dev) | ||
247 | goto fail1; | ||
248 | |||
249 | if (usb_kbd_alloc_mem(dev, kbd)) | ||
250 | goto fail2; | ||
251 | |||
252 | kbd->usbdev = dev; | ||
253 | kbd->dev = input_dev; | ||
254 | |||
255 | if (dev->manufacturer) | ||
256 | strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); | ||
257 | |||
258 | if (dev->product) { | ||
259 | if (dev->manufacturer) | ||
260 | strlcat(kbd->name, " ", sizeof(kbd->name)); | ||
261 | strlcat(kbd->name, dev->product, sizeof(kbd->name)); | ||
262 | } | ||
263 | |||
264 | if (!strlen(kbd->name)) | ||
265 | snprintf(kbd->name, sizeof(kbd->name), | ||
266 | "USB HIDBP Keyboard %04x:%04x", | ||
267 | le16_to_cpu(dev->descriptor.idVendor), | ||
268 | le16_to_cpu(dev->descriptor.idProduct)); | ||
269 | |||
270 | usb_make_path(dev, kbd->phys, sizeof(kbd->phys)); | ||
271 | strlcpy(kbd->phys, "/input0", sizeof(kbd->phys)); | ||
272 | |||
273 | input_dev->name = kbd->name; | ||
274 | input_dev->phys = kbd->phys; | ||
275 | usb_to_input_id(dev, &input_dev->id); | ||
276 | input_dev->cdev.dev = &iface->dev; | ||
277 | input_dev->private = kbd; | ||
278 | |||
279 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); | ||
280 | input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA); | ||
281 | |||
282 | for (i = 0; i < 255; i++) | ||
283 | set_bit(usb_kbd_keycode[i], input_dev->keybit); | ||
284 | clear_bit(0, input_dev->keybit); | ||
285 | |||
286 | input_dev->event = usb_kbd_event; | ||
287 | input_dev->open = usb_kbd_open; | ||
288 | input_dev->close = usb_kbd_close; | ||
289 | |||
290 | usb_fill_int_urb(kbd->irq, dev, pipe, | ||
291 | kbd->new, (maxp > 8 ? 8 : maxp), | ||
292 | usb_kbd_irq, kbd, endpoint->bInterval); | ||
293 | kbd->irq->transfer_dma = kbd->new_dma; | ||
294 | kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
295 | |||
296 | kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||
297 | kbd->cr->bRequest = 0x09; | ||
298 | kbd->cr->wValue = cpu_to_le16(0x200); | ||
299 | kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); | ||
300 | kbd->cr->wLength = cpu_to_le16(1); | ||
301 | |||
302 | usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0), | ||
303 | (void *) kbd->cr, kbd->leds, 1, | ||
304 | usb_kbd_led, kbd); | ||
305 | kbd->led->setup_dma = kbd->cr_dma; | ||
306 | kbd->led->transfer_dma = kbd->leds_dma; | ||
307 | kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); | ||
308 | |||
309 | input_register_device(kbd->dev); | ||
310 | |||
311 | usb_set_intfdata(iface, kbd); | ||
312 | return 0; | ||
313 | |||
314 | fail2: usb_kbd_free_mem(dev, kbd); | ||
315 | fail1: input_free_device(input_dev); | ||
316 | kfree(kbd); | ||
317 | return -ENOMEM; | ||
318 | } | ||
319 | |||
320 | static void usb_kbd_disconnect(struct usb_interface *intf) | ||
321 | { | ||
322 | struct usb_kbd *kbd = usb_get_intfdata (intf); | ||
323 | |||
324 | usb_set_intfdata(intf, NULL); | ||
325 | if (kbd) { | ||
326 | usb_kill_urb(kbd->irq); | ||
327 | input_unregister_device(kbd->dev); | ||
328 | usb_kbd_free_mem(interface_to_usbdev(intf), kbd); | ||
329 | kfree(kbd); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | static struct usb_device_id usb_kbd_id_table [] = { | ||
334 | { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, | ||
335 | USB_INTERFACE_PROTOCOL_KEYBOARD) }, | ||
336 | { } /* Terminating entry */ | ||
337 | }; | ||
338 | |||
339 | MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); | ||
340 | |||
341 | static struct usb_driver usb_kbd_driver = { | ||
342 | .name = "usbkbd", | ||
343 | .probe = usb_kbd_probe, | ||
344 | .disconnect = usb_kbd_disconnect, | ||
345 | .id_table = usb_kbd_id_table, | ||
346 | }; | ||
347 | |||
348 | static int __init usb_kbd_init(void) | ||
349 | { | ||
350 | int result = usb_register(&usb_kbd_driver); | ||
351 | if (result == 0) | ||
352 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
353 | return result; | ||
354 | } | ||
355 | |||
356 | static void __exit usb_kbd_exit(void) | ||
357 | { | ||
358 | usb_deregister(&usb_kbd_driver); | ||
359 | } | ||
360 | |||
361 | module_init(usb_kbd_init); | ||
362 | module_exit(usb_kbd_exit); | ||
diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c new file mode 100644 index 000000000000..692fd6087779 --- /dev/null +++ b/drivers/hid/usbhid/usbmouse.c | |||
@@ -0,0 +1,245 @@ | |||
1 | /* | ||
2 | * $Id: usbmouse.c,v 1.15 2001/12/27 10:37:41 vojtech Exp $ | ||
3 | * | ||
4 | * Copyright (c) 1999-2001 Vojtech Pavlik | ||
5 | * | ||
6 | * USB HIDBP Mouse support | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | * Should you need to contact me, the author, you can do so either by | ||
25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
27 | */ | ||
28 | |||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/usb/input.h> | ||
34 | #include <linux/hid.h> | ||
35 | |||
36 | /* | ||
37 | * Version Information | ||
38 | */ | ||
39 | #define DRIVER_VERSION "v1.6" | ||
40 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | ||
41 | #define DRIVER_DESC "USB HID Boot Protocol mouse driver" | ||
42 | #define DRIVER_LICENSE "GPL" | ||
43 | |||
44 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
45 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
46 | MODULE_LICENSE(DRIVER_LICENSE); | ||
47 | |||
48 | struct usb_mouse { | ||
49 | char name[128]; | ||
50 | char phys[64]; | ||
51 | struct usb_device *usbdev; | ||
52 | struct input_dev *dev; | ||
53 | struct urb *irq; | ||
54 | |||
55 | signed char *data; | ||
56 | dma_addr_t data_dma; | ||
57 | }; | ||
58 | |||
59 | static void usb_mouse_irq(struct urb *urb) | ||
60 | { | ||
61 | struct usb_mouse *mouse = urb->context; | ||
62 | signed char *data = mouse->data; | ||
63 | struct input_dev *dev = mouse->dev; | ||
64 | int status; | ||
65 | |||
66 | switch (urb->status) { | ||
67 | case 0: /* success */ | ||
68 | break; | ||
69 | case -ECONNRESET: /* unlink */ | ||
70 | case -ENOENT: | ||
71 | case -ESHUTDOWN: | ||
72 | return; | ||
73 | /* -EPIPE: should clear the halt */ | ||
74 | default: /* error */ | ||
75 | goto resubmit; | ||
76 | } | ||
77 | |||
78 | input_report_key(dev, BTN_LEFT, data[0] & 0x01); | ||
79 | input_report_key(dev, BTN_RIGHT, data[0] & 0x02); | ||
80 | input_report_key(dev, BTN_MIDDLE, data[0] & 0x04); | ||
81 | input_report_key(dev, BTN_SIDE, data[0] & 0x08); | ||
82 | input_report_key(dev, BTN_EXTRA, data[0] & 0x10); | ||
83 | |||
84 | input_report_rel(dev, REL_X, data[1]); | ||
85 | input_report_rel(dev, REL_Y, data[2]); | ||
86 | input_report_rel(dev, REL_WHEEL, data[3]); | ||
87 | |||
88 | input_sync(dev); | ||
89 | resubmit: | ||
90 | status = usb_submit_urb (urb, GFP_ATOMIC); | ||
91 | if (status) | ||
92 | err ("can't resubmit intr, %s-%s/input0, status %d", | ||
93 | mouse->usbdev->bus->bus_name, | ||
94 | mouse->usbdev->devpath, status); | ||
95 | } | ||
96 | |||
97 | static int usb_mouse_open(struct input_dev *dev) | ||
98 | { | ||
99 | struct usb_mouse *mouse = dev->private; | ||
100 | |||
101 | mouse->irq->dev = mouse->usbdev; | ||
102 | if (usb_submit_urb(mouse->irq, GFP_KERNEL)) | ||
103 | return -EIO; | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static void usb_mouse_close(struct input_dev *dev) | ||
109 | { | ||
110 | struct usb_mouse *mouse = dev->private; | ||
111 | |||
112 | usb_kill_urb(mouse->irq); | ||
113 | } | ||
114 | |||
115 | static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
116 | { | ||
117 | struct usb_device *dev = interface_to_usbdev(intf); | ||
118 | struct usb_host_interface *interface; | ||
119 | struct usb_endpoint_descriptor *endpoint; | ||
120 | struct usb_mouse *mouse; | ||
121 | struct input_dev *input_dev; | ||
122 | int pipe, maxp; | ||
123 | |||
124 | interface = intf->cur_altsetting; | ||
125 | |||
126 | if (interface->desc.bNumEndpoints != 1) | ||
127 | return -ENODEV; | ||
128 | |||
129 | endpoint = &interface->endpoint[0].desc; | ||
130 | if (!usb_endpoint_is_int_in(endpoint)) | ||
131 | return -ENODEV; | ||
132 | |||
133 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
134 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | ||
135 | |||
136 | mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL); | ||
137 | input_dev = input_allocate_device(); | ||
138 | if (!mouse || !input_dev) | ||
139 | goto fail1; | ||
140 | |||
141 | mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma); | ||
142 | if (!mouse->data) | ||
143 | goto fail1; | ||
144 | |||
145 | mouse->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
146 | if (!mouse->irq) | ||
147 | goto fail2; | ||
148 | |||
149 | mouse->usbdev = dev; | ||
150 | mouse->dev = input_dev; | ||
151 | |||
152 | if (dev->manufacturer) | ||
153 | strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name)); | ||
154 | |||
155 | if (dev->product) { | ||
156 | if (dev->manufacturer) | ||
157 | strlcat(mouse->name, " ", sizeof(mouse->name)); | ||
158 | strlcat(mouse->name, dev->product, sizeof(mouse->name)); | ||
159 | } | ||
160 | |||
161 | if (!strlen(mouse->name)) | ||
162 | snprintf(mouse->name, sizeof(mouse->name), | ||
163 | "USB HIDBP Mouse %04x:%04x", | ||
164 | le16_to_cpu(dev->descriptor.idVendor), | ||
165 | le16_to_cpu(dev->descriptor.idProduct)); | ||
166 | |||
167 | usb_make_path(dev, mouse->phys, sizeof(mouse->phys)); | ||
168 | strlcat(mouse->phys, "/input0", sizeof(mouse->phys)); | ||
169 | |||
170 | input_dev->name = mouse->name; | ||
171 | input_dev->phys = mouse->phys; | ||
172 | usb_to_input_id(dev, &input_dev->id); | ||
173 | input_dev->cdev.dev = &intf->dev; | ||
174 | |||
175 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
176 | input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
177 | input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
178 | input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA); | ||
179 | input_dev->relbit[0] |= BIT(REL_WHEEL); | ||
180 | |||
181 | input_dev->private = mouse; | ||
182 | input_dev->open = usb_mouse_open; | ||
183 | input_dev->close = usb_mouse_close; | ||
184 | |||
185 | usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data, | ||
186 | (maxp > 8 ? 8 : maxp), | ||
187 | usb_mouse_irq, mouse, endpoint->bInterval); | ||
188 | mouse->irq->transfer_dma = mouse->data_dma; | ||
189 | mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
190 | |||
191 | input_register_device(mouse->dev); | ||
192 | |||
193 | usb_set_intfdata(intf, mouse); | ||
194 | return 0; | ||
195 | |||
196 | fail2: usb_buffer_free(dev, 8, mouse->data, mouse->data_dma); | ||
197 | fail1: input_free_device(input_dev); | ||
198 | kfree(mouse); | ||
199 | return -ENOMEM; | ||
200 | } | ||
201 | |||
202 | static void usb_mouse_disconnect(struct usb_interface *intf) | ||
203 | { | ||
204 | struct usb_mouse *mouse = usb_get_intfdata (intf); | ||
205 | |||
206 | usb_set_intfdata(intf, NULL); | ||
207 | if (mouse) { | ||
208 | usb_kill_urb(mouse->irq); | ||
209 | input_unregister_device(mouse->dev); | ||
210 | usb_free_urb(mouse->irq); | ||
211 | usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma); | ||
212 | kfree(mouse); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | static struct usb_device_id usb_mouse_id_table [] = { | ||
217 | { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, | ||
218 | USB_INTERFACE_PROTOCOL_MOUSE) }, | ||
219 | { } /* Terminating entry */ | ||
220 | }; | ||
221 | |||
222 | MODULE_DEVICE_TABLE (usb, usb_mouse_id_table); | ||
223 | |||
224 | static struct usb_driver usb_mouse_driver = { | ||
225 | .name = "usbmouse", | ||
226 | .probe = usb_mouse_probe, | ||
227 | .disconnect = usb_mouse_disconnect, | ||
228 | .id_table = usb_mouse_id_table, | ||
229 | }; | ||
230 | |||
231 | static int __init usb_mouse_init(void) | ||
232 | { | ||
233 | int retval = usb_register(&usb_mouse_driver); | ||
234 | if (retval == 0) | ||
235 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
236 | return retval; | ||
237 | } | ||
238 | |||
239 | static void __exit usb_mouse_exit(void) | ||
240 | { | ||
241 | usb_deregister(&usb_mouse_driver); | ||
242 | } | ||
243 | |||
244 | module_init(usb_mouse_init); | ||
245 | module_exit(usb_mouse_exit); | ||