diff options
Diffstat (limited to 'drivers/usb/input')
-rw-r--r-- | drivers/usb/input/Kconfig | 237 | ||||
-rw-r--r-- | drivers/usb/input/Makefile | 39 | ||||
-rw-r--r-- | drivers/usb/input/aiptek.c | 2283 | ||||
-rw-r--r-- | drivers/usb/input/ati_remote.c | 850 | ||||
-rw-r--r-- | drivers/usb/input/fixp-arith.h | 90 | ||||
-rw-r--r-- | drivers/usb/input/hid-core.c | 1864 | ||||
-rw-r--r-- | drivers/usb/input/hid-debug.h | 720 | ||||
-rw-r--r-- | drivers/usb/input/hid-ff.c | 94 | ||||
-rw-r--r-- | drivers/usb/input/hid-input.c | 630 | ||||
-rw-r--r-- | drivers/usb/input/hid-lgff.c | 528 | ||||
-rw-r--r-- | drivers/usb/input/hid-tmff.c | 463 | ||||
-rw-r--r-- | drivers/usb/input/hid.h | 510 | ||||
-rw-r--r-- | drivers/usb/input/hiddev.c | 844 | ||||
-rw-r--r-- | drivers/usb/input/kbtab.c | 241 | ||||
-rw-r--r-- | drivers/usb/input/mtouchusb.c | 367 | ||||
-rw-r--r-- | drivers/usb/input/pid.c | 295 | ||||
-rw-r--r-- | drivers/usb/input/pid.h | 62 | ||||
-rw-r--r-- | drivers/usb/input/powermate.c | 464 | ||||
-rw-r--r-- | drivers/usb/input/touchkitusb.c | 310 | ||||
-rw-r--r-- | drivers/usb/input/usbkbd.c | 370 | ||||
-rw-r--r-- | drivers/usb/input/usbmouse.c | 252 | ||||
-rw-r--r-- | drivers/usb/input/wacom.c | 951 | ||||
-rw-r--r-- | drivers/usb/input/xpad.c | 362 |
23 files changed, 12826 insertions, 0 deletions
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig new file mode 100644 index 000000000000..d28e7eab6f98 --- /dev/null +++ b/drivers/usb/input/Kconfig | |||
@@ -0,0 +1,237 @@ | |||
1 | # | ||
2 | # USB Input driver configuration | ||
3 | # | ||
4 | comment "USB Input Devices" | ||
5 | depends on USB | ||
6 | |||
7 | config USB_HID | ||
8 | tristate "USB Human Interface Device (full HID) support" | ||
9 | depends on USB | ||
10 | ---help--- | ||
11 | Say Y here if you want full HID support to connect keyboards, | ||
12 | mice, joysticks, graphic tablets, or any other HID based devices | ||
13 | to your computer via USB. You also need to select HID Input layer | ||
14 | support (below) if you want to use keyboards, mice, joysticks and | ||
15 | the like ... as well as Uninterruptible Power Supply (UPS) and | ||
16 | monitor control devices. | ||
17 | |||
18 | You can't use this driver and the HIDBP (Boot Protocol) keyboard | ||
19 | and mouse drivers at the same time. More information is available: | ||
20 | <file:Documentation/input/input.txt>. | ||
21 | |||
22 | If unsure, say Y. | ||
23 | |||
24 | To compile this driver as a module, choose M here: the | ||
25 | module will be called usbhid. | ||
26 | |||
27 | comment "Input core support is needed for USB HID input layer or HIDBP support" | ||
28 | depends on USB_HID && INPUT=n | ||
29 | |||
30 | config USB_HIDINPUT | ||
31 | bool "HID input layer support" | ||
32 | default y | ||
33 | depends on INPUT && USB_HID | ||
34 | help | ||
35 | Say Y here if you want to use a USB keyboard, mouse or joystick, | ||
36 | or any other HID input device. | ||
37 | |||
38 | If unsure, say Y. | ||
39 | |||
40 | config HID_FF | ||
41 | bool "Force feedback support (EXPERIMENTAL)" | ||
42 | depends on USB_HIDINPUT && EXPERIMENTAL | ||
43 | help | ||
44 | Say Y here is you want force feedback support for a few HID devices. | ||
45 | See below for a list of supported devices. | ||
46 | |||
47 | See <file:Documentation/input/ff.txt> for a description of the force | ||
48 | feedback API. | ||
49 | |||
50 | If unsure, say N. | ||
51 | |||
52 | config HID_PID | ||
53 | bool "PID Devices (Microsoft Sidewinder Force Feedback 2)" | ||
54 | depends on HID_FF | ||
55 | help | ||
56 | Say Y here if you have a PID-compliant joystick and wish to enable force | ||
57 | feedback for it. The Microsoft Sidewinder Force Feedback 2 is one such | ||
58 | device. | ||
59 | |||
60 | config LOGITECH_FF | ||
61 | bool "Logitech WingMan *3D support" | ||
62 | depends on HID_FF | ||
63 | help | ||
64 | Say Y here if you have one of these devices: | ||
65 | - Logitech WingMan Cordless RumblePad | ||
66 | - Logitech WingMan Force 3D | ||
67 | and if you want to enable force feedback for them. | ||
68 | Note: if you say N here, this device will still be supported, but without | ||
69 | force feedback. | ||
70 | |||
71 | config THRUSTMASTER_FF | ||
72 | bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)" | ||
73 | depends on HID_FF && EXPERIMENTAL | ||
74 | help | ||
75 | Say Y here if you have a THRUSTMASTER FireStore Dual Power 2, | ||
76 | and want to enable force feedback support for it. | ||
77 | Note: if you say N here, this device will still be supported, but without | ||
78 | force feedback. | ||
79 | |||
80 | config USB_HIDDEV | ||
81 | bool "/dev/hiddev raw HID device support" | ||
82 | depends on USB_HID | ||
83 | help | ||
84 | Say Y here if you want to support HID devices (from the USB | ||
85 | specification standpoint) that aren't strictly user interface | ||
86 | devices, like monitor controls and Uninterruptable Power Supplies. | ||
87 | |||
88 | This module supports these devices separately using a separate | ||
89 | event interface on /dev/usb/hiddevX (char 180:96 to 180:111). | ||
90 | |||
91 | If unsure, say Y. | ||
92 | |||
93 | menu "USB HID Boot Protocol drivers" | ||
94 | depends on USB!=n && USB_HID!=y | ||
95 | |||
96 | config USB_KBD | ||
97 | tristate "USB HIDBP Keyboard (simple Boot) support" | ||
98 | depends on USB && INPUT | ||
99 | ---help--- | ||
100 | Say Y here only if you are absolutely sure that you don't want | ||
101 | to use the generic HID driver for your USB keyboard and prefer | ||
102 | to use the keyboard in its limited Boot Protocol mode instead. | ||
103 | |||
104 | This is almost certainly not what you want. This is mostly | ||
105 | useful for embedded applications or simple keyboards. | ||
106 | |||
107 | To compile this driver as a module, choose M here: the | ||
108 | module will be called usbkbd. | ||
109 | |||
110 | If even remotely unsure, say N. | ||
111 | |||
112 | config USB_MOUSE | ||
113 | tristate "USB HIDBP Mouse (simple Boot) support" | ||
114 | depends on USB && INPUT | ||
115 | ---help--- | ||
116 | Say Y here only if you are absolutely sure that you don't want | ||
117 | to use the generic HID driver for your USB mouse and prefer | ||
118 | to use the mouse in its limited Boot Protocol mode instead. | ||
119 | |||
120 | This is almost certainly not what you want. This is mostly | ||
121 | useful for embedded applications or simple mice. | ||
122 | |||
123 | To compile this driver as a module, choose M here: the | ||
124 | module will be called usbmouse. | ||
125 | |||
126 | If even remotely unsure, say N. | ||
127 | |||
128 | endmenu | ||
129 | |||
130 | config USB_AIPTEK | ||
131 | tristate "Aiptek 6000U/8000U tablet support" | ||
132 | depends on USB && INPUT | ||
133 | help | ||
134 | Say Y here if you want to use the USB version of the Aiptek 6000U | ||
135 | or Aiptek 8000U tablet. Make sure to say Y to "Mouse support" | ||
136 | (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" | ||
137 | (CONFIG_INPUT_EVDEV) as well. | ||
138 | |||
139 | To compile this driver as a module, choose M here: the | ||
140 | module will be called aiptek. | ||
141 | |||
142 | config USB_WACOM | ||
143 | tristate "Wacom Intuos/Graphire tablet support" | ||
144 | depends on USB && INPUT | ||
145 | help | ||
146 | Say Y here if you want to use the USB version of the Wacom Intuos | ||
147 | or Graphire tablet. Make sure to say Y to "Mouse support" | ||
148 | (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" | ||
149 | (CONFIG_INPUT_EVDEV) as well. | ||
150 | |||
151 | To compile this driver as a module, choose M here: the | ||
152 | module will be called wacom. | ||
153 | |||
154 | config USB_KBTAB | ||
155 | tristate "KB Gear JamStudio tablet support" | ||
156 | depends on USB && INPUT | ||
157 | help | ||
158 | Say Y here if you want to use the USB version of the KB Gear | ||
159 | JamStudio tablet. Make sure to say Y to "Mouse support" | ||
160 | (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" | ||
161 | (CONFIG_INPUT_EVDEV) as well. | ||
162 | |||
163 | To compile this driver as a module, choose M here: the | ||
164 | module will be called kbtab. | ||
165 | |||
166 | config USB_POWERMATE | ||
167 | tristate "Griffin PowerMate and Contour Jog support" | ||
168 | depends on USB && INPUT | ||
169 | ---help--- | ||
170 | Say Y here if you want to use Griffin PowerMate or Contour Jog devices. | ||
171 | These are aluminum dials which can measure clockwise and anticlockwise | ||
172 | rotation. The dial also acts as a pushbutton. The base contains an LED | ||
173 | which can be instructed to pulse or to switch to a particular intensity. | ||
174 | |||
175 | You can download userspace tools from | ||
176 | <http://sowerbutts.com/powermate/>. | ||
177 | |||
178 | To compile this driver as a module, choose M here: the | ||
179 | module will be called powermate. | ||
180 | |||
181 | config USB_MTOUCH | ||
182 | tristate "MicroTouch USB Touchscreen Driver" | ||
183 | depends on USB && INPUT | ||
184 | ---help--- | ||
185 | Say Y here if you want to use a MicroTouch (Now 3M) USB | ||
186 | Touchscreen controller. | ||
187 | |||
188 | See <file:Documentation/usb/mtouch.txt> for additional information. | ||
189 | |||
190 | To compile this driver as a module, choose M here: the | ||
191 | module will be called mtouchusb. | ||
192 | |||
193 | config USB_EGALAX | ||
194 | tristate "eGalax TouchKit USB Touchscreen Driver" | ||
195 | depends on USB && INPUT | ||
196 | ---help--- | ||
197 | Say Y here if you want to use a eGalax TouchKit USB | ||
198 | Touchscreen controller. | ||
199 | |||
200 | The driver has been tested on a Xenarc 700TSV monitor | ||
201 | with eGalax touchscreen. | ||
202 | |||
203 | Have a look at <http://linux.chapter7.ch/touchkit/> for | ||
204 | a usage description and the required user-space stuff. | ||
205 | |||
206 | To compile this driver as a module, choose M here: the | ||
207 | module will be called touchkitusb. | ||
208 | |||
209 | config USB_XPAD | ||
210 | tristate "X-Box gamepad support" | ||
211 | depends on USB && INPUT | ||
212 | ---help--- | ||
213 | Say Y here if you want to use the X-Box pad with your computer. | ||
214 | Make sure to say Y to "Joystick support" (CONFIG_INPUT_JOYDEV) | ||
215 | and/or "Event interface support" (CONFIG_INPUT_EVDEV) as well. | ||
216 | |||
217 | For information about how to connect the X-Box pad to USB, see | ||
218 | <file:Documentation/input/xpad.txt>. | ||
219 | |||
220 | To compile this driver as a module, choose M here: the | ||
221 | module will be called xpad. | ||
222 | |||
223 | config USB_ATI_REMOTE | ||
224 | tristate "ATI / X10 USB RF remote control" | ||
225 | depends on USB && INPUT | ||
226 | ---help--- | ||
227 | Say Y here if you want to use an ATI or X10 "Lola" USB remote control. | ||
228 | These are RF remotes with USB receivers. | ||
229 | The ATI remote comes with many of ATI's All-In-Wonder video cards. | ||
230 | The X10 "Lola" remote is available at: | ||
231 | <http://www.x10.com/products/lola_sg1.htm> | ||
232 | This driver provides mouse pointer, left and right mouse buttons, | ||
233 | and maps all the other remote buttons to keypress events. | ||
234 | |||
235 | To compile this driver as a module, choose M here: the module will be | ||
236 | called ati_remote. | ||
237 | |||
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile new file mode 100644 index 000000000000..6bcedd16b0a1 --- /dev/null +++ b/drivers/usb/input/Makefile | |||
@@ -0,0 +1,39 @@ | |||
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_USB_HIDINPUT),y) | ||
14 | usbhid-objs += hid-input.o | ||
15 | endif | ||
16 | ifeq ($(CONFIG_HID_PID),y) | ||
17 | usbhid-objs += pid.o | ||
18 | endif | ||
19 | ifeq ($(CONFIG_LOGITECH_FF),y) | ||
20 | usbhid-objs += hid-lgff.o | ||
21 | endif | ||
22 | ifeq ($(CONFIG_THRUSTMASTER_FF),y) | ||
23 | usbhid-objs += hid-tmff.o | ||
24 | endif | ||
25 | ifeq ($(CONFIG_HID_FF),y) | ||
26 | usbhid-objs += hid-ff.o | ||
27 | endif | ||
28 | |||
29 | obj-$(CONFIG_USB_AIPTEK) += aiptek.o | ||
30 | obj-$(CONFIG_USB_ATI_REMOTE) += ati_remote.o | ||
31 | obj-$(CONFIG_USB_HID) += usbhid.o | ||
32 | obj-$(CONFIG_USB_KBD) += usbkbd.o | ||
33 | obj-$(CONFIG_USB_KBTAB) += kbtab.o | ||
34 | obj-$(CONFIG_USB_MOUSE) += usbmouse.o | ||
35 | obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o | ||
36 | obj-$(CONFIG_USB_EGALAX) += touchkitusb.o | ||
37 | obj-$(CONFIG_USB_POWERMATE) += powermate.o | ||
38 | obj-$(CONFIG_USB_WACOM) += wacom.o | ||
39 | obj-$(CONFIG_USB_XPAD) += xpad.o | ||
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c new file mode 100644 index 000000000000..d7fea9ea301b --- /dev/null +++ b/drivers/usb/input/aiptek.c | |||
@@ -0,0 +1,2283 @@ | |||
1 | /* | ||
2 | * Native support for the Aiptek HyperPen USB Tablets | ||
3 | * (4000U/5000U/6000U/8000U/12000U) | ||
4 | * | ||
5 | * Copyright (c) 2001 Chris Atenasio <chris@crud.net> | ||
6 | * Copyright (c) 2002-2004 Bryan W. Headley <bwheadley@earthlink.net> | ||
7 | * | ||
8 | * based on wacom.c by | ||
9 | * Vojtech Pavlik <vojtech@suse.cz> | ||
10 | * Andreas Bach Aaen <abach@stofanet.dk> | ||
11 | * Clifford Wolf <clifford@clifford.at> | ||
12 | * Sam Mosel <sam.mosel@computer.org> | ||
13 | * James E. Blair <corvus@gnu.org> | ||
14 | * Daniel Egger <egger@suse.de> | ||
15 | * | ||
16 | * Many thanks to Oliver Kuechemann for his support. | ||
17 | * | ||
18 | * ChangeLog: | ||
19 | * v0.1 - Initial release | ||
20 | * v0.2 - Hack to get around fake event 28's. (Bryan W. Headley) | ||
21 | * v0.3 - Make URB dynamic (Bryan W. Headley, Jun-8-2002) | ||
22 | * Released to Linux 2.4.19 and 2.5.x | ||
23 | * v0.4 - Rewrote substantial portions of the code to deal with | ||
24 | * corrected control sequences, timing, dynamic configuration, | ||
25 | * support of 6000U - 12000U, procfs, and macro key support | ||
26 | * (Jan-1-2003 - Feb-5-2003, Bryan W. Headley) | ||
27 | * v1.0 - Added support for diagnostic messages, count of messages | ||
28 | * received from URB - Mar-8-2003, Bryan W. Headley | ||
29 | * v1.1 - added support for tablet resolution, changed DV and proximity | ||
30 | * some corrections - Jun-22-2003, martin schneebacher | ||
31 | * - Added support for the sysfs interface, deprecating the | ||
32 | * procfs interface for 2.5.x kernel. Also added support for | ||
33 | * Wheel command. Bryan W. Headley July-15-2003. | ||
34 | * v1.2 - Reworked jitter timer as a kernel thread. | ||
35 | * Bryan W. Headley November-28-2003/Jan-10-2004. | ||
36 | * v1.3 - Repaired issue of kernel thread going nuts on single-processor | ||
37 | * machines, introduced programmableDelay as a command line | ||
38 | * parameter. Feb 7 2004, Bryan W. Headley. | ||
39 | * v1.4 - Re-wire jitter so it does not require a thread. Courtesy of | ||
40 | * Rene van Paassen. Added reporting of physical pointer device | ||
41 | * (e.g., stylus, mouse in reports 2, 3, 4, 5. We don't know | ||
42 | * for reports 1, 6.) | ||
43 | * what physical device reports for reports 1, 6.) Also enabled | ||
44 | * MOUSE and LENS tool button modes. Renamed "rubber" to "eraser". | ||
45 | * Feb 20, 2004, Bryan W. Headley. | ||
46 | * v1.5 - Added previousJitterable, so we don't do jitter delay when the | ||
47 | * user is holding a button down for periods of time. | ||
48 | * | ||
49 | * NOTE: | ||
50 | * This kernel driver is augmented by the "Aiptek" XFree86 input | ||
51 | * driver for your X server, as well as the Gaiptek GUI Front-end | ||
52 | * "Tablet Manager". | ||
53 | * These three products are highly interactive with one another, | ||
54 | * so therefore it's easier to document them all as one subsystem. | ||
55 | * Please visit the project's "home page", located at, | ||
56 | * http://aiptektablet.sourceforge.net. | ||
57 | * | ||
58 | * This program is free software; you can redistribute it and/or modify | ||
59 | * it under the terms of the GNU General Public License as published by | ||
60 | * the Free Software Foundation; either version 2 of the License, or | ||
61 | * (at your option) any later version. | ||
62 | * | ||
63 | * This program is distributed in the hope that it will be useful, | ||
64 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
65 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
66 | * GNU General Public License for more details. | ||
67 | * | ||
68 | * You should have received a copy of the GNU General Public License | ||
69 | * along with this program; if not, write to the Free Software | ||
70 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
71 | */ | ||
72 | |||
73 | #include <linux/jiffies.h> | ||
74 | #include <linux/kernel.h> | ||
75 | #include <linux/slab.h> | ||
76 | #include <linux/input.h> | ||
77 | #include <linux/module.h> | ||
78 | #include <linux/init.h> | ||
79 | #include <linux/usb.h> | ||
80 | #include <linux/sched.h> | ||
81 | #include <asm/uaccess.h> | ||
82 | #include <asm/unaligned.h> | ||
83 | |||
84 | /* | ||
85 | * Version Information | ||
86 | */ | ||
87 | #define DRIVER_VERSION "v1.5 (May-15-2004)" | ||
88 | #define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio" | ||
89 | #define DRIVER_DESC "Aiptek HyperPen USB Tablet Driver (Linux 2.6.x)" | ||
90 | |||
91 | /* | ||
92 | * Aiptek status packet: | ||
93 | * | ||
94 | * (returned as Report 1 - relative coordinates from mouse and stylus) | ||
95 | * | ||
96 | * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 | ||
97 | * byte0 0 0 0 0 0 0 0 1 | ||
98 | * byte1 0 0 0 0 0 BS2 BS Tip | ||
99 | * byte2 X7 X6 X5 X4 X3 X2 X1 X0 | ||
100 | * byte3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 | ||
101 | * | ||
102 | * (returned as Report 2 - absolute coordinates from the stylus) | ||
103 | * | ||
104 | * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 | ||
105 | * byte0 0 0 0 0 0 0 1 0 | ||
106 | * byte1 X7 X6 X5 X4 X3 X2 X1 X0 | ||
107 | * byte2 X15 X14 X13 X12 X11 X10 X9 X8 | ||
108 | * byte3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 | ||
109 | * byte4 Y15 Y14 Y13 Y12 Y11 Y10 Y9 Y8 | ||
110 | * byte5 * * * BS2 BS1 Tip IR DV | ||
111 | * byte6 P7 P6 P5 P4 P3 P2 P1 P0 | ||
112 | * byte7 P15 P14 P13 P12 P11 P10 P9 P8 | ||
113 | * | ||
114 | * (returned as Report 3 - absolute coordinates from the mouse) | ||
115 | * | ||
116 | * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 | ||
117 | * byte0 0 0 0 0 0 0 1 0 | ||
118 | * byte1 X7 X6 X5 X4 X3 X2 X1 X0 | ||
119 | * byte2 X15 X14 X13 X12 X11 X10 X9 X8 | ||
120 | * byte3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 | ||
121 | * byte4 Y15 Y14 Y13 Y12 Y11 Y10 Y9 Y8 | ||
122 | * byte5 * * * BS2 BS1 Tip IR DV | ||
123 | * byte6 P7 P6 P5 P4 P3 P2 P1 P0 | ||
124 | * byte7 P15 P14 P13 P12 P11 P10 P9 P8 | ||
125 | * | ||
126 | * (returned as Report 4 - macrokeys from the stylus) | ||
127 | * | ||
128 | * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 | ||
129 | * byte0 0 0 0 0 0 1 0 0 | ||
130 | * byte1 0 0 0 BS2 BS Tip IR DV | ||
131 | * byte2 0 0 0 0 0 0 1 0 | ||
132 | * byte3 0 0 0 K4 K3 K2 K1 K0 | ||
133 | * byte4 P7 P6 P5 P4 P3 P2 P1 P0 | ||
134 | * byte5 P15 P14 P13 P12 P11 P10 P9 P8 | ||
135 | * | ||
136 | * (returned as Report 5 - macrokeys from the mouse) | ||
137 | * | ||
138 | * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 | ||
139 | * byte0 0 0 0 0 0 1 0 0 | ||
140 | * byte1 0 0 0 BS2 BS Tip IR DV | ||
141 | * byte2 0 0 0 0 0 0 1 0 | ||
142 | * byte3 0 0 0 K4 K3 K2 K1 K0 | ||
143 | * byte4 P7 P6 P5 P4 P3 P2 P1 P0 | ||
144 | * byte5 P15 P14 P13 P12 P11 P10 P9 P8 | ||
145 | * | ||
146 | * IR: In Range = Proximity on | ||
147 | * DV = Data Valid | ||
148 | * BS = Barrel Switch (as in, macro keys) | ||
149 | * BS2 also referred to as Tablet Pick | ||
150 | * | ||
151 | * Command Summary: | ||
152 | * | ||
153 | * Use report_type CONTROL (3) | ||
154 | * Use report_id 2 | ||
155 | * | ||
156 | * Command/Data Description Return Bytes Return Value | ||
157 | * 0x10/0x00 SwitchToMouse 0 | ||
158 | * 0x10/0x01 SwitchToTablet 0 | ||
159 | * 0x18/0x04 SetResolution 0 | ||
160 | * 0x12/0xFF AutoGainOn 0 | ||
161 | * 0x17/0x00 FilterOn 0 | ||
162 | * 0x01/0x00 GetXExtension 2 MaxX | ||
163 | * 0x01/0x01 GetYExtension 2 MaxY | ||
164 | * 0x02/0x00 GetModelCode 2 ModelCode = LOBYTE | ||
165 | * 0x03/0x00 GetODMCode 2 ODMCode | ||
166 | * 0x08/0x00 GetPressureLevels 2 =512 | ||
167 | * 0x04/0x00 GetFirmwareVersion 2 Firmware Version | ||
168 | * 0x11/0x02 EnableMacroKeys 0 | ||
169 | * | ||
170 | * To initialize the tablet: | ||
171 | * | ||
172 | * (1) Send Resolution500LPI (Command) | ||
173 | * (2) Query for Model code (Option Report) | ||
174 | * (3) Query for ODM code (Option Report) | ||
175 | * (4) Query for firmware (Option Report) | ||
176 | * (5) Query for GetXExtension (Option Report) | ||
177 | * (6) Query for GetYExtension (Option Report) | ||
178 | * (7) Query for GetPressureLevels (Option Report) | ||
179 | * (8) SwitchToTablet for Absolute coordinates, or | ||
180 | * SwitchToMouse for Relative coordinates (Command) | ||
181 | * (9) EnableMacroKeys (Command) | ||
182 | * (10) FilterOn (Command) | ||
183 | * (11) AutoGainOn (Command) | ||
184 | * | ||
185 | * (Step 9 can be omitted, but you'll then have no function keys.) | ||
186 | */ | ||
187 | |||
188 | #define USB_VENDOR_ID_AIPTEK 0x08ca | ||
189 | #define USB_REQ_GET_REPORT 0x01 | ||
190 | #define USB_REQ_SET_REPORT 0x09 | ||
191 | |||
192 | /* PointerMode codes | ||
193 | */ | ||
194 | #define AIPTEK_POINTER_ONLY_MOUSE_MODE 0 | ||
195 | #define AIPTEK_POINTER_ONLY_STYLUS_MODE 1 | ||
196 | #define AIPTEK_POINTER_EITHER_MODE 2 | ||
197 | |||
198 | #define AIPTEK_POINTER_ALLOW_MOUSE_MODE(a) \ | ||
199 | (a == AIPTEK_POINTER_ONLY_MOUSE_MODE || \ | ||
200 | a == AIPTEK_POINTER_EITHER_MODE) | ||
201 | #define AIPTEK_POINTER_ALLOW_STYLUS_MODE(a) \ | ||
202 | (a == AIPTEK_POINTER_ONLY_STYLUS_MODE || \ | ||
203 | a == AIPTEK_POINTER_EITHER_MODE) | ||
204 | |||
205 | /* CoordinateMode code | ||
206 | */ | ||
207 | #define AIPTEK_COORDINATE_RELATIVE_MODE 0 | ||
208 | #define AIPTEK_COORDINATE_ABSOLUTE_MODE 1 | ||
209 | |||
210 | /* XTilt and YTilt values | ||
211 | */ | ||
212 | #define AIPTEK_TILT_MIN (-128) | ||
213 | #define AIPTEK_TILT_MAX 127 | ||
214 | #define AIPTEK_TILT_DISABLE (-10101) | ||
215 | |||
216 | /* Wheel values | ||
217 | */ | ||
218 | #define AIPTEK_WHEEL_MIN 0 | ||
219 | #define AIPTEK_WHEEL_MAX 1024 | ||
220 | #define AIPTEK_WHEEL_DISABLE (-10101) | ||
221 | |||
222 | /* ToolCode values, which BTW are 0x140 .. 0x14f | ||
223 | * We have things set up such that if TOOL_BUTTON_FIRED_BIT is | ||
224 | * not set, we'll send one instance of AIPTEK_TOOL_BUTTON_xxx. | ||
225 | * | ||
226 | * Whenever the user resets the value, TOOL_BUTTON_FIRED_BIT will | ||
227 | * get reset. | ||
228 | */ | ||
229 | #define TOOL_BUTTON(x) ((x) & 0x14f) | ||
230 | #define TOOL_BUTTON_FIRED(x) ((x) & 0x200) | ||
231 | #define TOOL_BUTTON_FIRED_BIT 0x200 | ||
232 | /* toolMode codes | ||
233 | */ | ||
234 | #define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN | ||
235 | #define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN | ||
236 | #define AIPTEK_TOOL_BUTTON_PENCIL_MODE BTN_TOOL_PENCIL | ||
237 | #define AIPTEK_TOOL_BUTTON_BRUSH_MODE BTN_TOOL_BRUSH | ||
238 | #define AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE BTN_TOOL_AIRBRUSH | ||
239 | #define AIPTEK_TOOL_BUTTON_ERASER_MODE BTN_TOOL_RUBBER | ||
240 | #define AIPTEK_TOOL_BUTTON_MOUSE_MODE BTN_TOOL_MOUSE | ||
241 | #define AIPTEK_TOOL_BUTTON_LENS_MODE BTN_TOOL_LENS | ||
242 | |||
243 | /* Diagnostic message codes | ||
244 | */ | ||
245 | #define AIPTEK_DIAGNOSTIC_NA 0 | ||
246 | #define AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE 1 | ||
247 | #define AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE 2 | ||
248 | #define AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED 3 | ||
249 | |||
250 | /* Time to wait (in ms) to help mask hand jittering | ||
251 | * when pressing the stylus buttons. | ||
252 | */ | ||
253 | #define AIPTEK_JITTER_DELAY_DEFAULT 50 | ||
254 | |||
255 | /* Time to wait (in ms) in-between sending the tablet | ||
256 | * a command and beginning the process of reading the return | ||
257 | * sequence from the tablet. | ||
258 | */ | ||
259 | #define AIPTEK_PROGRAMMABLE_DELAY_25 25 | ||
260 | #define AIPTEK_PROGRAMMABLE_DELAY_50 50 | ||
261 | #define AIPTEK_PROGRAMMABLE_DELAY_100 100 | ||
262 | #define AIPTEK_PROGRAMMABLE_DELAY_200 200 | ||
263 | #define AIPTEK_PROGRAMMABLE_DELAY_300 300 | ||
264 | #define AIPTEK_PROGRAMMABLE_DELAY_400 400 | ||
265 | #define AIPTEK_PROGRAMMABLE_DELAY_DEFAULT AIPTEK_PROGRAMMABLE_DELAY_400 | ||
266 | |||
267 | /* Mouse button programming | ||
268 | */ | ||
269 | #define AIPTEK_MOUSE_LEFT_BUTTON 0x01 | ||
270 | #define AIPTEK_MOUSE_RIGHT_BUTTON 0x02 | ||
271 | #define AIPTEK_MOUSE_MIDDLE_BUTTON 0x04 | ||
272 | |||
273 | /* Stylus button programming | ||
274 | */ | ||
275 | #define AIPTEK_STYLUS_LOWER_BUTTON 0x08 | ||
276 | #define AIPTEK_STYLUS_UPPER_BUTTON 0x10 | ||
277 | |||
278 | /* Length of incoming packet from the tablet | ||
279 | */ | ||
280 | #define AIPTEK_PACKET_LENGTH 8 | ||
281 | |||
282 | /* We report in EV_MISC both the proximity and | ||
283 | * whether the report came from the stylus, tablet mouse | ||
284 | * or "unknown" -- Unknown when the tablet is in relative | ||
285 | * mode, because we only get report 1's. | ||
286 | */ | ||
287 | #define AIPTEK_REPORT_TOOL_UNKNOWN 0x10 | ||
288 | #define AIPTEK_REPORT_TOOL_STYLUS 0x20 | ||
289 | #define AIPTEK_REPORT_TOOL_MOUSE 0x40 | ||
290 | |||
291 | static int programmableDelay = AIPTEK_PROGRAMMABLE_DELAY_DEFAULT; | ||
292 | static int jitterDelay = AIPTEK_JITTER_DELAY_DEFAULT; | ||
293 | |||
294 | struct aiptek_features { | ||
295 | int odmCode; /* Tablet manufacturer code */ | ||
296 | int modelCode; /* Tablet model code (not unique) */ | ||
297 | int firmwareCode; /* prom/eeprom version */ | ||
298 | char usbPath[64 + 1]; /* device's physical usb path */ | ||
299 | char inputPath[64 + 1]; /* input device path */ | ||
300 | }; | ||
301 | |||
302 | struct aiptek_settings { | ||
303 | int pointerMode; /* stylus-, mouse-only or either */ | ||
304 | int coordinateMode; /* absolute/relative coords */ | ||
305 | int toolMode; /* pen, pencil, brush, etc. tool */ | ||
306 | int xTilt; /* synthetic xTilt amount */ | ||
307 | int yTilt; /* synthetic yTilt amount */ | ||
308 | int wheel; /* synthetic wheel amount */ | ||
309 | int stylusButtonUpper; /* stylus upper btn delivers... */ | ||
310 | int stylusButtonLower; /* stylus lower btn delivers... */ | ||
311 | int mouseButtonLeft; /* mouse left btn delivers... */ | ||
312 | int mouseButtonMiddle; /* mouse middle btn delivers... */ | ||
313 | int mouseButtonRight; /* mouse right btn delivers... */ | ||
314 | int programmableDelay; /* delay for tablet programming */ | ||
315 | int jitterDelay; /* delay for hand jittering */ | ||
316 | }; | ||
317 | |||
318 | struct aiptek { | ||
319 | struct input_dev inputdev; /* input device struct */ | ||
320 | struct usb_device *usbdev; /* usb device struct */ | ||
321 | struct urb *urb; /* urb for incoming reports */ | ||
322 | dma_addr_t data_dma; /* our dma stuffage */ | ||
323 | struct aiptek_features features; /* tablet's array of features */ | ||
324 | struct aiptek_settings curSetting; /* tablet's current programmable */ | ||
325 | struct aiptek_settings newSetting; /* ... and new param settings */ | ||
326 | unsigned int ifnum; /* interface number for IO */ | ||
327 | int openCount; /* module use counter */ | ||
328 | int diagnostic; /* tablet diagnostic codes */ | ||
329 | unsigned long eventCount; /* event count */ | ||
330 | int inDelay; /* jitter: in jitter delay? */ | ||
331 | unsigned long endDelay; /* jitter: time when delay ends */ | ||
332 | int previousJitterable; /* jitterable prev value */ | ||
333 | unsigned char *data; /* incoming packet data */ | ||
334 | }; | ||
335 | |||
336 | /* | ||
337 | * Permit easy lookup of keyboard events to send, versus | ||
338 | * the bitmap which comes from the tablet. This hides the | ||
339 | * issue that the F_keys are not sequentially numbered. | ||
340 | */ | ||
341 | static int macroKeyEvents[] = { | ||
342 | KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, | ||
343 | KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, | ||
344 | KEY_F12, KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17, | ||
345 | KEY_F18, KEY_F19, KEY_F20, KEY_F21, KEY_F22, KEY_F23, | ||
346 | KEY_F24, KEY_STOP, KEY_AGAIN, KEY_PROPS, KEY_UNDO, | ||
347 | KEY_FRONT, KEY_COPY, KEY_OPEN, KEY_PASTE, 0 | ||
348 | }; | ||
349 | |||
350 | /*********************************************************************** | ||
351 | * Relative reports deliver values in 2's complement format to | ||
352 | * deal with negative offsets. | ||
353 | */ | ||
354 | static int aiptek_convert_from_2s_complement(unsigned char c) | ||
355 | { | ||
356 | int ret; | ||
357 | unsigned char b = c; | ||
358 | int negate = 0; | ||
359 | |||
360 | if ((b & 0x80) != 0) { | ||
361 | b = ~b; | ||
362 | b--; | ||
363 | negate = 1; | ||
364 | } | ||
365 | ret = b; | ||
366 | ret = (negate == 1) ? -ret : ret; | ||
367 | return ret; | ||
368 | } | ||
369 | |||
370 | /*********************************************************************** | ||
371 | * aiptek_irq can receive one of six potential reports. | ||
372 | * The documentation for each is in the body of the function. | ||
373 | * | ||
374 | * The tablet reports on several attributes per invocation of | ||
375 | * aiptek_irq. Because the Linux Input Event system allows the | ||
376 | * transmission of ONE attribute per input_report_xxx() call, | ||
377 | * collation has to be done on the other end to reconstitute | ||
378 | * a complete tablet report. Further, the number of Input Event reports | ||
379 | * submitted varies, depending on what USB report type, and circumstance. | ||
380 | * To deal with this, EV_MSC is used to indicate an 'end-of-report' | ||
381 | * message. This has been an undocumented convention understood by the kernel | ||
382 | * tablet driver and clients such as gpm and XFree86's tablet drivers. | ||
383 | * | ||
384 | * Of the information received from the tablet, the one piece I | ||
385 | * cannot transmit is the proximity bit (without resorting to an EV_MSC | ||
386 | * convention above.) I therefore have taken over REL_MISC and ABS_MISC | ||
387 | * (for relative and absolute reports, respectively) for communicating | ||
388 | * Proximity. Why two events? I thought it interesting to know if the | ||
389 | * Proximity event occured while the tablet was in absolute or relative | ||
390 | * mode. | ||
391 | * | ||
392 | * Other tablets use the notion of a certain minimum stylus pressure | ||
393 | * to infer proximity. While that could have been done, that is yet | ||
394 | * another 'by convention' behavior, the documentation for which | ||
395 | * would be spread between two (or more) pieces of software. | ||
396 | * | ||
397 | * EV_MSC usage was terminated for this purpose in Linux 2.5.x, and | ||
398 | * replaced with the input_sync() method (which emits EV_SYN.) | ||
399 | */ | ||
400 | |||
401 | static void aiptek_irq(struct urb *urb, struct pt_regs *regs) | ||
402 | { | ||
403 | struct aiptek *aiptek = urb->context; | ||
404 | unsigned char *data = aiptek->data; | ||
405 | struct input_dev *inputdev = &aiptek->inputdev; | ||
406 | int jitterable = 0; | ||
407 | int retval, macro, x, y, z, left, right, middle, p, dv, tip, bs, pck; | ||
408 | |||
409 | switch (urb->status) { | ||
410 | case 0: | ||
411 | /* Success */ | ||
412 | break; | ||
413 | |||
414 | case -ECONNRESET: | ||
415 | case -ENOENT: | ||
416 | case -ESHUTDOWN: | ||
417 | /* This urb is terminated, clean up */ | ||
418 | dbg("%s - urb shutting down with status: %d", | ||
419 | __FUNCTION__, urb->status); | ||
420 | return; | ||
421 | |||
422 | default: | ||
423 | dbg("%s - nonzero urb status received: %d", | ||
424 | __FUNCTION__, urb->status); | ||
425 | goto exit; | ||
426 | } | ||
427 | |||
428 | /* See if we are in a delay loop -- throw out report if true. | ||
429 | */ | ||
430 | if (aiptek->inDelay == 1 && time_after(aiptek->endDelay, jiffies)) { | ||
431 | goto exit; | ||
432 | } | ||
433 | |||
434 | aiptek->inDelay = 0; | ||
435 | aiptek->eventCount++; | ||
436 | |||
437 | /* Report 1 delivers relative coordinates with either a stylus | ||
438 | * or the mouse. You do not know, however, which input | ||
439 | * tool generated the event. | ||
440 | */ | ||
441 | if (data[0] == 1) { | ||
442 | if (aiptek->curSetting.coordinateMode == | ||
443 | AIPTEK_COORDINATE_ABSOLUTE_MODE) { | ||
444 | aiptek->diagnostic = | ||
445 | AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE; | ||
446 | } else { | ||
447 | input_regs(inputdev, regs); | ||
448 | |||
449 | x = aiptek_convert_from_2s_complement(data[2]); | ||
450 | y = aiptek_convert_from_2s_complement(data[3]); | ||
451 | |||
452 | /* jitterable keeps track of whether any button has been pressed. | ||
453 | * We're also using it to remap the physical mouse button mask | ||
454 | * to pseudo-settings. (We don't specifically care about it's | ||
455 | * value after moving/transposing mouse button bitmasks, except | ||
456 | * that a non-zero value indicates that one or more | ||
457 | * mouse button was pressed.) | ||
458 | */ | ||
459 | jitterable = data[5] & 0x07; | ||
460 | |||
461 | left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0; | ||
462 | right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0; | ||
463 | middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0; | ||
464 | |||
465 | input_report_key(inputdev, BTN_LEFT, left); | ||
466 | input_report_key(inputdev, BTN_MIDDLE, middle); | ||
467 | input_report_key(inputdev, BTN_RIGHT, right); | ||
468 | input_report_rel(inputdev, REL_X, x); | ||
469 | input_report_rel(inputdev, REL_Y, y); | ||
470 | input_report_rel(inputdev, REL_MISC, 1 | AIPTEK_REPORT_TOOL_UNKNOWN); | ||
471 | |||
472 | /* Wheel support is in the form of a single-event | ||
473 | * firing. | ||
474 | */ | ||
475 | if (aiptek->curSetting.wheel != AIPTEK_WHEEL_DISABLE) { | ||
476 | input_report_rel(inputdev, REL_WHEEL, | ||
477 | aiptek->curSetting.wheel); | ||
478 | aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE; | ||
479 | } | ||
480 | input_sync(inputdev); | ||
481 | } | ||
482 | } | ||
483 | /* Report 2 is delivered only by the stylus, and delivers | ||
484 | * absolute coordinates. | ||
485 | */ | ||
486 | else if (data[0] == 2) { | ||
487 | if (aiptek->curSetting.coordinateMode == AIPTEK_COORDINATE_RELATIVE_MODE) { | ||
488 | aiptek->diagnostic = AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE; | ||
489 | } else if (!AIPTEK_POINTER_ALLOW_STYLUS_MODE | ||
490 | (aiptek->curSetting.pointerMode)) { | ||
491 | aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED; | ||
492 | } else { | ||
493 | input_regs(inputdev, regs); | ||
494 | |||
495 | x = le16_to_cpu(get_unaligned((__le16 *) (data + 1))); | ||
496 | y = le16_to_cpu(get_unaligned((__le16 *) (data + 3))); | ||
497 | z = le16_to_cpu(get_unaligned((__le16 *) (data + 6))); | ||
498 | |||
499 | p = (data[5] & 0x01) != 0 ? 1 : 0; | ||
500 | dv = (data[5] & 0x02) != 0 ? 1 : 0; | ||
501 | tip = (data[5] & 0x04) != 0 ? 1 : 0; | ||
502 | |||
503 | /* Use jitterable to re-arrange button masks | ||
504 | */ | ||
505 | jitterable = data[5] & 0x18; | ||
506 | |||
507 | bs = (data[5] & aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0; | ||
508 | pck = (data[5] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0; | ||
509 | |||
510 | /* dv indicates 'data valid' (e.g., the tablet is in sync | ||
511 | * and has delivered a "correct" report) We will ignore | ||
512 | * all 'bad' reports... | ||
513 | */ | ||
514 | if (dv != 0) { | ||
515 | /* If we've not already sent a tool_button_?? code, do | ||
516 | * so now. Then set FIRED_BIT so it won't be resent unless | ||
517 | * the user forces FIRED_BIT off. | ||
518 | */ | ||
519 | if (TOOL_BUTTON_FIRED | ||
520 | (aiptek->curSetting.toolMode) == 0) { | ||
521 | input_report_key(inputdev, | ||
522 | TOOL_BUTTON(aiptek->curSetting.toolMode), | ||
523 | 1); | ||
524 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | ||
525 | } | ||
526 | |||
527 | if (p != 0) { | ||
528 | input_report_abs(inputdev, ABS_X, x); | ||
529 | input_report_abs(inputdev, ABS_Y, y); | ||
530 | input_report_abs(inputdev, ABS_PRESSURE, z); | ||
531 | |||
532 | input_report_key(inputdev, BTN_TOUCH, tip); | ||
533 | input_report_key(inputdev, BTN_STYLUS, bs); | ||
534 | input_report_key(inputdev, BTN_STYLUS2, pck); | ||
535 | |||
536 | if (aiptek->curSetting.xTilt != | ||
537 | AIPTEK_TILT_DISABLE) { | ||
538 | input_report_abs(inputdev, | ||
539 | ABS_TILT_X, | ||
540 | aiptek->curSetting.xTilt); | ||
541 | } | ||
542 | if (aiptek->curSetting.yTilt != AIPTEK_TILT_DISABLE) { | ||
543 | input_report_abs(inputdev, | ||
544 | ABS_TILT_Y, | ||
545 | aiptek->curSetting.yTilt); | ||
546 | } | ||
547 | |||
548 | /* Wheel support is in the form of a single-event | ||
549 | * firing. | ||
550 | */ | ||
551 | if (aiptek->curSetting.wheel != | ||
552 | AIPTEK_WHEEL_DISABLE) { | ||
553 | input_report_abs(inputdev, | ||
554 | ABS_WHEEL, | ||
555 | aiptek->curSetting.wheel); | ||
556 | aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE; | ||
557 | } | ||
558 | } | ||
559 | input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_STYLUS); | ||
560 | input_sync(inputdev); | ||
561 | } | ||
562 | } | ||
563 | } | ||
564 | /* Report 3's come from the mouse in absolute mode. | ||
565 | */ | ||
566 | else if (data[0] == 3) { | ||
567 | if (aiptek->curSetting.coordinateMode == AIPTEK_COORDINATE_RELATIVE_MODE) { | ||
568 | aiptek->diagnostic = AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE; | ||
569 | } else if (!AIPTEK_POINTER_ALLOW_MOUSE_MODE | ||
570 | (aiptek->curSetting.pointerMode)) { | ||
571 | aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED; | ||
572 | } else { | ||
573 | input_regs(inputdev, regs); | ||
574 | x = le16_to_cpu(get_unaligned((__le16 *) (data + 1))); | ||
575 | y = le16_to_cpu(get_unaligned((__le16 *) (data + 3))); | ||
576 | |||
577 | jitterable = data[5] & 0x1c; | ||
578 | |||
579 | p = (data[5] & 0x01) != 0 ? 1 : 0; | ||
580 | dv = (data[5] & 0x02) != 0 ? 1 : 0; | ||
581 | left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0; | ||
582 | right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0; | ||
583 | middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0; | ||
584 | |||
585 | if (dv != 0) { | ||
586 | /* If we've not already sent a tool_button_?? code, do | ||
587 | * so now. Then set FIRED_BIT so it won't be resent unless | ||
588 | * the user forces FIRED_BIT off. | ||
589 | */ | ||
590 | if (TOOL_BUTTON_FIRED | ||
591 | (aiptek->curSetting.toolMode) == 0) { | ||
592 | input_report_key(inputdev, | ||
593 | TOOL_BUTTON(aiptek->curSetting.toolMode), | ||
594 | 1); | ||
595 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | ||
596 | } | ||
597 | |||
598 | if (p != 0) { | ||
599 | input_report_abs(inputdev, ABS_X, x); | ||
600 | input_report_abs(inputdev, ABS_Y, y); | ||
601 | |||
602 | input_report_key(inputdev, BTN_LEFT, left); | ||
603 | input_report_key(inputdev, BTN_MIDDLE, middle); | ||
604 | input_report_key(inputdev, BTN_RIGHT, right); | ||
605 | |||
606 | /* Wheel support is in the form of a single-event | ||
607 | * firing. | ||
608 | */ | ||
609 | if (aiptek->curSetting.wheel != AIPTEK_WHEEL_DISABLE) { | ||
610 | input_report_abs(inputdev, | ||
611 | ABS_WHEEL, | ||
612 | aiptek->curSetting.wheel); | ||
613 | aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE; | ||
614 | } | ||
615 | } | ||
616 | input_report_rel(inputdev, REL_MISC, p | AIPTEK_REPORT_TOOL_MOUSE); | ||
617 | input_sync(inputdev); | ||
618 | } | ||
619 | } | ||
620 | } | ||
621 | /* Report 4s come from the macro keys when pressed by stylus | ||
622 | */ | ||
623 | else if (data[0] == 4) { | ||
624 | jitterable = data[1] & 0x18; | ||
625 | |||
626 | p = (data[1] & 0x01) != 0 ? 1 : 0; | ||
627 | dv = (data[1] & 0x02) != 0 ? 1 : 0; | ||
628 | tip = (data[1] & 0x04) != 0 ? 1 : 0; | ||
629 | bs = (data[1] & aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0; | ||
630 | pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0; | ||
631 | |||
632 | macro = data[3]; | ||
633 | z = le16_to_cpu(get_unaligned((__le16 *) (data + 4))); | ||
634 | |||
635 | if (dv != 0) { | ||
636 | input_regs(inputdev, regs); | ||
637 | |||
638 | /* If we've not already sent a tool_button_?? code, do | ||
639 | * so now. Then set FIRED_BIT so it won't be resent unless | ||
640 | * the user forces FIRED_BIT off. | ||
641 | */ | ||
642 | if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) { | ||
643 | input_report_key(inputdev, | ||
644 | TOOL_BUTTON(aiptek->curSetting.toolMode), | ||
645 | 1); | ||
646 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | ||
647 | } | ||
648 | |||
649 | if (p != 0) { | ||
650 | input_report_key(inputdev, BTN_TOUCH, tip); | ||
651 | input_report_key(inputdev, BTN_STYLUS, bs); | ||
652 | input_report_key(inputdev, BTN_STYLUS2, pck); | ||
653 | input_report_abs(inputdev, ABS_PRESSURE, z); | ||
654 | } | ||
655 | |||
656 | /* For safety, we're sending key 'break' codes for the | ||
657 | * neighboring macro keys. | ||
658 | */ | ||
659 | if (macro > 0) { | ||
660 | input_report_key(inputdev, | ||
661 | macroKeyEvents[macro - 1], 0); | ||
662 | } | ||
663 | if (macro < 25) { | ||
664 | input_report_key(inputdev, | ||
665 | macroKeyEvents[macro + 1], 0); | ||
666 | } | ||
667 | input_report_key(inputdev, macroKeyEvents[macro], p); | ||
668 | input_report_abs(inputdev, ABS_MISC, | ||
669 | p | AIPTEK_REPORT_TOOL_STYLUS); | ||
670 | input_sync(inputdev); | ||
671 | } | ||
672 | } | ||
673 | /* Report 5s come from the macro keys when pressed by mouse | ||
674 | */ | ||
675 | else if (data[0] == 5) { | ||
676 | jitterable = data[1] & 0x1c; | ||
677 | |||
678 | p = (data[1] & 0x01) != 0 ? 1 : 0; | ||
679 | dv = (data[1] & 0x02) != 0 ? 1 : 0; | ||
680 | left = (data[1]& aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0; | ||
681 | right = (data[1] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0; | ||
682 | middle = (data[1] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0; | ||
683 | macro = data[3]; | ||
684 | |||
685 | if (dv != 0) { | ||
686 | input_regs(inputdev, regs); | ||
687 | |||
688 | /* If we've not already sent a tool_button_?? code, do | ||
689 | * so now. Then set FIRED_BIT so it won't be resent unless | ||
690 | * the user forces FIRED_BIT off. | ||
691 | */ | ||
692 | if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) { | ||
693 | input_report_key(inputdev, | ||
694 | TOOL_BUTTON(aiptek->curSetting.toolMode), | ||
695 | 1); | ||
696 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | ||
697 | } | ||
698 | |||
699 | if (p != 0) { | ||
700 | input_report_key(inputdev, BTN_LEFT, left); | ||
701 | input_report_key(inputdev, BTN_MIDDLE, middle); | ||
702 | input_report_key(inputdev, BTN_RIGHT, right); | ||
703 | } | ||
704 | |||
705 | /* For safety, we're sending key 'break' codes for the | ||
706 | * neighboring macro keys. | ||
707 | */ | ||
708 | if (macro > 0) { | ||
709 | input_report_key(inputdev, | ||
710 | macroKeyEvents[macro - 1], 0); | ||
711 | } | ||
712 | if (macro < 25) { | ||
713 | input_report_key(inputdev, | ||
714 | macroKeyEvents[macro + 1], 0); | ||
715 | } | ||
716 | |||
717 | input_report_key(inputdev, macroKeyEvents[macro], 1); | ||
718 | input_report_rel(inputdev, ABS_MISC, | ||
719 | p | AIPTEK_REPORT_TOOL_MOUSE); | ||
720 | input_sync(inputdev); | ||
721 | } | ||
722 | } | ||
723 | /* We have no idea which tool can generate a report 6. Theoretically, | ||
724 | * neither need to, having been given reports 4 & 5 for such use. | ||
725 | * However, report 6 is the 'official-looking' report for macroKeys; | ||
726 | * reports 4 & 5 supposively are used to support unnamed, unknown | ||
727 | * hat switches (which just so happen to be the macroKeys.) | ||
728 | */ | ||
729 | else if (data[0] == 6) { | ||
730 | macro = le16_to_cpu(get_unaligned((__le16 *) (data + 1))); | ||
731 | input_regs(inputdev, regs); | ||
732 | |||
733 | if (macro > 0) { | ||
734 | input_report_key(inputdev, macroKeyEvents[macro - 1], | ||
735 | 0); | ||
736 | } | ||
737 | if (macro < 25) { | ||
738 | input_report_key(inputdev, macroKeyEvents[macro + 1], | ||
739 | 0); | ||
740 | } | ||
741 | |||
742 | /* If we've not already sent a tool_button_?? code, do | ||
743 | * so now. Then set FIRED_BIT so it won't be resent unless | ||
744 | * the user forces FIRED_BIT off. | ||
745 | */ | ||
746 | if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) { | ||
747 | input_report_key(inputdev, | ||
748 | TOOL_BUTTON(aiptek->curSetting. | ||
749 | toolMode), 1); | ||
750 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | ||
751 | } | ||
752 | |||
753 | input_report_key(inputdev, macroKeyEvents[macro], 1); | ||
754 | input_report_abs(inputdev, ABS_MISC, | ||
755 | 1 | AIPTEK_REPORT_TOOL_UNKNOWN); | ||
756 | input_sync(inputdev); | ||
757 | } else { | ||
758 | dbg("Unknown report %d", data[0]); | ||
759 | } | ||
760 | |||
761 | /* Jitter may occur when the user presses a button on the stlyus | ||
762 | * or the mouse. What we do to prevent that is wait 'x' milliseconds | ||
763 | * following a 'jitterable' event, which should give the hand some time | ||
764 | * stabilize itself. | ||
765 | * | ||
766 | * We just introduced aiptek->previousJitterable to carry forth the | ||
767 | * notion that jitter occurs when the button state changes from on to off: | ||
768 | * a person drawing, holding a button down is not subject to jittering. | ||
769 | * With that in mind, changing from upper button depressed to lower button | ||
770 | * WILL transition through a jitter delay. | ||
771 | */ | ||
772 | |||
773 | if (aiptek->previousJitterable != jitterable && | ||
774 | aiptek->curSetting.jitterDelay != 0 && aiptek->inDelay != 1) { | ||
775 | aiptek->endDelay = jiffies + | ||
776 | ((aiptek->curSetting.jitterDelay * HZ) / 1000); | ||
777 | aiptek->inDelay = 1; | ||
778 | } | ||
779 | aiptek->previousJitterable = jitterable; | ||
780 | |||
781 | exit: | ||
782 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
783 | if (retval != 0) { | ||
784 | err("%s - usb_submit_urb failed with result %d", | ||
785 | __FUNCTION__, retval); | ||
786 | } | ||
787 | } | ||
788 | |||
789 | /*********************************************************************** | ||
790 | * These are the USB id's known so far. We do not identify them to | ||
791 | * specific Aiptek model numbers, because there has been overlaps, | ||
792 | * use, and reuse of id's in existing models. Certain models have | ||
793 | * been known to use more than one ID, indicative perhaps of | ||
794 | * manufacturing revisions. In any event, we consider these | ||
795 | * IDs to not be model-specific nor unique. | ||
796 | */ | ||
797 | static const struct usb_device_id aiptek_ids[] = { | ||
798 | {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x01)}, | ||
799 | {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x10)}, | ||
800 | {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x20)}, | ||
801 | {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x21)}, | ||
802 | {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x22)}, | ||
803 | {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x23)}, | ||
804 | {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x24)}, | ||
805 | {} | ||
806 | }; | ||
807 | |||
808 | MODULE_DEVICE_TABLE(usb, aiptek_ids); | ||
809 | |||
810 | /*********************************************************************** | ||
811 | * Open an instance of the tablet driver. | ||
812 | */ | ||
813 | static int aiptek_open(struct input_dev *inputdev) | ||
814 | { | ||
815 | struct aiptek *aiptek = inputdev->private; | ||
816 | |||
817 | if (aiptek->openCount++ > 0) { | ||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | aiptek->urb->dev = aiptek->usbdev; | ||
822 | if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) { | ||
823 | aiptek->openCount--; | ||
824 | return -EIO; | ||
825 | } | ||
826 | |||
827 | return 0; | ||
828 | } | ||
829 | |||
830 | /*********************************************************************** | ||
831 | * Close an instance of the tablet driver. | ||
832 | */ | ||
833 | static void aiptek_close(struct input_dev *inputdev) | ||
834 | { | ||
835 | struct aiptek *aiptek = inputdev->private; | ||
836 | |||
837 | if (--aiptek->openCount == 0) { | ||
838 | usb_kill_urb(aiptek->urb); | ||
839 | } | ||
840 | } | ||
841 | |||
842 | /*********************************************************************** | ||
843 | * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x, | ||
844 | * where they were known as usb_set_report and usb_get_report. | ||
845 | */ | ||
846 | static int | ||
847 | aiptek_set_report(struct aiptek *aiptek, | ||
848 | unsigned char report_type, | ||
849 | unsigned char report_id, void *buffer, int size) | ||
850 | { | ||
851 | return usb_control_msg(aiptek->usbdev, | ||
852 | usb_sndctrlpipe(aiptek->usbdev, 0), | ||
853 | USB_REQ_SET_REPORT, | ||
854 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | | ||
855 | USB_DIR_OUT, (report_type << 8) + report_id, | ||
856 | aiptek->ifnum, buffer, size, 5000); | ||
857 | } | ||
858 | |||
859 | static int | ||
860 | aiptek_get_report(struct aiptek *aiptek, | ||
861 | unsigned char report_type, | ||
862 | unsigned char report_id, void *buffer, int size) | ||
863 | { | ||
864 | return usb_control_msg(aiptek->usbdev, | ||
865 | usb_rcvctrlpipe(aiptek->usbdev, 0), | ||
866 | USB_REQ_GET_REPORT, | ||
867 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | | ||
868 | USB_DIR_IN, (report_type << 8) + report_id, | ||
869 | aiptek->ifnum, buffer, size, 5000); | ||
870 | } | ||
871 | |||
872 | /*********************************************************************** | ||
873 | * Send a command to the tablet. | ||
874 | */ | ||
875 | static int | ||
876 | aiptek_command(struct aiptek *aiptek, unsigned char command, unsigned char data) | ||
877 | { | ||
878 | const int sizeof_buf = 3 * sizeof(u8); | ||
879 | int ret; | ||
880 | u8 *buf; | ||
881 | |||
882 | buf = kmalloc(sizeof_buf, GFP_KERNEL); | ||
883 | if (!buf) | ||
884 | return -ENOMEM; | ||
885 | |||
886 | buf[0] = 2; | ||
887 | buf[1] = command; | ||
888 | buf[2] = data; | ||
889 | |||
890 | if ((ret = | ||
891 | aiptek_set_report(aiptek, 3, 2, buf, sizeof_buf)) != sizeof_buf) { | ||
892 | dbg("aiptek_program: failed, tried to send: 0x%02x 0x%02x", | ||
893 | command, data); | ||
894 | } | ||
895 | kfree(buf); | ||
896 | return ret < 0 ? ret : 0; | ||
897 | } | ||
898 | |||
899 | /*********************************************************************** | ||
900 | * Retrieve information from the tablet. Querying info is defined as first | ||
901 | * sending the {command,data} sequence as a command, followed by a wait | ||
902 | * (aka, "programmaticDelay") and then a "read" request. | ||
903 | */ | ||
904 | static int | ||
905 | aiptek_query(struct aiptek *aiptek, unsigned char command, unsigned char data) | ||
906 | { | ||
907 | const int sizeof_buf = 3 * sizeof(u8); | ||
908 | int ret; | ||
909 | u8 *buf; | ||
910 | |||
911 | buf = kmalloc(sizeof_buf, GFP_KERNEL); | ||
912 | if (!buf) | ||
913 | return -ENOMEM; | ||
914 | |||
915 | buf[0] = 2; | ||
916 | buf[1] = command; | ||
917 | buf[2] = data; | ||
918 | |||
919 | if (aiptek_command(aiptek, command, data) != 0) { | ||
920 | kfree(buf); | ||
921 | return -EIO; | ||
922 | } | ||
923 | msleep(aiptek->curSetting.programmableDelay); | ||
924 | |||
925 | if ((ret = | ||
926 | aiptek_get_report(aiptek, 3, 2, buf, sizeof_buf)) != sizeof_buf) { | ||
927 | dbg("aiptek_query failed: returned 0x%02x 0x%02x 0x%02x", | ||
928 | buf[0], buf[1], buf[2]); | ||
929 | ret = -EIO; | ||
930 | } else { | ||
931 | ret = le16_to_cpu(get_unaligned((__le16 *) (buf + 1))); | ||
932 | } | ||
933 | kfree(buf); | ||
934 | return ret; | ||
935 | } | ||
936 | |||
937 | /*********************************************************************** | ||
938 | * Program the tablet into either absolute or relative mode. | ||
939 | * We also get information about the tablet's size. | ||
940 | */ | ||
941 | static int aiptek_program_tablet(struct aiptek *aiptek) | ||
942 | { | ||
943 | int ret; | ||
944 | /* Execute Resolution500LPI */ | ||
945 | if ((ret = aiptek_command(aiptek, 0x18, 0x04)) < 0) | ||
946 | return ret; | ||
947 | |||
948 | /* Query getModelCode */ | ||
949 | if ((ret = aiptek_query(aiptek, 0x02, 0x00)) < 0) | ||
950 | return ret; | ||
951 | aiptek->features.modelCode = ret & 0xff; | ||
952 | |||
953 | /* Query getODMCode */ | ||
954 | if ((ret = aiptek_query(aiptek, 0x03, 0x00)) < 0) | ||
955 | return ret; | ||
956 | aiptek->features.odmCode = ret; | ||
957 | |||
958 | /* Query getFirmwareCode */ | ||
959 | if ((ret = aiptek_query(aiptek, 0x04, 0x00)) < 0) | ||
960 | return ret; | ||
961 | aiptek->features.firmwareCode = ret; | ||
962 | |||
963 | /* Query getXextension */ | ||
964 | if ((ret = aiptek_query(aiptek, 0x01, 0x00)) < 0) | ||
965 | return ret; | ||
966 | aiptek->inputdev.absmin[ABS_X] = 0; | ||
967 | aiptek->inputdev.absmax[ABS_X] = ret - 1; | ||
968 | |||
969 | /* Query getYextension */ | ||
970 | if ((ret = aiptek_query(aiptek, 0x01, 0x01)) < 0) | ||
971 | return ret; | ||
972 | aiptek->inputdev.absmin[ABS_Y] = 0; | ||
973 | aiptek->inputdev.absmax[ABS_Y] = ret - 1; | ||
974 | |||
975 | /* Query getPressureLevels */ | ||
976 | if ((ret = aiptek_query(aiptek, 0x08, 0x00)) < 0) | ||
977 | return ret; | ||
978 | aiptek->inputdev.absmin[ABS_PRESSURE] = 0; | ||
979 | aiptek->inputdev.absmax[ABS_PRESSURE] = ret - 1; | ||
980 | |||
981 | /* Depending on whether we are in absolute or relative mode, we will | ||
982 | * do a switchToTablet(absolute) or switchToMouse(relative) command. | ||
983 | */ | ||
984 | if (aiptek->curSetting.coordinateMode == | ||
985 | AIPTEK_COORDINATE_ABSOLUTE_MODE) { | ||
986 | /* Execute switchToTablet */ | ||
987 | if ((ret = aiptek_command(aiptek, 0x10, 0x01)) < 0) { | ||
988 | return ret; | ||
989 | } | ||
990 | } else { | ||
991 | /* Execute switchToMouse */ | ||
992 | if ((ret = aiptek_command(aiptek, 0x10, 0x00)) < 0) { | ||
993 | return ret; | ||
994 | } | ||
995 | } | ||
996 | |||
997 | /* Enable the macro keys */ | ||
998 | if ((ret = aiptek_command(aiptek, 0x11, 0x02)) < 0) | ||
999 | return ret; | ||
1000 | #if 0 | ||
1001 | /* Execute FilterOn */ | ||
1002 | if ((ret = aiptek_command(aiptek, 0x17, 0x00)) < 0) | ||
1003 | return ret; | ||
1004 | #endif | ||
1005 | |||
1006 | /* Execute AutoGainOn */ | ||
1007 | if ((ret = aiptek_command(aiptek, 0x12, 0xff)) < 0) | ||
1008 | return ret; | ||
1009 | |||
1010 | /* Reset the eventCount, so we track events from last (re)programming | ||
1011 | */ | ||
1012 | aiptek->diagnostic = AIPTEK_DIAGNOSTIC_NA; | ||
1013 | aiptek->eventCount = 0; | ||
1014 | |||
1015 | return 0; | ||
1016 | } | ||
1017 | |||
1018 | /*********************************************************************** | ||
1019 | * Sysfs functions. Sysfs prefers that individually-tunable parameters | ||
1020 | * exist in their separate pseudo-files. Summary data that is immutable | ||
1021 | * may exist in a singular file so long as you don't define a writeable | ||
1022 | * interface. | ||
1023 | */ | ||
1024 | |||
1025 | /*********************************************************************** | ||
1026 | * support the 'size' file -- display support | ||
1027 | */ | ||
1028 | static ssize_t show_tabletSize(struct device *dev, char *buf) | ||
1029 | { | ||
1030 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1031 | |||
1032 | if (aiptek == NULL) | ||
1033 | return 0; | ||
1034 | |||
1035 | return snprintf(buf, PAGE_SIZE, "%dx%d\n", | ||
1036 | aiptek->inputdev.absmax[ABS_X] + 1, | ||
1037 | aiptek->inputdev.absmax[ABS_Y] + 1); | ||
1038 | } | ||
1039 | |||
1040 | /* These structs define the sysfs files, param #1 is the name of the | ||
1041 | * file, param 2 is the file permissions, param 3 & 4 are to the | ||
1042 | * output generator and input parser routines. Absence of a routine is | ||
1043 | * permitted -- it only means can't either 'cat' the file, or send data | ||
1044 | * to it. | ||
1045 | */ | ||
1046 | static DEVICE_ATTR(size, S_IRUGO, show_tabletSize, NULL); | ||
1047 | |||
1048 | /*********************************************************************** | ||
1049 | * support routines for the 'product_id' file | ||
1050 | */ | ||
1051 | static ssize_t show_tabletProductId(struct device *dev, char *buf) | ||
1052 | { | ||
1053 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1054 | |||
1055 | if (aiptek == NULL) | ||
1056 | return 0; | ||
1057 | |||
1058 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", | ||
1059 | aiptek->inputdev.id.product); | ||
1060 | } | ||
1061 | |||
1062 | static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL); | ||
1063 | |||
1064 | /*********************************************************************** | ||
1065 | * support routines for the 'vendor_id' file | ||
1066 | */ | ||
1067 | static ssize_t show_tabletVendorId(struct device *dev, char *buf) | ||
1068 | { | ||
1069 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1070 | |||
1071 | if (aiptek == NULL) | ||
1072 | return 0; | ||
1073 | |||
1074 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev.id.vendor); | ||
1075 | } | ||
1076 | |||
1077 | static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL); | ||
1078 | |||
1079 | /*********************************************************************** | ||
1080 | * support routines for the 'vendor' file | ||
1081 | */ | ||
1082 | static ssize_t show_tabletManufacturer(struct device *dev, char *buf) | ||
1083 | { | ||
1084 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1085 | int retval; | ||
1086 | |||
1087 | if (aiptek == NULL) | ||
1088 | return 0; | ||
1089 | |||
1090 | retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->manufacturer); | ||
1091 | return retval; | ||
1092 | } | ||
1093 | |||
1094 | static DEVICE_ATTR(vendor, S_IRUGO, show_tabletManufacturer, NULL); | ||
1095 | |||
1096 | /*********************************************************************** | ||
1097 | * support routines for the 'product' file | ||
1098 | */ | ||
1099 | static ssize_t show_tabletProduct(struct device *dev, char *buf) | ||
1100 | { | ||
1101 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1102 | int retval; | ||
1103 | |||
1104 | if (aiptek == NULL) | ||
1105 | return 0; | ||
1106 | |||
1107 | retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->product); | ||
1108 | return retval; | ||
1109 | } | ||
1110 | |||
1111 | static DEVICE_ATTR(product, S_IRUGO, show_tabletProduct, NULL); | ||
1112 | |||
1113 | /*********************************************************************** | ||
1114 | * support routines for the 'pointer_mode' file. Note that this file | ||
1115 | * both displays current setting and allows reprogramming. | ||
1116 | */ | ||
1117 | static ssize_t show_tabletPointerMode(struct device *dev, char *buf) | ||
1118 | { | ||
1119 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1120 | char *s; | ||
1121 | |||
1122 | if (aiptek == NULL) | ||
1123 | return 0; | ||
1124 | |||
1125 | switch (aiptek->curSetting.pointerMode) { | ||
1126 | case AIPTEK_POINTER_ONLY_STYLUS_MODE: | ||
1127 | s = "stylus"; | ||
1128 | break; | ||
1129 | |||
1130 | case AIPTEK_POINTER_ONLY_MOUSE_MODE: | ||
1131 | s = "mouse"; | ||
1132 | break; | ||
1133 | |||
1134 | case AIPTEK_POINTER_EITHER_MODE: | ||
1135 | s = "either"; | ||
1136 | break; | ||
1137 | |||
1138 | default: | ||
1139 | s = "unknown"; | ||
1140 | break; | ||
1141 | } | ||
1142 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1143 | } | ||
1144 | |||
1145 | static ssize_t | ||
1146 | store_tabletPointerMode(struct device *dev, const char *buf, size_t count) | ||
1147 | { | ||
1148 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1149 | if (aiptek == NULL) | ||
1150 | return 0; | ||
1151 | |||
1152 | if (strcmp(buf, "stylus") == 0) { | ||
1153 | aiptek->newSetting.pointerMode = | ||
1154 | AIPTEK_POINTER_ONLY_STYLUS_MODE; | ||
1155 | } else if (strcmp(buf, "mouse") == 0) { | ||
1156 | aiptek->newSetting.pointerMode = AIPTEK_POINTER_ONLY_MOUSE_MODE; | ||
1157 | } else if (strcmp(buf, "either") == 0) { | ||
1158 | aiptek->newSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE; | ||
1159 | } | ||
1160 | return count; | ||
1161 | } | ||
1162 | |||
1163 | static DEVICE_ATTR(pointer_mode, | ||
1164 | S_IRUGO | S_IWUGO, | ||
1165 | show_tabletPointerMode, store_tabletPointerMode); | ||
1166 | |||
1167 | /*********************************************************************** | ||
1168 | * support routines for the 'coordinate_mode' file. Note that this file | ||
1169 | * both displays current setting and allows reprogramming. | ||
1170 | */ | ||
1171 | static ssize_t show_tabletCoordinateMode(struct device *dev, char *buf) | ||
1172 | { | ||
1173 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1174 | char *s; | ||
1175 | |||
1176 | if (aiptek == NULL) | ||
1177 | return 0; | ||
1178 | |||
1179 | switch (aiptek->curSetting.coordinateMode) { | ||
1180 | case AIPTEK_COORDINATE_ABSOLUTE_MODE: | ||
1181 | s = "absolute"; | ||
1182 | break; | ||
1183 | |||
1184 | case AIPTEK_COORDINATE_RELATIVE_MODE: | ||
1185 | s = "relative"; | ||
1186 | break; | ||
1187 | |||
1188 | default: | ||
1189 | s = "unknown"; | ||
1190 | break; | ||
1191 | } | ||
1192 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1193 | } | ||
1194 | |||
1195 | static ssize_t | ||
1196 | store_tabletCoordinateMode(struct device *dev, const char *buf, size_t count) | ||
1197 | { | ||
1198 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1199 | if (aiptek == NULL) | ||
1200 | return 0; | ||
1201 | |||
1202 | if (strcmp(buf, "absolute") == 0) { | ||
1203 | aiptek->newSetting.pointerMode = | ||
1204 | AIPTEK_COORDINATE_ABSOLUTE_MODE; | ||
1205 | } else if (strcmp(buf, "relative") == 0) { | ||
1206 | aiptek->newSetting.pointerMode = | ||
1207 | AIPTEK_COORDINATE_RELATIVE_MODE; | ||
1208 | } | ||
1209 | return count; | ||
1210 | } | ||
1211 | |||
1212 | static DEVICE_ATTR(coordinate_mode, | ||
1213 | S_IRUGO | S_IWUGO, | ||
1214 | show_tabletCoordinateMode, store_tabletCoordinateMode); | ||
1215 | |||
1216 | /*********************************************************************** | ||
1217 | * support routines for the 'tool_mode' file. Note that this file | ||
1218 | * both displays current setting and allows reprogramming. | ||
1219 | */ | ||
1220 | static ssize_t show_tabletToolMode(struct device *dev, char *buf) | ||
1221 | { | ||
1222 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1223 | char *s; | ||
1224 | |||
1225 | if (aiptek == NULL) | ||
1226 | return 0; | ||
1227 | |||
1228 | switch (TOOL_BUTTON(aiptek->curSetting.toolMode)) { | ||
1229 | case AIPTEK_TOOL_BUTTON_MOUSE_MODE: | ||
1230 | s = "mouse"; | ||
1231 | break; | ||
1232 | |||
1233 | case AIPTEK_TOOL_BUTTON_ERASER_MODE: | ||
1234 | s = "eraser"; | ||
1235 | break; | ||
1236 | |||
1237 | case AIPTEK_TOOL_BUTTON_PENCIL_MODE: | ||
1238 | s = "pencil"; | ||
1239 | break; | ||
1240 | |||
1241 | case AIPTEK_TOOL_BUTTON_PEN_MODE: | ||
1242 | s = "pen"; | ||
1243 | break; | ||
1244 | |||
1245 | case AIPTEK_TOOL_BUTTON_BRUSH_MODE: | ||
1246 | s = "brush"; | ||
1247 | break; | ||
1248 | |||
1249 | case AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE: | ||
1250 | s = "airbrush"; | ||
1251 | break; | ||
1252 | |||
1253 | case AIPTEK_TOOL_BUTTON_LENS_MODE: | ||
1254 | s = "lens"; | ||
1255 | break; | ||
1256 | |||
1257 | default: | ||
1258 | s = "unknown"; | ||
1259 | break; | ||
1260 | } | ||
1261 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1262 | } | ||
1263 | |||
1264 | static ssize_t | ||
1265 | store_tabletToolMode(struct device *dev, const char *buf, size_t count) | ||
1266 | { | ||
1267 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1268 | if (aiptek == NULL) | ||
1269 | return 0; | ||
1270 | |||
1271 | if (strcmp(buf, "mouse") == 0) { | ||
1272 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_MOUSE_MODE; | ||
1273 | } else if (strcmp(buf, "eraser") == 0) { | ||
1274 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_ERASER_MODE; | ||
1275 | } else if (strcmp(buf, "pencil") == 0) { | ||
1276 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PENCIL_MODE; | ||
1277 | } else if (strcmp(buf, "pen") == 0) { | ||
1278 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PEN_MODE; | ||
1279 | } else if (strcmp(buf, "brush") == 0) { | ||
1280 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_BRUSH_MODE; | ||
1281 | } else if (strcmp(buf, "airbrush") == 0) { | ||
1282 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE; | ||
1283 | } else if (strcmp(buf, "lens") == 0) { | ||
1284 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_LENS_MODE; | ||
1285 | } | ||
1286 | |||
1287 | return count; | ||
1288 | } | ||
1289 | |||
1290 | static DEVICE_ATTR(tool_mode, | ||
1291 | S_IRUGO | S_IWUGO, | ||
1292 | show_tabletToolMode, store_tabletToolMode); | ||
1293 | |||
1294 | /*********************************************************************** | ||
1295 | * support routines for the 'xtilt' file. Note that this file | ||
1296 | * both displays current setting and allows reprogramming. | ||
1297 | */ | ||
1298 | static ssize_t show_tabletXtilt(struct device *dev, char *buf) | ||
1299 | { | ||
1300 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1301 | |||
1302 | if (aiptek == NULL) | ||
1303 | return 0; | ||
1304 | |||
1305 | if (aiptek->curSetting.xTilt == AIPTEK_TILT_DISABLE) { | ||
1306 | return snprintf(buf, PAGE_SIZE, "disable\n"); | ||
1307 | } else { | ||
1308 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
1309 | aiptek->curSetting.xTilt); | ||
1310 | } | ||
1311 | } | ||
1312 | |||
1313 | static ssize_t | ||
1314 | store_tabletXtilt(struct device *dev, const char *buf, size_t count) | ||
1315 | { | ||
1316 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1317 | int x; | ||
1318 | |||
1319 | if (aiptek == NULL) | ||
1320 | return 0; | ||
1321 | |||
1322 | if (strcmp(buf, "disable") == 0) { | ||
1323 | aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE; | ||
1324 | } else { | ||
1325 | x = (int)simple_strtol(buf, NULL, 10); | ||
1326 | if (x >= AIPTEK_TILT_MIN && x <= AIPTEK_TILT_MAX) { | ||
1327 | aiptek->newSetting.xTilt = x; | ||
1328 | } | ||
1329 | } | ||
1330 | return count; | ||
1331 | } | ||
1332 | |||
1333 | static DEVICE_ATTR(xtilt, | ||
1334 | S_IRUGO | S_IWUGO, show_tabletXtilt, store_tabletXtilt); | ||
1335 | |||
1336 | /*********************************************************************** | ||
1337 | * support routines for the 'ytilt' file. Note that this file | ||
1338 | * both displays current setting and allows reprogramming. | ||
1339 | */ | ||
1340 | static ssize_t show_tabletYtilt(struct device *dev, char *buf) | ||
1341 | { | ||
1342 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1343 | |||
1344 | if (aiptek == NULL) | ||
1345 | return 0; | ||
1346 | |||
1347 | if (aiptek->curSetting.yTilt == AIPTEK_TILT_DISABLE) { | ||
1348 | return snprintf(buf, PAGE_SIZE, "disable\n"); | ||
1349 | } else { | ||
1350 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
1351 | aiptek->curSetting.yTilt); | ||
1352 | } | ||
1353 | } | ||
1354 | |||
1355 | static ssize_t | ||
1356 | store_tabletYtilt(struct device *dev, const char *buf, size_t count) | ||
1357 | { | ||
1358 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1359 | int y; | ||
1360 | |||
1361 | if (aiptek == NULL) | ||
1362 | return 0; | ||
1363 | |||
1364 | if (strcmp(buf, "disable") == 0) { | ||
1365 | aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE; | ||
1366 | } else { | ||
1367 | y = (int)simple_strtol(buf, NULL, 10); | ||
1368 | if (y >= AIPTEK_TILT_MIN && y <= AIPTEK_TILT_MAX) { | ||
1369 | aiptek->newSetting.yTilt = y; | ||
1370 | } | ||
1371 | } | ||
1372 | return count; | ||
1373 | } | ||
1374 | |||
1375 | static DEVICE_ATTR(ytilt, | ||
1376 | S_IRUGO | S_IWUGO, show_tabletYtilt, store_tabletYtilt); | ||
1377 | |||
1378 | /*********************************************************************** | ||
1379 | * support routines for the 'jitter' file. Note that this file | ||
1380 | * both displays current setting and allows reprogramming. | ||
1381 | */ | ||
1382 | static ssize_t show_tabletJitterDelay(struct device *dev, char *buf) | ||
1383 | { | ||
1384 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1385 | |||
1386 | if (aiptek == NULL) | ||
1387 | return 0; | ||
1388 | |||
1389 | return snprintf(buf, PAGE_SIZE, "%d\n", aiptek->curSetting.jitterDelay); | ||
1390 | } | ||
1391 | |||
1392 | static ssize_t | ||
1393 | store_tabletJitterDelay(struct device *dev, const char *buf, size_t count) | ||
1394 | { | ||
1395 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1396 | |||
1397 | if (aiptek == NULL) | ||
1398 | return 0; | ||
1399 | |||
1400 | aiptek->newSetting.jitterDelay = (int)simple_strtol(buf, NULL, 10); | ||
1401 | return count; | ||
1402 | } | ||
1403 | |||
1404 | static DEVICE_ATTR(jitter, | ||
1405 | S_IRUGO | S_IWUGO, | ||
1406 | show_tabletJitterDelay, store_tabletJitterDelay); | ||
1407 | |||
1408 | /*********************************************************************** | ||
1409 | * support routines for the 'delay' file. Note that this file | ||
1410 | * both displays current setting and allows reprogramming. | ||
1411 | */ | ||
1412 | static ssize_t show_tabletProgrammableDelay(struct device *dev, char *buf) | ||
1413 | { | ||
1414 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1415 | |||
1416 | if (aiptek == NULL) | ||
1417 | return 0; | ||
1418 | |||
1419 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
1420 | aiptek->curSetting.programmableDelay); | ||
1421 | } | ||
1422 | |||
1423 | static ssize_t | ||
1424 | store_tabletProgrammableDelay(struct device *dev, const char *buf, size_t count) | ||
1425 | { | ||
1426 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1427 | |||
1428 | if (aiptek == NULL) | ||
1429 | return 0; | ||
1430 | |||
1431 | aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, NULL, 10); | ||
1432 | return count; | ||
1433 | } | ||
1434 | |||
1435 | static DEVICE_ATTR(delay, | ||
1436 | S_IRUGO | S_IWUGO, | ||
1437 | show_tabletProgrammableDelay, store_tabletProgrammableDelay); | ||
1438 | |||
1439 | /*********************************************************************** | ||
1440 | * support routines for the 'input_path' file. Note that this file | ||
1441 | * only displays current setting. | ||
1442 | */ | ||
1443 | static ssize_t show_tabletInputDevice(struct device *dev, char *buf) | ||
1444 | { | ||
1445 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1446 | |||
1447 | if (aiptek == NULL) | ||
1448 | return 0; | ||
1449 | |||
1450 | return snprintf(buf, PAGE_SIZE, "/dev/input/%s\n", | ||
1451 | aiptek->features.inputPath); | ||
1452 | } | ||
1453 | |||
1454 | static DEVICE_ATTR(input_path, S_IRUGO, show_tabletInputDevice, NULL); | ||
1455 | |||
1456 | /*********************************************************************** | ||
1457 | * support routines for the 'event_count' file. Note that this file | ||
1458 | * only displays current setting. | ||
1459 | */ | ||
1460 | static ssize_t show_tabletEventsReceived(struct device *dev, char *buf) | ||
1461 | { | ||
1462 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1463 | |||
1464 | if (aiptek == NULL) | ||
1465 | return 0; | ||
1466 | |||
1467 | return snprintf(buf, PAGE_SIZE, "%ld\n", aiptek->eventCount); | ||
1468 | } | ||
1469 | |||
1470 | static DEVICE_ATTR(event_count, S_IRUGO, show_tabletEventsReceived, NULL); | ||
1471 | |||
1472 | /*********************************************************************** | ||
1473 | * support routines for the 'diagnostic' file. Note that this file | ||
1474 | * only displays current setting. | ||
1475 | */ | ||
1476 | static ssize_t show_tabletDiagnosticMessage(struct device *dev, char *buf) | ||
1477 | { | ||
1478 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1479 | char *retMsg; | ||
1480 | |||
1481 | if (aiptek == NULL) | ||
1482 | return 0; | ||
1483 | |||
1484 | switch (aiptek->diagnostic) { | ||
1485 | case AIPTEK_DIAGNOSTIC_NA: | ||
1486 | retMsg = "no errors\n"; | ||
1487 | break; | ||
1488 | |||
1489 | case AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE: | ||
1490 | retMsg = "Error: receiving relative reports\n"; | ||
1491 | break; | ||
1492 | |||
1493 | case AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE: | ||
1494 | retMsg = "Error: receiving absolute reports\n"; | ||
1495 | break; | ||
1496 | |||
1497 | case AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED: | ||
1498 | if (aiptek->curSetting.pointerMode == | ||
1499 | AIPTEK_POINTER_ONLY_MOUSE_MODE) { | ||
1500 | retMsg = "Error: receiving stylus reports\n"; | ||
1501 | } else { | ||
1502 | retMsg = "Error: receiving mouse reports\n"; | ||
1503 | } | ||
1504 | break; | ||
1505 | |||
1506 | default: | ||
1507 | return 0; | ||
1508 | } | ||
1509 | return snprintf(buf, PAGE_SIZE, retMsg); | ||
1510 | } | ||
1511 | |||
1512 | static DEVICE_ATTR(diagnostic, S_IRUGO, show_tabletDiagnosticMessage, NULL); | ||
1513 | |||
1514 | /*********************************************************************** | ||
1515 | * support routines for the 'stylus_upper' file. Note that this file | ||
1516 | * both displays current setting and allows for setting changing. | ||
1517 | */ | ||
1518 | static ssize_t show_tabletStylusUpper(struct device *dev, char *buf) | ||
1519 | { | ||
1520 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1521 | char *s; | ||
1522 | |||
1523 | if (aiptek == NULL) | ||
1524 | return 0; | ||
1525 | |||
1526 | switch (aiptek->curSetting.stylusButtonUpper) { | ||
1527 | case AIPTEK_STYLUS_UPPER_BUTTON: | ||
1528 | s = "upper"; | ||
1529 | break; | ||
1530 | |||
1531 | case AIPTEK_STYLUS_LOWER_BUTTON: | ||
1532 | s = "lower"; | ||
1533 | break; | ||
1534 | |||
1535 | default: | ||
1536 | s = "unknown"; | ||
1537 | break; | ||
1538 | } | ||
1539 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1540 | } | ||
1541 | |||
1542 | static ssize_t | ||
1543 | store_tabletStylusUpper(struct device *dev, const char *buf, size_t count) | ||
1544 | { | ||
1545 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1546 | |||
1547 | if (aiptek == NULL) | ||
1548 | return 0; | ||
1549 | |||
1550 | if (strcmp(buf, "upper") == 0) { | ||
1551 | aiptek->newSetting.stylusButtonUpper = | ||
1552 | AIPTEK_STYLUS_UPPER_BUTTON; | ||
1553 | } else if (strcmp(buf, "lower") == 0) { | ||
1554 | aiptek->newSetting.stylusButtonUpper = | ||
1555 | AIPTEK_STYLUS_LOWER_BUTTON; | ||
1556 | } | ||
1557 | return count; | ||
1558 | } | ||
1559 | |||
1560 | static DEVICE_ATTR(stylus_upper, | ||
1561 | S_IRUGO | S_IWUGO, | ||
1562 | show_tabletStylusUpper, store_tabletStylusUpper); | ||
1563 | |||
1564 | /*********************************************************************** | ||
1565 | * support routines for the 'stylus_lower' file. Note that this file | ||
1566 | * both displays current setting and allows for setting changing. | ||
1567 | */ | ||
1568 | static ssize_t show_tabletStylusLower(struct device *dev, char *buf) | ||
1569 | { | ||
1570 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1571 | char *s; | ||
1572 | |||
1573 | if (aiptek == NULL) | ||
1574 | return 0; | ||
1575 | |||
1576 | switch (aiptek->curSetting.stylusButtonLower) { | ||
1577 | case AIPTEK_STYLUS_UPPER_BUTTON: | ||
1578 | s = "upper"; | ||
1579 | break; | ||
1580 | |||
1581 | case AIPTEK_STYLUS_LOWER_BUTTON: | ||
1582 | s = "lower"; | ||
1583 | break; | ||
1584 | |||
1585 | default: | ||
1586 | s = "unknown"; | ||
1587 | break; | ||
1588 | } | ||
1589 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1590 | } | ||
1591 | |||
1592 | static ssize_t | ||
1593 | store_tabletStylusLower(struct device *dev, const char *buf, size_t count) | ||
1594 | { | ||
1595 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1596 | |||
1597 | if (aiptek == NULL) | ||
1598 | return 0; | ||
1599 | |||
1600 | if (strcmp(buf, "upper") == 0) { | ||
1601 | aiptek->newSetting.stylusButtonLower = | ||
1602 | AIPTEK_STYLUS_UPPER_BUTTON; | ||
1603 | } else if (strcmp(buf, "lower") == 0) { | ||
1604 | aiptek->newSetting.stylusButtonLower = | ||
1605 | AIPTEK_STYLUS_LOWER_BUTTON; | ||
1606 | } | ||
1607 | return count; | ||
1608 | } | ||
1609 | |||
1610 | static DEVICE_ATTR(stylus_lower, | ||
1611 | S_IRUGO | S_IWUGO, | ||
1612 | show_tabletStylusLower, store_tabletStylusLower); | ||
1613 | |||
1614 | /*********************************************************************** | ||
1615 | * support routines for the 'mouse_left' file. Note that this file | ||
1616 | * both displays current setting and allows for setting changing. | ||
1617 | */ | ||
1618 | static ssize_t show_tabletMouseLeft(struct device *dev, char *buf) | ||
1619 | { | ||
1620 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1621 | char *s; | ||
1622 | |||
1623 | if (aiptek == NULL) | ||
1624 | return 0; | ||
1625 | |||
1626 | switch (aiptek->curSetting.mouseButtonLeft) { | ||
1627 | case AIPTEK_MOUSE_LEFT_BUTTON: | ||
1628 | s = "left"; | ||
1629 | break; | ||
1630 | |||
1631 | case AIPTEK_MOUSE_MIDDLE_BUTTON: | ||
1632 | s = "middle"; | ||
1633 | break; | ||
1634 | |||
1635 | case AIPTEK_MOUSE_RIGHT_BUTTON: | ||
1636 | s = "right"; | ||
1637 | break; | ||
1638 | |||
1639 | default: | ||
1640 | s = "unknown"; | ||
1641 | break; | ||
1642 | } | ||
1643 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1644 | } | ||
1645 | |||
1646 | static ssize_t | ||
1647 | store_tabletMouseLeft(struct device *dev, const char *buf, size_t count) | ||
1648 | { | ||
1649 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1650 | |||
1651 | if (aiptek == NULL) | ||
1652 | return 0; | ||
1653 | |||
1654 | if (strcmp(buf, "left") == 0) { | ||
1655 | aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_LEFT_BUTTON; | ||
1656 | } else if (strcmp(buf, "middle") == 0) { | ||
1657 | aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_MIDDLE_BUTTON; | ||
1658 | } else if (strcmp(buf, "right") == 0) { | ||
1659 | aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_RIGHT_BUTTON; | ||
1660 | } | ||
1661 | return count; | ||
1662 | } | ||
1663 | |||
1664 | static DEVICE_ATTR(mouse_left, | ||
1665 | S_IRUGO | S_IWUGO, | ||
1666 | show_tabletMouseLeft, store_tabletMouseLeft); | ||
1667 | |||
1668 | /*********************************************************************** | ||
1669 | * support routines for the 'mouse_middle' file. Note that this file | ||
1670 | * both displays current setting and allows for setting changing. | ||
1671 | */ | ||
1672 | static ssize_t show_tabletMouseMiddle(struct device *dev, char *buf) | ||
1673 | { | ||
1674 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1675 | char *s; | ||
1676 | |||
1677 | if (aiptek == NULL) | ||
1678 | return 0; | ||
1679 | |||
1680 | switch (aiptek->curSetting.mouseButtonMiddle) { | ||
1681 | case AIPTEK_MOUSE_LEFT_BUTTON: | ||
1682 | s = "left"; | ||
1683 | break; | ||
1684 | |||
1685 | case AIPTEK_MOUSE_MIDDLE_BUTTON: | ||
1686 | s = "middle"; | ||
1687 | break; | ||
1688 | |||
1689 | case AIPTEK_MOUSE_RIGHT_BUTTON: | ||
1690 | s = "right"; | ||
1691 | break; | ||
1692 | |||
1693 | default: | ||
1694 | s = "unknown"; | ||
1695 | break; | ||
1696 | } | ||
1697 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1698 | } | ||
1699 | |||
1700 | static ssize_t | ||
1701 | store_tabletMouseMiddle(struct device *dev, const char *buf, size_t count) | ||
1702 | { | ||
1703 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1704 | |||
1705 | if (aiptek == NULL) | ||
1706 | return 0; | ||
1707 | |||
1708 | if (strcmp(buf, "left") == 0) { | ||
1709 | aiptek->newSetting.mouseButtonMiddle = AIPTEK_MOUSE_LEFT_BUTTON; | ||
1710 | } else if (strcmp(buf, "middle") == 0) { | ||
1711 | aiptek->newSetting.mouseButtonMiddle = | ||
1712 | AIPTEK_MOUSE_MIDDLE_BUTTON; | ||
1713 | } else if (strcmp(buf, "right") == 0) { | ||
1714 | aiptek->newSetting.mouseButtonMiddle = | ||
1715 | AIPTEK_MOUSE_RIGHT_BUTTON; | ||
1716 | } | ||
1717 | return count; | ||
1718 | } | ||
1719 | |||
1720 | static DEVICE_ATTR(mouse_middle, | ||
1721 | S_IRUGO | S_IWUGO, | ||
1722 | show_tabletMouseMiddle, store_tabletMouseMiddle); | ||
1723 | |||
1724 | /*********************************************************************** | ||
1725 | * support routines for the 'mouse_right' file. Note that this file | ||
1726 | * both displays current setting and allows for setting changing. | ||
1727 | */ | ||
1728 | static ssize_t show_tabletMouseRight(struct device *dev, char *buf) | ||
1729 | { | ||
1730 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1731 | char *s; | ||
1732 | |||
1733 | if (aiptek == NULL) | ||
1734 | return 0; | ||
1735 | |||
1736 | switch (aiptek->curSetting.mouseButtonRight) { | ||
1737 | case AIPTEK_MOUSE_LEFT_BUTTON: | ||
1738 | s = "left"; | ||
1739 | break; | ||
1740 | |||
1741 | case AIPTEK_MOUSE_MIDDLE_BUTTON: | ||
1742 | s = "middle"; | ||
1743 | break; | ||
1744 | |||
1745 | case AIPTEK_MOUSE_RIGHT_BUTTON: | ||
1746 | s = "right"; | ||
1747 | break; | ||
1748 | |||
1749 | default: | ||
1750 | s = "unknown"; | ||
1751 | break; | ||
1752 | } | ||
1753 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1754 | } | ||
1755 | |||
1756 | static ssize_t | ||
1757 | store_tabletMouseRight(struct device *dev, const char *buf, size_t count) | ||
1758 | { | ||
1759 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1760 | |||
1761 | if (aiptek == NULL) | ||
1762 | return 0; | ||
1763 | |||
1764 | if (strcmp(buf, "left") == 0) { | ||
1765 | aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_LEFT_BUTTON; | ||
1766 | } else if (strcmp(buf, "middle") == 0) { | ||
1767 | aiptek->newSetting.mouseButtonRight = | ||
1768 | AIPTEK_MOUSE_MIDDLE_BUTTON; | ||
1769 | } else if (strcmp(buf, "right") == 0) { | ||
1770 | aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON; | ||
1771 | } | ||
1772 | return count; | ||
1773 | } | ||
1774 | |||
1775 | static DEVICE_ATTR(mouse_right, | ||
1776 | S_IRUGO | S_IWUGO, | ||
1777 | show_tabletMouseRight, store_tabletMouseRight); | ||
1778 | |||
1779 | /*********************************************************************** | ||
1780 | * support routines for the 'wheel' file. Note that this file | ||
1781 | * both displays current setting and allows for setting changing. | ||
1782 | */ | ||
1783 | static ssize_t show_tabletWheel(struct device *dev, char *buf) | ||
1784 | { | ||
1785 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1786 | |||
1787 | if (aiptek == NULL) | ||
1788 | return 0; | ||
1789 | |||
1790 | if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) { | ||
1791 | return snprintf(buf, PAGE_SIZE, "disable\n"); | ||
1792 | } else { | ||
1793 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
1794 | aiptek->curSetting.wheel); | ||
1795 | } | ||
1796 | } | ||
1797 | |||
1798 | static ssize_t | ||
1799 | store_tabletWheel(struct device *dev, const char *buf, size_t count) | ||
1800 | { | ||
1801 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1802 | |||
1803 | if (aiptek == NULL) | ||
1804 | return 0; | ||
1805 | |||
1806 | aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10); | ||
1807 | return count; | ||
1808 | } | ||
1809 | |||
1810 | static DEVICE_ATTR(wheel, | ||
1811 | S_IRUGO | S_IWUGO, show_tabletWheel, store_tabletWheel); | ||
1812 | |||
1813 | /*********************************************************************** | ||
1814 | * support routines for the 'execute' file. Note that this file | ||
1815 | * both displays current setting and allows for setting changing. | ||
1816 | */ | ||
1817 | static ssize_t show_tabletExecute(struct device *dev, char *buf) | ||
1818 | { | ||
1819 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1820 | |||
1821 | if (aiptek == NULL) | ||
1822 | return 0; | ||
1823 | |||
1824 | /* There is nothing useful to display, so a one-line manual | ||
1825 | * is in order... | ||
1826 | */ | ||
1827 | return snprintf(buf, PAGE_SIZE, | ||
1828 | "Write anything to this file to program your tablet.\n"); | ||
1829 | } | ||
1830 | |||
1831 | static ssize_t | ||
1832 | store_tabletExecute(struct device *dev, const char *buf, size_t count) | ||
1833 | { | ||
1834 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1835 | |||
1836 | if (aiptek == NULL) | ||
1837 | return 0; | ||
1838 | |||
1839 | /* We do not care what you write to this file. Merely the action | ||
1840 | * of writing to this file triggers a tablet reprogramming. | ||
1841 | */ | ||
1842 | memcpy(&aiptek->curSetting, &aiptek->newSetting, | ||
1843 | sizeof(struct aiptek_settings)); | ||
1844 | |||
1845 | if (aiptek_program_tablet(aiptek) < 0) | ||
1846 | return -EIO; | ||
1847 | |||
1848 | return count; | ||
1849 | } | ||
1850 | |||
1851 | static DEVICE_ATTR(execute, | ||
1852 | S_IRUGO | S_IWUGO, show_tabletExecute, store_tabletExecute); | ||
1853 | |||
1854 | /*********************************************************************** | ||
1855 | * support routines for the 'odm_code' file. Note that this file | ||
1856 | * only displays current setting. | ||
1857 | */ | ||
1858 | static ssize_t show_tabletODMCode(struct device *dev, char *buf) | ||
1859 | { | ||
1860 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1861 | |||
1862 | if (aiptek == NULL) | ||
1863 | return 0; | ||
1864 | |||
1865 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.odmCode); | ||
1866 | } | ||
1867 | |||
1868 | static DEVICE_ATTR(odm_code, S_IRUGO, show_tabletODMCode, NULL); | ||
1869 | |||
1870 | /*********************************************************************** | ||
1871 | * support routines for the 'model_code' file. Note that this file | ||
1872 | * only displays current setting. | ||
1873 | */ | ||
1874 | static ssize_t show_tabletModelCode(struct device *dev, char *buf) | ||
1875 | { | ||
1876 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1877 | |||
1878 | if (aiptek == NULL) | ||
1879 | return 0; | ||
1880 | |||
1881 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.modelCode); | ||
1882 | } | ||
1883 | |||
1884 | static DEVICE_ATTR(model_code, S_IRUGO, show_tabletModelCode, NULL); | ||
1885 | |||
1886 | /*********************************************************************** | ||
1887 | * support routines for the 'firmware_code' file. Note that this file | ||
1888 | * only displays current setting. | ||
1889 | */ | ||
1890 | static ssize_t show_firmwareCode(struct device *dev, char *buf) | ||
1891 | { | ||
1892 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1893 | |||
1894 | if (aiptek == NULL) | ||
1895 | return 0; | ||
1896 | |||
1897 | return snprintf(buf, PAGE_SIZE, "%04x\n", | ||
1898 | aiptek->features.firmwareCode); | ||
1899 | } | ||
1900 | |||
1901 | static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL); | ||
1902 | |||
1903 | /*********************************************************************** | ||
1904 | * This routine removes all existing sysfs files managed by this device | ||
1905 | * driver. | ||
1906 | */ | ||
1907 | static void aiptek_delete_files(struct device *dev) | ||
1908 | { | ||
1909 | device_remove_file(dev, &dev_attr_size); | ||
1910 | device_remove_file(dev, &dev_attr_product_id); | ||
1911 | device_remove_file(dev, &dev_attr_vendor_id); | ||
1912 | device_remove_file(dev, &dev_attr_vendor); | ||
1913 | device_remove_file(dev, &dev_attr_product); | ||
1914 | device_remove_file(dev, &dev_attr_pointer_mode); | ||
1915 | device_remove_file(dev, &dev_attr_coordinate_mode); | ||
1916 | device_remove_file(dev, &dev_attr_tool_mode); | ||
1917 | device_remove_file(dev, &dev_attr_xtilt); | ||
1918 | device_remove_file(dev, &dev_attr_ytilt); | ||
1919 | device_remove_file(dev, &dev_attr_jitter); | ||
1920 | device_remove_file(dev, &dev_attr_delay); | ||
1921 | device_remove_file(dev, &dev_attr_input_path); | ||
1922 | device_remove_file(dev, &dev_attr_event_count); | ||
1923 | device_remove_file(dev, &dev_attr_diagnostic); | ||
1924 | device_remove_file(dev, &dev_attr_odm_code); | ||
1925 | device_remove_file(dev, &dev_attr_model_code); | ||
1926 | device_remove_file(dev, &dev_attr_firmware_code); | ||
1927 | device_remove_file(dev, &dev_attr_stylus_lower); | ||
1928 | device_remove_file(dev, &dev_attr_stylus_upper); | ||
1929 | device_remove_file(dev, &dev_attr_mouse_left); | ||
1930 | device_remove_file(dev, &dev_attr_mouse_middle); | ||
1931 | device_remove_file(dev, &dev_attr_mouse_right); | ||
1932 | device_remove_file(dev, &dev_attr_wheel); | ||
1933 | device_remove_file(dev, &dev_attr_execute); | ||
1934 | } | ||
1935 | |||
1936 | /*********************************************************************** | ||
1937 | * This routine creates the sysfs files managed by this device | ||
1938 | * driver. | ||
1939 | */ | ||
1940 | static int aiptek_add_files(struct device *dev) | ||
1941 | { | ||
1942 | int ret; | ||
1943 | |||
1944 | if ((ret = device_create_file(dev, &dev_attr_size)) || | ||
1945 | (ret = device_create_file(dev, &dev_attr_product_id)) || | ||
1946 | (ret = device_create_file(dev, &dev_attr_vendor_id)) || | ||
1947 | (ret = device_create_file(dev, &dev_attr_vendor)) || | ||
1948 | (ret = device_create_file(dev, &dev_attr_product)) || | ||
1949 | (ret = device_create_file(dev, &dev_attr_pointer_mode)) || | ||
1950 | (ret = device_create_file(dev, &dev_attr_coordinate_mode)) || | ||
1951 | (ret = device_create_file(dev, &dev_attr_tool_mode)) || | ||
1952 | (ret = device_create_file(dev, &dev_attr_xtilt)) || | ||
1953 | (ret = device_create_file(dev, &dev_attr_ytilt)) || | ||
1954 | (ret = device_create_file(dev, &dev_attr_jitter)) || | ||
1955 | (ret = device_create_file(dev, &dev_attr_delay)) || | ||
1956 | (ret = device_create_file(dev, &dev_attr_input_path)) || | ||
1957 | (ret = device_create_file(dev, &dev_attr_event_count)) || | ||
1958 | (ret = device_create_file(dev, &dev_attr_diagnostic)) || | ||
1959 | (ret = device_create_file(dev, &dev_attr_odm_code)) || | ||
1960 | (ret = device_create_file(dev, &dev_attr_model_code)) || | ||
1961 | (ret = device_create_file(dev, &dev_attr_firmware_code)) || | ||
1962 | (ret = device_create_file(dev, &dev_attr_stylus_lower)) || | ||
1963 | (ret = device_create_file(dev, &dev_attr_stylus_upper)) || | ||
1964 | (ret = device_create_file(dev, &dev_attr_mouse_left)) || | ||
1965 | (ret = device_create_file(dev, &dev_attr_mouse_middle)) || | ||
1966 | (ret = device_create_file(dev, &dev_attr_mouse_right)) || | ||
1967 | (ret = device_create_file(dev, &dev_attr_wheel)) || | ||
1968 | (ret = device_create_file(dev, &dev_attr_execute))) { | ||
1969 | err("aiptek: killing own sysfs device files\n"); | ||
1970 | aiptek_delete_files(dev); | ||
1971 | } | ||
1972 | return ret; | ||
1973 | } | ||
1974 | |||
1975 | /*********************************************************************** | ||
1976 | * This routine is called when a tablet has been identified. It basically | ||
1977 | * sets up the tablet and the driver's internal structures. | ||
1978 | */ | ||
1979 | static int | ||
1980 | aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
1981 | { | ||
1982 | struct usb_device *usbdev = interface_to_usbdev(intf); | ||
1983 | struct usb_endpoint_descriptor *endpoint; | ||
1984 | struct aiptek *aiptek; | ||
1985 | struct input_dev *inputdev; | ||
1986 | struct input_handle *inputhandle; | ||
1987 | struct list_head *node, *next; | ||
1988 | char path[64 + 1]; | ||
1989 | int i; | ||
1990 | int speeds[] = { 0, | ||
1991 | AIPTEK_PROGRAMMABLE_DELAY_50, | ||
1992 | AIPTEK_PROGRAMMABLE_DELAY_400, | ||
1993 | AIPTEK_PROGRAMMABLE_DELAY_25, | ||
1994 | AIPTEK_PROGRAMMABLE_DELAY_100, | ||
1995 | AIPTEK_PROGRAMMABLE_DELAY_200, | ||
1996 | AIPTEK_PROGRAMMABLE_DELAY_300 | ||
1997 | }; | ||
1998 | |||
1999 | /* programmableDelay is where the command-line specified | ||
2000 | * delay is kept. We make it the first element of speeds[], | ||
2001 | * so therefore, your override speed is tried first, then the | ||
2002 | * remainder. Note that the default value of 400ms will be tried | ||
2003 | * if you do not specify any command line parameter. | ||
2004 | */ | ||
2005 | speeds[0] = programmableDelay; | ||
2006 | |||
2007 | if ((aiptek = kmalloc(sizeof(struct aiptek), GFP_KERNEL)) == NULL) | ||
2008 | return -ENOMEM; | ||
2009 | memset(aiptek, 0, sizeof(struct aiptek)); | ||
2010 | |||
2011 | aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH, | ||
2012 | SLAB_ATOMIC, &aiptek->data_dma); | ||
2013 | if (aiptek->data == NULL) { | ||
2014 | kfree(aiptek); | ||
2015 | return -ENOMEM; | ||
2016 | } | ||
2017 | |||
2018 | aiptek->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
2019 | if (aiptek->urb == NULL) { | ||
2020 | usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, | ||
2021 | aiptek->data_dma); | ||
2022 | kfree(aiptek); | ||
2023 | return -ENOMEM; | ||
2024 | } | ||
2025 | |||
2026 | /* Set up the curSettings struct. Said struct contains the current | ||
2027 | * programmable parameters. The newSetting struct contains changes | ||
2028 | * the user makes to the settings via the sysfs interface. Those | ||
2029 | * changes are not "committed" to curSettings until the user | ||
2030 | * writes to the sysfs/.../execute file. | ||
2031 | */ | ||
2032 | aiptek->curSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE; | ||
2033 | aiptek->curSetting.coordinateMode = AIPTEK_COORDINATE_ABSOLUTE_MODE; | ||
2034 | aiptek->curSetting.toolMode = AIPTEK_TOOL_BUTTON_PEN_MODE; | ||
2035 | aiptek->curSetting.xTilt = AIPTEK_TILT_DISABLE; | ||
2036 | aiptek->curSetting.yTilt = AIPTEK_TILT_DISABLE; | ||
2037 | aiptek->curSetting.mouseButtonLeft = AIPTEK_MOUSE_LEFT_BUTTON; | ||
2038 | aiptek->curSetting.mouseButtonMiddle = AIPTEK_MOUSE_MIDDLE_BUTTON; | ||
2039 | aiptek->curSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON; | ||
2040 | aiptek->curSetting.stylusButtonUpper = AIPTEK_STYLUS_UPPER_BUTTON; | ||
2041 | aiptek->curSetting.stylusButtonLower = AIPTEK_STYLUS_LOWER_BUTTON; | ||
2042 | aiptek->curSetting.jitterDelay = jitterDelay; | ||
2043 | aiptek->curSetting.programmableDelay = programmableDelay; | ||
2044 | |||
2045 | /* Both structs should have equivalent settings | ||
2046 | */ | ||
2047 | memcpy(&aiptek->newSetting, &aiptek->curSetting, | ||
2048 | sizeof(struct aiptek_settings)); | ||
2049 | |||
2050 | /* Now program the capacities of the tablet, in terms of being | ||
2051 | * an input device. | ||
2052 | */ | ||
2053 | aiptek->inputdev.evbit[0] |= BIT(EV_KEY) | ||
2054 | | BIT(EV_ABS) | ||
2055 | | BIT(EV_REL) | ||
2056 | | BIT(EV_MSC); | ||
2057 | |||
2058 | aiptek->inputdev.absbit[0] |= | ||
2059 | (BIT(ABS_X) | | ||
2060 | BIT(ABS_Y) | | ||
2061 | BIT(ABS_PRESSURE) | | ||
2062 | BIT(ABS_TILT_X) | | ||
2063 | BIT(ABS_TILT_Y) | BIT(ABS_WHEEL) | BIT(ABS_MISC)); | ||
2064 | |||
2065 | aiptek->inputdev.relbit[0] |= | ||
2066 | (BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC)); | ||
2067 | |||
2068 | aiptek->inputdev.keybit[LONG(BTN_LEFT)] |= | ||
2069 | (BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE)); | ||
2070 | |||
2071 | aiptek->inputdev.keybit[LONG(BTN_DIGI)] |= | ||
2072 | (BIT(BTN_TOOL_PEN) | | ||
2073 | BIT(BTN_TOOL_RUBBER) | | ||
2074 | BIT(BTN_TOOL_PENCIL) | | ||
2075 | BIT(BTN_TOOL_AIRBRUSH) | | ||
2076 | BIT(BTN_TOOL_BRUSH) | | ||
2077 | BIT(BTN_TOOL_MOUSE) | | ||
2078 | BIT(BTN_TOOL_LENS) | | ||
2079 | BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2)); | ||
2080 | |||
2081 | aiptek->inputdev.mscbit[0] = BIT(MSC_SERIAL); | ||
2082 | |||
2083 | /* Programming the tablet macro keys needs to be done with a for loop | ||
2084 | * as the keycodes are discontiguous. | ||
2085 | */ | ||
2086 | for (i = 0; i < sizeof(macroKeyEvents) / sizeof(macroKeyEvents[0]); ++i) | ||
2087 | set_bit(macroKeyEvents[i], aiptek->inputdev.keybit); | ||
2088 | |||
2089 | /* Set up client data, pointers to open and close routines | ||
2090 | * for the input device. | ||
2091 | */ | ||
2092 | aiptek->inputdev.private = aiptek; | ||
2093 | aiptek->inputdev.open = aiptek_open; | ||
2094 | aiptek->inputdev.close = aiptek_close; | ||
2095 | |||
2096 | /* Determine the usb devices' physical path. | ||
2097 | * Asketh not why we always pretend we're using "../input0", | ||
2098 | * but I suspect this will have to be refactored one | ||
2099 | * day if a single USB device can be a keyboard & a mouse | ||
2100 | * & a tablet, and the inputX number actually will tell | ||
2101 | * us something... | ||
2102 | */ | ||
2103 | if (usb_make_path(usbdev, path, 64) > 0) | ||
2104 | sprintf(aiptek->features.usbPath, "%s/input0", path); | ||
2105 | |||
2106 | /* Program the input device coordinate capacities. We do not yet | ||
2107 | * know what maximum X, Y, and Z values are, so we're putting fake | ||
2108 | * values in. Later, we'll ask the tablet to put in the correct | ||
2109 | * values. | ||
2110 | */ | ||
2111 | aiptek->inputdev.absmin[ABS_X] = 0; | ||
2112 | aiptek->inputdev.absmax[ABS_X] = 2999; | ||
2113 | aiptek->inputdev.absmin[ABS_Y] = 0; | ||
2114 | aiptek->inputdev.absmax[ABS_Y] = 2249; | ||
2115 | aiptek->inputdev.absmin[ABS_PRESSURE] = 0; | ||
2116 | aiptek->inputdev.absmax[ABS_PRESSURE] = 511; | ||
2117 | aiptek->inputdev.absmin[ABS_TILT_X] = AIPTEK_TILT_MIN; | ||
2118 | aiptek->inputdev.absmax[ABS_TILT_X] = AIPTEK_TILT_MAX; | ||
2119 | aiptek->inputdev.absmin[ABS_TILT_Y] = AIPTEK_TILT_MIN; | ||
2120 | aiptek->inputdev.absmax[ABS_TILT_Y] = AIPTEK_TILT_MAX; | ||
2121 | aiptek->inputdev.absmin[ABS_WHEEL] = AIPTEK_WHEEL_MIN; | ||
2122 | aiptek->inputdev.absmax[ABS_WHEEL] = AIPTEK_WHEEL_MAX - 1; | ||
2123 | aiptek->inputdev.absfuzz[ABS_X] = 0; | ||
2124 | aiptek->inputdev.absfuzz[ABS_Y] = 0; | ||
2125 | aiptek->inputdev.absfuzz[ABS_PRESSURE] = 0; | ||
2126 | aiptek->inputdev.absfuzz[ABS_TILT_X] = 0; | ||
2127 | aiptek->inputdev.absfuzz[ABS_TILT_Y] = 0; | ||
2128 | aiptek->inputdev.absfuzz[ABS_WHEEL] = 0; | ||
2129 | aiptek->inputdev.absflat[ABS_X] = 0; | ||
2130 | aiptek->inputdev.absflat[ABS_Y] = 0; | ||
2131 | aiptek->inputdev.absflat[ABS_PRESSURE] = 0; | ||
2132 | aiptek->inputdev.absflat[ABS_TILT_X] = 0; | ||
2133 | aiptek->inputdev.absflat[ABS_TILT_Y] = 0; | ||
2134 | aiptek->inputdev.absflat[ABS_WHEEL] = 0; | ||
2135 | aiptek->inputdev.name = "Aiptek"; | ||
2136 | aiptek->inputdev.phys = aiptek->features.usbPath; | ||
2137 | aiptek->inputdev.id.bustype = BUS_USB; | ||
2138 | aiptek->inputdev.id.vendor = le16_to_cpu(usbdev->descriptor.idVendor); | ||
2139 | aiptek->inputdev.id.product = le16_to_cpu(usbdev->descriptor.idProduct); | ||
2140 | aiptek->inputdev.id.version = le16_to_cpu(usbdev->descriptor.bcdDevice); | ||
2141 | |||
2142 | aiptek->usbdev = usbdev; | ||
2143 | aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber; | ||
2144 | aiptek->inDelay = 0; | ||
2145 | aiptek->endDelay = 0; | ||
2146 | aiptek->previousJitterable = 0; | ||
2147 | |||
2148 | endpoint = &intf->altsetting[0].endpoint[0].desc; | ||
2149 | |||
2150 | /* Go set up our URB, which is called when the tablet receives | ||
2151 | * input. | ||
2152 | */ | ||
2153 | usb_fill_int_urb(aiptek->urb, | ||
2154 | aiptek->usbdev, | ||
2155 | usb_rcvintpipe(aiptek->usbdev, | ||
2156 | endpoint->bEndpointAddress), | ||
2157 | aiptek->data, 8, aiptek_irq, aiptek, | ||
2158 | endpoint->bInterval); | ||
2159 | |||
2160 | aiptek->urb->transfer_dma = aiptek->data_dma; | ||
2161 | aiptek->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
2162 | |||
2163 | /* Register the tablet as an Input Device | ||
2164 | */ | ||
2165 | input_register_device(&aiptek->inputdev); | ||
2166 | |||
2167 | /* We now will look for the evdev device which is mapped to | ||
2168 | * the tablet. The partial name is kept in the link list of | ||
2169 | * input_handles associated with this input device. | ||
2170 | * What identifies an evdev input_handler is that it begins | ||
2171 | * with 'event', continues with a digit, and that in turn | ||
2172 | * is mapped to /{devfs}/input/eventN. | ||
2173 | */ | ||
2174 | inputdev = &aiptek->inputdev; | ||
2175 | list_for_each_safe(node, next, &inputdev->h_list) { | ||
2176 | inputhandle = to_handle(node); | ||
2177 | if (strncmp(inputhandle->name, "event", 5) == 0) { | ||
2178 | strcpy(aiptek->features.inputPath, inputhandle->name); | ||
2179 | break; | ||
2180 | } | ||
2181 | } | ||
2182 | |||
2183 | info("input: Aiptek on %s (%s)\n", path, aiptek->features.inputPath); | ||
2184 | |||
2185 | /* Program the tablet. This sets the tablet up in the mode | ||
2186 | * specified in newSetting, and also queries the tablet's | ||
2187 | * physical capacities. | ||
2188 | * | ||
2189 | * Sanity check: if a tablet doesn't like the slow programmatic | ||
2190 | * delay, we often get sizes of 0x0. Let's use that as an indicator | ||
2191 | * to try faster delays, up to 25 ms. If that logic fails, well, you'll | ||
2192 | * have to explain to us how your tablet thinks it's 0x0, and yet that's | ||
2193 | * not an error :-) | ||
2194 | */ | ||
2195 | |||
2196 | for (i = 0; i < sizeof(speeds) / sizeof(speeds[0]); ++i) { | ||
2197 | aiptek->curSetting.programmableDelay = speeds[i]; | ||
2198 | (void)aiptek_program_tablet(aiptek); | ||
2199 | if (aiptek->inputdev.absmax[ABS_X] > 0) { | ||
2200 | info("input: Aiptek using %d ms programming speed\n", | ||
2201 | aiptek->curSetting.programmableDelay); | ||
2202 | break; | ||
2203 | } | ||
2204 | } | ||
2205 | |||
2206 | /* Associate this driver's struct with the usb interface. | ||
2207 | */ | ||
2208 | usb_set_intfdata(intf, aiptek); | ||
2209 | |||
2210 | /* Set up the sysfs files | ||
2211 | */ | ||
2212 | aiptek_add_files(&intf->dev); | ||
2213 | |||
2214 | /* Make sure the evdev module is loaded. Assuming evdev IS a module :-) | ||
2215 | */ | ||
2216 | if (request_module("evdev") != 0) | ||
2217 | info("aiptek: error loading 'evdev' module"); | ||
2218 | |||
2219 | return 0; | ||
2220 | } | ||
2221 | |||
2222 | /* Forward declaration */ | ||
2223 | static void aiptek_disconnect(struct usb_interface *intf); | ||
2224 | |||
2225 | static struct usb_driver aiptek_driver = { | ||
2226 | .owner = THIS_MODULE, | ||
2227 | .name = "aiptek", | ||
2228 | .probe = aiptek_probe, | ||
2229 | .disconnect = aiptek_disconnect, | ||
2230 | .id_table = aiptek_ids, | ||
2231 | }; | ||
2232 | |||
2233 | /*********************************************************************** | ||
2234 | * Deal with tablet disconnecting from the system. | ||
2235 | */ | ||
2236 | static void aiptek_disconnect(struct usb_interface *intf) | ||
2237 | { | ||
2238 | struct aiptek *aiptek = usb_get_intfdata(intf); | ||
2239 | |||
2240 | /* Disassociate driver's struct with usb interface | ||
2241 | */ | ||
2242 | usb_set_intfdata(intf, NULL); | ||
2243 | if (aiptek != NULL) { | ||
2244 | /* Free & unhook everything from the system. | ||
2245 | */ | ||
2246 | usb_kill_urb(aiptek->urb); | ||
2247 | input_unregister_device(&aiptek->inputdev); | ||
2248 | aiptek_delete_files(&intf->dev); | ||
2249 | usb_free_urb(aiptek->urb); | ||
2250 | usb_buffer_free(interface_to_usbdev(intf), | ||
2251 | AIPTEK_PACKET_LENGTH, | ||
2252 | aiptek->data, aiptek->data_dma); | ||
2253 | kfree(aiptek); | ||
2254 | aiptek = NULL; | ||
2255 | } | ||
2256 | } | ||
2257 | |||
2258 | static int __init aiptek_init(void) | ||
2259 | { | ||
2260 | int result = usb_register(&aiptek_driver); | ||
2261 | if (result == 0) { | ||
2262 | info(DRIVER_VERSION ": " DRIVER_AUTHOR); | ||
2263 | info(DRIVER_DESC); | ||
2264 | } | ||
2265 | return result; | ||
2266 | } | ||
2267 | |||
2268 | static void __exit aiptek_exit(void) | ||
2269 | { | ||
2270 | usb_deregister(&aiptek_driver); | ||
2271 | } | ||
2272 | |||
2273 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
2274 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
2275 | MODULE_LICENSE("GPL"); | ||
2276 | |||
2277 | module_param(programmableDelay, int, 0); | ||
2278 | MODULE_PARM_DESC(programmableDelay, "delay used during tablet programming"); | ||
2279 | module_param(jitterDelay, int, 0); | ||
2280 | MODULE_PARM_DESC(jitterDelay, "stylus/mouse settlement delay"); | ||
2281 | |||
2282 | module_init(aiptek_init); | ||
2283 | module_exit(aiptek_exit); | ||
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c new file mode 100644 index 000000000000..355add5c29f5 --- /dev/null +++ b/drivers/usb/input/ati_remote.c | |||
@@ -0,0 +1,850 @@ | |||
1 | /* | ||
2 | * USB ATI Remote support | ||
3 | * | ||
4 | * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net> | ||
5 | * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev | ||
6 | * | ||
7 | * This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including | ||
8 | * porting to the 2.6 kernel interfaces, along with other modification | ||
9 | * to better match the style of the existing usb/input drivers. However, the | ||
10 | * protocol and hardware handling is essentially unchanged from 2.1.1. | ||
11 | * | ||
12 | * The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by | ||
13 | * Vojtech Pavlik. | ||
14 | * | ||
15 | * Changes: | ||
16 | * | ||
17 | * Feb 2004: Torrey Hoffman <thoffman@arnor.net> | ||
18 | * Version 2.2.0 | ||
19 | * Jun 2004: Torrey Hoffman <thoffman@arnor.net> | ||
20 | * Version 2.2.1 | ||
21 | * Added key repeat support contributed by: | ||
22 | * Vincent Vanackere <vanackere@lif.univ-mrs.fr> | ||
23 | * Added support for the "Lola" remote contributed by: | ||
24 | * Seth Cohn <sethcohn@yahoo.com> | ||
25 | * | ||
26 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | ||
27 | * | ||
28 | * This program is free software; you can redistribute it and/or modify | ||
29 | * it under the terms of the GNU General Public License as published by | ||
30 | * the Free Software Foundation; either version 2 of the License, or | ||
31 | * (at your option) any later version. | ||
32 | * | ||
33 | * This program is distributed in the hope that it will be useful, | ||
34 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
35 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
36 | * GNU General Public License for more details. | ||
37 | * | ||
38 | * You should have received a copy of the GNU General Public License | ||
39 | * along with this program; if not, write to the Free Software | ||
40 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
41 | * | ||
42 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | ||
43 | * | ||
44 | * Hardware & software notes | ||
45 | * | ||
46 | * These remote controls are distributed by ATI as part of their | ||
47 | * "All-In-Wonder" video card packages. The receiver self-identifies as a | ||
48 | * "USB Receiver" with manufacturer "X10 Wireless Technology Inc". | ||
49 | * | ||
50 | * The "Lola" remote is available from X10. See: | ||
51 | * http://www.x10.com/products/lola_sg1.htm | ||
52 | * The Lola is similar to the ATI remote but has no mouse support, and slightly | ||
53 | * different keys. | ||
54 | * | ||
55 | * It is possible to use multiple receivers and remotes on multiple computers | ||
56 | * simultaneously by configuring them to use specific channels. | ||
57 | * | ||
58 | * The RF protocol used by the remote supports 16 distinct channels, 1 to 16. | ||
59 | * Actually, it may even support more, at least in some revisions of the | ||
60 | * hardware. | ||
61 | * | ||
62 | * Each remote can be configured to transmit on one channel as follows: | ||
63 | * - Press and hold the "hand icon" button. | ||
64 | * - When the red LED starts to blink, let go of the "hand icon" button. | ||
65 | * - When it stops blinking, input the channel code as two digits, from 01 | ||
66 | * to 16, and press the hand icon again. | ||
67 | * | ||
68 | * The timing can be a little tricky. Try loading the module with debug=1 | ||
69 | * to have the kernel print out messages about the remote control number | ||
70 | * and mask. Note: debugging prints remote numbers as zero-based hexadecimal. | ||
71 | * | ||
72 | * The driver has a "channel_mask" parameter. This bitmask specifies which | ||
73 | * channels will be ignored by the module. To mask out channels, just add | ||
74 | * all the 2^channel_number values together. | ||
75 | * | ||
76 | * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote | ||
77 | * ignore signals coming from remote controls transmitting on channel 4, but | ||
78 | * accept all other channels. | ||
79 | * | ||
80 | * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be | ||
81 | * ignored. | ||
82 | * | ||
83 | * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this | ||
84 | * parameter are unused. | ||
85 | * | ||
86 | */ | ||
87 | |||
88 | #include <linux/config.h> | ||
89 | #include <linux/kernel.h> | ||
90 | #include <linux/errno.h> | ||
91 | #include <linux/init.h> | ||
92 | #include <linux/slab.h> | ||
93 | #include <linux/module.h> | ||
94 | #include <linux/moduleparam.h> | ||
95 | #include <linux/input.h> | ||
96 | #include <linux/usb.h> | ||
97 | #include <linux/wait.h> | ||
98 | |||
99 | /* | ||
100 | * Module and Version Information, Module Parameters | ||
101 | */ | ||
102 | |||
103 | #define ATI_REMOTE_VENDOR_ID 0x0bc7 | ||
104 | #define ATI_REMOTE_PRODUCT_ID 0x004 | ||
105 | #define LOLA_REMOTE_PRODUCT_ID 0x002 | ||
106 | #define MEDION_REMOTE_PRODUCT_ID 0x006 | ||
107 | |||
108 | #define DRIVER_VERSION "2.2.1" | ||
109 | #define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" | ||
110 | #define DRIVER_DESC "ATI/X10 RF USB Remote Control" | ||
111 | |||
112 | #define NAME_BUFSIZE 80 /* size of product name, path buffers */ | ||
113 | #define DATA_BUFSIZE 63 /* size of URB data buffers */ | ||
114 | #define ATI_INPUTNUM 1 /* Which input device to register as */ | ||
115 | |||
116 | static unsigned long channel_mask = 0; | ||
117 | module_param(channel_mask, ulong, 0444); | ||
118 | MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); | ||
119 | |||
120 | static int debug = 0; | ||
121 | module_param(debug, int, 0444); | ||
122 | MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); | ||
123 | |||
124 | #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) | ||
125 | #undef err | ||
126 | #define err(format, arg...) printk(KERN_ERR format , ## arg) | ||
127 | |||
128 | static struct usb_device_id ati_remote_table[] = { | ||
129 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, | ||
130 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, | ||
131 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) }, | ||
132 | {} /* Terminating entry */ | ||
133 | }; | ||
134 | |||
135 | MODULE_DEVICE_TABLE(usb, ati_remote_table); | ||
136 | |||
137 | /* Get hi and low bytes of a 16-bits int */ | ||
138 | #define HI(a) ((unsigned char)((a) >> 8)) | ||
139 | #define LO(a) ((unsigned char)((a) & 0xff)) | ||
140 | |||
141 | #define SEND_FLAG_IN_PROGRESS 1 | ||
142 | #define SEND_FLAG_COMPLETE 2 | ||
143 | |||
144 | /* Device initialization strings */ | ||
145 | static char init1[] = { 0x01, 0x00, 0x20, 0x14 }; | ||
146 | static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; | ||
147 | |||
148 | /* Acceleration curve for directional control pad */ | ||
149 | static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; | ||
150 | |||
151 | /* Duplicate event filtering time. | ||
152 | * Sequential, identical KIND_FILTERED inputs with less than | ||
153 | * FILTER_TIME jiffies between them are considered as repeat | ||
154 | * events. The hardware generates 5 events for the first keypress | ||
155 | * and we have to take this into account for an accurate repeat | ||
156 | * behaviour. | ||
157 | * (HZ / 20) == 50 ms and works well for me. | ||
158 | */ | ||
159 | #define FILTER_TIME (HZ / 20) | ||
160 | |||
161 | static DECLARE_MUTEX(disconnect_sem); | ||
162 | |||
163 | struct ati_remote { | ||
164 | struct input_dev idev; | ||
165 | struct usb_device *udev; | ||
166 | struct usb_interface *interface; | ||
167 | |||
168 | struct urb *irq_urb; | ||
169 | struct urb *out_urb; | ||
170 | struct usb_endpoint_descriptor *endpoint_in; | ||
171 | struct usb_endpoint_descriptor *endpoint_out; | ||
172 | unsigned char *inbuf; | ||
173 | unsigned char *outbuf; | ||
174 | dma_addr_t inbuf_dma; | ||
175 | dma_addr_t outbuf_dma; | ||
176 | |||
177 | int open; /* open counter */ | ||
178 | |||
179 | unsigned char old_data[2]; /* Detect duplicate events */ | ||
180 | unsigned long old_jiffies; | ||
181 | unsigned long acc_jiffies; /* handle acceleration */ | ||
182 | unsigned int repeat_count; | ||
183 | |||
184 | char name[NAME_BUFSIZE]; | ||
185 | char phys[NAME_BUFSIZE]; | ||
186 | |||
187 | wait_queue_head_t wait; | ||
188 | int send_flags; | ||
189 | }; | ||
190 | |||
191 | /* "Kinds" of messages sent from the hardware to the driver. */ | ||
192 | #define KIND_END 0 | ||
193 | #define KIND_LITERAL 1 /* Simply pass to input system */ | ||
194 | #define KIND_FILTERED 2 /* Add artificial key-up events, drop keyrepeats */ | ||
195 | #define KIND_LU 3 /* Directional keypad diagonals - left up, */ | ||
196 | #define KIND_RU 4 /* right up, */ | ||
197 | #define KIND_LD 5 /* left down, */ | ||
198 | #define KIND_RD 6 /* right down */ | ||
199 | #define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/ | ||
200 | |||
201 | /* Translation table from hardware messages to input events. */ | ||
202 | static struct | ||
203 | { | ||
204 | short kind; | ||
205 | unsigned char data1, data2; | ||
206 | int type; | ||
207 | unsigned int code; | ||
208 | int value; | ||
209 | } ati_remote_tbl[] = | ||
210 | { | ||
211 | /* Directional control pad axes */ | ||
212 | {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ | ||
213 | {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ | ||
214 | {KIND_ACCEL, 0x37, 0x72, EV_REL, REL_Y, -1}, /* up */ | ||
215 | {KIND_ACCEL, 0x38, 0x73, EV_REL, REL_Y, 1}, /* down */ | ||
216 | /* Directional control pad diagonals */ | ||
217 | {KIND_LU, 0x39, 0x74, EV_REL, 0, 0}, /* left up */ | ||
218 | {KIND_RU, 0x3a, 0x75, EV_REL, 0, 0}, /* right up */ | ||
219 | {KIND_LD, 0x3c, 0x77, EV_REL, 0, 0}, /* left down */ | ||
220 | {KIND_RD, 0x3b, 0x76, EV_REL, 0, 0}, /* right down */ | ||
221 | |||
222 | /* "Mouse button" buttons */ | ||
223 | {KIND_LITERAL, 0x3d, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */ | ||
224 | {KIND_LITERAL, 0x3e, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */ | ||
225 | {KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ | ||
226 | {KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ | ||
227 | |||
228 | /* Artificial "doubleclick" events are generated by the hardware. | ||
229 | * They are mapped to the "side" and "extra" mouse buttons here. */ | ||
230 | {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ | ||
231 | {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ | ||
232 | |||
233 | /* keyboard. */ | ||
234 | {KIND_FILTERED, 0xd2, 0x0d, EV_KEY, KEY_1, 1}, | ||
235 | {KIND_FILTERED, 0xd3, 0x0e, EV_KEY, KEY_2, 1}, | ||
236 | {KIND_FILTERED, 0xd4, 0x0f, EV_KEY, KEY_3, 1}, | ||
237 | {KIND_FILTERED, 0xd5, 0x10, EV_KEY, KEY_4, 1}, | ||
238 | {KIND_FILTERED, 0xd6, 0x11, EV_KEY, KEY_5, 1}, | ||
239 | {KIND_FILTERED, 0xd7, 0x12, EV_KEY, KEY_6, 1}, | ||
240 | {KIND_FILTERED, 0xd8, 0x13, EV_KEY, KEY_7, 1}, | ||
241 | {KIND_FILTERED, 0xd9, 0x14, EV_KEY, KEY_8, 1}, | ||
242 | {KIND_FILTERED, 0xda, 0x15, EV_KEY, KEY_9, 1}, | ||
243 | {KIND_FILTERED, 0xdc, 0x17, EV_KEY, KEY_0, 1}, | ||
244 | {KIND_FILTERED, 0xc5, 0x00, EV_KEY, KEY_A, 1}, | ||
245 | {KIND_FILTERED, 0xc6, 0x01, EV_KEY, KEY_B, 1}, | ||
246 | {KIND_FILTERED, 0xde, 0x19, EV_KEY, KEY_C, 1}, | ||
247 | {KIND_FILTERED, 0xe0, 0x1b, EV_KEY, KEY_D, 1}, | ||
248 | {KIND_FILTERED, 0xe6, 0x21, EV_KEY, KEY_E, 1}, | ||
249 | {KIND_FILTERED, 0xe8, 0x23, EV_KEY, KEY_F, 1}, | ||
250 | |||
251 | /* "special" keys */ | ||
252 | {KIND_FILTERED, 0xdd, 0x18, EV_KEY, KEY_KPENTER, 1}, /* "check" */ | ||
253 | {KIND_FILTERED, 0xdb, 0x16, EV_KEY, KEY_MENU, 1}, /* "menu" */ | ||
254 | {KIND_FILTERED, 0xc7, 0x02, EV_KEY, KEY_POWER, 1}, /* Power */ | ||
255 | {KIND_FILTERED, 0xc8, 0x03, EV_KEY, KEY_TV, 1}, /* TV */ | ||
256 | {KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_DVD, 1}, /* DVD */ | ||
257 | {KIND_FILTERED, 0xca, 0x05, EV_KEY, KEY_WWW, 1}, /* WEB */ | ||
258 | {KIND_FILTERED, 0xcb, 0x06, EV_KEY, KEY_BOOKMARKS, 1}, /* "book" */ | ||
259 | {KIND_FILTERED, 0xcc, 0x07, EV_KEY, KEY_EDIT, 1}, /* "hand" */ | ||
260 | {KIND_FILTERED, 0xe1, 0x1c, EV_KEY, KEY_COFFEE, 1}, /* "timer" */ | ||
261 | {KIND_FILTERED, 0xe5, 0x20, EV_KEY, KEY_FRONT, 1}, /* "max" */ | ||
262 | {KIND_FILTERED, 0xe2, 0x1d, EV_KEY, KEY_LEFT, 1}, /* left */ | ||
263 | {KIND_FILTERED, 0xe4, 0x1f, EV_KEY, KEY_RIGHT, 1}, /* right */ | ||
264 | {KIND_FILTERED, 0xe7, 0x22, EV_KEY, KEY_DOWN, 1}, /* down */ | ||
265 | {KIND_FILTERED, 0xdf, 0x1a, EV_KEY, KEY_UP, 1}, /* up */ | ||
266 | {KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_OK, 1}, /* "OK" */ | ||
267 | {KIND_FILTERED, 0xce, 0x09, EV_KEY, KEY_VOLUMEDOWN, 1}, /* VOL + */ | ||
268 | {KIND_FILTERED, 0xcd, 0x08, EV_KEY, KEY_VOLUMEUP, 1}, /* VOL - */ | ||
269 | {KIND_FILTERED, 0xcf, 0x0a, EV_KEY, KEY_MUTE, 1}, /* MUTE */ | ||
270 | {KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELUP, 1}, /* CH + */ | ||
271 | {KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELDOWN, 1},/* CH - */ | ||
272 | {KIND_FILTERED, 0xec, 0x27, EV_KEY, KEY_RECORD, 1}, /* ( o) red */ | ||
273 | {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* ( >) */ | ||
274 | {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */ | ||
275 | {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */ | ||
276 | {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ | ||
277 | {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */ | ||
278 | {KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1}, /* (<-) */ | ||
279 | {KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1}, /* (>+) */ | ||
280 | {KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1}, /* PLAYING */ | ||
281 | {KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1}, /* TOP */ | ||
282 | {KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1}, /* END */ | ||
283 | {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */ | ||
284 | |||
285 | {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} | ||
286 | }; | ||
287 | |||
288 | /* Local function prototypes */ | ||
289 | static void ati_remote_dump (unsigned char *data, unsigned int actual_length); | ||
290 | static void ati_remote_delete (struct ati_remote *dev); | ||
291 | static int ati_remote_open (struct input_dev *inputdev); | ||
292 | static void ati_remote_close (struct input_dev *inputdev); | ||
293 | static int ati_remote_sendpacket (struct ati_remote *ati_remote, u16 cmd, unsigned char *data); | ||
294 | static void ati_remote_irq_out (struct urb *urb, struct pt_regs *regs); | ||
295 | static void ati_remote_irq_in (struct urb *urb, struct pt_regs *regs); | ||
296 | static void ati_remote_input_report (struct urb *urb, struct pt_regs *regs); | ||
297 | static int ati_remote_initialize (struct ati_remote *ati_remote); | ||
298 | static int ati_remote_probe (struct usb_interface *interface, const struct usb_device_id *id); | ||
299 | static void ati_remote_disconnect (struct usb_interface *interface); | ||
300 | |||
301 | /* usb specific object to register with the usb subsystem */ | ||
302 | static struct usb_driver ati_remote_driver = { | ||
303 | .owner = THIS_MODULE, | ||
304 | .name = "ati_remote", | ||
305 | .probe = ati_remote_probe, | ||
306 | .disconnect = ati_remote_disconnect, | ||
307 | .id_table = ati_remote_table, | ||
308 | }; | ||
309 | |||
310 | /* | ||
311 | * ati_remote_dump_input | ||
312 | */ | ||
313 | static void ati_remote_dump(unsigned char *data, unsigned int len) | ||
314 | { | ||
315 | if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00)) | ||
316 | warn("Weird byte 0x%02x", data[0]); | ||
317 | else if (len == 4) | ||
318 | warn("Weird key %02x %02x %02x %02x", | ||
319 | data[0], data[1], data[2], data[3]); | ||
320 | else | ||
321 | warn("Weird data, len=%d %02x %02x %02x %02x %02x %02x ...", | ||
322 | len, data[0], data[1], data[2], data[3], data[4], data[5]); | ||
323 | } | ||
324 | |||
325 | /* | ||
326 | * ati_remote_open | ||
327 | */ | ||
328 | static int ati_remote_open(struct input_dev *inputdev) | ||
329 | { | ||
330 | struct ati_remote *ati_remote = inputdev->private; | ||
331 | int retval = 0; | ||
332 | |||
333 | down(&disconnect_sem); | ||
334 | |||
335 | if (ati_remote->open++) | ||
336 | goto exit; | ||
337 | |||
338 | /* On first open, submit the read urb which was set up previously. */ | ||
339 | ati_remote->irq_urb->dev = ati_remote->udev; | ||
340 | if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) { | ||
341 | dev_err(&ati_remote->interface->dev, | ||
342 | "%s: usb_submit_urb failed!\n", __FUNCTION__); | ||
343 | ati_remote->open--; | ||
344 | retval = -EIO; | ||
345 | } | ||
346 | |||
347 | exit: | ||
348 | up(&disconnect_sem); | ||
349 | return retval; | ||
350 | } | ||
351 | |||
352 | /* | ||
353 | * ati_remote_close | ||
354 | */ | ||
355 | static void ati_remote_close(struct input_dev *inputdev) | ||
356 | { | ||
357 | struct ati_remote *ati_remote = inputdev->private; | ||
358 | |||
359 | if (!--ati_remote->open) | ||
360 | usb_kill_urb(ati_remote->irq_urb); | ||
361 | } | ||
362 | |||
363 | /* | ||
364 | * ati_remote_irq_out | ||
365 | */ | ||
366 | static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs) | ||
367 | { | ||
368 | struct ati_remote *ati_remote = urb->context; | ||
369 | |||
370 | if (urb->status) { | ||
371 | dev_dbg(&ati_remote->interface->dev, "%s: status %d\n", | ||
372 | __FUNCTION__, urb->status); | ||
373 | return; | ||
374 | } | ||
375 | |||
376 | ati_remote->send_flags |= SEND_FLAG_COMPLETE; | ||
377 | wmb(); | ||
378 | wake_up(&ati_remote->wait); | ||
379 | } | ||
380 | |||
381 | /* | ||
382 | * ati_remote_sendpacket | ||
383 | * | ||
384 | * Used to send device initialization strings | ||
385 | */ | ||
386 | static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data) | ||
387 | { | ||
388 | int retval = 0; | ||
389 | |||
390 | /* Set up out_urb */ | ||
391 | memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd)); | ||
392 | ((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd); | ||
393 | |||
394 | ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1; | ||
395 | ati_remote->out_urb->dev = ati_remote->udev; | ||
396 | ati_remote->send_flags = SEND_FLAG_IN_PROGRESS; | ||
397 | |||
398 | retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC); | ||
399 | if (retval) { | ||
400 | dev_dbg(&ati_remote->interface->dev, | ||
401 | "sendpacket: usb_submit_urb failed: %d\n", retval); | ||
402 | return retval; | ||
403 | } | ||
404 | |||
405 | wait_event_timeout(ati_remote->wait, | ||
406 | ((ati_remote->out_urb->status != -EINPROGRESS) || | ||
407 | (ati_remote->send_flags & SEND_FLAG_COMPLETE)), | ||
408 | HZ); | ||
409 | usb_kill_urb(ati_remote->out_urb); | ||
410 | |||
411 | return retval; | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * ati_remote_event_lookup | ||
416 | */ | ||
417 | static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) | ||
418 | { | ||
419 | int i; | ||
420 | |||
421 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { | ||
422 | /* | ||
423 | * Decide if the table entry matches the remote input. | ||
424 | */ | ||
425 | if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) && | ||
426 | ((((ati_remote_tbl[i].data1 >> 4) - | ||
427 | (d1 >> 4) + rem) & 0x0f) == 0x0f) && | ||
428 | (ati_remote_tbl[i].data2 == d2)) | ||
429 | return i; | ||
430 | |||
431 | } | ||
432 | return -1; | ||
433 | } | ||
434 | |||
435 | /* | ||
436 | * ati_remote_report_input | ||
437 | */ | ||
438 | static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | ||
439 | { | ||
440 | struct ati_remote *ati_remote = urb->context; | ||
441 | unsigned char *data= ati_remote->inbuf; | ||
442 | struct input_dev *dev = &ati_remote->idev; | ||
443 | int index, acc; | ||
444 | int remote_num; | ||
445 | |||
446 | /* Deal with strange looking inputs */ | ||
447 | if ( (urb->actual_length != 4) || (data[0] != 0x14) || | ||
448 | ((data[3] & 0x0f) != 0x00) ) { | ||
449 | ati_remote_dump(data, urb->actual_length); | ||
450 | return; | ||
451 | } | ||
452 | |||
453 | /* Mask unwanted remote channels. */ | ||
454 | /* note: remote_num is 0-based, channel 1 on remote == 0 here */ | ||
455 | remote_num = (data[3] >> 4) & 0x0f; | ||
456 | if (channel_mask & (1 << (remote_num + 1))) { | ||
457 | dbginfo(&ati_remote->interface->dev, | ||
458 | "Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n", | ||
459 | remote_num, data[1], data[2], channel_mask); | ||
460 | return; | ||
461 | } | ||
462 | |||
463 | /* Look up event code index in translation table */ | ||
464 | index = ati_remote_event_lookup(remote_num, data[1], data[2]); | ||
465 | if (index < 0) { | ||
466 | dev_warn(&ati_remote->interface->dev, | ||
467 | "Unknown input from channel 0x%02x: data %02x,%02x\n", | ||
468 | remote_num, data[1], data[2]); | ||
469 | return; | ||
470 | } | ||
471 | dbginfo(&ati_remote->interface->dev, | ||
472 | "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", | ||
473 | remote_num, data[1], data[2], index, ati_remote_tbl[index].code); | ||
474 | |||
475 | if (ati_remote_tbl[index].kind == KIND_LITERAL) { | ||
476 | input_regs(dev, regs); | ||
477 | input_event(dev, ati_remote_tbl[index].type, | ||
478 | ati_remote_tbl[index].code, | ||
479 | ati_remote_tbl[index].value); | ||
480 | input_sync(dev); | ||
481 | |||
482 | ati_remote->old_jiffies = jiffies; | ||
483 | return; | ||
484 | } | ||
485 | |||
486 | if (ati_remote_tbl[index].kind == KIND_FILTERED) { | ||
487 | /* Filter duplicate events which happen "too close" together. */ | ||
488 | if ((ati_remote->old_data[0] == data[1]) && | ||
489 | (ati_remote->old_data[1] == data[2]) && | ||
490 | ((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) { | ||
491 | ati_remote->repeat_count++; | ||
492 | } | ||
493 | else { | ||
494 | ati_remote->repeat_count = 0; | ||
495 | } | ||
496 | |||
497 | ati_remote->old_data[0] = data[1]; | ||
498 | ati_remote->old_data[1] = data[2]; | ||
499 | ati_remote->old_jiffies = jiffies; | ||
500 | |||
501 | if ((ati_remote->repeat_count > 0) | ||
502 | && (ati_remote->repeat_count < 5)) | ||
503 | return; | ||
504 | |||
505 | |||
506 | input_regs(dev, regs); | ||
507 | input_event(dev, ati_remote_tbl[index].type, | ||
508 | ati_remote_tbl[index].code, 1); | ||
509 | input_event(dev, ati_remote_tbl[index].type, | ||
510 | ati_remote_tbl[index].code, 0); | ||
511 | input_sync(dev); | ||
512 | |||
513 | return; | ||
514 | } | ||
515 | |||
516 | /* | ||
517 | * Other event kinds are from the directional control pad, and have an | ||
518 | * acceleration factor applied to them. Without this acceleration, the | ||
519 | * control pad is mostly unusable. | ||
520 | * | ||
521 | * If elapsed time since last event is > 1/4 second, user "stopped", | ||
522 | * so reset acceleration. Otherwise, user is probably holding the control | ||
523 | * pad down, so we increase acceleration, ramping up over two seconds to | ||
524 | * a maximum speed. The acceleration curve is #defined above. | ||
525 | */ | ||
526 | if ((jiffies - ati_remote->old_jiffies) > (HZ >> 2)) { | ||
527 | acc = 1; | ||
528 | ati_remote->acc_jiffies = jiffies; | ||
529 | } | ||
530 | else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 3)) acc = accel[0]; | ||
531 | else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 2)) acc = accel[1]; | ||
532 | else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 1)) acc = accel[2]; | ||
533 | else if ((jiffies - ati_remote->acc_jiffies) < HZ ) acc = accel[3]; | ||
534 | else if ((jiffies - ati_remote->acc_jiffies) < HZ+(HZ>>1)) acc = accel[4]; | ||
535 | else if ((jiffies - ati_remote->acc_jiffies) < (HZ << 1)) acc = accel[5]; | ||
536 | else acc = accel[6]; | ||
537 | |||
538 | input_regs(dev, regs); | ||
539 | switch (ati_remote_tbl[index].kind) { | ||
540 | case KIND_ACCEL: | ||
541 | input_event(dev, ati_remote_tbl[index].type, | ||
542 | ati_remote_tbl[index].code, | ||
543 | ati_remote_tbl[index].value * acc); | ||
544 | break; | ||
545 | case KIND_LU: | ||
546 | input_report_rel(dev, REL_X, -acc); | ||
547 | input_report_rel(dev, REL_Y, -acc); | ||
548 | break; | ||
549 | case KIND_RU: | ||
550 | input_report_rel(dev, REL_X, acc); | ||
551 | input_report_rel(dev, REL_Y, -acc); | ||
552 | break; | ||
553 | case KIND_LD: | ||
554 | input_report_rel(dev, REL_X, -acc); | ||
555 | input_report_rel(dev, REL_Y, acc); | ||
556 | break; | ||
557 | case KIND_RD: | ||
558 | input_report_rel(dev, REL_X, acc); | ||
559 | input_report_rel(dev, REL_Y, acc); | ||
560 | break; | ||
561 | default: | ||
562 | dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", | ||
563 | ati_remote_tbl[index].kind); | ||
564 | } | ||
565 | input_sync(dev); | ||
566 | |||
567 | ati_remote->old_jiffies = jiffies; | ||
568 | ati_remote->old_data[0] = data[1]; | ||
569 | ati_remote->old_data[1] = data[2]; | ||
570 | } | ||
571 | |||
572 | /* | ||
573 | * ati_remote_irq_in | ||
574 | */ | ||
575 | static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs) | ||
576 | { | ||
577 | struct ati_remote *ati_remote = urb->context; | ||
578 | int retval; | ||
579 | |||
580 | switch (urb->status) { | ||
581 | case 0: /* success */ | ||
582 | ati_remote_input_report(urb, regs); | ||
583 | break; | ||
584 | case -ECONNRESET: /* unlink */ | ||
585 | case -ENOENT: | ||
586 | case -ESHUTDOWN: | ||
587 | dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n", | ||
588 | __FUNCTION__); | ||
589 | return; | ||
590 | default: /* error */ | ||
591 | dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", | ||
592 | __FUNCTION__, urb->status); | ||
593 | } | ||
594 | |||
595 | retval = usb_submit_urb(urb, SLAB_ATOMIC); | ||
596 | if (retval) | ||
597 | dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", | ||
598 | __FUNCTION__, retval); | ||
599 | } | ||
600 | |||
601 | /* | ||
602 | * ati_remote_delete | ||
603 | */ | ||
604 | static void ati_remote_delete(struct ati_remote *ati_remote) | ||
605 | { | ||
606 | if (!ati_remote) return; | ||
607 | |||
608 | if (ati_remote->irq_urb) | ||
609 | usb_kill_urb(ati_remote->irq_urb); | ||
610 | |||
611 | if (ati_remote->out_urb) | ||
612 | usb_kill_urb(ati_remote->out_urb); | ||
613 | |||
614 | input_unregister_device(&ati_remote->idev); | ||
615 | |||
616 | if (ati_remote->inbuf) | ||
617 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, | ||
618 | ati_remote->inbuf, ati_remote->inbuf_dma); | ||
619 | |||
620 | if (ati_remote->outbuf) | ||
621 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, | ||
622 | ati_remote->inbuf, ati_remote->outbuf_dma); | ||
623 | |||
624 | if (ati_remote->irq_urb) | ||
625 | usb_free_urb(ati_remote->irq_urb); | ||
626 | |||
627 | if (ati_remote->out_urb) | ||
628 | usb_free_urb(ati_remote->out_urb); | ||
629 | |||
630 | kfree(ati_remote); | ||
631 | } | ||
632 | |||
633 | static void ati_remote_input_init(struct ati_remote *ati_remote) | ||
634 | { | ||
635 | struct input_dev *idev = &(ati_remote->idev); | ||
636 | int i; | ||
637 | |||
638 | idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
639 | idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | | ||
640 | BIT(BTN_SIDE) | BIT(BTN_EXTRA) ); | ||
641 | idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
642 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) | ||
643 | if (ati_remote_tbl[i].type == EV_KEY) | ||
644 | set_bit(ati_remote_tbl[i].code, idev->keybit); | ||
645 | |||
646 | idev->private = ati_remote; | ||
647 | idev->open = ati_remote_open; | ||
648 | idev->close = ati_remote_close; | ||
649 | |||
650 | idev->name = ati_remote->name; | ||
651 | idev->phys = ati_remote->phys; | ||
652 | |||
653 | idev->id.bustype = BUS_USB; | ||
654 | idev->id.vendor = le16_to_cpu(ati_remote->udev->descriptor.idVendor); | ||
655 | idev->id.product = le16_to_cpu(ati_remote->udev->descriptor.idProduct); | ||
656 | idev->id.version = le16_to_cpu(ati_remote->udev->descriptor.bcdDevice); | ||
657 | } | ||
658 | |||
659 | static int ati_remote_initialize(struct ati_remote *ati_remote) | ||
660 | { | ||
661 | struct usb_device *udev = ati_remote->udev; | ||
662 | int pipe, maxp; | ||
663 | |||
664 | init_waitqueue_head(&ati_remote->wait); | ||
665 | |||
666 | /* Set up irq_urb */ | ||
667 | pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); | ||
668 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
669 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; | ||
670 | |||
671 | usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, | ||
672 | maxp, ati_remote_irq_in, ati_remote, | ||
673 | ati_remote->endpoint_in->bInterval); | ||
674 | ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; | ||
675 | ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
676 | |||
677 | /* Set up out_urb */ | ||
678 | pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); | ||
679 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
680 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; | ||
681 | |||
682 | usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, | ||
683 | maxp, ati_remote_irq_out, ati_remote, | ||
684 | ati_remote->endpoint_out->bInterval); | ||
685 | ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; | ||
686 | ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
687 | |||
688 | /* send initialization strings */ | ||
689 | if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || | ||
690 | (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { | ||
691 | dev_err(&ati_remote->interface->dev, | ||
692 | "Initializing ati_remote hardware failed.\n"); | ||
693 | return 1; | ||
694 | } | ||
695 | |||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | /* | ||
700 | * ati_remote_probe | ||
701 | */ | ||
702 | static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id) | ||
703 | { | ||
704 | struct usb_device *udev = interface_to_usbdev(interface); | ||
705 | struct ati_remote *ati_remote = NULL; | ||
706 | struct usb_host_interface *iface_host; | ||
707 | int retval = -ENOMEM; | ||
708 | char path[64]; | ||
709 | |||
710 | /* Allocate and clear an ati_remote struct */ | ||
711 | if (!(ati_remote = kmalloc(sizeof (struct ati_remote), GFP_KERNEL))) | ||
712 | return -ENOMEM; | ||
713 | memset(ati_remote, 0x00, sizeof (struct ati_remote)); | ||
714 | |||
715 | iface_host = interface->cur_altsetting; | ||
716 | if (iface_host->desc.bNumEndpoints != 2) { | ||
717 | err("%s: Unexpected desc.bNumEndpoints\n", __FUNCTION__); | ||
718 | retval = -ENODEV; | ||
719 | goto error; | ||
720 | } | ||
721 | |||
722 | ati_remote->endpoint_in = &(iface_host->endpoint[0].desc); | ||
723 | ati_remote->endpoint_out = &(iface_host->endpoint[1].desc); | ||
724 | ati_remote->udev = udev; | ||
725 | ati_remote->interface = interface; | ||
726 | |||
727 | if (!(ati_remote->endpoint_in->bEndpointAddress & 0x80)) { | ||
728 | err("%s: Unexpected endpoint_in->bEndpointAddress\n", __FUNCTION__); | ||
729 | retval = -ENODEV; | ||
730 | goto error; | ||
731 | } | ||
732 | if ((ati_remote->endpoint_in->bmAttributes & 3) != 3) { | ||
733 | err("%s: Unexpected endpoint_in->bmAttributes\n", __FUNCTION__); | ||
734 | retval = -ENODEV; | ||
735 | goto error; | ||
736 | } | ||
737 | if (le16_to_cpu(ati_remote->endpoint_in->wMaxPacketSize) == 0) { | ||
738 | err("%s: endpoint_in message size==0? \n", __FUNCTION__); | ||
739 | retval = -ENODEV; | ||
740 | goto error; | ||
741 | } | ||
742 | |||
743 | /* Allocate URB buffers, URBs */ | ||
744 | ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC, | ||
745 | &ati_remote->inbuf_dma); | ||
746 | if (!ati_remote->inbuf) | ||
747 | goto error; | ||
748 | |||
749 | ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC, | ||
750 | &ati_remote->outbuf_dma); | ||
751 | if (!ati_remote->outbuf) | ||
752 | goto error; | ||
753 | |||
754 | ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
755 | if (!ati_remote->irq_urb) | ||
756 | goto error; | ||
757 | |||
758 | ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
759 | if (!ati_remote->out_urb) | ||
760 | goto error; | ||
761 | |||
762 | usb_make_path(udev, path, NAME_BUFSIZE); | ||
763 | sprintf(ati_remote->phys, "%s/input%d", path, ATI_INPUTNUM); | ||
764 | if (udev->manufacturer) | ||
765 | strcat(ati_remote->name, udev->manufacturer); | ||
766 | |||
767 | if (udev->product) | ||
768 | sprintf(ati_remote->name, "%s %s", ati_remote->name, udev->product); | ||
769 | |||
770 | if (!strlen(ati_remote->name)) | ||
771 | sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)", | ||
772 | le16_to_cpu(ati_remote->udev->descriptor.idVendor), | ||
773 | le16_to_cpu(ati_remote->udev->descriptor.idProduct)); | ||
774 | |||
775 | /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ | ||
776 | retval = ati_remote_initialize(ati_remote); | ||
777 | if (retval) | ||
778 | goto error; | ||
779 | |||
780 | /* Set up and register input device */ | ||
781 | ati_remote_input_init(ati_remote); | ||
782 | input_register_device(&ati_remote->idev); | ||
783 | |||
784 | dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n", | ||
785 | ati_remote->name, path); | ||
786 | |||
787 | usb_set_intfdata(interface, ati_remote); | ||
788 | |||
789 | error: | ||
790 | if (retval) | ||
791 | ati_remote_delete(ati_remote); | ||
792 | |||
793 | return retval; | ||
794 | } | ||
795 | |||
796 | /* | ||
797 | * ati_remote_disconnect | ||
798 | */ | ||
799 | static void ati_remote_disconnect(struct usb_interface *interface) | ||
800 | { | ||
801 | struct ati_remote *ati_remote; | ||
802 | |||
803 | down(&disconnect_sem); | ||
804 | |||
805 | ati_remote = usb_get_intfdata(interface); | ||
806 | usb_set_intfdata(interface, NULL); | ||
807 | if (!ati_remote) { | ||
808 | warn("%s - null device?\n", __FUNCTION__); | ||
809 | return; | ||
810 | } | ||
811 | |||
812 | ati_remote_delete(ati_remote); | ||
813 | |||
814 | up(&disconnect_sem); | ||
815 | } | ||
816 | |||
817 | /* | ||
818 | * ati_remote_init | ||
819 | */ | ||
820 | static int __init ati_remote_init(void) | ||
821 | { | ||
822 | int result; | ||
823 | |||
824 | result = usb_register(&ati_remote_driver); | ||
825 | if (result) | ||
826 | err("usb_register error #%d\n", result); | ||
827 | else | ||
828 | info("Registered USB driver " DRIVER_DESC " v. " DRIVER_VERSION); | ||
829 | |||
830 | return result; | ||
831 | } | ||
832 | |||
833 | /* | ||
834 | * ati_remote_exit | ||
835 | */ | ||
836 | static void __exit ati_remote_exit(void) | ||
837 | { | ||
838 | usb_deregister(&ati_remote_driver); | ||
839 | } | ||
840 | |||
841 | /* | ||
842 | * module specification | ||
843 | */ | ||
844 | |||
845 | module_init(ati_remote_init); | ||
846 | module_exit(ati_remote_exit); | ||
847 | |||
848 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
849 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
850 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/input/fixp-arith.h b/drivers/usb/input/fixp-arith.h new file mode 100644 index 000000000000..26ca5b890a61 --- /dev/null +++ b/drivers/usb/input/fixp-arith.h | |||
@@ -0,0 +1,90 @@ | |||
1 | #ifndef _FIXP_ARITH_H | ||
2 | #define _FIXP_ARITH_H | ||
3 | |||
4 | /* | ||
5 | * $$ | ||
6 | * | ||
7 | * Simplistic fixed-point arithmetics. | ||
8 | * Hmm, I'm probably duplicating some code :( | ||
9 | * | ||
10 | * Copyright (c) 2002 Johann Deneux | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
27 | * | ||
28 | * Should you need to contact me, the author, you can do so by | ||
29 | * e-mail - mail your message to <deneux@ifrance.com> | ||
30 | */ | ||
31 | |||
32 | #include <linux/types.h> | ||
33 | |||
34 | // The type representing fixed-point values | ||
35 | typedef s16 fixp_t; | ||
36 | |||
37 | #define FRAC_N 8 | ||
38 | #define FRAC_MASK ((1<<FRAC_N)-1) | ||
39 | |||
40 | // Not to be used directly. Use fixp_{cos,sin} | ||
41 | static fixp_t cos_table[45] = { | ||
42 | 0x0100, 0x00FF, 0x00FF, 0x00FE, 0x00FD, 0x00FC, 0x00FA, 0x00F8, | ||
43 | 0x00F6, 0x00F3, 0x00F0, 0x00ED, 0x00E9, 0x00E6, 0x00E2, 0x00DD, | ||
44 | 0x00D9, 0x00D4, 0x00CF, 0x00C9, 0x00C4, 0x00BE, 0x00B8, 0x00B1, | ||
45 | 0x00AB, 0x00A4, 0x009D, 0x0096, 0x008F, 0x0087, 0x0080, 0x0078, | ||
46 | 0x0070, 0x0068, 0x005F, 0x0057, 0x004F, 0x0046, 0x003D, 0x0035, | ||
47 | 0x002C, 0x0023, 0x001A, 0x0011, 0x0008 | ||
48 | }; | ||
49 | |||
50 | |||
51 | /* a: 123 -> 123.0 */ | ||
52 | static inline fixp_t fixp_new(s16 a) | ||
53 | { | ||
54 | return a<<FRAC_N; | ||
55 | } | ||
56 | |||
57 | /* a: 0xFFFF -> -1.0 | ||
58 | 0x8000 -> 1.0 | ||
59 | 0x0000 -> 0.0 | ||
60 | */ | ||
61 | static inline fixp_t fixp_new16(s16 a) | ||
62 | { | ||
63 | return ((s32)a)>>(16-FRAC_N); | ||
64 | } | ||
65 | |||
66 | static inline fixp_t fixp_cos(unsigned int degrees) | ||
67 | { | ||
68 | int quadrant = (degrees / 90) & 3; | ||
69 | unsigned int i = degrees % 90; | ||
70 | |||
71 | if (quadrant == 1 || quadrant == 3) { | ||
72 | i = 89 - i; | ||
73 | } | ||
74 | |||
75 | i >>= 1; | ||
76 | |||
77 | return (quadrant == 1 || quadrant == 2)? -cos_table[i] : cos_table[i]; | ||
78 | } | ||
79 | |||
80 | static inline fixp_t fixp_sin(unsigned int degrees) | ||
81 | { | ||
82 | return -fixp_cos(degrees + 90); | ||
83 | } | ||
84 | |||
85 | static inline fixp_t fixp_mult(fixp_t a, fixp_t b) | ||
86 | { | ||
87 | return ((s32)(a*b))>>FRAC_N; | ||
88 | } | ||
89 | |||
90 | #endif | ||
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c new file mode 100644 index 000000000000..7662cf4e2621 --- /dev/null +++ b/drivers/usb/input/hid-core.c | |||
@@ -0,0 +1,1864 @@ | |||
1 | /* | ||
2 | * USB HID support for Linux | ||
3 | * | ||
4 | * Copyright (c) 1999 Andreas Gal | ||
5 | * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@suse.cz> | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
12 | * any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/list.h> | ||
21 | #include <linux/mm.h> | ||
22 | #include <linux/smp_lock.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <asm/unaligned.h> | ||
25 | #include <asm/byteorder.h> | ||
26 | #include <linux/input.h> | ||
27 | #include <linux/wait.h> | ||
28 | |||
29 | #undef DEBUG | ||
30 | #undef DEBUG_DATA | ||
31 | |||
32 | #include <linux/usb.h> | ||
33 | |||
34 | #include "hid.h" | ||
35 | #include <linux/hiddev.h> | ||
36 | |||
37 | /* | ||
38 | * Version Information | ||
39 | */ | ||
40 | |||
41 | #define DRIVER_VERSION "v2.01" | ||
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 | * Register a new report for a device. | ||
58 | */ | ||
59 | |||
60 | static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id) | ||
61 | { | ||
62 | struct hid_report_enum *report_enum = device->report_enum + type; | ||
63 | struct hid_report *report; | ||
64 | |||
65 | if (report_enum->report_id_hash[id]) | ||
66 | return report_enum->report_id_hash[id]; | ||
67 | |||
68 | if (!(report = kmalloc(sizeof(struct hid_report), GFP_KERNEL))) | ||
69 | return NULL; | ||
70 | memset(report, 0, sizeof(struct hid_report)); | ||
71 | |||
72 | if (id != 0) | ||
73 | report_enum->numbered = 1; | ||
74 | |||
75 | report->id = id; | ||
76 | report->type = type; | ||
77 | report->size = 0; | ||
78 | report->device = device; | ||
79 | report_enum->report_id_hash[id] = report; | ||
80 | |||
81 | list_add_tail(&report->list, &report_enum->report_list); | ||
82 | |||
83 | return report; | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | * Register a new field for this report. | ||
88 | */ | ||
89 | |||
90 | static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) | ||
91 | { | ||
92 | struct hid_field *field; | ||
93 | |||
94 | if (report->maxfield == HID_MAX_FIELDS) { | ||
95 | dbg("too many fields in report"); | ||
96 | return NULL; | ||
97 | } | ||
98 | |||
99 | if (!(field = kmalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage) | ||
100 | + values * sizeof(unsigned), GFP_KERNEL))) return NULL; | ||
101 | |||
102 | memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage) | ||
103 | + values * sizeof(unsigned)); | ||
104 | |||
105 | field->index = report->maxfield++; | ||
106 | report->field[field->index] = field; | ||
107 | field->usage = (struct hid_usage *)(field + 1); | ||
108 | field->value = (unsigned *)(field->usage + usages); | ||
109 | field->report = report; | ||
110 | |||
111 | return field; | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * Open a collection. The type/usage is pushed on the stack. | ||
116 | */ | ||
117 | |||
118 | static int open_collection(struct hid_parser *parser, unsigned type) | ||
119 | { | ||
120 | struct hid_collection *collection; | ||
121 | unsigned usage; | ||
122 | |||
123 | usage = parser->local.usage[0]; | ||
124 | |||
125 | if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { | ||
126 | dbg("collection stack overflow"); | ||
127 | return -1; | ||
128 | } | ||
129 | |||
130 | if (parser->device->maxcollection == parser->device->collection_size) { | ||
131 | collection = kmalloc(sizeof(struct hid_collection) * | ||
132 | parser->device->collection_size * 2, GFP_KERNEL); | ||
133 | if (collection == NULL) { | ||
134 | dbg("failed to reallocate collection array"); | ||
135 | return -1; | ||
136 | } | ||
137 | memcpy(collection, parser->device->collection, | ||
138 | sizeof(struct hid_collection) * | ||
139 | parser->device->collection_size); | ||
140 | memset(collection + parser->device->collection_size, 0, | ||
141 | sizeof(struct hid_collection) * | ||
142 | parser->device->collection_size); | ||
143 | kfree(parser->device->collection); | ||
144 | parser->device->collection = collection; | ||
145 | parser->device->collection_size *= 2; | ||
146 | } | ||
147 | |||
148 | parser->collection_stack[parser->collection_stack_ptr++] = | ||
149 | parser->device->maxcollection; | ||
150 | |||
151 | collection = parser->device->collection + | ||
152 | parser->device->maxcollection++; | ||
153 | collection->type = type; | ||
154 | collection->usage = usage; | ||
155 | collection->level = parser->collection_stack_ptr - 1; | ||
156 | |||
157 | if (type == HID_COLLECTION_APPLICATION) | ||
158 | parser->device->maxapplication++; | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * Close a collection. | ||
165 | */ | ||
166 | |||
167 | static int close_collection(struct hid_parser *parser) | ||
168 | { | ||
169 | if (!parser->collection_stack_ptr) { | ||
170 | dbg("collection stack underflow"); | ||
171 | return -1; | ||
172 | } | ||
173 | parser->collection_stack_ptr--; | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | * Climb up the stack, search for the specified collection type | ||
179 | * and return the usage. | ||
180 | */ | ||
181 | |||
182 | static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) | ||
183 | { | ||
184 | int n; | ||
185 | for (n = parser->collection_stack_ptr - 1; n >= 0; n--) | ||
186 | if (parser->device->collection[parser->collection_stack[n]].type == type) | ||
187 | return parser->device->collection[parser->collection_stack[n]].usage; | ||
188 | return 0; /* we know nothing about this usage type */ | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | * Add a usage to the temporary parser table. | ||
193 | */ | ||
194 | |||
195 | static int hid_add_usage(struct hid_parser *parser, unsigned usage) | ||
196 | { | ||
197 | if (parser->local.usage_index >= HID_MAX_USAGES) { | ||
198 | dbg("usage index exceeded"); | ||
199 | return -1; | ||
200 | } | ||
201 | parser->local.usage[parser->local.usage_index] = usage; | ||
202 | parser->local.collection_index[parser->local.usage_index] = | ||
203 | parser->collection_stack_ptr ? | ||
204 | parser->collection_stack[parser->collection_stack_ptr - 1] : 0; | ||
205 | parser->local.usage_index++; | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | * Register a new field for this report. | ||
211 | */ | ||
212 | |||
213 | static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags) | ||
214 | { | ||
215 | struct hid_report *report; | ||
216 | struct hid_field *field; | ||
217 | int usages; | ||
218 | unsigned offset; | ||
219 | int i; | ||
220 | |||
221 | if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) { | ||
222 | dbg("hid_register_report failed"); | ||
223 | return -1; | ||
224 | } | ||
225 | |||
226 | if (parser->global.logical_maximum < parser->global.logical_minimum) { | ||
227 | dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum); | ||
228 | return -1; | ||
229 | } | ||
230 | |||
231 | offset = report->size; | ||
232 | report->size += parser->global.report_size * parser->global.report_count; | ||
233 | |||
234 | if (!parser->local.usage_index) /* Ignore padding fields */ | ||
235 | return 0; | ||
236 | |||
237 | usages = max_t(int, parser->local.usage_index, parser->global.report_count); | ||
238 | |||
239 | if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL) | ||
240 | return 0; | ||
241 | |||
242 | field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL); | ||
243 | field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL); | ||
244 | field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); | ||
245 | |||
246 | for (i = 0; i < usages; i++) { | ||
247 | int j = i; | ||
248 | /* Duplicate the last usage we parsed if we have excess values */ | ||
249 | if (i >= parser->local.usage_index) | ||
250 | j = parser->local.usage_index - 1; | ||
251 | field->usage[i].hid = parser->local.usage[j]; | ||
252 | field->usage[i].collection_index = | ||
253 | parser->local.collection_index[j]; | ||
254 | } | ||
255 | |||
256 | field->maxusage = usages; | ||
257 | field->flags = flags; | ||
258 | field->report_offset = offset; | ||
259 | field->report_type = report_type; | ||
260 | field->report_size = parser->global.report_size; | ||
261 | field->report_count = parser->global.report_count; | ||
262 | field->logical_minimum = parser->global.logical_minimum; | ||
263 | field->logical_maximum = parser->global.logical_maximum; | ||
264 | field->physical_minimum = parser->global.physical_minimum; | ||
265 | field->physical_maximum = parser->global.physical_maximum; | ||
266 | field->unit_exponent = parser->global.unit_exponent; | ||
267 | field->unit = parser->global.unit; | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | /* | ||
273 | * Read data value from item. | ||
274 | */ | ||
275 | |||
276 | static __inline__ __u32 item_udata(struct hid_item *item) | ||
277 | { | ||
278 | switch (item->size) { | ||
279 | case 1: return item->data.u8; | ||
280 | case 2: return item->data.u16; | ||
281 | case 4: return item->data.u32; | ||
282 | } | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static __inline__ __s32 item_sdata(struct hid_item *item) | ||
287 | { | ||
288 | switch (item->size) { | ||
289 | case 1: return item->data.s8; | ||
290 | case 2: return item->data.s16; | ||
291 | case 4: return item->data.s32; | ||
292 | } | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | /* | ||
297 | * Process a global item. | ||
298 | */ | ||
299 | |||
300 | static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | ||
301 | { | ||
302 | switch (item->tag) { | ||
303 | |||
304 | case HID_GLOBAL_ITEM_TAG_PUSH: | ||
305 | |||
306 | if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) { | ||
307 | dbg("global enviroment stack overflow"); | ||
308 | return -1; | ||
309 | } | ||
310 | |||
311 | memcpy(parser->global_stack + parser->global_stack_ptr++, | ||
312 | &parser->global, sizeof(struct hid_global)); | ||
313 | return 0; | ||
314 | |||
315 | case HID_GLOBAL_ITEM_TAG_POP: | ||
316 | |||
317 | if (!parser->global_stack_ptr) { | ||
318 | dbg("global enviroment stack underflow"); | ||
319 | return -1; | ||
320 | } | ||
321 | |||
322 | memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr, | ||
323 | sizeof(struct hid_global)); | ||
324 | return 0; | ||
325 | |||
326 | case HID_GLOBAL_ITEM_TAG_USAGE_PAGE: | ||
327 | parser->global.usage_page = item_udata(item); | ||
328 | return 0; | ||
329 | |||
330 | case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM: | ||
331 | parser->global.logical_minimum = item_sdata(item); | ||
332 | return 0; | ||
333 | |||
334 | case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM: | ||
335 | if (parser->global.logical_minimum < 0) | ||
336 | parser->global.logical_maximum = item_sdata(item); | ||
337 | else | ||
338 | parser->global.logical_maximum = item_udata(item); | ||
339 | return 0; | ||
340 | |||
341 | case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM: | ||
342 | parser->global.physical_minimum = item_sdata(item); | ||
343 | return 0; | ||
344 | |||
345 | case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM: | ||
346 | if (parser->global.physical_minimum < 0) | ||
347 | parser->global.physical_maximum = item_sdata(item); | ||
348 | else | ||
349 | parser->global.physical_maximum = item_udata(item); | ||
350 | return 0; | ||
351 | |||
352 | case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: | ||
353 | parser->global.unit_exponent = item_sdata(item); | ||
354 | return 0; | ||
355 | |||
356 | case HID_GLOBAL_ITEM_TAG_UNIT: | ||
357 | parser->global.unit = item_udata(item); | ||
358 | return 0; | ||
359 | |||
360 | case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: | ||
361 | if ((parser->global.report_size = item_udata(item)) > 32) { | ||
362 | dbg("invalid report_size %d", parser->global.report_size); | ||
363 | return -1; | ||
364 | } | ||
365 | return 0; | ||
366 | |||
367 | case HID_GLOBAL_ITEM_TAG_REPORT_COUNT: | ||
368 | if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) { | ||
369 | dbg("invalid report_count %d", parser->global.report_count); | ||
370 | return -1; | ||
371 | } | ||
372 | return 0; | ||
373 | |||
374 | case HID_GLOBAL_ITEM_TAG_REPORT_ID: | ||
375 | if ((parser->global.report_id = item_udata(item)) == 0) { | ||
376 | dbg("report_id 0 is invalid"); | ||
377 | return -1; | ||
378 | } | ||
379 | return 0; | ||
380 | |||
381 | default: | ||
382 | dbg("unknown global tag 0x%x", item->tag); | ||
383 | return -1; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | /* | ||
388 | * Process a local item. | ||
389 | */ | ||
390 | |||
391 | static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) | ||
392 | { | ||
393 | __u32 data; | ||
394 | unsigned n; | ||
395 | |||
396 | if (item->size == 0) { | ||
397 | dbg("item data expected for local item"); | ||
398 | return -1; | ||
399 | } | ||
400 | |||
401 | data = item_udata(item); | ||
402 | |||
403 | switch (item->tag) { | ||
404 | |||
405 | case HID_LOCAL_ITEM_TAG_DELIMITER: | ||
406 | |||
407 | if (data) { | ||
408 | /* | ||
409 | * We treat items before the first delimiter | ||
410 | * as global to all usage sets (branch 0). | ||
411 | * In the moment we process only these global | ||
412 | * items and the first delimiter set. | ||
413 | */ | ||
414 | if (parser->local.delimiter_depth != 0) { | ||
415 | dbg("nested delimiters"); | ||
416 | return -1; | ||
417 | } | ||
418 | parser->local.delimiter_depth++; | ||
419 | parser->local.delimiter_branch++; | ||
420 | } else { | ||
421 | if (parser->local.delimiter_depth < 1) { | ||
422 | dbg("bogus close delimiter"); | ||
423 | return -1; | ||
424 | } | ||
425 | parser->local.delimiter_depth--; | ||
426 | } | ||
427 | return 1; | ||
428 | |||
429 | case HID_LOCAL_ITEM_TAG_USAGE: | ||
430 | |||
431 | if (parser->local.delimiter_branch > 1) { | ||
432 | dbg("alternative usage ignored"); | ||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | if (item->size <= 2) | ||
437 | data = (parser->global.usage_page << 16) + data; | ||
438 | |||
439 | return hid_add_usage(parser, data); | ||
440 | |||
441 | case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: | ||
442 | |||
443 | if (parser->local.delimiter_branch > 1) { | ||
444 | dbg("alternative usage ignored"); | ||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | if (item->size <= 2) | ||
449 | data = (parser->global.usage_page << 16) + data; | ||
450 | |||
451 | parser->local.usage_minimum = data; | ||
452 | return 0; | ||
453 | |||
454 | case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM: | ||
455 | |||
456 | if (parser->local.delimiter_branch > 1) { | ||
457 | dbg("alternative usage ignored"); | ||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | if (item->size <= 2) | ||
462 | data = (parser->global.usage_page << 16) + data; | ||
463 | |||
464 | for (n = parser->local.usage_minimum; n <= data; n++) | ||
465 | if (hid_add_usage(parser, n)) { | ||
466 | dbg("hid_add_usage failed\n"); | ||
467 | return -1; | ||
468 | } | ||
469 | return 0; | ||
470 | |||
471 | default: | ||
472 | |||
473 | dbg("unknown local item tag 0x%x", item->tag); | ||
474 | return 0; | ||
475 | } | ||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | /* | ||
480 | * Process a main item. | ||
481 | */ | ||
482 | |||
483 | static int hid_parser_main(struct hid_parser *parser, struct hid_item *item) | ||
484 | { | ||
485 | __u32 data; | ||
486 | int ret; | ||
487 | |||
488 | data = item_udata(item); | ||
489 | |||
490 | switch (item->tag) { | ||
491 | case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION: | ||
492 | ret = open_collection(parser, data & 0xff); | ||
493 | break; | ||
494 | case HID_MAIN_ITEM_TAG_END_COLLECTION: | ||
495 | ret = close_collection(parser); | ||
496 | break; | ||
497 | case HID_MAIN_ITEM_TAG_INPUT: | ||
498 | ret = hid_add_field(parser, HID_INPUT_REPORT, data); | ||
499 | break; | ||
500 | case HID_MAIN_ITEM_TAG_OUTPUT: | ||
501 | ret = hid_add_field(parser, HID_OUTPUT_REPORT, data); | ||
502 | break; | ||
503 | case HID_MAIN_ITEM_TAG_FEATURE: | ||
504 | ret = hid_add_field(parser, HID_FEATURE_REPORT, data); | ||
505 | break; | ||
506 | default: | ||
507 | dbg("unknown main item tag 0x%x", item->tag); | ||
508 | ret = 0; | ||
509 | } | ||
510 | |||
511 | memset(&parser->local, 0, sizeof(parser->local)); /* Reset the local parser environment */ | ||
512 | |||
513 | return ret; | ||
514 | } | ||
515 | |||
516 | /* | ||
517 | * Process a reserved item. | ||
518 | */ | ||
519 | |||
520 | static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item) | ||
521 | { | ||
522 | dbg("reserved item type, tag 0x%x", item->tag); | ||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | /* | ||
527 | * Free a report and all registered fields. The field->usage and | ||
528 | * field->value table's are allocated behind the field, so we need | ||
529 | * only to free(field) itself. | ||
530 | */ | ||
531 | |||
532 | static void hid_free_report(struct hid_report *report) | ||
533 | { | ||
534 | unsigned n; | ||
535 | |||
536 | for (n = 0; n < report->maxfield; n++) | ||
537 | kfree(report->field[n]); | ||
538 | kfree(report); | ||
539 | } | ||
540 | |||
541 | /* | ||
542 | * Free a device structure, all reports, and all fields. | ||
543 | */ | ||
544 | |||
545 | static void hid_free_device(struct hid_device *device) | ||
546 | { | ||
547 | unsigned i,j; | ||
548 | |||
549 | hid_ff_exit(device); | ||
550 | |||
551 | for (i = 0; i < HID_REPORT_TYPES; i++) { | ||
552 | struct hid_report_enum *report_enum = device->report_enum + i; | ||
553 | |||
554 | for (j = 0; j < 256; j++) { | ||
555 | struct hid_report *report = report_enum->report_id_hash[j]; | ||
556 | if (report) | ||
557 | hid_free_report(report); | ||
558 | } | ||
559 | } | ||
560 | |||
561 | if (device->rdesc) | ||
562 | kfree(device->rdesc); | ||
563 | kfree(device); | ||
564 | } | ||
565 | |||
566 | /* | ||
567 | * Fetch a report description item from the data stream. We support long | ||
568 | * items, though they are not used yet. | ||
569 | */ | ||
570 | |||
571 | static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) | ||
572 | { | ||
573 | u8 b; | ||
574 | |||
575 | if ((end - start) <= 0) | ||
576 | return NULL; | ||
577 | |||
578 | b = *start++; | ||
579 | |||
580 | item->type = (b >> 2) & 3; | ||
581 | item->tag = (b >> 4) & 15; | ||
582 | |||
583 | if (item->tag == HID_ITEM_TAG_LONG) { | ||
584 | |||
585 | item->format = HID_ITEM_FORMAT_LONG; | ||
586 | |||
587 | if ((end - start) < 2) | ||
588 | return NULL; | ||
589 | |||
590 | item->size = *start++; | ||
591 | item->tag = *start++; | ||
592 | |||
593 | if ((end - start) < item->size) | ||
594 | return NULL; | ||
595 | |||
596 | item->data.longdata = start; | ||
597 | start += item->size; | ||
598 | return start; | ||
599 | } | ||
600 | |||
601 | item->format = HID_ITEM_FORMAT_SHORT; | ||
602 | item->size = b & 3; | ||
603 | |||
604 | switch (item->size) { | ||
605 | |||
606 | case 0: | ||
607 | return start; | ||
608 | |||
609 | case 1: | ||
610 | if ((end - start) < 1) | ||
611 | return NULL; | ||
612 | item->data.u8 = *start++; | ||
613 | return start; | ||
614 | |||
615 | case 2: | ||
616 | if ((end - start) < 2) | ||
617 | return NULL; | ||
618 | item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start)); | ||
619 | start = (__u8 *)((__le16 *)start + 1); | ||
620 | return start; | ||
621 | |||
622 | case 3: | ||
623 | item->size++; | ||
624 | if ((end - start) < 4) | ||
625 | return NULL; | ||
626 | item->data.u32 = le32_to_cpu(get_unaligned((__le32*)start)); | ||
627 | start = (__u8 *)((__le32 *)start + 1); | ||
628 | return start; | ||
629 | } | ||
630 | |||
631 | return NULL; | ||
632 | } | ||
633 | |||
634 | /* | ||
635 | * Parse a report description into a hid_device structure. Reports are | ||
636 | * enumerated, fields are attached to these reports. | ||
637 | */ | ||
638 | |||
639 | static struct hid_device *hid_parse_report(__u8 *start, unsigned size) | ||
640 | { | ||
641 | struct hid_device *device; | ||
642 | struct hid_parser *parser; | ||
643 | struct hid_item item; | ||
644 | __u8 *end; | ||
645 | unsigned i; | ||
646 | static int (*dispatch_type[])(struct hid_parser *parser, | ||
647 | struct hid_item *item) = { | ||
648 | hid_parser_main, | ||
649 | hid_parser_global, | ||
650 | hid_parser_local, | ||
651 | hid_parser_reserved | ||
652 | }; | ||
653 | |||
654 | if (!(device = kmalloc(sizeof(struct hid_device), GFP_KERNEL))) | ||
655 | return NULL; | ||
656 | memset(device, 0, sizeof(struct hid_device)); | ||
657 | |||
658 | if (!(device->collection = kmalloc(sizeof(struct hid_collection) * | ||
659 | HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) { | ||
660 | kfree(device); | ||
661 | return NULL; | ||
662 | } | ||
663 | memset(device->collection, 0, sizeof(struct hid_collection) * | ||
664 | HID_DEFAULT_NUM_COLLECTIONS); | ||
665 | device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; | ||
666 | |||
667 | for (i = 0; i < HID_REPORT_TYPES; i++) | ||
668 | INIT_LIST_HEAD(&device->report_enum[i].report_list); | ||
669 | |||
670 | if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) { | ||
671 | kfree(device->collection); | ||
672 | kfree(device); | ||
673 | return NULL; | ||
674 | } | ||
675 | memcpy(device->rdesc, start, size); | ||
676 | device->rsize = size; | ||
677 | |||
678 | if (!(parser = kmalloc(sizeof(struct hid_parser), GFP_KERNEL))) { | ||
679 | kfree(device->rdesc); | ||
680 | kfree(device->collection); | ||
681 | kfree(device); | ||
682 | return NULL; | ||
683 | } | ||
684 | memset(parser, 0, sizeof(struct hid_parser)); | ||
685 | parser->device = device; | ||
686 | |||
687 | end = start + size; | ||
688 | while ((start = fetch_item(start, end, &item)) != NULL) { | ||
689 | |||
690 | if (item.format != HID_ITEM_FORMAT_SHORT) { | ||
691 | dbg("unexpected long global item"); | ||
692 | kfree(device->collection); | ||
693 | hid_free_device(device); | ||
694 | kfree(parser); | ||
695 | return NULL; | ||
696 | } | ||
697 | |||
698 | if (dispatch_type[item.type](parser, &item)) { | ||
699 | dbg("item %u %u %u %u parsing failed\n", | ||
700 | item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); | ||
701 | kfree(device->collection); | ||
702 | hid_free_device(device); | ||
703 | kfree(parser); | ||
704 | return NULL; | ||
705 | } | ||
706 | |||
707 | if (start == end) { | ||
708 | if (parser->collection_stack_ptr) { | ||
709 | dbg("unbalanced collection at end of report description"); | ||
710 | kfree(device->collection); | ||
711 | hid_free_device(device); | ||
712 | kfree(parser); | ||
713 | return NULL; | ||
714 | } | ||
715 | if (parser->local.delimiter_depth) { | ||
716 | dbg("unbalanced delimiter at end of report description"); | ||
717 | kfree(device->collection); | ||
718 | hid_free_device(device); | ||
719 | kfree(parser); | ||
720 | return NULL; | ||
721 | } | ||
722 | kfree(parser); | ||
723 | return device; | ||
724 | } | ||
725 | } | ||
726 | |||
727 | dbg("item fetching failed at offset %d\n", (int)(end - start)); | ||
728 | kfree(device->collection); | ||
729 | hid_free_device(device); | ||
730 | kfree(parser); | ||
731 | return NULL; | ||
732 | } | ||
733 | |||
734 | /* | ||
735 | * Convert a signed n-bit integer to signed 32-bit integer. Common | ||
736 | * cases are done through the compiler, the screwed things has to be | ||
737 | * done by hand. | ||
738 | */ | ||
739 | |||
740 | static __inline__ __s32 snto32(__u32 value, unsigned n) | ||
741 | { | ||
742 | switch (n) { | ||
743 | case 8: return ((__s8)value); | ||
744 | case 16: return ((__s16)value); | ||
745 | case 32: return ((__s32)value); | ||
746 | } | ||
747 | return value & (1 << (n - 1)) ? value | (-1 << n) : value; | ||
748 | } | ||
749 | |||
750 | /* | ||
751 | * Convert a signed 32-bit integer to a signed n-bit integer. | ||
752 | */ | ||
753 | |||
754 | static __inline__ __u32 s32ton(__s32 value, unsigned n) | ||
755 | { | ||
756 | __s32 a = value >> (n - 1); | ||
757 | if (a && a != -1) | ||
758 | return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1; | ||
759 | return value & ((1 << n) - 1); | ||
760 | } | ||
761 | |||
762 | /* | ||
763 | * Extract/implement a data field from/to a report. | ||
764 | */ | ||
765 | |||
766 | static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) | ||
767 | { | ||
768 | report += (offset >> 5) << 2; offset &= 31; | ||
769 | return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1 << n) - 1); | ||
770 | } | ||
771 | |||
772 | static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) | ||
773 | { | ||
774 | report += (offset >> 5) << 2; offset &= 31; | ||
775 | put_unaligned((get_unaligned((__le64*)report) | ||
776 | & cpu_to_le64(~((((__u64) 1 << n) - 1) << offset))) | ||
777 | | cpu_to_le64((__u64)value << offset), (__le64*)report); | ||
778 | } | ||
779 | |||
780 | /* | ||
781 | * Search an array for a value. | ||
782 | */ | ||
783 | |||
784 | static __inline__ int search(__s32 *array, __s32 value, unsigned n) | ||
785 | { | ||
786 | while (n--) { | ||
787 | if (*array++ == value) | ||
788 | return 0; | ||
789 | } | ||
790 | return -1; | ||
791 | } | ||
792 | |||
793 | static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, struct pt_regs *regs) | ||
794 | { | ||
795 | hid_dump_input(usage, value); | ||
796 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
797 | hidinput_hid_event(hid, field, usage, value, regs); | ||
798 | if (hid->claimed & HID_CLAIMED_HIDDEV) | ||
799 | hiddev_hid_event(hid, field, usage, value, regs); | ||
800 | } | ||
801 | |||
802 | /* | ||
803 | * Analyse a received field, and fetch the data from it. The field | ||
804 | * content is stored for next report processing (we do differential | ||
805 | * reporting to the layer). | ||
806 | */ | ||
807 | |||
808 | static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, struct pt_regs *regs) | ||
809 | { | ||
810 | unsigned n; | ||
811 | unsigned count = field->report_count; | ||
812 | unsigned offset = field->report_offset; | ||
813 | unsigned size = field->report_size; | ||
814 | __s32 min = field->logical_minimum; | ||
815 | __s32 max = field->logical_maximum; | ||
816 | __s32 *value; | ||
817 | |||
818 | if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC))) | ||
819 | return; | ||
820 | |||
821 | for (n = 0; n < count; n++) { | ||
822 | |||
823 | value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) : | ||
824 | extract(data, offset + n * size, size); | ||
825 | |||
826 | if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */ | ||
827 | && value[n] >= min && value[n] <= max | ||
828 | && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) | ||
829 | goto exit; | ||
830 | } | ||
831 | |||
832 | for (n = 0; n < count; n++) { | ||
833 | |||
834 | if (HID_MAIN_ITEM_VARIABLE & field->flags) { | ||
835 | hid_process_event(hid, field, &field->usage[n], value[n], regs); | ||
836 | continue; | ||
837 | } | ||
838 | |||
839 | if (field->value[n] >= min && field->value[n] <= max | ||
840 | && field->usage[field->value[n] - min].hid | ||
841 | && search(value, field->value[n], count)) | ||
842 | hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, regs); | ||
843 | |||
844 | if (value[n] >= min && value[n] <= max | ||
845 | && field->usage[value[n] - min].hid | ||
846 | && search(field->value, value[n], count)) | ||
847 | hid_process_event(hid, field, &field->usage[value[n] - min], 1, regs); | ||
848 | } | ||
849 | |||
850 | memcpy(field->value, value, count * sizeof(__s32)); | ||
851 | exit: | ||
852 | kfree(value); | ||
853 | } | ||
854 | |||
855 | static int hid_input_report(int type, struct urb *urb, struct pt_regs *regs) | ||
856 | { | ||
857 | struct hid_device *hid = urb->context; | ||
858 | struct hid_report_enum *report_enum = hid->report_enum + type; | ||
859 | u8 *data = urb->transfer_buffer; | ||
860 | int len = urb->actual_length; | ||
861 | struct hid_report *report; | ||
862 | int n, size; | ||
863 | |||
864 | if (!len) { | ||
865 | dbg("empty report"); | ||
866 | return -1; | ||
867 | } | ||
868 | |||
869 | #ifdef DEBUG_DATA | ||
870 | printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un"); | ||
871 | #endif | ||
872 | |||
873 | n = 0; /* Normally report number is 0 */ | ||
874 | if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */ | ||
875 | n = *data++; | ||
876 | len--; | ||
877 | } | ||
878 | |||
879 | #ifdef DEBUG_DATA | ||
880 | { | ||
881 | int i; | ||
882 | printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, len); | ||
883 | for (i = 0; i < len; i++) | ||
884 | printk(" %02x", data[i]); | ||
885 | printk("\n"); | ||
886 | } | ||
887 | #endif | ||
888 | |||
889 | if (!(report = report_enum->report_id_hash[n])) { | ||
890 | dbg("undefined report_id %d received", n); | ||
891 | return -1; | ||
892 | } | ||
893 | |||
894 | size = ((report->size - 1) >> 3) + 1; | ||
895 | |||
896 | if (len < size) | ||
897 | dbg("report %d is too short, (%d < %d)", report->id, len, size); | ||
898 | |||
899 | if (hid->claimed & HID_CLAIMED_HIDDEV) | ||
900 | hiddev_report_event(hid, report); | ||
901 | |||
902 | for (n = 0; n < report->maxfield; n++) | ||
903 | hid_input_field(hid, report->field[n], data, regs); | ||
904 | |||
905 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
906 | hidinput_report_event(hid, report); | ||
907 | |||
908 | return 0; | ||
909 | } | ||
910 | |||
911 | /* | ||
912 | * Input interrupt completion handler. | ||
913 | */ | ||
914 | |||
915 | static void hid_irq_in(struct urb *urb, struct pt_regs *regs) | ||
916 | { | ||
917 | struct hid_device *hid = urb->context; | ||
918 | int status; | ||
919 | |||
920 | switch (urb->status) { | ||
921 | case 0: /* success */ | ||
922 | hid_input_report(HID_INPUT_REPORT, urb, regs); | ||
923 | break; | ||
924 | case -ECONNRESET: /* unlink */ | ||
925 | case -ENOENT: | ||
926 | case -EPERM: | ||
927 | case -ESHUTDOWN: /* unplug */ | ||
928 | case -EILSEQ: /* unplug timeout on uhci */ | ||
929 | return; | ||
930 | case -ETIMEDOUT: /* NAK */ | ||
931 | break; | ||
932 | default: /* error */ | ||
933 | warn("input irq status %d received", urb->status); | ||
934 | } | ||
935 | |||
936 | status = usb_submit_urb(urb, SLAB_ATOMIC); | ||
937 | if (status) | ||
938 | err("can't resubmit intr, %s-%s/input%d, status %d", | ||
939 | hid->dev->bus->bus_name, hid->dev->devpath, | ||
940 | hid->ifnum, status); | ||
941 | } | ||
942 | |||
943 | /* | ||
944 | * Output the field into the report. | ||
945 | */ | ||
946 | |||
947 | static void hid_output_field(struct hid_field *field, __u8 *data) | ||
948 | { | ||
949 | unsigned count = field->report_count; | ||
950 | unsigned offset = field->report_offset; | ||
951 | unsigned size = field->report_size; | ||
952 | unsigned n; | ||
953 | |||
954 | for (n = 0; n < count; n++) { | ||
955 | if (field->logical_minimum < 0) /* signed values */ | ||
956 | implement(data, offset + n * size, size, s32ton(field->value[n], size)); | ||
957 | else /* unsigned values */ | ||
958 | implement(data, offset + n * size, size, field->value[n]); | ||
959 | } | ||
960 | } | ||
961 | |||
962 | /* | ||
963 | * Create a report. | ||
964 | */ | ||
965 | |||
966 | static void hid_output_report(struct hid_report *report, __u8 *data) | ||
967 | { | ||
968 | unsigned n; | ||
969 | |||
970 | if (report->id > 0) | ||
971 | *data++ = report->id; | ||
972 | |||
973 | for (n = 0; n < report->maxfield; n++) | ||
974 | hid_output_field(report->field[n], data); | ||
975 | } | ||
976 | |||
977 | /* | ||
978 | * Set a field value. The report this field belongs to has to be | ||
979 | * created and transferred to the device, to set this value in the | ||
980 | * device. | ||
981 | */ | ||
982 | |||
983 | int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) | ||
984 | { | ||
985 | unsigned size = field->report_size; | ||
986 | |||
987 | hid_dump_input(field->usage + offset, value); | ||
988 | |||
989 | if (offset >= field->report_count) { | ||
990 | dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count); | ||
991 | hid_dump_field(field, 8); | ||
992 | return -1; | ||
993 | } | ||
994 | if (field->logical_minimum < 0) { | ||
995 | if (value != snto32(s32ton(value, size), size)) { | ||
996 | dbg("value %d is out of range", value); | ||
997 | return -1; | ||
998 | } | ||
999 | } | ||
1000 | field->value[offset] = value; | ||
1001 | return 0; | ||
1002 | } | ||
1003 | |||
1004 | /* | ||
1005 | * Find a report field with a specified HID usage. | ||
1006 | */ | ||
1007 | |||
1008 | struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type) | ||
1009 | { | ||
1010 | struct hid_report *report; | ||
1011 | int i; | ||
1012 | |||
1013 | list_for_each_entry(report, &hid->report_enum[type].report_list, list) | ||
1014 | for (i = 0; i < report->maxfield; i++) | ||
1015 | if (report->field[i]->logical == wanted_usage) | ||
1016 | return report->field[i]; | ||
1017 | return NULL; | ||
1018 | } | ||
1019 | |||
1020 | static int hid_submit_out(struct hid_device *hid) | ||
1021 | { | ||
1022 | struct hid_report *report; | ||
1023 | |||
1024 | report = hid->out[hid->outtail]; | ||
1025 | |||
1026 | hid_output_report(report, hid->outbuf); | ||
1027 | hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); | ||
1028 | hid->urbout->dev = hid->dev; | ||
1029 | |||
1030 | dbg("submitting out urb"); | ||
1031 | |||
1032 | if (usb_submit_urb(hid->urbout, GFP_ATOMIC)) { | ||
1033 | err("usb_submit_urb(out) failed"); | ||
1034 | return -1; | ||
1035 | } | ||
1036 | |||
1037 | return 0; | ||
1038 | } | ||
1039 | |||
1040 | static int hid_submit_ctrl(struct hid_device *hid) | ||
1041 | { | ||
1042 | struct hid_report *report; | ||
1043 | unsigned char dir; | ||
1044 | int len; | ||
1045 | |||
1046 | report = hid->ctrl[hid->ctrltail].report; | ||
1047 | dir = hid->ctrl[hid->ctrltail].dir; | ||
1048 | |||
1049 | len = ((report->size - 1) >> 3) + 1 + (report->id > 0); | ||
1050 | if (dir == USB_DIR_OUT) { | ||
1051 | hid_output_report(report, hid->ctrlbuf); | ||
1052 | hid->urbctrl->pipe = usb_sndctrlpipe(hid->dev, 0); | ||
1053 | hid->urbctrl->transfer_buffer_length = len; | ||
1054 | } else { | ||
1055 | int maxpacket, padlen; | ||
1056 | |||
1057 | hid->urbctrl->pipe = usb_rcvctrlpipe(hid->dev, 0); | ||
1058 | maxpacket = usb_maxpacket(hid->dev, hid->urbctrl->pipe, 0); | ||
1059 | if (maxpacket > 0) { | ||
1060 | padlen = (len + maxpacket - 1) / maxpacket; | ||
1061 | padlen *= maxpacket; | ||
1062 | if (padlen > HID_BUFFER_SIZE) | ||
1063 | padlen = HID_BUFFER_SIZE; | ||
1064 | } else | ||
1065 | padlen = 0; | ||
1066 | hid->urbctrl->transfer_buffer_length = padlen; | ||
1067 | } | ||
1068 | hid->urbctrl->dev = hid->dev; | ||
1069 | |||
1070 | hid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; | ||
1071 | hid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT; | ||
1072 | hid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); | ||
1073 | hid->cr->wIndex = cpu_to_le16(hid->ifnum); | ||
1074 | hid->cr->wLength = cpu_to_le16(len); | ||
1075 | |||
1076 | dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u", | ||
1077 | hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", | ||
1078 | hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength); | ||
1079 | |||
1080 | if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) { | ||
1081 | err("usb_submit_urb(ctrl) failed"); | ||
1082 | return -1; | ||
1083 | } | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | /* | ||
1089 | * Output interrupt completion handler. | ||
1090 | */ | ||
1091 | |||
1092 | static void hid_irq_out(struct urb *urb, struct pt_regs *regs) | ||
1093 | { | ||
1094 | struct hid_device *hid = urb->context; | ||
1095 | unsigned long flags; | ||
1096 | int unplug = 0; | ||
1097 | |||
1098 | switch (urb->status) { | ||
1099 | case 0: /* success */ | ||
1100 | case -ESHUTDOWN: /* unplug */ | ||
1101 | case -EILSEQ: /* unplug timeout on uhci */ | ||
1102 | unplug = 1; | ||
1103 | case -ECONNRESET: /* unlink */ | ||
1104 | case -ENOENT: | ||
1105 | break; | ||
1106 | default: /* error */ | ||
1107 | warn("output irq status %d received", urb->status); | ||
1108 | } | ||
1109 | |||
1110 | spin_lock_irqsave(&hid->outlock, flags); | ||
1111 | |||
1112 | if (unplug) | ||
1113 | hid->outtail = hid->outhead; | ||
1114 | else | ||
1115 | hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); | ||
1116 | |||
1117 | if (hid->outhead != hid->outtail) { | ||
1118 | if (hid_submit_out(hid)) { | ||
1119 | clear_bit(HID_OUT_RUNNING, &hid->iofl);; | ||
1120 | wake_up(&hid->wait); | ||
1121 | } | ||
1122 | spin_unlock_irqrestore(&hid->outlock, flags); | ||
1123 | return; | ||
1124 | } | ||
1125 | |||
1126 | clear_bit(HID_OUT_RUNNING, &hid->iofl); | ||
1127 | spin_unlock_irqrestore(&hid->outlock, flags); | ||
1128 | wake_up(&hid->wait); | ||
1129 | } | ||
1130 | |||
1131 | /* | ||
1132 | * Control pipe completion handler. | ||
1133 | */ | ||
1134 | |||
1135 | static void hid_ctrl(struct urb *urb, struct pt_regs *regs) | ||
1136 | { | ||
1137 | struct hid_device *hid = urb->context; | ||
1138 | unsigned long flags; | ||
1139 | int unplug = 0; | ||
1140 | |||
1141 | spin_lock_irqsave(&hid->ctrllock, flags); | ||
1142 | |||
1143 | switch (urb->status) { | ||
1144 | case 0: /* success */ | ||
1145 | if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) | ||
1146 | hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs); | ||
1147 | case -ESHUTDOWN: /* unplug */ | ||
1148 | case -EILSEQ: /* unplug timectrl on uhci */ | ||
1149 | unplug = 1; | ||
1150 | case -ECONNRESET: /* unlink */ | ||
1151 | case -ENOENT: | ||
1152 | case -EPIPE: /* report not available */ | ||
1153 | break; | ||
1154 | default: /* error */ | ||
1155 | warn("ctrl urb status %d received", urb->status); | ||
1156 | } | ||
1157 | |||
1158 | if (unplug) | ||
1159 | hid->ctrltail = hid->ctrlhead; | ||
1160 | else | ||
1161 | hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); | ||
1162 | |||
1163 | if (hid->ctrlhead != hid->ctrltail) { | ||
1164 | if (hid_submit_ctrl(hid)) { | ||
1165 | clear_bit(HID_CTRL_RUNNING, &hid->iofl); | ||
1166 | wake_up(&hid->wait); | ||
1167 | } | ||
1168 | spin_unlock_irqrestore(&hid->ctrllock, flags); | ||
1169 | return; | ||
1170 | } | ||
1171 | |||
1172 | clear_bit(HID_CTRL_RUNNING, &hid->iofl); | ||
1173 | spin_unlock_irqrestore(&hid->ctrllock, flags); | ||
1174 | wake_up(&hid->wait); | ||
1175 | } | ||
1176 | |||
1177 | void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) | ||
1178 | { | ||
1179 | int head; | ||
1180 | unsigned long flags; | ||
1181 | |||
1182 | if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) | ||
1183 | return; | ||
1184 | |||
1185 | if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { | ||
1186 | |||
1187 | spin_lock_irqsave(&hid->outlock, flags); | ||
1188 | |||
1189 | if ((head = (hid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == hid->outtail) { | ||
1190 | spin_unlock_irqrestore(&hid->outlock, flags); | ||
1191 | warn("output queue full"); | ||
1192 | return; | ||
1193 | } | ||
1194 | |||
1195 | hid->out[hid->outhead] = report; | ||
1196 | hid->outhead = head; | ||
1197 | |||
1198 | if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl)) | ||
1199 | if (hid_submit_out(hid)) | ||
1200 | clear_bit(HID_OUT_RUNNING, &hid->iofl); | ||
1201 | |||
1202 | spin_unlock_irqrestore(&hid->outlock, flags); | ||
1203 | return; | ||
1204 | } | ||
1205 | |||
1206 | spin_lock_irqsave(&hid->ctrllock, flags); | ||
1207 | |||
1208 | if ((head = (hid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == hid->ctrltail) { | ||
1209 | spin_unlock_irqrestore(&hid->ctrllock, flags); | ||
1210 | warn("control queue full"); | ||
1211 | return; | ||
1212 | } | ||
1213 | |||
1214 | hid->ctrl[hid->ctrlhead].report = report; | ||
1215 | hid->ctrl[hid->ctrlhead].dir = dir; | ||
1216 | hid->ctrlhead = head; | ||
1217 | |||
1218 | if (!test_and_set_bit(HID_CTRL_RUNNING, &hid->iofl)) | ||
1219 | if (hid_submit_ctrl(hid)) | ||
1220 | clear_bit(HID_CTRL_RUNNING, &hid->iofl); | ||
1221 | |||
1222 | spin_unlock_irqrestore(&hid->ctrllock, flags); | ||
1223 | } | ||
1224 | |||
1225 | int hid_wait_io(struct hid_device *hid) | ||
1226 | { | ||
1227 | if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &hid->iofl) && | ||
1228 | !test_bit(HID_OUT_RUNNING, &hid->iofl)), | ||
1229 | 10*HZ)) { | ||
1230 | dbg("timeout waiting for ctrl or out queue to clear"); | ||
1231 | return -1; | ||
1232 | } | ||
1233 | |||
1234 | return 0; | ||
1235 | } | ||
1236 | |||
1237 | static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, | ||
1238 | unsigned char type, void *buf, int size) | ||
1239 | { | ||
1240 | int result, retries = 4; | ||
1241 | |||
1242 | memset(buf,0,size); // Make sure we parse really received data | ||
1243 | |||
1244 | do { | ||
1245 | result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
1246 | USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, | ||
1247 | (type << 8), ifnum, buf, size, USB_CTRL_GET_TIMEOUT); | ||
1248 | retries--; | ||
1249 | } while (result < size && retries); | ||
1250 | return result; | ||
1251 | } | ||
1252 | |||
1253 | int hid_open(struct hid_device *hid) | ||
1254 | { | ||
1255 | if (hid->open++) | ||
1256 | return 0; | ||
1257 | |||
1258 | hid->urbin->dev = hid->dev; | ||
1259 | |||
1260 | if (usb_submit_urb(hid->urbin, GFP_KERNEL)) | ||
1261 | return -EIO; | ||
1262 | |||
1263 | return 0; | ||
1264 | } | ||
1265 | |||
1266 | void hid_close(struct hid_device *hid) | ||
1267 | { | ||
1268 | if (!--hid->open) | ||
1269 | usb_kill_urb(hid->urbin); | ||
1270 | } | ||
1271 | |||
1272 | /* | ||
1273 | * Initialize all reports | ||
1274 | */ | ||
1275 | |||
1276 | void hid_init_reports(struct hid_device *hid) | ||
1277 | { | ||
1278 | struct hid_report *report; | ||
1279 | int err, ret; | ||
1280 | |||
1281 | list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) { | ||
1282 | int size = ((report->size - 1) >> 3) + 1 + hid->report_enum[HID_INPUT_REPORT].numbered; | ||
1283 | if (size > HID_BUFFER_SIZE) size = HID_BUFFER_SIZE; | ||
1284 | if (size > hid->urbin->transfer_buffer_length) | ||
1285 | hid->urbin->transfer_buffer_length = size; | ||
1286 | hid_submit_report(hid, report, USB_DIR_IN); | ||
1287 | } | ||
1288 | |||
1289 | list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) | ||
1290 | hid_submit_report(hid, report, USB_DIR_IN); | ||
1291 | |||
1292 | err = 0; | ||
1293 | ret = hid_wait_io(hid); | ||
1294 | while (ret) { | ||
1295 | err |= ret; | ||
1296 | if (test_bit(HID_CTRL_RUNNING, &hid->iofl)) | ||
1297 | usb_kill_urb(hid->urbctrl); | ||
1298 | if (test_bit(HID_OUT_RUNNING, &hid->iofl)) | ||
1299 | usb_kill_urb(hid->urbout); | ||
1300 | ret = hid_wait_io(hid); | ||
1301 | } | ||
1302 | |||
1303 | if (err) | ||
1304 | warn("timeout initializing reports\n"); | ||
1305 | |||
1306 | usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0), | ||
1307 | HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, | ||
1308 | hid->ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
1309 | } | ||
1310 | |||
1311 | #define USB_VENDOR_ID_WACOM 0x056a | ||
1312 | #define USB_DEVICE_ID_WACOM_PENPARTNER 0x0000 | ||
1313 | #define USB_DEVICE_ID_WACOM_GRAPHIRE 0x0010 | ||
1314 | #define USB_DEVICE_ID_WACOM_INTUOS 0x0020 | ||
1315 | #define USB_DEVICE_ID_WACOM_PL 0x0030 | ||
1316 | #define USB_DEVICE_ID_WACOM_INTUOS2 0x0040 | ||
1317 | #define USB_DEVICE_ID_WACOM_VOLITO 0x0060 | ||
1318 | #define USB_DEVICE_ID_WACOM_PTU 0x0003 | ||
1319 | |||
1320 | #define USB_VENDOR_ID_KBGEAR 0x084e | ||
1321 | #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 | ||
1322 | |||
1323 | #define USB_VENDOR_ID_AIPTEK 0x08ca | ||
1324 | #define USB_DEVICE_ID_AIPTEK_01 0x0001 | ||
1325 | #define USB_DEVICE_ID_AIPTEK_10 0x0010 | ||
1326 | #define USB_DEVICE_ID_AIPTEK_20 0x0020 | ||
1327 | #define USB_DEVICE_ID_AIPTEK_21 0x0021 | ||
1328 | #define USB_DEVICE_ID_AIPTEK_22 0x0022 | ||
1329 | #define USB_DEVICE_ID_AIPTEK_23 0x0023 | ||
1330 | #define USB_DEVICE_ID_AIPTEK_24 0x0024 | ||
1331 | |||
1332 | #define USB_VENDOR_ID_GRIFFIN 0x077d | ||
1333 | #define USB_DEVICE_ID_POWERMATE 0x0410 | ||
1334 | #define USB_DEVICE_ID_SOUNDKNOB 0x04AA | ||
1335 | |||
1336 | #define USB_VENDOR_ID_ATEN 0x0557 | ||
1337 | #define USB_DEVICE_ID_ATEN_UC100KM 0x2004 | ||
1338 | #define USB_DEVICE_ID_ATEN_CS124U 0x2202 | ||
1339 | #define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204 | ||
1340 | #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 | ||
1341 | #define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 | ||
1342 | |||
1343 | #define USB_VENDOR_ID_TOPMAX 0x0663 | ||
1344 | #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 | ||
1345 | |||
1346 | #define USB_VENDOR_ID_HAPP 0x078b | ||
1347 | #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 | ||
1348 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 | ||
1349 | #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 | ||
1350 | |||
1351 | #define USB_VENDOR_ID_MGE 0x0463 | ||
1352 | #define USB_DEVICE_ID_MGE_UPS 0xffff | ||
1353 | #define USB_DEVICE_ID_MGE_UPS1 0x0001 | ||
1354 | |||
1355 | #define USB_VENDOR_ID_ONTRAK 0x0a07 | ||
1356 | #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 | ||
1357 | |||
1358 | #define USB_VENDOR_ID_TANGTOP 0x0d3d | ||
1359 | #define USB_DEVICE_ID_TANGTOP_USBPS2 0x0001 | ||
1360 | |||
1361 | #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f | ||
1362 | #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 | ||
1363 | |||
1364 | #define USB_VENDOR_ID_A4TECH 0x09da | ||
1365 | #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 | ||
1366 | |||
1367 | #define USB_VENDOR_ID_CYPRESS 0x04b4 | ||
1368 | #define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 | ||
1369 | #define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500 | ||
1370 | |||
1371 | #define USB_VENDOR_ID_BERKSHIRE 0x0c98 | ||
1372 | #define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 | ||
1373 | |||
1374 | #define USB_VENDOR_ID_ALPS 0x0433 | ||
1375 | #define USB_DEVICE_ID_IBM_GAMEPAD 0x1101 | ||
1376 | |||
1377 | #define USB_VENDOR_ID_SAITEK 0x06a3 | ||
1378 | #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 | ||
1379 | |||
1380 | #define USB_VENDOR_ID_NEC 0x073e | ||
1381 | #define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 | ||
1382 | |||
1383 | #define USB_VENDOR_ID_CHIC 0x05fe | ||
1384 | #define USB_DEVICE_ID_CHIC_GAMEPAD 0x0014 | ||
1385 | |||
1386 | #define USB_VENDOR_ID_GLAB 0x06c2 | ||
1387 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 | ||
1388 | #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 | ||
1389 | #define USB_DEVICE_ID_8_8_8_IF_KIT 0x0045 | ||
1390 | #define USB_DEVICE_ID_0_0_4_IF_KIT 0x0040 | ||
1391 | #define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053 | ||
1392 | |||
1393 | #define USB_VENDOR_ID_WISEGROUP 0x0925 | ||
1394 | #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 | ||
1395 | #define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104 | ||
1396 | |||
1397 | #define USB_VENDOR_ID_CODEMERCS 0x07c0 | ||
1398 | #define USB_DEVICE_ID_CODEMERCS_IOW40 0x1500 | ||
1399 | #define USB_DEVICE_ID_CODEMERCS_IOW24 0x1501 | ||
1400 | #define USB_DEVICE_ID_CODEMERCS_IOW48 0x1502 | ||
1401 | #define USB_DEVICE_ID_CODEMERCS_IOW28 0x1503 | ||
1402 | |||
1403 | #define USB_VENDOR_ID_DELORME 0x1163 | ||
1404 | #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 | ||
1405 | |||
1406 | #define USB_VENDOR_ID_MCC 0x09db | ||
1407 | #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 | ||
1408 | #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a | ||
1409 | |||
1410 | #define USB_VENDOR_ID_CHICONY 0x04f2 | ||
1411 | #define USB_DEVICE_ID_CHICONY_USBHUB_KB 0x0100 | ||
1412 | |||
1413 | #define USB_VENDOR_ID_BTC 0x046e | ||
1414 | #define USB_DEVICE_ID_BTC_KEYBOARD 0x5303 | ||
1415 | |||
1416 | |||
1417 | /* | ||
1418 | * Alphabetically sorted blacklist by quirk type. | ||
1419 | */ | ||
1420 | |||
1421 | static struct hid_blacklist { | ||
1422 | __u16 idVendor; | ||
1423 | __u16 idProduct; | ||
1424 | unsigned quirks; | ||
1425 | } hid_blacklist[] = { | ||
1426 | |||
1427 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, | ||
1428 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE }, | ||
1429 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE }, | ||
1430 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21, HID_QUIRK_IGNORE }, | ||
1431 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE }, | ||
1432 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE }, | ||
1433 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE }, | ||
1434 | { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, | ||
1435 | { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE }, | ||
1436 | { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE }, | ||
1437 | { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE }, | ||
1438 | { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE }, | ||
1439 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE }, | ||
1440 | { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE }, | ||
1441 | { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, | ||
1442 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, | ||
1443 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, | ||
1444 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE }, | ||
1445 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE }, | ||
1446 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE }, | ||
1447 | { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, | ||
1448 | { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, | ||
1449 | { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, | ||
1450 | { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE }, | ||
1451 | { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE }, | ||
1452 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE }, | ||
1453 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE }, | ||
1454 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE }, | ||
1455 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE }, | ||
1456 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE }, | ||
1457 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE }, | ||
1458 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE }, | ||
1459 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE }, | ||
1460 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PENPARTNER, HID_QUIRK_IGNORE }, | ||
1461 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE }, | ||
1462 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE }, | ||
1463 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 2, HID_QUIRK_IGNORE }, | ||
1464 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 3, HID_QUIRK_IGNORE }, | ||
1465 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 4, HID_QUIRK_IGNORE }, | ||
1466 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE }, | ||
1467 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE }, | ||
1468 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE }, | ||
1469 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE }, | ||
1470 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE }, | ||
1471 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL, HID_QUIRK_IGNORE }, | ||
1472 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 1, HID_QUIRK_IGNORE }, | ||
1473 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 2, HID_QUIRK_IGNORE }, | ||
1474 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 3, HID_QUIRK_IGNORE }, | ||
1475 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 4, HID_QUIRK_IGNORE }, | ||
1476 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 5, HID_QUIRK_IGNORE }, | ||
1477 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 1, HID_QUIRK_IGNORE }, | ||
1478 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE }, | ||
1479 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE }, | ||
1480 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 4, HID_QUIRK_IGNORE }, | ||
1481 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 5, HID_QUIRK_IGNORE }, | ||
1482 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 7, HID_QUIRK_IGNORE }, | ||
1483 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO, HID_QUIRK_IGNORE }, | ||
1484 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE }, | ||
1485 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | ||
1486 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | ||
1487 | |||
1488 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, | ||
1489 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, | ||
1490 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, | ||
1491 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, | ||
1492 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, | ||
1493 | { USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_KEYBOARD, HID_QUIRK_NOGET}, | ||
1494 | { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET}, | ||
1495 | { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET }, | ||
1496 | |||
1497 | { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, | ||
1498 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, | ||
1499 | |||
1500 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, | ||
1501 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, | ||
1502 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | ||
1503 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | ||
1504 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | ||
1505 | { USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD }, | ||
1506 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, | ||
1507 | { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, | ||
1508 | |||
1509 | { 0, 0 } | ||
1510 | }; | ||
1511 | |||
1512 | static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) | ||
1513 | { | ||
1514 | if (!(hid->inbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->inbuf_dma))) | ||
1515 | return -1; | ||
1516 | if (!(hid->outbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->outbuf_dma))) | ||
1517 | return -1; | ||
1518 | if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), SLAB_ATOMIC, &hid->cr_dma))) | ||
1519 | return -1; | ||
1520 | if (!(hid->ctrlbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->ctrlbuf_dma))) | ||
1521 | return -1; | ||
1522 | |||
1523 | return 0; | ||
1524 | } | ||
1525 | |||
1526 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) | ||
1527 | { | ||
1528 | if (hid->inbuf) | ||
1529 | usb_buffer_free(dev, HID_BUFFER_SIZE, hid->inbuf, hid->inbuf_dma); | ||
1530 | if (hid->outbuf) | ||
1531 | usb_buffer_free(dev, HID_BUFFER_SIZE, hid->outbuf, hid->outbuf_dma); | ||
1532 | if (hid->cr) | ||
1533 | usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma); | ||
1534 | if (hid->ctrlbuf) | ||
1535 | usb_buffer_free(dev, HID_BUFFER_SIZE, hid->ctrlbuf, hid->ctrlbuf_dma); | ||
1536 | } | ||
1537 | |||
1538 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) | ||
1539 | { | ||
1540 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
1541 | struct usb_device *dev = interface_to_usbdev (intf); | ||
1542 | struct hid_descriptor *hdesc; | ||
1543 | struct hid_device *hid; | ||
1544 | unsigned quirks = 0, rsize = 0; | ||
1545 | char *buf, *rdesc; | ||
1546 | int n; | ||
1547 | |||
1548 | for (n = 0; hid_blacklist[n].idVendor; n++) | ||
1549 | if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) && | ||
1550 | (hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct))) | ||
1551 | quirks = hid_blacklist[n].quirks; | ||
1552 | |||
1553 | if (quirks & HID_QUIRK_IGNORE) | ||
1554 | return NULL; | ||
1555 | |||
1556 | if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->desc.bNumEndpoints) || | ||
1557 | usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { | ||
1558 | dbg("class descriptor not present\n"); | ||
1559 | return NULL; | ||
1560 | } | ||
1561 | |||
1562 | for (n = 0; n < hdesc->bNumDescriptors; n++) | ||
1563 | if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) | ||
1564 | rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); | ||
1565 | |||
1566 | if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { | ||
1567 | dbg("weird size of report descriptor (%u)", rsize); | ||
1568 | return NULL; | ||
1569 | } | ||
1570 | |||
1571 | if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) { | ||
1572 | dbg("couldn't allocate rdesc memory"); | ||
1573 | return NULL; | ||
1574 | } | ||
1575 | |||
1576 | if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) { | ||
1577 | dbg("reading report descriptor failed"); | ||
1578 | kfree(rdesc); | ||
1579 | return NULL; | ||
1580 | } | ||
1581 | |||
1582 | #ifdef DEBUG_DATA | ||
1583 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); | ||
1584 | for (n = 0; n < rsize; n++) | ||
1585 | printk(" %02x", (unsigned char) rdesc[n]); | ||
1586 | printk("\n"); | ||
1587 | #endif | ||
1588 | |||
1589 | if (!(hid = hid_parse_report(rdesc, n))) { | ||
1590 | dbg("parsing report descriptor failed"); | ||
1591 | kfree(rdesc); | ||
1592 | return NULL; | ||
1593 | } | ||
1594 | |||
1595 | kfree(rdesc); | ||
1596 | hid->quirks = quirks; | ||
1597 | |||
1598 | if (hid_alloc_buffers(dev, hid)) { | ||
1599 | hid_free_buffers(dev, hid); | ||
1600 | goto fail; | ||
1601 | } | ||
1602 | |||
1603 | for (n = 0; n < interface->desc.bNumEndpoints; n++) { | ||
1604 | |||
1605 | struct usb_endpoint_descriptor *endpoint; | ||
1606 | int pipe; | ||
1607 | int interval; | ||
1608 | |||
1609 | endpoint = &interface->endpoint[n].desc; | ||
1610 | if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */ | ||
1611 | continue; | ||
1612 | |||
1613 | /* handle potential highspeed HID correctly */ | ||
1614 | interval = endpoint->bInterval; | ||
1615 | if (dev->speed == USB_SPEED_HIGH) | ||
1616 | interval = 1 << (interval - 1); | ||
1617 | |||
1618 | /* Change the polling interval of mice. */ | ||
1619 | if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) | ||
1620 | interval = hid_mousepoll_interval; | ||
1621 | |||
1622 | if (endpoint->bEndpointAddress & USB_DIR_IN) { | ||
1623 | if (hid->urbin) | ||
1624 | continue; | ||
1625 | if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL))) | ||
1626 | goto fail; | ||
1627 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
1628 | usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0, | ||
1629 | hid_irq_in, hid, interval); | ||
1630 | hid->urbin->transfer_dma = hid->inbuf_dma; | ||
1631 | hid->urbin->transfer_flags |=(URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK); | ||
1632 | } else { | ||
1633 | if (hid->urbout) | ||
1634 | continue; | ||
1635 | if (!(hid->urbout = usb_alloc_urb(0, GFP_KERNEL))) | ||
1636 | goto fail; | ||
1637 | pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress); | ||
1638 | usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0, | ||
1639 | hid_irq_out, hid, interval); | ||
1640 | hid->urbout->transfer_dma = hid->outbuf_dma; | ||
1641 | hid->urbout->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK); | ||
1642 | } | ||
1643 | } | ||
1644 | |||
1645 | if (!hid->urbin) { | ||
1646 | err("couldn't find an input interrupt endpoint"); | ||
1647 | goto fail; | ||
1648 | } | ||
1649 | |||
1650 | init_waitqueue_head(&hid->wait); | ||
1651 | |||
1652 | spin_lock_init(&hid->outlock); | ||
1653 | spin_lock_init(&hid->ctrllock); | ||
1654 | |||
1655 | hid->version = le16_to_cpu(hdesc->bcdHID); | ||
1656 | hid->country = hdesc->bCountryCode; | ||
1657 | hid->dev = dev; | ||
1658 | hid->intf = intf; | ||
1659 | hid->ifnum = interface->desc.bInterfaceNumber; | ||
1660 | |||
1661 | hid->name[0] = 0; | ||
1662 | |||
1663 | if (!(buf = kmalloc(64, GFP_KERNEL))) | ||
1664 | goto fail; | ||
1665 | |||
1666 | if (dev->manufacturer) { | ||
1667 | strcat(hid->name, dev->manufacturer); | ||
1668 | if (dev->product) | ||
1669 | snprintf(hid->name, 64, "%s %s", hid->name, dev->product); | ||
1670 | } else if (dev->product) { | ||
1671 | snprintf(hid->name, 128, "%s", dev->product); | ||
1672 | } else | ||
1673 | snprintf(hid->name, 128, "%04x:%04x", | ||
1674 | le16_to_cpu(dev->descriptor.idVendor), | ||
1675 | le16_to_cpu(dev->descriptor.idProduct)); | ||
1676 | |||
1677 | usb_make_path(dev, buf, 64); | ||
1678 | snprintf(hid->phys, 64, "%s/input%d", buf, | ||
1679 | intf->altsetting[0].desc.bInterfaceNumber); | ||
1680 | |||
1681 | if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) | ||
1682 | hid->uniq[0] = 0; | ||
1683 | |||
1684 | kfree(buf); | ||
1685 | |||
1686 | hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); | ||
1687 | if (!hid->urbctrl) | ||
1688 | goto fail; | ||
1689 | usb_fill_control_urb(hid->urbctrl, dev, 0, (void *) hid->cr, | ||
1690 | hid->ctrlbuf, 1, hid_ctrl, hid); | ||
1691 | hid->urbctrl->setup_dma = hid->cr_dma; | ||
1692 | hid->urbctrl->transfer_dma = hid->ctrlbuf_dma; | ||
1693 | hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | URB_ASYNC_UNLINK); | ||
1694 | |||
1695 | return hid; | ||
1696 | |||
1697 | fail: | ||
1698 | |||
1699 | if (hid->urbin) | ||
1700 | usb_free_urb(hid->urbin); | ||
1701 | if (hid->urbout) | ||
1702 | usb_free_urb(hid->urbout); | ||
1703 | if (hid->urbctrl) | ||
1704 | usb_free_urb(hid->urbctrl); | ||
1705 | hid_free_buffers(dev, hid); | ||
1706 | hid_free_device(hid); | ||
1707 | |||
1708 | return NULL; | ||
1709 | } | ||
1710 | |||
1711 | static void hid_disconnect(struct usb_interface *intf) | ||
1712 | { | ||
1713 | struct hid_device *hid = usb_get_intfdata (intf); | ||
1714 | |||
1715 | if (!hid) | ||
1716 | return; | ||
1717 | |||
1718 | usb_set_intfdata(intf, NULL); | ||
1719 | usb_kill_urb(hid->urbin); | ||
1720 | usb_kill_urb(hid->urbout); | ||
1721 | usb_kill_urb(hid->urbctrl); | ||
1722 | |||
1723 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
1724 | hidinput_disconnect(hid); | ||
1725 | if (hid->claimed & HID_CLAIMED_HIDDEV) | ||
1726 | hiddev_disconnect(hid); | ||
1727 | |||
1728 | usb_free_urb(hid->urbin); | ||
1729 | usb_free_urb(hid->urbctrl); | ||
1730 | if (hid->urbout) | ||
1731 | usb_free_urb(hid->urbout); | ||
1732 | |||
1733 | hid_free_buffers(hid->dev, hid); | ||
1734 | hid_free_device(hid); | ||
1735 | } | ||
1736 | |||
1737 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
1738 | { | ||
1739 | struct hid_device *hid; | ||
1740 | char path[64]; | ||
1741 | int i; | ||
1742 | char *c; | ||
1743 | |||
1744 | dbg("HID probe called for ifnum %d", | ||
1745 | intf->altsetting->desc.bInterfaceNumber); | ||
1746 | |||
1747 | if (!(hid = usb_hid_configure(intf))) | ||
1748 | return -EIO; | ||
1749 | |||
1750 | hid_init_reports(hid); | ||
1751 | hid_dump_device(hid); | ||
1752 | |||
1753 | if (!hidinput_connect(hid)) | ||
1754 | hid->claimed |= HID_CLAIMED_INPUT; | ||
1755 | if (!hiddev_connect(hid)) | ||
1756 | hid->claimed |= HID_CLAIMED_HIDDEV; | ||
1757 | |||
1758 | usb_set_intfdata(intf, hid); | ||
1759 | |||
1760 | if (!hid->claimed) { | ||
1761 | printk ("HID device not claimed by input or hiddev\n"); | ||
1762 | hid_disconnect(intf); | ||
1763 | return -EIO; | ||
1764 | } | ||
1765 | |||
1766 | printk(KERN_INFO); | ||
1767 | |||
1768 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
1769 | printk("input"); | ||
1770 | if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV)) | ||
1771 | printk(","); | ||
1772 | if (hid->claimed & HID_CLAIMED_HIDDEV) | ||
1773 | printk("hiddev%d", hid->minor); | ||
1774 | |||
1775 | c = "Device"; | ||
1776 | for (i = 0; i < hid->maxcollection; i++) { | ||
1777 | if (hid->collection[i].type == HID_COLLECTION_APPLICATION && | ||
1778 | (hid->collection[i].usage & HID_USAGE_PAGE) == HID_UP_GENDESK && | ||
1779 | (hid->collection[i].usage & 0xffff) < ARRAY_SIZE(hid_types)) { | ||
1780 | c = hid_types[hid->collection[i].usage & 0xffff]; | ||
1781 | break; | ||
1782 | } | ||
1783 | } | ||
1784 | |||
1785 | usb_make_path(interface_to_usbdev(intf), path, 63); | ||
1786 | |||
1787 | printk(": USB HID v%x.%02x %s [%s] on %s\n", | ||
1788 | hid->version >> 8, hid->version & 0xff, c, hid->name, path); | ||
1789 | |||
1790 | return 0; | ||
1791 | } | ||
1792 | |||
1793 | static int hid_suspend(struct usb_interface *intf, u32 state) | ||
1794 | { | ||
1795 | struct hid_device *hid = usb_get_intfdata (intf); | ||
1796 | |||
1797 | usb_kill_urb(hid->urbin); | ||
1798 | intf->dev.power.power_state = state; | ||
1799 | dev_dbg(&intf->dev, "suspend\n"); | ||
1800 | return 0; | ||
1801 | } | ||
1802 | |||
1803 | static int hid_resume(struct usb_interface *intf) | ||
1804 | { | ||
1805 | struct hid_device *hid = usb_get_intfdata (intf); | ||
1806 | int status; | ||
1807 | |||
1808 | intf->dev.power.power_state = PM_SUSPEND_ON; | ||
1809 | if (hid->open) | ||
1810 | status = usb_submit_urb(hid->urbin, GFP_NOIO); | ||
1811 | else | ||
1812 | status = 0; | ||
1813 | dev_dbg(&intf->dev, "resume status %d\n", status); | ||
1814 | return status; | ||
1815 | } | ||
1816 | |||
1817 | static struct usb_device_id hid_usb_ids [] = { | ||
1818 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, | ||
1819 | .bInterfaceClass = USB_INTERFACE_CLASS_HID }, | ||
1820 | { } /* Terminating entry */ | ||
1821 | }; | ||
1822 | |||
1823 | MODULE_DEVICE_TABLE (usb, hid_usb_ids); | ||
1824 | |||
1825 | static struct usb_driver hid_driver = { | ||
1826 | .owner = THIS_MODULE, | ||
1827 | .name = "usbhid", | ||
1828 | .probe = hid_probe, | ||
1829 | .disconnect = hid_disconnect, | ||
1830 | .suspend = hid_suspend, | ||
1831 | .resume = hid_resume, | ||
1832 | .id_table = hid_usb_ids, | ||
1833 | }; | ||
1834 | |||
1835 | static int __init hid_init(void) | ||
1836 | { | ||
1837 | int retval; | ||
1838 | retval = hiddev_init(); | ||
1839 | if (retval) | ||
1840 | goto hiddev_init_fail; | ||
1841 | retval = usb_register(&hid_driver); | ||
1842 | if (retval) | ||
1843 | goto usb_register_fail; | ||
1844 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
1845 | |||
1846 | return 0; | ||
1847 | usb_register_fail: | ||
1848 | hiddev_exit(); | ||
1849 | hiddev_init_fail: | ||
1850 | return retval; | ||
1851 | } | ||
1852 | |||
1853 | static void __exit hid_exit(void) | ||
1854 | { | ||
1855 | usb_deregister(&hid_driver); | ||
1856 | hiddev_exit(); | ||
1857 | } | ||
1858 | |||
1859 | module_init(hid_init); | ||
1860 | module_exit(hid_exit); | ||
1861 | |||
1862 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
1863 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
1864 | MODULE_LICENSE(DRIVER_LICENSE); | ||
diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h new file mode 100644 index 000000000000..2b91705740a7 --- /dev/null +++ b/drivers/usb/input/hid-debug.h | |||
@@ -0,0 +1,720 @@ | |||
1 | /* | ||
2 | * $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $ | ||
3 | * | ||
4 | * (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de> | ||
5 | * (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz> | ||
6 | * | ||
7 | * Some debug stuff for the HID parser. | ||
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 | * Should you need to contact me, the author, you can do so either by | ||
26 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
27 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
28 | */ | ||
29 | |||
30 | #include <linux/input.h> | ||
31 | |||
32 | struct hid_usage_entry { | ||
33 | unsigned page; | ||
34 | unsigned usage; | ||
35 | char *description; | ||
36 | }; | ||
37 | |||
38 | static const struct hid_usage_entry hid_usage_table[] = { | ||
39 | { 0, 0, "Undefined" }, | ||
40 | { 1, 0, "GenericDesktop" }, | ||
41 | {0, 0x01, "Pointer"}, | ||
42 | {0, 0x02, "Mouse"}, | ||
43 | {0, 0x04, "Joystick"}, | ||
44 | {0, 0x05, "GamePad"}, | ||
45 | {0, 0x06, "Keyboard"}, | ||
46 | {0, 0x07, "Keypad"}, | ||
47 | {0, 0x08, "MultiAxis"}, | ||
48 | {0, 0x30, "X"}, | ||
49 | {0, 0x31, "Y"}, | ||
50 | {0, 0x32, "Z"}, | ||
51 | {0, 0x33, "Rx"}, | ||
52 | {0, 0x34, "Ry"}, | ||
53 | {0, 0x35, "Rz"}, | ||
54 | {0, 0x36, "Slider"}, | ||
55 | {0, 0x37, "Dial"}, | ||
56 | {0, 0x38, "Wheel"}, | ||
57 | {0, 0x39, "HatSwitch"}, | ||
58 | {0, 0x3a, "CountedBuffer"}, | ||
59 | {0, 0x3b, "ByteCount"}, | ||
60 | {0, 0x3c, "MotionWakeup"}, | ||
61 | {0, 0x3d, "Start"}, | ||
62 | {0, 0x3e, "Select"}, | ||
63 | {0, 0x40, "Vx"}, | ||
64 | {0, 0x41, "Vy"}, | ||
65 | {0, 0x42, "Vz"}, | ||
66 | {0, 0x43, "Vbrx"}, | ||
67 | {0, 0x44, "Vbry"}, | ||
68 | {0, 0x45, "Vbrz"}, | ||
69 | {0, 0x46, "Vno"}, | ||
70 | {0, 0x80, "SystemControl"}, | ||
71 | {0, 0x81, "SystemPowerDown"}, | ||
72 | {0, 0x82, "SystemSleep"}, | ||
73 | {0, 0x83, "SystemWakeUp"}, | ||
74 | {0, 0x84, "SystemContextMenu"}, | ||
75 | {0, 0x85, "SystemMainMenu"}, | ||
76 | {0, 0x86, "SystemAppMenu"}, | ||
77 | {0, 0x87, "SystemMenuHelp"}, | ||
78 | {0, 0x88, "SystemMenuExit"}, | ||
79 | {0, 0x89, "SystemMenuSelect"}, | ||
80 | {0, 0x8a, "SystemMenuRight"}, | ||
81 | {0, 0x8b, "SystemMenuLeft"}, | ||
82 | {0, 0x8c, "SystemMenuUp"}, | ||
83 | {0, 0x8d, "SystemMenuDown"}, | ||
84 | {0, 0x90, "D-PadUp"}, | ||
85 | {0, 0x91, "D-PadDown"}, | ||
86 | {0, 0x92, "D-PadRight"}, | ||
87 | {0, 0x93, "D-PadLeft"}, | ||
88 | { 7, 0, "Keyboard" }, | ||
89 | { 8, 0, "LED" }, | ||
90 | {0, 0x01, "NumLock"}, | ||
91 | {0, 0x02, "CapsLock"}, | ||
92 | {0, 0x03, "ScrollLock"}, | ||
93 | {0, 0x04, "Compose"}, | ||
94 | {0, 0x05, "Kana"}, | ||
95 | { 9, 0, "Button" }, | ||
96 | { 10, 0, "Ordinal" }, | ||
97 | { 12, 0, "Consumer" }, | ||
98 | {0, 0x238, "HorizontalWheel"}, | ||
99 | { 13, 0, "Digitizers" }, | ||
100 | {0, 0x01, "Digitizer"}, | ||
101 | {0, 0x02, "Pen"}, | ||
102 | {0, 0x03, "LightPen"}, | ||
103 | {0, 0x04, "TouchScreen"}, | ||
104 | {0, 0x05, "TouchPad"}, | ||
105 | {0, 0x20, "Stylus"}, | ||
106 | {0, 0x21, "Puck"}, | ||
107 | {0, 0x22, "Finger"}, | ||
108 | {0, 0x30, "TipPressure"}, | ||
109 | {0, 0x31, "BarrelPressure"}, | ||
110 | {0, 0x32, "InRange"}, | ||
111 | {0, 0x33, "Touch"}, | ||
112 | {0, 0x34, "UnTouch"}, | ||
113 | {0, 0x35, "Tap"}, | ||
114 | {0, 0x39, "TabletFunctionKey"}, | ||
115 | {0, 0x3a, "ProgramChangeKey"}, | ||
116 | {0, 0x3c, "Invert"}, | ||
117 | {0, 0x42, "TipSwitch"}, | ||
118 | {0, 0x43, "SecondaryTipSwitch"}, | ||
119 | {0, 0x44, "BarrelSwitch"}, | ||
120 | {0, 0x45, "Eraser"}, | ||
121 | {0, 0x46, "TabletPick"}, | ||
122 | { 15, 0, "PhysicalInterfaceDevice" }, | ||
123 | {0, 0x00, "Undefined"}, | ||
124 | {0, 0x01, "Physical_Interface_Device"}, | ||
125 | {0, 0x20, "Normal"}, | ||
126 | {0, 0x21, "Set_Effect_Report"}, | ||
127 | {0, 0x22, "Effect_Block_Index"}, | ||
128 | {0, 0x23, "Parameter_Block_Offset"}, | ||
129 | {0, 0x24, "ROM_Flag"}, | ||
130 | {0, 0x25, "Effect_Type"}, | ||
131 | {0, 0x26, "ET_Constant_Force"}, | ||
132 | {0, 0x27, "ET_Ramp"}, | ||
133 | {0, 0x28, "ET_Custom_Force_Data"}, | ||
134 | {0, 0x30, "ET_Square"}, | ||
135 | {0, 0x31, "ET_Sine"}, | ||
136 | {0, 0x32, "ET_Triangle"}, | ||
137 | {0, 0x33, "ET_Sawtooth_Up"}, | ||
138 | {0, 0x34, "ET_Sawtooth_Down"}, | ||
139 | {0, 0x40, "ET_Spring"}, | ||
140 | {0, 0x41, "ET_Damper"}, | ||
141 | {0, 0x42, "ET_Inertia"}, | ||
142 | {0, 0x43, "ET_Friction"}, | ||
143 | {0, 0x50, "Duration"}, | ||
144 | {0, 0x51, "Sample_Period"}, | ||
145 | {0, 0x52, "Gain"}, | ||
146 | {0, 0x53, "Trigger_Button"}, | ||
147 | {0, 0x54, "Trigger_Repeat_Interval"}, | ||
148 | {0, 0x55, "Axes_Enable"}, | ||
149 | {0, 0x56, "Direction_Enable"}, | ||
150 | {0, 0x57, "Direction"}, | ||
151 | {0, 0x58, "Type_Specific_Block_Offset"}, | ||
152 | {0, 0x59, "Block_Type"}, | ||
153 | {0, 0x5A, "Set_Envelope_Report"}, | ||
154 | {0, 0x5B, "Attack_Level"}, | ||
155 | {0, 0x5C, "Attack_Time"}, | ||
156 | {0, 0x5D, "Fade_Level"}, | ||
157 | {0, 0x5E, "Fade_Time"}, | ||
158 | {0, 0x5F, "Set_Condition_Report"}, | ||
159 | {0, 0x60, "CP_Offset"}, | ||
160 | {0, 0x61, "Positive_Coefficient"}, | ||
161 | {0, 0x62, "Negative_Coefficient"}, | ||
162 | {0, 0x63, "Positive_Saturation"}, | ||
163 | {0, 0x64, "Negative_Saturation"}, | ||
164 | {0, 0x65, "Dead_Band"}, | ||
165 | {0, 0x66, "Download_Force_Sample"}, | ||
166 | {0, 0x67, "Isoch_Custom_Force_Enable"}, | ||
167 | {0, 0x68, "Custom_Force_Data_Report"}, | ||
168 | {0, 0x69, "Custom_Force_Data"}, | ||
169 | {0, 0x6A, "Custom_Force_Vendor_Defined_Data"}, | ||
170 | {0, 0x6B, "Set_Custom_Force_Report"}, | ||
171 | {0, 0x6C, "Custom_Force_Data_Offset"}, | ||
172 | {0, 0x6D, "Sample_Count"}, | ||
173 | {0, 0x6E, "Set_Periodic_Report"}, | ||
174 | {0, 0x6F, "Offset"}, | ||
175 | {0, 0x70, "Magnitude"}, | ||
176 | {0, 0x71, "Phase"}, | ||
177 | {0, 0x72, "Period"}, | ||
178 | {0, 0x73, "Set_Constant_Force_Report"}, | ||
179 | {0, 0x74, "Set_Ramp_Force_Report"}, | ||
180 | {0, 0x75, "Ramp_Start"}, | ||
181 | {0, 0x76, "Ramp_End"}, | ||
182 | {0, 0x77, "Effect_Operation_Report"}, | ||
183 | {0, 0x78, "Effect_Operation"}, | ||
184 | {0, 0x79, "Op_Effect_Start"}, | ||
185 | {0, 0x7A, "Op_Effect_Start_Solo"}, | ||
186 | {0, 0x7B, "Op_Effect_Stop"}, | ||
187 | {0, 0x7C, "Loop_Count"}, | ||
188 | {0, 0x7D, "Device_Gain_Report"}, | ||
189 | {0, 0x7E, "Device_Gain"}, | ||
190 | {0, 0x7F, "PID_Pool_Report"}, | ||
191 | {0, 0x80, "RAM_Pool_Size"}, | ||
192 | {0, 0x81, "ROM_Pool_Size"}, | ||
193 | {0, 0x82, "ROM_Effect_Block_Count"}, | ||
194 | {0, 0x83, "Simultaneous_Effects_Max"}, | ||
195 | {0, 0x84, "Pool_Alignment"}, | ||
196 | {0, 0x85, "PID_Pool_Move_Report"}, | ||
197 | {0, 0x86, "Move_Source"}, | ||
198 | {0, 0x87, "Move_Destination"}, | ||
199 | {0, 0x88, "Move_Length"}, | ||
200 | {0, 0x89, "PID_Block_Load_Report"}, | ||
201 | {0, 0x8B, "Block_Load_Status"}, | ||
202 | {0, 0x8C, "Block_Load_Success"}, | ||
203 | {0, 0x8D, "Block_Load_Full"}, | ||
204 | {0, 0x8E, "Block_Load_Error"}, | ||
205 | {0, 0x8F, "Block_Handle"}, | ||
206 | {0, 0x90, "PID_Block_Free_Report"}, | ||
207 | {0, 0x91, "Type_Specific_Block_Handle"}, | ||
208 | {0, 0x92, "PID_State_Report"}, | ||
209 | {0, 0x94, "Effect_Playing"}, | ||
210 | {0, 0x95, "PID_Device_Control_Report"}, | ||
211 | {0, 0x96, "PID_Device_Control"}, | ||
212 | {0, 0x97, "DC_Enable_Actuators"}, | ||
213 | {0, 0x98, "DC_Disable_Actuators"}, | ||
214 | {0, 0x99, "DC_Stop_All_Effects"}, | ||
215 | {0, 0x9A, "DC_Device_Reset"}, | ||
216 | {0, 0x9B, "DC_Device_Pause"}, | ||
217 | {0, 0x9C, "DC_Device_Continue"}, | ||
218 | {0, 0x9F, "Device_Paused"}, | ||
219 | {0, 0xA0, "Actuators_Enabled"}, | ||
220 | {0, 0xA4, "Safety_Switch"}, | ||
221 | {0, 0xA5, "Actuator_Override_Switch"}, | ||
222 | {0, 0xA6, "Actuator_Power"}, | ||
223 | {0, 0xA7, "Start_Delay"}, | ||
224 | {0, 0xA8, "Parameter_Block_Size"}, | ||
225 | {0, 0xA9, "Device_Managed_Pool"}, | ||
226 | {0, 0xAA, "Shared_Parameter_Blocks"}, | ||
227 | {0, 0xAB, "Create_New_Effect_Report"}, | ||
228 | {0, 0xAC, "RAM_Pool_Available"}, | ||
229 | { 0x84, 0, "Power Device" }, | ||
230 | { 0x84, 0x02, "PresentStatus" }, | ||
231 | { 0x84, 0x03, "ChangeStatus" }, | ||
232 | { 0x84, 0x04, "UPS" }, | ||
233 | { 0x84, 0x05, "PowerSupply" }, | ||
234 | { 0x84, 0x10, "BatterySystem" }, | ||
235 | { 0x84, 0x11, "BatterySystemID" }, | ||
236 | { 0x84, 0x12, "Battery" }, | ||
237 | { 0x84, 0x13, "BatteryID" }, | ||
238 | { 0x84, 0x14, "Charger" }, | ||
239 | { 0x84, 0x15, "ChargerID" }, | ||
240 | { 0x84, 0x16, "PowerConverter" }, | ||
241 | { 0x84, 0x17, "PowerConverterID" }, | ||
242 | { 0x84, 0x18, "OutletSystem" }, | ||
243 | { 0x84, 0x19, "OutletSystemID" }, | ||
244 | { 0x84, 0x1a, "Input" }, | ||
245 | { 0x84, 0x1b, "InputID" }, | ||
246 | { 0x84, 0x1c, "Output" }, | ||
247 | { 0x84, 0x1d, "OutputID" }, | ||
248 | { 0x84, 0x1e, "Flow" }, | ||
249 | { 0x84, 0x1f, "FlowID" }, | ||
250 | { 0x84, 0x20, "Outlet" }, | ||
251 | { 0x84, 0x21, "OutletID" }, | ||
252 | { 0x84, 0x22, "Gang" }, | ||
253 | { 0x84, 0x24, "PowerSummary" }, | ||
254 | { 0x84, 0x25, "PowerSummaryID" }, | ||
255 | { 0x84, 0x30, "Voltage" }, | ||
256 | { 0x84, 0x31, "Current" }, | ||
257 | { 0x84, 0x32, "Frequency" }, | ||
258 | { 0x84, 0x33, "ApparentPower" }, | ||
259 | { 0x84, 0x35, "PercentLoad" }, | ||
260 | { 0x84, 0x40, "ConfigVoltage" }, | ||
261 | { 0x84, 0x41, "ConfigCurrent" }, | ||
262 | { 0x84, 0x43, "ConfigApparentPower" }, | ||
263 | { 0x84, 0x53, "LowVoltageTransfer" }, | ||
264 | { 0x84, 0x54, "HighVoltageTransfer" }, | ||
265 | { 0x84, 0x56, "DelayBeforeStartup" }, | ||
266 | { 0x84, 0x57, "DelayBeforeShutdown" }, | ||
267 | { 0x84, 0x58, "Test" }, | ||
268 | { 0x84, 0x5a, "AudibleAlarmControl" }, | ||
269 | { 0x84, 0x60, "Present" }, | ||
270 | { 0x84, 0x61, "Good" }, | ||
271 | { 0x84, 0x62, "InternalFailure" }, | ||
272 | { 0x84, 0x65, "Overload" }, | ||
273 | { 0x84, 0x66, "OverCharged" }, | ||
274 | { 0x84, 0x67, "OverTemperature" }, | ||
275 | { 0x84, 0x68, "ShutdownRequested" }, | ||
276 | { 0x84, 0x69, "ShutdownImminent" }, | ||
277 | { 0x84, 0x6b, "SwitchOn/Off" }, | ||
278 | { 0x84, 0x6c, "Switchable" }, | ||
279 | { 0x84, 0x6d, "Used" }, | ||
280 | { 0x84, 0x6e, "Boost" }, | ||
281 | { 0x84, 0x73, "CommunicationLost" }, | ||
282 | { 0x84, 0xfd, "iManufacturer" }, | ||
283 | { 0x84, 0xfe, "iProduct" }, | ||
284 | { 0x84, 0xff, "iSerialNumber" }, | ||
285 | { 0x85, 0, "Battery System" }, | ||
286 | { 0x85, 0x01, "SMBBatteryMode" }, | ||
287 | { 0x85, 0x02, "SMBBatteryStatus" }, | ||
288 | { 0x85, 0x03, "SMBAlarmWarning" }, | ||
289 | { 0x85, 0x04, "SMBChargerMode" }, | ||
290 | { 0x85, 0x05, "SMBChargerStatus" }, | ||
291 | { 0x85, 0x06, "SMBChargerSpecInfo" }, | ||
292 | { 0x85, 0x07, "SMBSelectorState" }, | ||
293 | { 0x85, 0x08, "SMBSelectorPresets" }, | ||
294 | { 0x85, 0x09, "SMBSelectorInfo" }, | ||
295 | { 0x85, 0x29, "RemainingCapacityLimit" }, | ||
296 | { 0x85, 0x2c, "CapacityMode" }, | ||
297 | { 0x85, 0x42, "BelowRemainingCapacityLimit" }, | ||
298 | { 0x85, 0x44, "Charging" }, | ||
299 | { 0x85, 0x45, "Discharging" }, | ||
300 | { 0x85, 0x4b, "NeedReplacement" }, | ||
301 | { 0x85, 0x66, "RemainingCapacity" }, | ||
302 | { 0x85, 0x68, "RunTimeToEmpty" }, | ||
303 | { 0x85, 0x6a, "AverageTimeToFull" }, | ||
304 | { 0x85, 0x83, "DesignCapacity" }, | ||
305 | { 0x85, 0x85, "ManufacturerDate" }, | ||
306 | { 0x85, 0x89, "iDeviceChemistry" }, | ||
307 | { 0x85, 0x8b, "Rechargable" }, | ||
308 | { 0x85, 0x8f, "iOEMInformation" }, | ||
309 | { 0x85, 0x8d, "CapacityGranularity1" }, | ||
310 | { 0x85, 0xd0, "ACPresent" }, | ||
311 | /* pages 0xff00 to 0xffff are vendor-specific */ | ||
312 | { 0xffff, 0, "Vendor-specific-FF" }, | ||
313 | { 0, 0, NULL } | ||
314 | }; | ||
315 | |||
316 | static void resolv_usage_page(unsigned page) { | ||
317 | const struct hid_usage_entry *p; | ||
318 | |||
319 | for (p = hid_usage_table; p->description; p++) | ||
320 | if (p->page == page) { | ||
321 | printk("%s", p->description); | ||
322 | return; | ||
323 | } | ||
324 | printk("%04x", page); | ||
325 | } | ||
326 | |||
327 | static void resolv_usage(unsigned usage) { | ||
328 | const struct hid_usage_entry *p; | ||
329 | |||
330 | resolv_usage_page(usage >> 16); | ||
331 | printk("."); | ||
332 | for (p = hid_usage_table; p->description; p++) | ||
333 | if (p->page == (usage >> 16)) { | ||
334 | for(++p; p->description && p->usage != 0; p++) | ||
335 | if (p->usage == (usage & 0xffff)) { | ||
336 | printk("%s", p->description); | ||
337 | return; | ||
338 | } | ||
339 | break; | ||
340 | } | ||
341 | printk("%04x", usage & 0xffff); | ||
342 | } | ||
343 | |||
344 | __inline__ static void tab(int n) { | ||
345 | while (n--) printk(" "); | ||
346 | } | ||
347 | |||
348 | static void hid_dump_field(struct hid_field *field, int n) { | ||
349 | int j; | ||
350 | |||
351 | if (field->physical) { | ||
352 | tab(n); | ||
353 | printk("Physical("); | ||
354 | resolv_usage(field->physical); printk(")\n"); | ||
355 | } | ||
356 | if (field->logical) { | ||
357 | tab(n); | ||
358 | printk("Logical("); | ||
359 | resolv_usage(field->logical); printk(")\n"); | ||
360 | } | ||
361 | tab(n); printk("Usage(%d)\n", field->maxusage); | ||
362 | for (j = 0; j < field->maxusage; j++) { | ||
363 | tab(n+2);resolv_usage(field->usage[j].hid); printk("\n"); | ||
364 | } | ||
365 | if (field->logical_minimum != field->logical_maximum) { | ||
366 | tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum); | ||
367 | tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum); | ||
368 | } | ||
369 | if (field->physical_minimum != field->physical_maximum) { | ||
370 | tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum); | ||
371 | tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum); | ||
372 | } | ||
373 | if (field->unit_exponent) { | ||
374 | tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent); | ||
375 | } | ||
376 | if (field->unit) { | ||
377 | char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" }; | ||
378 | char *units[5][8] = { | ||
379 | { "None", "None", "None", "None", "None", "None", "None", "None" }, | ||
380 | { "None", "Centimeter", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" }, | ||
381 | { "None", "Radians", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" }, | ||
382 | { "None", "Inch", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" }, | ||
383 | { "None", "Degrees", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" } | ||
384 | }; | ||
385 | |||
386 | int i; | ||
387 | int sys; | ||
388 | __u32 data = field->unit; | ||
389 | |||
390 | /* First nibble tells us which system we're in. */ | ||
391 | sys = data & 0xf; | ||
392 | data >>= 4; | ||
393 | |||
394 | if(sys > 4) { | ||
395 | tab(n); printk("Unit(Invalid)\n"); | ||
396 | } | ||
397 | else { | ||
398 | int earlier_unit = 0; | ||
399 | |||
400 | tab(n); printk("Unit(%s : ", systems[sys]); | ||
401 | |||
402 | for (i=1 ; i<sizeof(__u32)*2 ; i++) { | ||
403 | char nibble = data & 0xf; | ||
404 | data >>= 4; | ||
405 | if (nibble != 0) { | ||
406 | if(earlier_unit++ > 0) | ||
407 | printk("*"); | ||
408 | printk("%s", units[sys][i]); | ||
409 | if(nibble != 1) { | ||
410 | /* This is a _signed_ nibble(!) */ | ||
411 | |||
412 | int val = nibble & 0x7; | ||
413 | if(nibble & 0x08) | ||
414 | val = -((0x7 & ~val) +1); | ||
415 | printk("^%d", val); | ||
416 | } | ||
417 | } | ||
418 | } | ||
419 | printk(")\n"); | ||
420 | } | ||
421 | } | ||
422 | tab(n); printk("Report Size(%u)\n", field->report_size); | ||
423 | tab(n); printk("Report Count(%u)\n", field->report_count); | ||
424 | tab(n); printk("Report Offset(%u)\n", field->report_offset); | ||
425 | |||
426 | tab(n); printk("Flags( "); | ||
427 | j = field->flags; | ||
428 | printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : ""); | ||
429 | printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array "); | ||
430 | printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute "); | ||
431 | printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : ""); | ||
432 | printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : ""); | ||
433 | printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : ""); | ||
434 | printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : ""); | ||
435 | printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : ""); | ||
436 | printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : ""); | ||
437 | printk(")\n"); | ||
438 | } | ||
439 | |||
440 | static void __attribute__((unused)) hid_dump_device(struct hid_device *device) { | ||
441 | struct hid_report_enum *report_enum; | ||
442 | struct hid_report *report; | ||
443 | struct list_head *list; | ||
444 | unsigned i,k; | ||
445 | static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; | ||
446 | |||
447 | for (i = 0; i < HID_REPORT_TYPES; i++) { | ||
448 | report_enum = device->report_enum + i; | ||
449 | list = report_enum->report_list.next; | ||
450 | while (list != &report_enum->report_list) { | ||
451 | report = (struct hid_report *) list; | ||
452 | tab(2); | ||
453 | printk("%s", table[i]); | ||
454 | if (report->id) | ||
455 | printk("(%d)", report->id); | ||
456 | printk("[%s]", table[report->type]); | ||
457 | printk("\n"); | ||
458 | for (k = 0; k < report->maxfield; k++) { | ||
459 | tab(4); | ||
460 | printk("Field(%d)\n", k); | ||
461 | hid_dump_field(report->field[k], 6); | ||
462 | } | ||
463 | list = list->next; | ||
464 | } | ||
465 | } | ||
466 | } | ||
467 | |||
468 | static void __attribute__((unused)) hid_dump_input(struct hid_usage *usage, __s32 value) { | ||
469 | printk("hid-debug: input "); | ||
470 | resolv_usage(usage->hid); | ||
471 | printk(" = %d\n", value); | ||
472 | } | ||
473 | |||
474 | |||
475 | static char *events[EV_MAX + 1] = { | ||
476 | [EV_SYN] = "Sync", [EV_KEY] = "Key", | ||
477 | [EV_REL] = "Relative", [EV_ABS] = "Absolute", | ||
478 | [EV_MSC] = "Misc", [EV_LED] = "LED", | ||
479 | [EV_SND] = "Sound", [EV_REP] = "Repeat", | ||
480 | [EV_FF] = "ForceFeedback", [EV_PWR] = "Power", | ||
481 | [EV_FF_STATUS] = "ForceFeedbackStatus", | ||
482 | }; | ||
483 | |||
484 | static char *syncs[2] = { | ||
485 | [SYN_REPORT] = "Report", [SYN_CONFIG] = "Config", | ||
486 | }; | ||
487 | static char *keys[KEY_MAX + 1] = { | ||
488 | [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc", | ||
489 | [KEY_1] = "1", [KEY_2] = "2", | ||
490 | [KEY_3] = "3", [KEY_4] = "4", | ||
491 | [KEY_5] = "5", [KEY_6] = "6", | ||
492 | [KEY_7] = "7", [KEY_8] = "8", | ||
493 | [KEY_9] = "9", [KEY_0] = "0", | ||
494 | [KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal", | ||
495 | [KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab", | ||
496 | [KEY_Q] = "Q", [KEY_W] = "W", | ||
497 | [KEY_E] = "E", [KEY_R] = "R", | ||
498 | [KEY_T] = "T", [KEY_Y] = "Y", | ||
499 | [KEY_U] = "U", [KEY_I] = "I", | ||
500 | [KEY_O] = "O", [KEY_P] = "P", | ||
501 | [KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace", | ||
502 | [KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl", | ||
503 | [KEY_A] = "A", [KEY_S] = "S", | ||
504 | [KEY_D] = "D", [KEY_F] = "F", | ||
505 | [KEY_G] = "G", [KEY_H] = "H", | ||
506 | [KEY_J] = "J", [KEY_K] = "K", | ||
507 | [KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon", | ||
508 | [KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave", | ||
509 | [KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash", | ||
510 | [KEY_Z] = "Z", [KEY_X] = "X", | ||
511 | [KEY_C] = "C", [KEY_V] = "V", | ||
512 | [KEY_B] = "B", [KEY_N] = "N", | ||
513 | [KEY_M] = "M", [KEY_COMMA] = "Comma", | ||
514 | [KEY_DOT] = "Dot", [KEY_SLASH] = "Slash", | ||
515 | [KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk", | ||
516 | [KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space", | ||
517 | [KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1", | ||
518 | [KEY_F2] = "F2", [KEY_F3] = "F3", | ||
519 | [KEY_F4] = "F4", [KEY_F5] = "F5", | ||
520 | [KEY_F6] = "F6", [KEY_F7] = "F7", | ||
521 | [KEY_F8] = "F8", [KEY_F9] = "F9", | ||
522 | [KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock", | ||
523 | [KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7", | ||
524 | [KEY_KP8] = "KP8", [KEY_KP9] = "KP9", | ||
525 | [KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4", | ||
526 | [KEY_KP5] = "KP5", [KEY_KP6] = "KP6", | ||
527 | [KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1", | ||
528 | [KEY_KP2] = "KP2", [KEY_KP3] = "KP3", | ||
529 | [KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot", | ||
530 | [KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd", | ||
531 | [KEY_F11] = "F11", [KEY_F12] = "F12", | ||
532 | [KEY_RO] = "RO", [KEY_KATAKANA] = "Katakana", | ||
533 | [KEY_HIRAGANA] = "HIRAGANA", [KEY_HENKAN] = "Henkan", | ||
534 | [KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan", | ||
535 | [KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter", | ||
536 | [KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash", | ||
537 | [KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt", | ||
538 | [KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home", | ||
539 | [KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp", | ||
540 | [KEY_LEFT] = "Left", [KEY_RIGHT] = "Right", | ||
541 | [KEY_END] = "End", [KEY_DOWN] = "Down", | ||
542 | [KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert", | ||
543 | [KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro", | ||
544 | [KEY_MUTE] = "Mute", [KEY_VOLUMEDOWN] = "VolumeDown", | ||
545 | [KEY_VOLUMEUP] = "VolumeUp", [KEY_POWER] = "Power", | ||
546 | [KEY_KPEQUAL] = "KPEqual", [KEY_KPPLUSMINUS] = "KPPlusMinus", | ||
547 | [KEY_PAUSE] = "Pause", [KEY_KPCOMMA] = "KPComma", | ||
548 | [KEY_HANGUEL] = "Hanguel", [KEY_HANJA] = "Hanja", | ||
549 | [KEY_YEN] = "Yen", [KEY_LEFTMETA] = "LeftMeta", | ||
550 | [KEY_RIGHTMETA] = "RightMeta", [KEY_COMPOSE] = "Compose", | ||
551 | [KEY_STOP] = "Stop", [KEY_AGAIN] = "Again", | ||
552 | [KEY_PROPS] = "Props", [KEY_UNDO] = "Undo", | ||
553 | [KEY_FRONT] = "Front", [KEY_COPY] = "Copy", | ||
554 | [KEY_OPEN] = "Open", [KEY_PASTE] = "Paste", | ||
555 | [KEY_FIND] = "Find", [KEY_CUT] = "Cut", | ||
556 | [KEY_HELP] = "Help", [KEY_MENU] = "Menu", | ||
557 | [KEY_CALC] = "Calc", [KEY_SETUP] = "Setup", | ||
558 | [KEY_SLEEP] = "Sleep", [KEY_WAKEUP] = "WakeUp", | ||
559 | [KEY_FILE] = "File", [KEY_SENDFILE] = "SendFile", | ||
560 | [KEY_DELETEFILE] = "DeleteFile", [KEY_XFER] = "X-fer", | ||
561 | [KEY_PROG1] = "Prog1", [KEY_PROG2] = "Prog2", | ||
562 | [KEY_WWW] = "WWW", [KEY_MSDOS] = "MSDOS", | ||
563 | [KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction", | ||
564 | [KEY_CYCLEWINDOWS] = "CycleWindows", [KEY_MAIL] = "Mail", | ||
565 | [KEY_BOOKMARKS] = "Bookmarks", [KEY_COMPUTER] = "Computer", | ||
566 | [KEY_BACK] = "Back", [KEY_FORWARD] = "Forward", | ||
567 | [KEY_CLOSECD] = "CloseCD", [KEY_EJECTCD] = "EjectCD", | ||
568 | [KEY_EJECTCLOSECD] = "EjectCloseCD", [KEY_NEXTSONG] = "NextSong", | ||
569 | [KEY_PLAYPAUSE] = "PlayPause", [KEY_PREVIOUSSONG] = "PreviousSong", | ||
570 | [KEY_STOPCD] = "StopCD", [KEY_RECORD] = "Record", | ||
571 | [KEY_REWIND] = "Rewind", [KEY_PHONE] = "Phone", | ||
572 | [KEY_ISO] = "ISOKey", [KEY_CONFIG] = "Config", | ||
573 | [KEY_HOMEPAGE] = "HomePage", [KEY_REFRESH] = "Refresh", | ||
574 | [KEY_EXIT] = "Exit", [KEY_MOVE] = "Move", | ||
575 | [KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp", | ||
576 | [KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis", | ||
577 | [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_F13] = "F13", | ||
578 | [KEY_F14] = "F14", [KEY_F15] = "F15", | ||
579 | [KEY_F16] = "F16", [KEY_F17] = "F17", | ||
580 | [KEY_F18] = "F18", [KEY_F19] = "F19", | ||
581 | [KEY_F20] = "F20", [KEY_F21] = "F21", | ||
582 | [KEY_F22] = "F22", [KEY_F23] = "F23", | ||
583 | [KEY_F24] = "F24", [KEY_PLAYCD] = "PlayCD", | ||
584 | [KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3", | ||
585 | [KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend", | ||
586 | [KEY_CLOSE] = "Close", [KEY_PLAY] = "Play", | ||
587 | [KEY_FASTFORWARD] = "Fast Forward", [KEY_BASSBOOST] = "Bass Boost", | ||
588 | [KEY_PRINT] = "Print", [KEY_HP] = "HP", | ||
589 | [KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound", | ||
590 | [KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email", | ||
591 | [KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search", | ||
592 | [KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance", | ||
593 | [KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop", | ||
594 | [KEY_ALTERASE] = "Alternate Erase", [KEY_CANCEL] = "Cancel", | ||
595 | [KEY_BRIGHTNESSDOWN] = "Brightness down", [KEY_BRIGHTNESSUP] = "Brightness up", | ||
596 | [KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown", | ||
597 | [BTN_0] = "Btn0", [BTN_1] = "Btn1", | ||
598 | [BTN_2] = "Btn2", [BTN_3] = "Btn3", | ||
599 | [BTN_4] = "Btn4", [BTN_5] = "Btn5", | ||
600 | [BTN_6] = "Btn6", [BTN_7] = "Btn7", | ||
601 | [BTN_8] = "Btn8", [BTN_9] = "Btn9", | ||
602 | [BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn", | ||
603 | [BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn", | ||
604 | [BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn", | ||
605 | [BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn", | ||
606 | [BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn", | ||
607 | [BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn", | ||
608 | [BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn", | ||
609 | [BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2", | ||
610 | [BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4", | ||
611 | [BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6", | ||
612 | [BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA", | ||
613 | [BTN_B] = "BtnB", [BTN_C] = "BtnC", | ||
614 | [BTN_X] = "BtnX", [BTN_Y] = "BtnY", | ||
615 | [BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL", | ||
616 | [BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2", | ||
617 | [BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect", | ||
618 | [BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode", | ||
619 | [BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR", | ||
620 | [BTN_TOOL_PEN] = "ToolPen", [BTN_TOOL_RUBBER] = "ToolRubber", | ||
621 | [BTN_TOOL_BRUSH] = "ToolBrush", [BTN_TOOL_PENCIL] = "ToolPencil", | ||
622 | [BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger", | ||
623 | [BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens", | ||
624 | [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus", | ||
625 | [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "Tool Doubletap", | ||
626 | [BTN_TOOL_TRIPLETAP] = "Tool Tripletap", [BTN_GEAR_DOWN] = "WheelBtn", | ||
627 | [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok", | ||
628 | [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto", | ||
629 | [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2", | ||
630 | [KEY_OPTION] = "Option", [KEY_INFO] = "Info", | ||
631 | [KEY_TIME] = "Time", [KEY_VENDOR] = "Vendor", | ||
632 | [KEY_ARCHIVE] = "Archive", [KEY_PROGRAM] = "Program", | ||
633 | [KEY_CHANNEL] = "Channel", [KEY_FAVORITES] = "Favorites", | ||
634 | [KEY_EPG] = "EPG", [KEY_PVR] = "PVR", | ||
635 | [KEY_MHP] = "MHP", [KEY_LANGUAGE] = "Language", | ||
636 | [KEY_TITLE] = "Title", [KEY_SUBTITLE] = "Subtitle", | ||
637 | [KEY_ANGLE] = "Angle", [KEY_ZOOM] = "Zoom", | ||
638 | [KEY_MODE] = "Mode", [KEY_KEYBOARD] = "Keyboard", | ||
639 | [KEY_SCREEN] = "Screen", [KEY_PC] = "PC", | ||
640 | [KEY_TV] = "TV", [KEY_TV2] = "TV2", | ||
641 | [KEY_VCR] = "VCR", [KEY_VCR2] = "VCR2", | ||
642 | [KEY_SAT] = "Sat", [KEY_SAT2] = "Sat2", | ||
643 | [KEY_CD] = "CD", [KEY_TAPE] = "Tape", | ||
644 | [KEY_RADIO] = "Radio", [KEY_TUNER] = "Tuner", | ||
645 | [KEY_PLAYER] = "Player", [KEY_TEXT] = "Text", | ||
646 | [KEY_DVD] = "DVD", [KEY_AUX] = "Aux", | ||
647 | [KEY_MP3] = "MP3", [KEY_AUDIO] = "Audio", | ||
648 | [KEY_VIDEO] = "Video", [KEY_DIRECTORY] = "Directory", | ||
649 | [KEY_LIST] = "List", [KEY_MEMO] = "Memo", | ||
650 | [KEY_CALENDAR] = "Calendar", [KEY_RED] = "Red", | ||
651 | [KEY_GREEN] = "Green", [KEY_YELLOW] = "Yellow", | ||
652 | [KEY_BLUE] = "Blue", [KEY_CHANNELUP] = "ChannelUp", | ||
653 | [KEY_CHANNELDOWN] = "ChannelDown", [KEY_FIRST] = "First", | ||
654 | [KEY_LAST] = "Last", [KEY_AB] = "AB", | ||
655 | [KEY_NEXT] = "Next", [KEY_RESTART] = "Restart", | ||
656 | [KEY_SLOW] = "Slow", [KEY_SHUFFLE] = "Shuffle", | ||
657 | [KEY_BREAK] = "Break", [KEY_PREVIOUS] = "Previous", | ||
658 | [KEY_DIGITS] = "Digits", [KEY_TEEN] = "TEEN", | ||
659 | [KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "DeleteEOL", | ||
660 | [KEY_DEL_EOS] = "DeleteEOS", [KEY_INS_LINE] = "InsertLine", | ||
661 | [KEY_DEL_LINE] = "DeleteLine", | ||
662 | }; | ||
663 | |||
664 | static char *relatives[REL_MAX + 1] = { | ||
665 | [REL_X] = "X", [REL_Y] = "Y", | ||
666 | [REL_Z] = "Z", [REL_HWHEEL] = "HWheel", | ||
667 | [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel", | ||
668 | [REL_MISC] = "Misc", | ||
669 | }; | ||
670 | |||
671 | static char *absolutes[ABS_MAX + 1] = { | ||
672 | [ABS_X] = "X", [ABS_Y] = "Y", | ||
673 | [ABS_Z] = "Z", [ABS_RX] = "Rx", | ||
674 | [ABS_RY] = "Ry", [ABS_RZ] = "Rz", | ||
675 | [ABS_THROTTLE] = "Throttle", [ABS_RUDDER] = "Rudder", | ||
676 | [ABS_WHEEL] = "Wheel", [ABS_GAS] = "Gas", | ||
677 | [ABS_BRAKE] = "Brake", [ABS_HAT0X] = "Hat0X", | ||
678 | [ABS_HAT0Y] = "Hat0Y", [ABS_HAT1X] = "Hat1X", | ||
679 | [ABS_HAT1Y] = "Hat1Y", [ABS_HAT2X] = "Hat2X", | ||
680 | [ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X", | ||
681 | [ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure", | ||
682 | [ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt", | ||
683 | [ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "Tool Width", | ||
684 | [ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc", | ||
685 | }; | ||
686 | |||
687 | static char *misc[MSC_MAX + 1] = { | ||
688 | [MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled", | ||
689 | [MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData" | ||
690 | }; | ||
691 | |||
692 | static char *leds[LED_MAX + 1] = { | ||
693 | [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", | ||
694 | [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", | ||
695 | [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", | ||
696 | [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", | ||
697 | [LED_MISC] = "Misc", | ||
698 | }; | ||
699 | |||
700 | static char *repeats[REP_MAX + 1] = { | ||
701 | [REP_DELAY] = "Delay", [REP_PERIOD] = "Period" | ||
702 | }; | ||
703 | |||
704 | static char *sounds[SND_MAX + 1] = { | ||
705 | [SND_CLICK] = "Click", [SND_BELL] = "Bell", | ||
706 | [SND_TONE] = "Tone" | ||
707 | }; | ||
708 | |||
709 | static char **names[EV_MAX + 1] = { | ||
710 | [EV_SYN] = syncs, [EV_KEY] = keys, | ||
711 | [EV_REL] = relatives, [EV_ABS] = absolutes, | ||
712 | [EV_MSC] = misc, [EV_LED] = leds, | ||
713 | [EV_SND] = sounds, [EV_REP] = repeats, | ||
714 | }; | ||
715 | |||
716 | static void __attribute__((unused)) resolv_event(__u8 type, __u16 code) { | ||
717 | |||
718 | printk("%s.%s", events[type] ? events[type] : "?", | ||
719 | names[type] ? (names[type][code] ? names[type][code] : "?") : "?"); | ||
720 | } | ||
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c new file mode 100644 index 000000000000..72e698658b53 --- /dev/null +++ b/drivers/usb/input/hid-ff.c | |||
@@ -0,0 +1,94 @@ | |||
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 "hid.h" | ||
36 | |||
37 | /* Drivers' initializing functions */ | ||
38 | extern int hid_lgff_init(struct hid_device* hid); | ||
39 | extern int hid_lg3d_init(struct hid_device* hid); | ||
40 | extern int hid_pid_init(struct hid_device* hid); | ||
41 | extern int hid_tmff_init(struct hid_device* hid); | ||
42 | |||
43 | /* | ||
44 | * This table contains pointers to initializers. To add support for new | ||
45 | * devices, you need to add the USB vendor and product ids here. | ||
46 | */ | ||
47 | struct hid_ff_initializer { | ||
48 | u16 idVendor; | ||
49 | u16 idProduct; | ||
50 | int (*init)(struct hid_device*); | ||
51 | }; | ||
52 | |||
53 | static struct hid_ff_initializer inits[] = { | ||
54 | #ifdef CONFIG_LOGITECH_FF | ||
55 | {0x46d, 0xc211, hid_lgff_init}, // Logitech Cordless rumble pad | ||
56 | {0x46d, 0xc283, hid_lgff_init}, // Logitech Wingman Force 3d | ||
57 | {0x46d, 0xc295, hid_lgff_init}, // Logitech MOMO force wheel | ||
58 | {0x46d, 0xc219, hid_lgff_init}, // Logitech Cordless rumble pad 2 | ||
59 | #endif | ||
60 | #ifdef CONFIG_HID_PID | ||
61 | {0x45e, 0x001b, hid_pid_init}, | ||
62 | #endif | ||
63 | #ifdef CONFIG_THRUSTMASTER_FF | ||
64 | {0x44f, 0xb304, hid_tmff_init}, | ||
65 | #endif | ||
66 | {0, 0, NULL} /* Terminating entry */ | ||
67 | }; | ||
68 | |||
69 | static struct hid_ff_initializer *hid_get_ff_init(__u16 idVendor, | ||
70 | __u16 idProduct) | ||
71 | { | ||
72 | struct hid_ff_initializer *init; | ||
73 | for (init = inits; | ||
74 | init->idVendor | ||
75 | && !(init->idVendor == idVendor | ||
76 | && init->idProduct == idProduct); | ||
77 | init++); | ||
78 | |||
79 | return init->idVendor? init : NULL; | ||
80 | } | ||
81 | |||
82 | int hid_ff_init(struct hid_device* hid) | ||
83 | { | ||
84 | struct hid_ff_initializer *init; | ||
85 | |||
86 | init = hid_get_ff_init(le16_to_cpu(hid->dev->descriptor.idVendor), | ||
87 | le16_to_cpu(hid->dev->descriptor.idProduct)); | ||
88 | |||
89 | if (!init) { | ||
90 | dbg("hid_ff_init could not find initializer"); | ||
91 | return -ENOSYS; | ||
92 | } | ||
93 | return init->init(hid); | ||
94 | } | ||
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c new file mode 100644 index 000000000000..5553c3553e9d --- /dev/null +++ b/drivers/usb/input/hid-input.c | |||
@@ -0,0 +1,630 @@ | |||
1 | /* | ||
2 | * $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $ | ||
3 | * | ||
4 | * Copyright (c) 2000-2001 Vojtech Pavlik | ||
5 | * | ||
6 | * USB HID to Linux Input mapping | ||
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/module.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/input.h> | ||
33 | #include <linux/usb.h> | ||
34 | |||
35 | #undef DEBUG | ||
36 | |||
37 | #include "hid.h" | ||
38 | |||
39 | #define unk KEY_UNKNOWN | ||
40 | |||
41 | static unsigned char hid_keyboard[256] = { | ||
42 | 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, | ||
43 | 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, | ||
44 | 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, | ||
45 | 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, | ||
46 | 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, | ||
47 | 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, | ||
48 | 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, | ||
49 | 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, | ||
50 | 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk, | ||
51 | 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, | ||
52 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, | ||
53 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, | ||
54 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, | ||
55 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, | ||
56 | 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, | ||
57 | 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk | ||
58 | }; | ||
59 | |||
60 | static struct { | ||
61 | __s32 x; | ||
62 | __s32 y; | ||
63 | } hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; | ||
64 | |||
65 | #define map_abs(c) do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; } while (0) | ||
66 | #define map_rel(c) do { usage->code = c; usage->type = EV_REL; bit = input->relbit; max = REL_MAX; } while (0) | ||
67 | #define map_key(c) do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; } while (0) | ||
68 | #define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0) | ||
69 | #define map_ff(c) do { usage->code = c; usage->type = EV_FF; bit = input->ffbit; max = FF_MAX; } while (0) | ||
70 | |||
71 | #define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) | ||
72 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) | ||
73 | #define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0) | ||
74 | |||
75 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, | ||
76 | struct hid_usage *usage) | ||
77 | { | ||
78 | struct input_dev *input = &hidinput->input; | ||
79 | struct hid_device *device = hidinput->input.private; | ||
80 | int max, code; | ||
81 | unsigned long *bit; | ||
82 | |||
83 | field->hidinput = hidinput; | ||
84 | |||
85 | #ifdef DEBUG | ||
86 | printk(KERN_DEBUG "Mapping: "); | ||
87 | resolv_usage(usage->hid); | ||
88 | printk(" ---> "); | ||
89 | #endif | ||
90 | |||
91 | if (field->flags & HID_MAIN_ITEM_CONSTANT) | ||
92 | goto ignore; | ||
93 | |||
94 | switch (usage->hid & HID_USAGE_PAGE) { | ||
95 | |||
96 | case HID_UP_UNDEFINED: | ||
97 | goto ignore; | ||
98 | |||
99 | case HID_UP_KEYBOARD: | ||
100 | |||
101 | set_bit(EV_REP, input->evbit); | ||
102 | |||
103 | if ((usage->hid & HID_USAGE) < 256) { | ||
104 | if (!hid_keyboard[usage->hid & HID_USAGE]) goto ignore; | ||
105 | map_key_clear(hid_keyboard[usage->hid & HID_USAGE]); | ||
106 | } else | ||
107 | map_key(KEY_UNKNOWN); | ||
108 | |||
109 | break; | ||
110 | |||
111 | case HID_UP_BUTTON: | ||
112 | |||
113 | code = ((usage->hid - 1) & 0xf); | ||
114 | |||
115 | switch (field->application) { | ||
116 | case HID_GD_MOUSE: | ||
117 | case HID_GD_POINTER: code += 0x110; break; | ||
118 | case HID_GD_JOYSTICK: code += 0x120; break; | ||
119 | case HID_GD_GAMEPAD: code += 0x130; break; | ||
120 | default: | ||
121 | switch (field->physical) { | ||
122 | case HID_GD_MOUSE: | ||
123 | case HID_GD_POINTER: code += 0x110; break; | ||
124 | case HID_GD_JOYSTICK: code += 0x120; break; | ||
125 | case HID_GD_GAMEPAD: code += 0x130; break; | ||
126 | default: code += 0x100; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | map_key(code); | ||
131 | break; | ||
132 | |||
133 | case HID_UP_GENDESK: | ||
134 | |||
135 | if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */ | ||
136 | switch (usage->hid & 0xf) { | ||
137 | case 0x1: map_key_clear(KEY_POWER); break; | ||
138 | case 0x2: map_key_clear(KEY_SLEEP); break; | ||
139 | case 0x3: map_key_clear(KEY_WAKEUP); break; | ||
140 | default: goto unknown; | ||
141 | } | ||
142 | break; | ||
143 | } | ||
144 | |||
145 | if ((usage->hid & 0xf0) == 0x90) { /* D-pad */ | ||
146 | switch (usage->hid) { | ||
147 | case HID_GD_UP: usage->hat_dir = 1; break; | ||
148 | case HID_GD_DOWN: usage->hat_dir = 5; break; | ||
149 | case HID_GD_RIGHT: usage->hat_dir = 3; break; | ||
150 | case HID_GD_LEFT: usage->hat_dir = 7; break; | ||
151 | default: goto unknown; | ||
152 | } | ||
153 | if (field->dpad) { | ||
154 | map_abs(field->dpad); | ||
155 | goto ignore; | ||
156 | } | ||
157 | map_abs(ABS_HAT0X); | ||
158 | break; | ||
159 | } | ||
160 | |||
161 | switch (usage->hid) { | ||
162 | |||
163 | /* These usage IDs map directly to the usage codes. */ | ||
164 | case HID_GD_X: case HID_GD_Y: case HID_GD_Z: | ||
165 | case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: | ||
166 | case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: | ||
167 | if (field->flags & HID_MAIN_ITEM_RELATIVE) | ||
168 | map_rel(usage->hid & 0xf); | ||
169 | else | ||
170 | map_abs(usage->hid & 0xf); | ||
171 | break; | ||
172 | |||
173 | case HID_GD_HATSWITCH: | ||
174 | usage->hat_min = field->logical_minimum; | ||
175 | usage->hat_max = field->logical_maximum; | ||
176 | map_abs(ABS_HAT0X); | ||
177 | break; | ||
178 | |||
179 | case HID_GD_START: map_key_clear(BTN_START); break; | ||
180 | case HID_GD_SELECT: map_key_clear(BTN_SELECT); break; | ||
181 | |||
182 | default: goto unknown; | ||
183 | } | ||
184 | |||
185 | break; | ||
186 | |||
187 | case HID_UP_LED: | ||
188 | if (((usage->hid - 1) & 0xffff) >= LED_MAX) | ||
189 | goto ignore; | ||
190 | map_led((usage->hid - 1) & 0xffff); | ||
191 | break; | ||
192 | |||
193 | case HID_UP_DIGITIZER: | ||
194 | |||
195 | switch (usage->hid & 0xff) { | ||
196 | |||
197 | case 0x30: /* TipPressure */ | ||
198 | if (!test_bit(BTN_TOUCH, input->keybit)) { | ||
199 | device->quirks |= HID_QUIRK_NOTOUCH; | ||
200 | set_bit(EV_KEY, input->evbit); | ||
201 | set_bit(BTN_TOUCH, input->keybit); | ||
202 | } | ||
203 | |||
204 | map_abs_clear(ABS_PRESSURE); | ||
205 | break; | ||
206 | |||
207 | case 0x32: /* InRange */ | ||
208 | switch (field->physical & 0xff) { | ||
209 | case 0x21: map_key(BTN_TOOL_MOUSE); break; | ||
210 | case 0x22: map_key(BTN_TOOL_FINGER); break; | ||
211 | default: map_key(BTN_TOOL_PEN); break; | ||
212 | } | ||
213 | break; | ||
214 | |||
215 | case 0x3c: /* Invert */ | ||
216 | map_key_clear(BTN_TOOL_RUBBER); | ||
217 | break; | ||
218 | |||
219 | case 0x33: /* Touch */ | ||
220 | case 0x42: /* TipSwitch */ | ||
221 | case 0x43: /* TipSwitch2 */ | ||
222 | device->quirks &= ~HID_QUIRK_NOTOUCH; | ||
223 | map_key_clear(BTN_TOUCH); | ||
224 | break; | ||
225 | |||
226 | case 0x44: /* BarrelSwitch */ | ||
227 | map_key_clear(BTN_STYLUS); | ||
228 | break; | ||
229 | |||
230 | default: goto unknown; | ||
231 | } | ||
232 | break; | ||
233 | |||
234 | case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */ | ||
235 | |||
236 | switch (usage->hid & HID_USAGE) { | ||
237 | case 0x000: goto ignore; | ||
238 | case 0x034: map_key_clear(KEY_SLEEP); break; | ||
239 | case 0x036: map_key_clear(BTN_MISC); break; | ||
240 | case 0x08a: map_key_clear(KEY_WWW); break; | ||
241 | case 0x095: map_key_clear(KEY_HELP); break; | ||
242 | case 0x0b0: map_key_clear(KEY_PLAY); break; | ||
243 | case 0x0b1: map_key_clear(KEY_PAUSE); break; | ||
244 | case 0x0b2: map_key_clear(KEY_RECORD); break; | ||
245 | case 0x0b3: map_key_clear(KEY_FASTFORWARD); break; | ||
246 | case 0x0b4: map_key_clear(KEY_REWIND); break; | ||
247 | case 0x0b5: map_key_clear(KEY_NEXTSONG); break; | ||
248 | case 0x0b6: map_key_clear(KEY_PREVIOUSSONG); break; | ||
249 | case 0x0b7: map_key_clear(KEY_STOPCD); break; | ||
250 | case 0x0b8: map_key_clear(KEY_EJECTCD); break; | ||
251 | case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break; | ||
252 | case 0x0e0: map_abs_clear(ABS_VOLUME); break; | ||
253 | case 0x0e2: map_key_clear(KEY_MUTE); break; | ||
254 | case 0x0e5: map_key_clear(KEY_BASSBOOST); break; | ||
255 | case 0x0e9: map_key_clear(KEY_VOLUMEUP); break; | ||
256 | case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break; | ||
257 | case 0x183: map_key_clear(KEY_CONFIG); break; | ||
258 | case 0x18a: map_key_clear(KEY_MAIL); break; | ||
259 | case 0x192: map_key_clear(KEY_CALC); break; | ||
260 | case 0x194: map_key_clear(KEY_FILE); break; | ||
261 | case 0x21a: map_key_clear(KEY_UNDO); break; | ||
262 | case 0x21b: map_key_clear(KEY_COPY); break; | ||
263 | case 0x21c: map_key_clear(KEY_CUT); break; | ||
264 | case 0x21d: map_key_clear(KEY_PASTE); break; | ||
265 | case 0x221: map_key_clear(KEY_FIND); break; | ||
266 | case 0x223: map_key_clear(KEY_HOMEPAGE); break; | ||
267 | case 0x224: map_key_clear(KEY_BACK); break; | ||
268 | case 0x225: map_key_clear(KEY_FORWARD); break; | ||
269 | case 0x226: map_key_clear(KEY_STOP); break; | ||
270 | case 0x227: map_key_clear(KEY_REFRESH); break; | ||
271 | case 0x22a: map_key_clear(KEY_BOOKMARKS); break; | ||
272 | case 0x238: map_rel(REL_HWHEEL); break; | ||
273 | default: goto unknown; | ||
274 | } | ||
275 | break; | ||
276 | |||
277 | case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */ | ||
278 | |||
279 | set_bit(EV_REP, input->evbit); | ||
280 | switch (usage->hid & HID_USAGE) { | ||
281 | case 0x021: map_key_clear(KEY_PRINT); break; | ||
282 | case 0x070: map_key_clear(KEY_HP); break; | ||
283 | case 0x071: map_key_clear(KEY_CAMERA); break; | ||
284 | case 0x072: map_key_clear(KEY_SOUND); break; | ||
285 | case 0x073: map_key_clear(KEY_QUESTION); break; | ||
286 | case 0x080: map_key_clear(KEY_EMAIL); break; | ||
287 | case 0x081: map_key_clear(KEY_CHAT); break; | ||
288 | case 0x082: map_key_clear(KEY_SEARCH); break; | ||
289 | case 0x083: map_key_clear(KEY_CONNECT); break; | ||
290 | case 0x084: map_key_clear(KEY_FINANCE); break; | ||
291 | case 0x085: map_key_clear(KEY_SPORT); break; | ||
292 | case 0x086: map_key_clear(KEY_SHOP); break; | ||
293 | default: goto ignore; | ||
294 | } | ||
295 | break; | ||
296 | |||
297 | case HID_UP_MSVENDOR: | ||
298 | |||
299 | goto ignore; | ||
300 | |||
301 | case HID_UP_PID: | ||
302 | |||
303 | set_bit(EV_FF, input->evbit); | ||
304 | switch(usage->hid & HID_USAGE) { | ||
305 | case 0x26: map_ff_effect(FF_CONSTANT); goto ignore; | ||
306 | case 0x27: map_ff_effect(FF_RAMP); goto ignore; | ||
307 | case 0x28: map_ff_effect(FF_CUSTOM); goto ignore; | ||
308 | case 0x30: map_ff_effect(FF_SQUARE); map_ff_effect(FF_PERIODIC); goto ignore; | ||
309 | case 0x31: map_ff_effect(FF_SINE); map_ff_effect(FF_PERIODIC); goto ignore; | ||
310 | case 0x32: map_ff_effect(FF_TRIANGLE); map_ff_effect(FF_PERIODIC); goto ignore; | ||
311 | case 0x33: map_ff_effect(FF_SAW_UP); map_ff_effect(FF_PERIODIC); goto ignore; | ||
312 | case 0x34: map_ff_effect(FF_SAW_DOWN); map_ff_effect(FF_PERIODIC); goto ignore; | ||
313 | case 0x40: map_ff_effect(FF_SPRING); goto ignore; | ||
314 | case 0x41: map_ff_effect(FF_DAMPER); goto ignore; | ||
315 | case 0x42: map_ff_effect(FF_INERTIA); goto ignore; | ||
316 | case 0x43: map_ff_effect(FF_FRICTION); goto ignore; | ||
317 | case 0x7e: map_ff(FF_GAIN); break; | ||
318 | case 0x83: input->ff_effects_max = field->value[0]; goto ignore; | ||
319 | case 0x98: map_ff(FF_AUTOCENTER); break; | ||
320 | case 0xa4: map_key_clear(BTN_DEAD); break; | ||
321 | default: goto ignore; | ||
322 | } | ||
323 | break; | ||
324 | |||
325 | default: | ||
326 | unknown: | ||
327 | if (field->report_size == 1) { | ||
328 | if (field->report->type == HID_OUTPUT_REPORT) { | ||
329 | map_led(LED_MISC); | ||
330 | break; | ||
331 | } | ||
332 | map_key(BTN_MISC); | ||
333 | break; | ||
334 | } | ||
335 | if (field->flags & HID_MAIN_ITEM_RELATIVE) { | ||
336 | map_rel(REL_MISC); | ||
337 | break; | ||
338 | } | ||
339 | map_abs(ABS_MISC); | ||
340 | break; | ||
341 | } | ||
342 | |||
343 | set_bit(usage->type, input->evbit); | ||
344 | |||
345 | while (usage->code <= max && test_and_set_bit(usage->code, bit)) | ||
346 | usage->code = find_next_zero_bit(bit, max + 1, usage->code); | ||
347 | |||
348 | if (usage->code > max) | ||
349 | goto ignore; | ||
350 | |||
351 | if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && | ||
352 | (usage->type == EV_REL) && (usage->code == REL_WHEEL)) | ||
353 | set_bit(REL_HWHEEL, bit); | ||
354 | |||
355 | if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) | ||
356 | || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) | ||
357 | goto ignore; | ||
358 | |||
359 | if (usage->type == EV_ABS) { | ||
360 | |||
361 | int a = field->logical_minimum; | ||
362 | int b = field->logical_maximum; | ||
363 | |||
364 | if ((device->quirks & HID_QUIRK_BADPAD) && (usage->code == ABS_X || usage->code == ABS_Y)) { | ||
365 | a = field->logical_minimum = 0; | ||
366 | b = field->logical_maximum = 255; | ||
367 | } | ||
368 | |||
369 | if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) | ||
370 | input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); | ||
371 | else input_set_abs_params(input, usage->code, a, b, 0, 0); | ||
372 | |||
373 | } | ||
374 | |||
375 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { | ||
376 | int i; | ||
377 | for (i = usage->code; i < usage->code + 2 && i <= max; i++) { | ||
378 | input_set_abs_params(input, i, -1, 1, 0, 0); | ||
379 | set_bit(i, input->absbit); | ||
380 | } | ||
381 | if (usage->hat_dir && !field->dpad) | ||
382 | field->dpad = usage->code; | ||
383 | } | ||
384 | |||
385 | #ifdef DEBUG | ||
386 | resolv_event(usage->type, usage->code); | ||
387 | printk("\n"); | ||
388 | #endif | ||
389 | return; | ||
390 | |||
391 | ignore: | ||
392 | #ifdef DEBUG | ||
393 | printk("IGNORED\n"); | ||
394 | #endif | ||
395 | return; | ||
396 | } | ||
397 | |||
398 | void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, struct pt_regs *regs) | ||
399 | { | ||
400 | struct input_dev *input = &field->hidinput->input; | ||
401 | int *quirks = &hid->quirks; | ||
402 | |||
403 | if (!input) | ||
404 | return; | ||
405 | |||
406 | input_regs(input, regs); | ||
407 | |||
408 | if (!usage->type) | ||
409 | return; | ||
410 | |||
411 | if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) | ||
412 | || ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) { | ||
413 | if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON; | ||
414 | else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON; | ||
415 | return; | ||
416 | } | ||
417 | |||
418 | if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) { | ||
419 | input_event(input, usage->type, REL_HWHEEL, value); | ||
420 | return; | ||
421 | } | ||
422 | |||
423 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { | ||
424 | int hat_dir = usage->hat_dir; | ||
425 | if (!hat_dir) | ||
426 | hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; | ||
427 | if (hat_dir < 0 || hat_dir > 8) hat_dir = 0; | ||
428 | input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x); | ||
429 | input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y); | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */ | ||
434 | *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT); | ||
435 | return; | ||
436 | } | ||
437 | |||
438 | if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */ | ||
439 | if (value) { | ||
440 | input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1); | ||
441 | return; | ||
442 | } | ||
443 | input_event(input, usage->type, usage->code, 0); | ||
444 | input_event(input, usage->type, BTN_TOOL_RUBBER, 0); | ||
445 | return; | ||
446 | } | ||
447 | |||
448 | if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */ | ||
449 | int a = field->logical_minimum; | ||
450 | int b = field->logical_maximum; | ||
451 | input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3)); | ||
452 | } | ||
453 | |||
454 | if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */ | ||
455 | input->ff_effects_max = value; | ||
456 | dbg("Maximum Effects - %d",input->ff_effects_max); | ||
457 | return; | ||
458 | } | ||
459 | |||
460 | if (usage->hid == (HID_UP_PID | 0x7fUL)) { | ||
461 | dbg("PID Pool Report\n"); | ||
462 | return; | ||
463 | } | ||
464 | |||
465 | if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ | ||
466 | return; | ||
467 | |||
468 | input_event(input, usage->type, usage->code, value); | ||
469 | |||
470 | if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY)) | ||
471 | input_event(input, usage->type, usage->code, 0); | ||
472 | } | ||
473 | |||
474 | void hidinput_report_event(struct hid_device *hid, struct hid_report *report) | ||
475 | { | ||
476 | struct list_head *lh; | ||
477 | struct hid_input *hidinput; | ||
478 | |||
479 | list_for_each (lh, &hid->inputs) { | ||
480 | hidinput = list_entry(lh, struct hid_input, list); | ||
481 | input_sync(&hidinput->input); | ||
482 | } | ||
483 | } | ||
484 | |||
485 | static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field) | ||
486 | { | ||
487 | struct hid_report *report; | ||
488 | int i, j; | ||
489 | |||
490 | list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) { | ||
491 | for (i = 0; i < report->maxfield; i++) { | ||
492 | *field = report->field[i]; | ||
493 | for (j = 0; j < (*field)->maxusage; j++) | ||
494 | if ((*field)->usage[j].type == type && (*field)->usage[j].code == code) | ||
495 | return j; | ||
496 | } | ||
497 | } | ||
498 | return -1; | ||
499 | } | ||
500 | |||
501 | static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | ||
502 | { | ||
503 | struct hid_device *hid = dev->private; | ||
504 | struct hid_field *field; | ||
505 | int offset; | ||
506 | |||
507 | if (type == EV_FF) | ||
508 | return hid_ff_event(hid, dev, type, code, value); | ||
509 | |||
510 | if (type != EV_LED) | ||
511 | return -1; | ||
512 | |||
513 | if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) { | ||
514 | warn("event field not found"); | ||
515 | return -1; | ||
516 | } | ||
517 | |||
518 | hid_set_field(field, offset, value); | ||
519 | hid_submit_report(hid, field->report, USB_DIR_OUT); | ||
520 | |||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | static int hidinput_open(struct input_dev *dev) | ||
525 | { | ||
526 | struct hid_device *hid = dev->private; | ||
527 | return hid_open(hid); | ||
528 | } | ||
529 | |||
530 | static void hidinput_close(struct input_dev *dev) | ||
531 | { | ||
532 | struct hid_device *hid = dev->private; | ||
533 | hid_close(hid); | ||
534 | } | ||
535 | |||
536 | /* | ||
537 | * Register the input device; print a message. | ||
538 | * Configure the input layer interface | ||
539 | * Read all reports and initialize the absolute field values. | ||
540 | */ | ||
541 | |||
542 | int hidinput_connect(struct hid_device *hid) | ||
543 | { | ||
544 | struct usb_device *dev = hid->dev; | ||
545 | struct hid_report *report; | ||
546 | struct hid_input *hidinput = NULL; | ||
547 | int i, j, k; | ||
548 | |||
549 | INIT_LIST_HEAD(&hid->inputs); | ||
550 | |||
551 | for (i = 0; i < hid->maxcollection; i++) | ||
552 | if (hid->collection[i].type == HID_COLLECTION_APPLICATION || | ||
553 | hid->collection[i].type == HID_COLLECTION_PHYSICAL) | ||
554 | if (IS_INPUT_APPLICATION(hid->collection[i].usage)) | ||
555 | break; | ||
556 | |||
557 | if (i == hid->maxcollection) | ||
558 | return -1; | ||
559 | |||
560 | for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) | ||
561 | list_for_each_entry(report, &hid->report_enum[k].report_list, list) { | ||
562 | |||
563 | if (!report->maxfield) | ||
564 | continue; | ||
565 | |||
566 | if (!hidinput) { | ||
567 | hidinput = kmalloc(sizeof(*hidinput), GFP_KERNEL); | ||
568 | if (!hidinput) { | ||
569 | err("Out of memory during hid input probe"); | ||
570 | return -1; | ||
571 | } | ||
572 | memset(hidinput, 0, sizeof(*hidinput)); | ||
573 | |||
574 | list_add_tail(&hidinput->list, &hid->inputs); | ||
575 | |||
576 | hidinput->input.private = hid; | ||
577 | hidinput->input.event = hidinput_input_event; | ||
578 | hidinput->input.open = hidinput_open; | ||
579 | hidinput->input.close = hidinput_close; | ||
580 | |||
581 | hidinput->input.name = hid->name; | ||
582 | hidinput->input.phys = hid->phys; | ||
583 | hidinput->input.uniq = hid->uniq; | ||
584 | hidinput->input.id.bustype = BUS_USB; | ||
585 | hidinput->input.id.vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
586 | hidinput->input.id.product = le16_to_cpu(dev->descriptor.idProduct); | ||
587 | hidinput->input.id.version = le16_to_cpu(dev->descriptor.bcdDevice); | ||
588 | hidinput->input.dev = &hid->intf->dev; | ||
589 | } | ||
590 | |||
591 | for (i = 0; i < report->maxfield; i++) | ||
592 | for (j = 0; j < report->field[i]->maxusage; j++) | ||
593 | hidinput_configure_usage(hidinput, report->field[i], | ||
594 | report->field[i]->usage + j); | ||
595 | |||
596 | if (hid->quirks & HID_QUIRK_MULTI_INPUT) { | ||
597 | /* This will leave hidinput NULL, so that it | ||
598 | * allocates another one if we have more inputs on | ||
599 | * the same interface. Some devices (e.g. Happ's | ||
600 | * UGCI) cram a lot of unrelated inputs into the | ||
601 | * same interface. */ | ||
602 | hidinput->report = report; | ||
603 | input_register_device(&hidinput->input); | ||
604 | hidinput = NULL; | ||
605 | } | ||
606 | } | ||
607 | |||
608 | /* This only gets called when we are a single-input (most of the | ||
609 | * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is | ||
610 | * only useful in this case, and not for multi-input quirks. */ | ||
611 | if (hidinput) { | ||
612 | hid_ff_init(hid); | ||
613 | input_register_device(&hidinput->input); | ||
614 | } | ||
615 | |||
616 | return 0; | ||
617 | } | ||
618 | |||
619 | void hidinput_disconnect(struct hid_device *hid) | ||
620 | { | ||
621 | struct list_head *lh, *next; | ||
622 | struct hid_input *hidinput; | ||
623 | |||
624 | list_for_each_safe(lh, next, &hid->inputs) { | ||
625 | hidinput = list_entry(lh, struct hid_input, list); | ||
626 | input_unregister_device(&hidinput->input); | ||
627 | list_del(&hidinput->list); | ||
628 | kfree(hidinput); | ||
629 | } | ||
630 | } | ||
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c new file mode 100644 index 000000000000..0d7404bab92f --- /dev/null +++ b/drivers/usb/input/hid-lgff.c | |||
@@ -0,0 +1,528 @@ | |||
1 | /* | ||
2 | * $$ | ||
3 | * | ||
4 | * Force feedback support for hid-compliant for some of the devices from | ||
5 | * Logitech, namely: | ||
6 | * - WingMan Cordless RumblePad | ||
7 | * - WingMan Force 3D | ||
8 | * | ||
9 | * Copyright (c) 2002-2004 Johann Deneux | ||
10 | */ | ||
11 | |||
12 | /* | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
26 | * | ||
27 | * Should you need to contact me, the author, you can do so by | ||
28 | * e-mail - mail your message to <johann.deneux@it.uu.se> | ||
29 | */ | ||
30 | |||
31 | #include <linux/input.h> | ||
32 | #include <linux/sched.h> | ||
33 | |||
34 | //#define DEBUG | ||
35 | #include <linux/usb.h> | ||
36 | |||
37 | #include <linux/circ_buf.h> | ||
38 | |||
39 | #include "hid.h" | ||
40 | #include "fixp-arith.h" | ||
41 | |||
42 | |||
43 | /* Periodicity of the update */ | ||
44 | #define PERIOD (HZ/10) | ||
45 | |||
46 | #define RUN_AT(t) (jiffies + (t)) | ||
47 | |||
48 | /* Effect status */ | ||
49 | #define EFFECT_STARTED 0 /* Effect is going to play after some time | ||
50 | (ff_replay.delay) */ | ||
51 | #define EFFECT_PLAYING 1 /* Effect is being played */ | ||
52 | #define EFFECT_USED 2 | ||
53 | |||
54 | // For lgff_device::flags | ||
55 | #define DEVICE_CLOSING 0 /* The driver is being unitialised */ | ||
56 | |||
57 | /* Check that the current process can access an effect */ | ||
58 | #define CHECK_OWNERSHIP(effect) (current->pid == 0 \ | ||
59 | || effect.owner == current->pid) | ||
60 | |||
61 | #define LGFF_CHECK_OWNERSHIP(i, l) \ | ||
62 | (i>=0 && i<LGFF_EFFECTS \ | ||
63 | && test_bit(EFFECT_USED, l->effects[i].flags) \ | ||
64 | && CHECK_OWNERSHIP(l->effects[i])) | ||
65 | |||
66 | #define LGFF_EFFECTS 8 | ||
67 | |||
68 | struct device_type { | ||
69 | u16 idVendor; | ||
70 | u16 idProduct; | ||
71 | signed short *ff; | ||
72 | }; | ||
73 | |||
74 | struct lgff_effect { | ||
75 | pid_t owner; | ||
76 | |||
77 | struct ff_effect effect; | ||
78 | |||
79 | unsigned long flags[1]; | ||
80 | unsigned int count; /* Number of times left to play */ | ||
81 | unsigned long started_at; /* When the effect started to play */ | ||
82 | }; | ||
83 | |||
84 | struct lgff_device { | ||
85 | struct hid_device* hid; | ||
86 | |||
87 | struct hid_report* constant; | ||
88 | struct hid_report* rumble; | ||
89 | struct hid_report* condition; | ||
90 | |||
91 | struct lgff_effect effects[LGFF_EFFECTS]; | ||
92 | spinlock_t lock; /* device-level lock. Having locks on | ||
93 | a per-effect basis could be nice, but | ||
94 | isn't really necessary */ | ||
95 | |||
96 | unsigned long flags[1]; /* Contains various information about the | ||
97 | state of the driver for this device */ | ||
98 | |||
99 | struct timer_list timer; | ||
100 | }; | ||
101 | |||
102 | /* Callbacks */ | ||
103 | static void hid_lgff_exit(struct hid_device* hid); | ||
104 | static int hid_lgff_event(struct hid_device *hid, struct input_dev *input, | ||
105 | unsigned int type, unsigned int code, int value); | ||
106 | static int hid_lgff_flush(struct input_dev *input, struct file *file); | ||
107 | static int hid_lgff_upload_effect(struct input_dev *input, | ||
108 | struct ff_effect *effect); | ||
109 | static int hid_lgff_erase(struct input_dev *input, int id); | ||
110 | |||
111 | /* Local functions */ | ||
112 | static void hid_lgff_input_init(struct hid_device* hid); | ||
113 | static void hid_lgff_timer(unsigned long timer_data); | ||
114 | static struct hid_report* hid_lgff_duplicate_report(struct hid_report*); | ||
115 | static void hid_lgff_delete_report(struct hid_report*); | ||
116 | |||
117 | static signed short ff_rumble[] = { | ||
118 | FF_RUMBLE, | ||
119 | -1 | ||
120 | }; | ||
121 | |||
122 | static signed short ff_joystick[] = { | ||
123 | FF_CONSTANT, | ||
124 | -1 | ||
125 | }; | ||
126 | |||
127 | static struct device_type devices[] = { | ||
128 | {0x046d, 0xc211, ff_rumble}, | ||
129 | {0x046d, 0xc219, ff_rumble}, | ||
130 | {0x046d, 0xc283, ff_joystick}, | ||
131 | {0x0000, 0x0000, ff_joystick} | ||
132 | }; | ||
133 | |||
134 | int hid_lgff_init(struct hid_device* hid) | ||
135 | { | ||
136 | struct lgff_device *private; | ||
137 | struct hid_report* report; | ||
138 | struct hid_field* field; | ||
139 | |||
140 | /* Find the report to use */ | ||
141 | if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) { | ||
142 | err("No output report found"); | ||
143 | return -1; | ||
144 | } | ||
145 | /* Check that the report looks ok */ | ||
146 | report = (struct hid_report*)hid->report_enum[HID_OUTPUT_REPORT].report_list.next; | ||
147 | if (!report) { | ||
148 | err("NULL output report"); | ||
149 | return -1; | ||
150 | } | ||
151 | field = report->field[0]; | ||
152 | if (!field) { | ||
153 | err("NULL field"); | ||
154 | return -1; | ||
155 | } | ||
156 | |||
157 | private = kmalloc(sizeof(struct lgff_device), GFP_KERNEL); | ||
158 | if (!private) | ||
159 | return -1; | ||
160 | memset(private, 0, sizeof(struct lgff_device)); | ||
161 | hid->ff_private = private; | ||
162 | |||
163 | /* Input init */ | ||
164 | hid_lgff_input_init(hid); | ||
165 | |||
166 | |||
167 | private->constant = hid_lgff_duplicate_report(report); | ||
168 | if (!private->constant) { | ||
169 | kfree(private); | ||
170 | return -1; | ||
171 | } | ||
172 | private->constant->field[0]->value[0] = 0x51; | ||
173 | private->constant->field[0]->value[1] = 0x08; | ||
174 | private->constant->field[0]->value[2] = 0x7f; | ||
175 | private->constant->field[0]->value[3] = 0x7f; | ||
176 | |||
177 | private->rumble = hid_lgff_duplicate_report(report); | ||
178 | if (!private->rumble) { | ||
179 | hid_lgff_delete_report(private->constant); | ||
180 | kfree(private); | ||
181 | return -1; | ||
182 | } | ||
183 | private->rumble->field[0]->value[0] = 0x42; | ||
184 | |||
185 | |||
186 | private->condition = hid_lgff_duplicate_report(report); | ||
187 | if (!private->condition) { | ||
188 | hid_lgff_delete_report(private->rumble); | ||
189 | hid_lgff_delete_report(private->constant); | ||
190 | kfree(private); | ||
191 | return -1; | ||
192 | } | ||
193 | |||
194 | private->hid = hid; | ||
195 | |||
196 | spin_lock_init(&private->lock); | ||
197 | init_timer(&private->timer); | ||
198 | private->timer.data = (unsigned long)private; | ||
199 | private->timer.function = hid_lgff_timer; | ||
200 | |||
201 | /* Event and exit callbacks */ | ||
202 | hid->ff_exit = hid_lgff_exit; | ||
203 | hid->ff_event = hid_lgff_event; | ||
204 | |||
205 | /* Start the update task */ | ||
206 | private->timer.expires = RUN_AT(PERIOD); | ||
207 | add_timer(&private->timer); /*TODO: only run the timer when at least | ||
208 | one effect is playing */ | ||
209 | |||
210 | printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n"); | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static struct hid_report* hid_lgff_duplicate_report(struct hid_report* report) | ||
216 | { | ||
217 | struct hid_report* ret; | ||
218 | |||
219 | ret = kmalloc(sizeof(struct lgff_device), GFP_KERNEL); | ||
220 | if (!ret) | ||
221 | return NULL; | ||
222 | *ret = *report; | ||
223 | |||
224 | ret->field[0] = kmalloc(sizeof(struct hid_field), GFP_KERNEL); | ||
225 | if (!ret->field[0]) { | ||
226 | kfree(ret); | ||
227 | return NULL; | ||
228 | } | ||
229 | *ret->field[0] = *report->field[0]; | ||
230 | |||
231 | ret->field[0]->value = kmalloc(sizeof(s32[8]), GFP_KERNEL); | ||
232 | if (!ret->field[0]->value) { | ||
233 | kfree(ret->field[0]); | ||
234 | kfree(ret); | ||
235 | return NULL; | ||
236 | } | ||
237 | memset(ret->field[0]->value, 0, sizeof(s32[8])); | ||
238 | |||
239 | return ret; | ||
240 | } | ||
241 | |||
242 | static void hid_lgff_delete_report(struct hid_report* report) | ||
243 | { | ||
244 | if (report) { | ||
245 | kfree(report->field[0]->value); | ||
246 | kfree(report->field[0]); | ||
247 | kfree(report); | ||
248 | } | ||
249 | } | ||
250 | |||
251 | static void hid_lgff_input_init(struct hid_device* hid) | ||
252 | { | ||
253 | struct device_type* dev = devices; | ||
254 | signed short* ff; | ||
255 | u16 idVendor = le16_to_cpu(hid->dev->descriptor.idVendor); | ||
256 | u16 idProduct = le16_to_cpu(hid->dev->descriptor.idProduct); | ||
257 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
258 | |||
259 | while (dev->idVendor && (idVendor != dev->idVendor || idProduct != dev->idProduct)) | ||
260 | dev++; | ||
261 | |||
262 | ff = dev->ff; | ||
263 | |||
264 | while (*ff >= 0) { | ||
265 | set_bit(*ff, hidinput->input.ffbit); | ||
266 | ++ff; | ||
267 | } | ||
268 | |||
269 | hidinput->input.upload_effect = hid_lgff_upload_effect; | ||
270 | hidinput->input.flush = hid_lgff_flush; | ||
271 | |||
272 | set_bit(EV_FF, hidinput->input.evbit); | ||
273 | hidinput->input.ff_effects_max = LGFF_EFFECTS; | ||
274 | } | ||
275 | |||
276 | static void hid_lgff_exit(struct hid_device* hid) | ||
277 | { | ||
278 | struct lgff_device *lgff = hid->ff_private; | ||
279 | |||
280 | set_bit(DEVICE_CLOSING, lgff->flags); | ||
281 | del_timer_sync(&lgff->timer); | ||
282 | |||
283 | hid_lgff_delete_report(lgff->condition); | ||
284 | hid_lgff_delete_report(lgff->rumble); | ||
285 | hid_lgff_delete_report(lgff->constant); | ||
286 | |||
287 | kfree(lgff); | ||
288 | } | ||
289 | |||
290 | static int hid_lgff_event(struct hid_device *hid, struct input_dev* input, | ||
291 | unsigned int type, unsigned int code, int value) | ||
292 | { | ||
293 | struct lgff_device *lgff = hid->ff_private; | ||
294 | struct lgff_effect *effect = lgff->effects + code; | ||
295 | unsigned long flags; | ||
296 | |||
297 | if (type != EV_FF) return -EINVAL; | ||
298 | if (!LGFF_CHECK_OWNERSHIP(code, lgff)) return -EACCES; | ||
299 | if (value < 0) return -EINVAL; | ||
300 | |||
301 | spin_lock_irqsave(&lgff->lock, flags); | ||
302 | |||
303 | if (value > 0) { | ||
304 | if (test_bit(EFFECT_STARTED, effect->flags)) { | ||
305 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
306 | return -EBUSY; | ||
307 | } | ||
308 | if (test_bit(EFFECT_PLAYING, effect->flags)) { | ||
309 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
310 | return -EBUSY; | ||
311 | } | ||
312 | |||
313 | effect->count = value; | ||
314 | |||
315 | if (effect->effect.replay.delay) { | ||
316 | set_bit(EFFECT_STARTED, effect->flags); | ||
317 | } else { | ||
318 | set_bit(EFFECT_PLAYING, effect->flags); | ||
319 | } | ||
320 | effect->started_at = jiffies; | ||
321 | } | ||
322 | else { /* value == 0 */ | ||
323 | clear_bit(EFFECT_STARTED, effect->flags); | ||
324 | clear_bit(EFFECT_PLAYING, effect->flags); | ||
325 | } | ||
326 | |||
327 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
328 | |||
329 | return 0; | ||
330 | |||
331 | } | ||
332 | |||
333 | /* Erase all effects this process owns */ | ||
334 | static int hid_lgff_flush(struct input_dev *dev, struct file *file) | ||
335 | { | ||
336 | struct hid_device *hid = dev->private; | ||
337 | struct lgff_device *lgff = hid->ff_private; | ||
338 | int i; | ||
339 | |||
340 | for (i=0; i<dev->ff_effects_max; ++i) { | ||
341 | |||
342 | /*NOTE: no need to lock here. The only times EFFECT_USED is | ||
343 | modified is when effects are uploaded or when an effect is | ||
344 | erased. But a process cannot close its dev/input/eventX fd | ||
345 | and perform ioctls on the same fd all at the same time */ | ||
346 | if ( current->pid == lgff->effects[i].owner | ||
347 | && test_bit(EFFECT_USED, lgff->effects[i].flags)) { | ||
348 | |||
349 | if (hid_lgff_erase(dev, i)) | ||
350 | warn("erase effect %d failed", i); | ||
351 | } | ||
352 | |||
353 | } | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static int hid_lgff_erase(struct input_dev *dev, int id) | ||
359 | { | ||
360 | struct hid_device *hid = dev->private; | ||
361 | struct lgff_device *lgff = hid->ff_private; | ||
362 | unsigned long flags; | ||
363 | |||
364 | if (!LGFF_CHECK_OWNERSHIP(id, lgff)) return -EACCES; | ||
365 | |||
366 | spin_lock_irqsave(&lgff->lock, flags); | ||
367 | lgff->effects[id].flags[0] = 0; | ||
368 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int hid_lgff_upload_effect(struct input_dev* input, | ||
374 | struct ff_effect* effect) | ||
375 | { | ||
376 | struct hid_device *hid = input->private; | ||
377 | struct lgff_device *lgff = hid->ff_private; | ||
378 | struct lgff_effect new; | ||
379 | int id; | ||
380 | unsigned long flags; | ||
381 | |||
382 | dbg("ioctl rumble"); | ||
383 | |||
384 | if (!test_bit(effect->type, input->ffbit)) return -EINVAL; | ||
385 | |||
386 | spin_lock_irqsave(&lgff->lock, flags); | ||
387 | |||
388 | if (effect->id == -1) { | ||
389 | int i; | ||
390 | |||
391 | for (i=0; i<LGFF_EFFECTS && test_bit(EFFECT_USED, lgff->effects[i].flags); ++i); | ||
392 | if (i >= LGFF_EFFECTS) { | ||
393 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
394 | return -ENOSPC; | ||
395 | } | ||
396 | |||
397 | effect->id = i; | ||
398 | lgff->effects[i].owner = current->pid; | ||
399 | lgff->effects[i].flags[0] = 0; | ||
400 | set_bit(EFFECT_USED, lgff->effects[i].flags); | ||
401 | } | ||
402 | else if (!LGFF_CHECK_OWNERSHIP(effect->id, lgff)) { | ||
403 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
404 | return -EACCES; | ||
405 | } | ||
406 | |||
407 | id = effect->id; | ||
408 | new = lgff->effects[id]; | ||
409 | |||
410 | new.effect = *effect; | ||
411 | |||
412 | if (test_bit(EFFECT_STARTED, lgff->effects[id].flags) | ||
413 | || test_bit(EFFECT_STARTED, lgff->effects[id].flags)) { | ||
414 | |||
415 | /* Changing replay parameters is not allowed (for the time | ||
416 | being) */ | ||
417 | if (new.effect.replay.delay != lgff->effects[id].effect.replay.delay | ||
418 | || new.effect.replay.length != lgff->effects[id].effect.replay.length) { | ||
419 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
420 | return -ENOSYS; | ||
421 | } | ||
422 | |||
423 | lgff->effects[id] = new; | ||
424 | |||
425 | } else { | ||
426 | lgff->effects[id] = new; | ||
427 | } | ||
428 | |||
429 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | static void hid_lgff_timer(unsigned long timer_data) | ||
434 | { | ||
435 | struct lgff_device *lgff = (struct lgff_device*)timer_data; | ||
436 | struct hid_device *hid = lgff->hid; | ||
437 | unsigned long flags; | ||
438 | int x = 0x7f, y = 0x7f; // Coordinates of constant effects | ||
439 | unsigned int left = 0, right = 0; // Rumbling | ||
440 | int i; | ||
441 | |||
442 | spin_lock_irqsave(&lgff->lock, flags); | ||
443 | |||
444 | for (i=0; i<LGFF_EFFECTS; ++i) { | ||
445 | struct lgff_effect* effect = lgff->effects +i; | ||
446 | |||
447 | if (test_bit(EFFECT_PLAYING, effect->flags)) { | ||
448 | |||
449 | switch (effect->effect.type) { | ||
450 | case FF_CONSTANT: { | ||
451 | //TODO: handle envelopes | ||
452 | int degrees = effect->effect.direction * 360 >> 16; | ||
453 | x += fixp_mult(fixp_sin(degrees), | ||
454 | fixp_new16(effect->effect.u.constant.level)); | ||
455 | y += fixp_mult(-fixp_cos(degrees), | ||
456 | fixp_new16(effect->effect.u.constant.level)); | ||
457 | } break; | ||
458 | case FF_RUMBLE: | ||
459 | right += effect->effect.u.rumble.strong_magnitude; | ||
460 | left += effect->effect.u.rumble.weak_magnitude; | ||
461 | break; | ||
462 | }; | ||
463 | |||
464 | /* One run of the effect is finished playing */ | ||
465 | if (time_after(jiffies, | ||
466 | effect->started_at | ||
467 | + effect->effect.replay.delay*HZ/1000 | ||
468 | + effect->effect.replay.length*HZ/1000)) { | ||
469 | dbg("Finished playing once %d", i); | ||
470 | if (--effect->count <= 0) { | ||
471 | dbg("Stopped %d", i); | ||
472 | clear_bit(EFFECT_PLAYING, effect->flags); | ||
473 | } | ||
474 | else { | ||
475 | dbg("Start again %d", i); | ||
476 | if (effect->effect.replay.length != 0) { | ||
477 | clear_bit(EFFECT_PLAYING, effect->flags); | ||
478 | set_bit(EFFECT_STARTED, effect->flags); | ||
479 | } | ||
480 | effect->started_at = jiffies; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | } else if (test_bit(EFFECT_STARTED, lgff->effects[i].flags)) { | ||
485 | /* Check if we should start playing the effect */ | ||
486 | if (time_after(jiffies, | ||
487 | lgff->effects[i].started_at | ||
488 | + lgff->effects[i].effect.replay.delay*HZ/1000)) { | ||
489 | dbg("Now playing %d", i); | ||
490 | clear_bit(EFFECT_STARTED, lgff->effects[i].flags); | ||
491 | set_bit(EFFECT_PLAYING, lgff->effects[i].flags); | ||
492 | } | ||
493 | } | ||
494 | } | ||
495 | |||
496 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff | ||
497 | |||
498 | // Clamp values | ||
499 | CLAMP(x); | ||
500 | CLAMP(y); | ||
501 | CLAMP(left); | ||
502 | CLAMP(right); | ||
503 | |||
504 | #undef CLAMP | ||
505 | |||
506 | if (x != lgff->constant->field[0]->value[2] | ||
507 | || y != lgff->constant->field[0]->value[3]) { | ||
508 | lgff->constant->field[0]->value[2] = x; | ||
509 | lgff->constant->field[0]->value[3] = y; | ||
510 | dbg("(x,y)=(%04x, %04x)", x, y); | ||
511 | hid_submit_report(hid, lgff->constant, USB_DIR_OUT); | ||
512 | } | ||
513 | |||
514 | if (left != lgff->rumble->field[0]->value[2] | ||
515 | || right != lgff->rumble->field[0]->value[3]) { | ||
516 | lgff->rumble->field[0]->value[2] = left; | ||
517 | lgff->rumble->field[0]->value[3] = right; | ||
518 | dbg("(left,right)=(%04x, %04x)", left, right); | ||
519 | hid_submit_report(hid, lgff->rumble, USB_DIR_OUT); | ||
520 | } | ||
521 | |||
522 | if (!test_bit(DEVICE_CLOSING, lgff->flags)) { | ||
523 | lgff->timer.expires = RUN_AT(PERIOD); | ||
524 | add_timer(&lgff->timer); | ||
525 | } | ||
526 | |||
527 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
528 | } | ||
diff --git a/drivers/usb/input/hid-tmff.c b/drivers/usb/input/hid-tmff.c new file mode 100644 index 000000000000..8f6a0a6f94a9 --- /dev/null +++ b/drivers/usb/input/hid-tmff.c | |||
@@ -0,0 +1,463 @@ | |||
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 | #include <linux/sched.h> | ||
32 | |||
33 | #undef DEBUG | ||
34 | #include <linux/usb.h> | ||
35 | |||
36 | #include <linux/circ_buf.h> | ||
37 | |||
38 | #include "hid.h" | ||
39 | #include "fixp-arith.h" | ||
40 | |||
41 | /* Usages for thrustmaster devices I know about */ | ||
42 | #define THRUSTMASTER_USAGE_RUMBLE_LR (HID_UP_GENDESK | 0xbb) | ||
43 | #define DELAY_CALC(t,delay) ((t) + (delay)*HZ/1000) | ||
44 | |||
45 | /* Effect status */ | ||
46 | #define EFFECT_STARTED 0 /* Effect is going to play after some time */ | ||
47 | #define EFFECT_PLAYING 1 /* Effect is playing */ | ||
48 | #define EFFECT_USED 2 | ||
49 | |||
50 | /* For tmff_device::flags */ | ||
51 | #define DEVICE_CLOSING 0 /* The driver is being unitialised */ | ||
52 | |||
53 | /* Check that the current process can access an effect */ | ||
54 | #define CHECK_OWNERSHIP(effect) (current->pid == 0 \ | ||
55 | || effect.owner == current->pid) | ||
56 | |||
57 | #define TMFF_CHECK_ID(id) ((id) >= 0 && (id) < TMFF_EFFECTS) | ||
58 | |||
59 | #define TMFF_CHECK_OWNERSHIP(i, l) \ | ||
60 | (test_bit(EFFECT_USED, l->effects[i].flags) \ | ||
61 | && CHECK_OWNERSHIP(l->effects[i])) | ||
62 | |||
63 | #define TMFF_EFFECTS 8 | ||
64 | |||
65 | struct tmff_effect { | ||
66 | pid_t owner; | ||
67 | |||
68 | struct ff_effect effect; | ||
69 | |||
70 | unsigned long flags[1]; | ||
71 | unsigned int count; /* Number of times left to play */ | ||
72 | |||
73 | unsigned long play_at; /* When the effect starts to play */ | ||
74 | unsigned long stop_at; /* When the effect ends */ | ||
75 | }; | ||
76 | |||
77 | struct tmff_device { | ||
78 | struct hid_device *hid; | ||
79 | |||
80 | struct hid_report *report; | ||
81 | |||
82 | struct hid_field *rumble; | ||
83 | |||
84 | unsigned int effects_playing; | ||
85 | struct tmff_effect effects[TMFF_EFFECTS]; | ||
86 | spinlock_t lock; /* device-level lock. Having locks on | ||
87 | a per-effect basis could be nice, but | ||
88 | isn't really necessary */ | ||
89 | |||
90 | unsigned long flags[1]; /* Contains various information about the | ||
91 | state of the driver for this device */ | ||
92 | |||
93 | struct timer_list timer; | ||
94 | }; | ||
95 | |||
96 | /* Callbacks */ | ||
97 | static void hid_tmff_exit(struct hid_device *hid); | ||
98 | static int hid_tmff_event(struct hid_device *hid, struct input_dev *input, | ||
99 | unsigned int type, unsigned int code, int value); | ||
100 | static int hid_tmff_flush(struct input_dev *input, struct file *file); | ||
101 | static int hid_tmff_upload_effect(struct input_dev *input, | ||
102 | struct ff_effect *effect); | ||
103 | static int hid_tmff_erase(struct input_dev *input, int id); | ||
104 | |||
105 | /* Local functions */ | ||
106 | static void hid_tmff_recalculate_timer(struct tmff_device *tmff); | ||
107 | static void hid_tmff_timer(unsigned long timer_data); | ||
108 | |||
109 | int hid_tmff_init(struct hid_device *hid) | ||
110 | { | ||
111 | struct tmff_device *private; | ||
112 | struct list_head *pos; | ||
113 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
114 | |||
115 | private = kmalloc(sizeof(struct tmff_device), GFP_KERNEL); | ||
116 | if (!private) | ||
117 | return -ENOMEM; | ||
118 | |||
119 | memset(private, 0, sizeof(struct tmff_device)); | ||
120 | hid->ff_private = private; | ||
121 | |||
122 | /* Find the report to use */ | ||
123 | __list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) { | ||
124 | struct hid_report *report = (struct hid_report *)pos; | ||
125 | int fieldnum; | ||
126 | |||
127 | for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) { | ||
128 | struct hid_field *field = report->field[fieldnum]; | ||
129 | |||
130 | if (field->maxusage <= 0) | ||
131 | continue; | ||
132 | |||
133 | switch (field->usage[0].hid) { | ||
134 | case THRUSTMASTER_USAGE_RUMBLE_LR: | ||
135 | if (field->report_count < 2) { | ||
136 | warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with report_count < 2"); | ||
137 | continue; | ||
138 | } | ||
139 | |||
140 | if (field->logical_maximum == field->logical_minimum) { | ||
141 | warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with logical_maximum == logical_minimum"); | ||
142 | continue; | ||
143 | } | ||
144 | |||
145 | if (private->report && private->report != report) { | ||
146 | warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR in other report"); | ||
147 | continue; | ||
148 | } | ||
149 | |||
150 | if (private->rumble && private->rumble != field) { | ||
151 | warn("ignoring duplicate THRUSTMASTER_USAGE_RUMBLE_LR"); | ||
152 | continue; | ||
153 | } | ||
154 | |||
155 | private->report = report; | ||
156 | private->rumble = field; | ||
157 | |||
158 | set_bit(FF_RUMBLE, hidinput->input.ffbit); | ||
159 | break; | ||
160 | |||
161 | default: | ||
162 | warn("ignoring unknown output usage %08x", field->usage[0].hid); | ||
163 | continue; | ||
164 | } | ||
165 | |||
166 | /* Fallthrough to here only when a valid usage is found */ | ||
167 | hidinput->input.upload_effect = hid_tmff_upload_effect; | ||
168 | hidinput->input.flush = hid_tmff_flush; | ||
169 | |||
170 | set_bit(EV_FF, hidinput->input.evbit); | ||
171 | hidinput->input.ff_effects_max = TMFF_EFFECTS; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | private->hid = hid; | ||
176 | |||
177 | spin_lock_init(&private->lock); | ||
178 | init_timer(&private->timer); | ||
179 | private->timer.data = (unsigned long)private; | ||
180 | private->timer.function = hid_tmff_timer; | ||
181 | |||
182 | /* Event and exit callbacks */ | ||
183 | hid->ff_exit = hid_tmff_exit; | ||
184 | hid->ff_event = hid_tmff_event; | ||
185 | |||
186 | info("Force feedback for ThrustMaster rumble pad devices by Zinx Verituse <zinx@epicsol.org>"); | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static void hid_tmff_exit(struct hid_device *hid) | ||
192 | { | ||
193 | struct tmff_device *tmff = hid->ff_private; | ||
194 | unsigned long flags; | ||
195 | |||
196 | spin_lock_irqsave(&tmff->lock, flags); | ||
197 | |||
198 | set_bit(DEVICE_CLOSING, tmff->flags); | ||
199 | del_timer_sync(&tmff->timer); | ||
200 | |||
201 | spin_unlock_irqrestore(&tmff->lock, flags); | ||
202 | |||
203 | kfree(tmff); | ||
204 | } | ||
205 | |||
206 | static int hid_tmff_event(struct hid_device *hid, struct input_dev *input, | ||
207 | unsigned int type, unsigned int code, int value) | ||
208 | { | ||
209 | struct tmff_device *tmff = hid->ff_private; | ||
210 | struct tmff_effect *effect = &tmff->effects[code]; | ||
211 | unsigned long flags; | ||
212 | |||
213 | if (type != EV_FF) | ||
214 | return -EINVAL; | ||
215 | if (!TMFF_CHECK_ID(code)) | ||
216 | return -EINVAL; | ||
217 | if (!TMFF_CHECK_OWNERSHIP(code, tmff)) | ||
218 | return -EACCES; | ||
219 | if (value < 0) | ||
220 | return -EINVAL; | ||
221 | |||
222 | spin_lock_irqsave(&tmff->lock, flags); | ||
223 | |||
224 | if (value > 0) { | ||
225 | set_bit(EFFECT_STARTED, effect->flags); | ||
226 | clear_bit(EFFECT_PLAYING, effect->flags); | ||
227 | effect->count = value; | ||
228 | effect->play_at = DELAY_CALC(jiffies, effect->effect.replay.delay); | ||
229 | } else { | ||
230 | clear_bit(EFFECT_STARTED, effect->flags); | ||
231 | clear_bit(EFFECT_PLAYING, effect->flags); | ||
232 | } | ||
233 | |||
234 | hid_tmff_recalculate_timer(tmff); | ||
235 | |||
236 | spin_unlock_irqrestore(&tmff->lock, flags); | ||
237 | |||
238 | return 0; | ||
239 | |||
240 | } | ||
241 | |||
242 | /* Erase all effects this process owns */ | ||
243 | |||
244 | static int hid_tmff_flush(struct input_dev *dev, struct file *file) | ||
245 | { | ||
246 | struct hid_device *hid = dev->private; | ||
247 | struct tmff_device *tmff = hid->ff_private; | ||
248 | int i; | ||
249 | |||
250 | for (i=0; i<dev->ff_effects_max; ++i) | ||
251 | |||
252 | /* NOTE: no need to lock here. The only times EFFECT_USED is | ||
253 | modified is when effects are uploaded or when an effect is | ||
254 | erased. But a process cannot close its dev/input/eventX fd | ||
255 | and perform ioctls on the same fd all at the same time */ | ||
256 | |||
257 | if (current->pid == tmff->effects[i].owner | ||
258 | && test_bit(EFFECT_USED, tmff->effects[i].flags)) | ||
259 | if (hid_tmff_erase(dev, i)) | ||
260 | warn("erase effect %d failed", i); | ||
261 | |||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static int hid_tmff_erase(struct input_dev *dev, int id) | ||
267 | { | ||
268 | struct hid_device *hid = dev->private; | ||
269 | struct tmff_device *tmff = hid->ff_private; | ||
270 | unsigned long flags; | ||
271 | |||
272 | if (!TMFF_CHECK_ID(id)) | ||
273 | return -EINVAL; | ||
274 | if (!TMFF_CHECK_OWNERSHIP(id, tmff)) | ||
275 | return -EACCES; | ||
276 | |||
277 | spin_lock_irqsave(&tmff->lock, flags); | ||
278 | |||
279 | tmff->effects[id].flags[0] = 0; | ||
280 | hid_tmff_recalculate_timer(tmff); | ||
281 | |||
282 | spin_unlock_irqrestore(&tmff->lock, flags); | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | static int hid_tmff_upload_effect(struct input_dev *input, | ||
288 | struct ff_effect *effect) | ||
289 | { | ||
290 | struct hid_device *hid = input->private; | ||
291 | struct tmff_device *tmff = hid->ff_private; | ||
292 | int id; | ||
293 | unsigned long flags; | ||
294 | |||
295 | if (!test_bit(effect->type, input->ffbit)) | ||
296 | return -EINVAL; | ||
297 | if (effect->id != -1 && !TMFF_CHECK_ID(effect->id)) | ||
298 | return -EINVAL; | ||
299 | |||
300 | spin_lock_irqsave(&tmff->lock, flags); | ||
301 | |||
302 | if (effect->id == -1) { | ||
303 | /* Find a free effect */ | ||
304 | for (id = 0; id < TMFF_EFFECTS && test_bit(EFFECT_USED, tmff->effects[id].flags); ++id); | ||
305 | |||
306 | if (id >= TMFF_EFFECTS) { | ||
307 | spin_unlock_irqrestore(&tmff->lock, flags); | ||
308 | return -ENOSPC; | ||
309 | } | ||
310 | |||
311 | effect->id = id; | ||
312 | tmff->effects[id].owner = current->pid; | ||
313 | tmff->effects[id].flags[0] = 0; | ||
314 | set_bit(EFFECT_USED, tmff->effects[id].flags); | ||
315 | |||
316 | } else { | ||
317 | /* Re-uploading an owned effect, to change parameters */ | ||
318 | id = effect->id; | ||
319 | clear_bit(EFFECT_PLAYING, tmff->effects[id].flags); | ||
320 | } | ||
321 | |||
322 | tmff->effects[id].effect = *effect; | ||
323 | |||
324 | hid_tmff_recalculate_timer(tmff); | ||
325 | |||
326 | spin_unlock_irqrestore(&tmff->lock, flags); | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | /* Start the timer for the next start/stop/delay */ | ||
331 | /* Always call this while tmff->lock is locked */ | ||
332 | |||
333 | static void hid_tmff_recalculate_timer(struct tmff_device *tmff) | ||
334 | { | ||
335 | int i; | ||
336 | int events = 0; | ||
337 | unsigned long next_time; | ||
338 | |||
339 | next_time = 0; /* Shut up compiler's incorrect warning */ | ||
340 | |||
341 | /* Find the next change in an effect's status */ | ||
342 | for (i = 0; i < TMFF_EFFECTS; ++i) { | ||
343 | struct tmff_effect *effect = &tmff->effects[i]; | ||
344 | unsigned long play_time; | ||
345 | |||
346 | if (!test_bit(EFFECT_STARTED, effect->flags)) | ||
347 | continue; | ||
348 | |||
349 | effect->stop_at = DELAY_CALC(effect->play_at, effect->effect.replay.length); | ||
350 | |||
351 | if (!test_bit(EFFECT_PLAYING, effect->flags)) | ||
352 | play_time = effect->play_at; | ||
353 | else | ||
354 | play_time = effect->stop_at; | ||
355 | |||
356 | events++; | ||
357 | |||
358 | if (time_after(jiffies, play_time)) | ||
359 | play_time = jiffies; | ||
360 | |||
361 | if (events == 1) | ||
362 | next_time = play_time; | ||
363 | else { | ||
364 | if (time_after(next_time, play_time)) | ||
365 | next_time = play_time; | ||
366 | } | ||
367 | } | ||
368 | |||
369 | if (!events && tmff->effects_playing) { | ||
370 | /* Treat all effects turning off as an event */ | ||
371 | events = 1; | ||
372 | next_time = jiffies; | ||
373 | } | ||
374 | |||
375 | if (!events) { | ||
376 | /* No events, no time, no need for a timer. */ | ||
377 | del_timer_sync(&tmff->timer); | ||
378 | return; | ||
379 | } | ||
380 | |||
381 | mod_timer(&tmff->timer, next_time); | ||
382 | } | ||
383 | |||
384 | /* Changes values from 0 to 0xffff into values from minimum to maximum */ | ||
385 | static inline int hid_tmff_scale(unsigned int in, int minimum, int maximum) | ||
386 | { | ||
387 | int ret; | ||
388 | |||
389 | ret = (in * (maximum - minimum) / 0xffff) + minimum; | ||
390 | if (ret < minimum) | ||
391 | return minimum; | ||
392 | if (ret > maximum) | ||
393 | return maximum; | ||
394 | return ret; | ||
395 | } | ||
396 | |||
397 | static void hid_tmff_timer(unsigned long timer_data) | ||
398 | { | ||
399 | struct tmff_device *tmff = (struct tmff_device *) timer_data; | ||
400 | struct hid_device *hid = tmff->hid; | ||
401 | unsigned long flags; | ||
402 | int left = 0, right = 0; /* Rumbling */ | ||
403 | int i; | ||
404 | |||
405 | spin_lock_irqsave(&tmff->lock, flags); | ||
406 | |||
407 | tmff->effects_playing = 0; | ||
408 | |||
409 | for (i = 0; i < TMFF_EFFECTS; ++i) { | ||
410 | struct tmff_effect *effect = &tmff->effects[i]; | ||
411 | |||
412 | if (!test_bit(EFFECT_STARTED, effect->flags)) | ||
413 | continue; | ||
414 | |||
415 | if (!time_after(jiffies, effect->play_at)) | ||
416 | continue; | ||
417 | |||
418 | if (time_after(jiffies, effect->stop_at)) { | ||
419 | |||
420 | dbg("Finished playing once %d", i); | ||
421 | clear_bit(EFFECT_PLAYING, effect->flags); | ||
422 | |||
423 | if (--effect->count <= 0) { | ||
424 | dbg("Stopped %d", i); | ||
425 | clear_bit(EFFECT_STARTED, effect->flags); | ||
426 | continue; | ||
427 | } else { | ||
428 | dbg("Start again %d", i); | ||
429 | effect->play_at = DELAY_CALC(jiffies, effect->effect.replay.delay); | ||
430 | continue; | ||
431 | } | ||
432 | } | ||
433 | |||
434 | ++tmff->effects_playing; | ||
435 | |||
436 | set_bit(EFFECT_PLAYING, effect->flags); | ||
437 | |||
438 | switch (effect->effect.type) { | ||
439 | case FF_RUMBLE: | ||
440 | right += effect->effect.u.rumble.strong_magnitude; | ||
441 | left += effect->effect.u.rumble.weak_magnitude; | ||
442 | break; | ||
443 | default: | ||
444 | BUG(); | ||
445 | break; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | left = hid_tmff_scale(left, tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); | ||
450 | right = hid_tmff_scale(right, tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); | ||
451 | |||
452 | if (left != tmff->rumble->value[0] || right != tmff->rumble->value[1]) { | ||
453 | tmff->rumble->value[0] = left; | ||
454 | tmff->rumble->value[1] = right; | ||
455 | dbg("(left,right)=(%08x, %08x)", left, right); | ||
456 | hid_submit_report(hid, tmff->report, USB_DIR_OUT); | ||
457 | } | ||
458 | |||
459 | if (!test_bit(DEVICE_CLOSING, tmff->flags)) | ||
460 | hid_tmff_recalculate_timer(tmff); | ||
461 | |||
462 | spin_unlock_irqrestore(&tmff->lock, flags); | ||
463 | } | ||
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h new file mode 100644 index 000000000000..6d9329c698d9 --- /dev/null +++ b/drivers/usb/input/hid.h | |||
@@ -0,0 +1,510 @@ | |||
1 | #ifndef __HID_H | ||
2 | #define __HID_H | ||
3 | |||
4 | /* | ||
5 | * $Id: hid.h,v 1.24 2001/12/27 10:37:41 vojtech Exp $ | ||
6 | * | ||
7 | * Copyright (c) 1999 Andreas Gal | ||
8 | * Copyright (c) 2000-2001 Vojtech Pavlik | ||
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 either by | ||
27 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
28 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
29 | */ | ||
30 | |||
31 | #include <linux/types.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/list.h> | ||
34 | |||
35 | /* | ||
36 | * USB HID (Human Interface Device) interface class code | ||
37 | */ | ||
38 | |||
39 | #define USB_INTERFACE_CLASS_HID 3 | ||
40 | |||
41 | /* | ||
42 | * HID class requests | ||
43 | */ | ||
44 | |||
45 | #define HID_REQ_GET_REPORT 0x01 | ||
46 | #define HID_REQ_GET_IDLE 0x02 | ||
47 | #define HID_REQ_GET_PROTOCOL 0x03 | ||
48 | #define HID_REQ_SET_REPORT 0x09 | ||
49 | #define HID_REQ_SET_IDLE 0x0A | ||
50 | #define HID_REQ_SET_PROTOCOL 0x0B | ||
51 | |||
52 | /* | ||
53 | * HID class descriptor types | ||
54 | */ | ||
55 | |||
56 | #define HID_DT_HID (USB_TYPE_CLASS | 0x01) | ||
57 | #define HID_DT_REPORT (USB_TYPE_CLASS | 0x02) | ||
58 | #define HID_DT_PHYSICAL (USB_TYPE_CLASS | 0x03) | ||
59 | |||
60 | /* | ||
61 | * We parse each description item into this structure. Short items data | ||
62 | * values are expanded to 32-bit signed int, long items contain a pointer | ||
63 | * into the data area. | ||
64 | */ | ||
65 | |||
66 | struct hid_item { | ||
67 | unsigned format; | ||
68 | __u8 size; | ||
69 | __u8 type; | ||
70 | __u8 tag; | ||
71 | union { | ||
72 | __u8 u8; | ||
73 | __s8 s8; | ||
74 | __u16 u16; | ||
75 | __s16 s16; | ||
76 | __u32 u32; | ||
77 | __s32 s32; | ||
78 | __u8 *longdata; | ||
79 | } data; | ||
80 | }; | ||
81 | |||
82 | /* | ||
83 | * HID report item format | ||
84 | */ | ||
85 | |||
86 | #define HID_ITEM_FORMAT_SHORT 0 | ||
87 | #define HID_ITEM_FORMAT_LONG 1 | ||
88 | |||
89 | /* | ||
90 | * Special tag indicating long items | ||
91 | */ | ||
92 | |||
93 | #define HID_ITEM_TAG_LONG 15 | ||
94 | |||
95 | /* | ||
96 | * HID report descriptor item type (prefix bit 2,3) | ||
97 | */ | ||
98 | |||
99 | #define HID_ITEM_TYPE_MAIN 0 | ||
100 | #define HID_ITEM_TYPE_GLOBAL 1 | ||
101 | #define HID_ITEM_TYPE_LOCAL 2 | ||
102 | #define HID_ITEM_TYPE_RESERVED 3 | ||
103 | |||
104 | /* | ||
105 | * HID report descriptor main item tags | ||
106 | */ | ||
107 | |||
108 | #define HID_MAIN_ITEM_TAG_INPUT 8 | ||
109 | #define HID_MAIN_ITEM_TAG_OUTPUT 9 | ||
110 | #define HID_MAIN_ITEM_TAG_FEATURE 11 | ||
111 | #define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION 10 | ||
112 | #define HID_MAIN_ITEM_TAG_END_COLLECTION 12 | ||
113 | |||
114 | /* | ||
115 | * HID report descriptor main item contents | ||
116 | */ | ||
117 | |||
118 | #define HID_MAIN_ITEM_CONSTANT 0x001 | ||
119 | #define HID_MAIN_ITEM_VARIABLE 0x002 | ||
120 | #define HID_MAIN_ITEM_RELATIVE 0x004 | ||
121 | #define HID_MAIN_ITEM_WRAP 0x008 | ||
122 | #define HID_MAIN_ITEM_NONLINEAR 0x010 | ||
123 | #define HID_MAIN_ITEM_NO_PREFERRED 0x020 | ||
124 | #define HID_MAIN_ITEM_NULL_STATE 0x040 | ||
125 | #define HID_MAIN_ITEM_VOLATILE 0x080 | ||
126 | #define HID_MAIN_ITEM_BUFFERED_BYTE 0x100 | ||
127 | |||
128 | /* | ||
129 | * HID report descriptor collection item types | ||
130 | */ | ||
131 | |||
132 | #define HID_COLLECTION_PHYSICAL 0 | ||
133 | #define HID_COLLECTION_APPLICATION 1 | ||
134 | #define HID_COLLECTION_LOGICAL 2 | ||
135 | |||
136 | /* | ||
137 | * HID report descriptor global item tags | ||
138 | */ | ||
139 | |||
140 | #define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0 | ||
141 | #define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM 1 | ||
142 | #define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM 2 | ||
143 | #define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM 3 | ||
144 | #define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM 4 | ||
145 | #define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 5 | ||
146 | #define HID_GLOBAL_ITEM_TAG_UNIT 6 | ||
147 | #define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 7 | ||
148 | #define HID_GLOBAL_ITEM_TAG_REPORT_ID 8 | ||
149 | #define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 9 | ||
150 | #define HID_GLOBAL_ITEM_TAG_PUSH 10 | ||
151 | #define HID_GLOBAL_ITEM_TAG_POP 11 | ||
152 | |||
153 | /* | ||
154 | * HID report descriptor local item tags | ||
155 | */ | ||
156 | |||
157 | #define HID_LOCAL_ITEM_TAG_USAGE 0 | ||
158 | #define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM 1 | ||
159 | #define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM 2 | ||
160 | #define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 3 | ||
161 | #define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM 4 | ||
162 | #define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM 5 | ||
163 | #define HID_LOCAL_ITEM_TAG_STRING_INDEX 7 | ||
164 | #define HID_LOCAL_ITEM_TAG_STRING_MINIMUM 8 | ||
165 | #define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM 9 | ||
166 | #define HID_LOCAL_ITEM_TAG_DELIMITER 10 | ||
167 | |||
168 | /* | ||
169 | * HID usage tables | ||
170 | */ | ||
171 | |||
172 | #define HID_USAGE_PAGE 0xffff0000 | ||
173 | |||
174 | #define HID_UP_UNDEFINED 0x00000000 | ||
175 | #define HID_UP_GENDESK 0x00010000 | ||
176 | #define HID_UP_KEYBOARD 0x00070000 | ||
177 | #define HID_UP_LED 0x00080000 | ||
178 | #define HID_UP_BUTTON 0x00090000 | ||
179 | #define HID_UP_ORDINAL 0x000a0000 | ||
180 | #define HID_UP_CONSUMER 0x000c0000 | ||
181 | #define HID_UP_DIGITIZER 0x000d0000 | ||
182 | #define HID_UP_PID 0x000f0000 | ||
183 | #define HID_UP_HPVENDOR 0xff7f0000 | ||
184 | #define HID_UP_MSVENDOR 0xff000000 | ||
185 | |||
186 | #define HID_USAGE 0x0000ffff | ||
187 | |||
188 | #define HID_GD_POINTER 0x00010001 | ||
189 | #define HID_GD_MOUSE 0x00010002 | ||
190 | #define HID_GD_JOYSTICK 0x00010004 | ||
191 | #define HID_GD_GAMEPAD 0x00010005 | ||
192 | #define HID_GD_KEYBOARD 0x00010006 | ||
193 | #define HID_GD_KEYPAD 0x00010007 | ||
194 | #define HID_GD_MULTIAXIS 0x00010008 | ||
195 | #define HID_GD_X 0x00010030 | ||
196 | #define HID_GD_Y 0x00010031 | ||
197 | #define HID_GD_Z 0x00010032 | ||
198 | #define HID_GD_RX 0x00010033 | ||
199 | #define HID_GD_RY 0x00010034 | ||
200 | #define HID_GD_RZ 0x00010035 | ||
201 | #define HID_GD_SLIDER 0x00010036 | ||
202 | #define HID_GD_DIAL 0x00010037 | ||
203 | #define HID_GD_WHEEL 0x00010038 | ||
204 | #define HID_GD_HATSWITCH 0x00010039 | ||
205 | #define HID_GD_BUFFER 0x0001003a | ||
206 | #define HID_GD_BYTECOUNT 0x0001003b | ||
207 | #define HID_GD_MOTION 0x0001003c | ||
208 | #define HID_GD_START 0x0001003d | ||
209 | #define HID_GD_SELECT 0x0001003e | ||
210 | #define HID_GD_VX 0x00010040 | ||
211 | #define HID_GD_VY 0x00010041 | ||
212 | #define HID_GD_VZ 0x00010042 | ||
213 | #define HID_GD_VBRX 0x00010043 | ||
214 | #define HID_GD_VBRY 0x00010044 | ||
215 | #define HID_GD_VBRZ 0x00010045 | ||
216 | #define HID_GD_VNO 0x00010046 | ||
217 | #define HID_GD_FEATURE 0x00010047 | ||
218 | #define HID_GD_UP 0x00010090 | ||
219 | #define HID_GD_DOWN 0x00010091 | ||
220 | #define HID_GD_RIGHT 0x00010092 | ||
221 | #define HID_GD_LEFT 0x00010093 | ||
222 | |||
223 | /* | ||
224 | * HID report types --- Ouch! HID spec says 1 2 3! | ||
225 | */ | ||
226 | |||
227 | #define HID_INPUT_REPORT 0 | ||
228 | #define HID_OUTPUT_REPORT 1 | ||
229 | #define HID_FEATURE_REPORT 2 | ||
230 | |||
231 | /* | ||
232 | * HID device quirks. | ||
233 | */ | ||
234 | |||
235 | #define HID_QUIRK_INVERT 0x001 | ||
236 | #define HID_QUIRK_NOTOUCH 0x002 | ||
237 | #define HID_QUIRK_IGNORE 0x004 | ||
238 | #define HID_QUIRK_NOGET 0x008 | ||
239 | #define HID_QUIRK_HIDDEV 0x010 | ||
240 | #define HID_QUIRK_BADPAD 0x020 | ||
241 | #define HID_QUIRK_MULTI_INPUT 0x040 | ||
242 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080 | ||
243 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100 | ||
244 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200 | ||
245 | |||
246 | /* | ||
247 | * This is the global environment of the parser. This information is | ||
248 | * persistent for main-items. The global environment can be saved and | ||
249 | * restored with PUSH/POP statements. | ||
250 | */ | ||
251 | |||
252 | struct hid_global { | ||
253 | unsigned usage_page; | ||
254 | __s32 logical_minimum; | ||
255 | __s32 logical_maximum; | ||
256 | __s32 physical_minimum; | ||
257 | __s32 physical_maximum; | ||
258 | __s32 unit_exponent; | ||
259 | unsigned unit; | ||
260 | unsigned report_id; | ||
261 | unsigned report_size; | ||
262 | unsigned report_count; | ||
263 | }; | ||
264 | |||
265 | /* | ||
266 | * This is the local environment. It is persistent up the next main-item. | ||
267 | */ | ||
268 | |||
269 | #define HID_MAX_DESCRIPTOR_SIZE 4096 | ||
270 | #define HID_MAX_USAGES 1024 | ||
271 | #define HID_DEFAULT_NUM_COLLECTIONS 16 | ||
272 | |||
273 | struct hid_local { | ||
274 | unsigned usage[HID_MAX_USAGES]; /* usage array */ | ||
275 | unsigned collection_index[HID_MAX_USAGES]; /* collection index array */ | ||
276 | unsigned usage_index; | ||
277 | unsigned usage_minimum; | ||
278 | unsigned delimiter_depth; | ||
279 | unsigned delimiter_branch; | ||
280 | }; | ||
281 | |||
282 | /* | ||
283 | * This is the collection stack. We climb up the stack to determine | ||
284 | * application and function of each field. | ||
285 | */ | ||
286 | |||
287 | struct hid_collection { | ||
288 | unsigned type; | ||
289 | unsigned usage; | ||
290 | unsigned level; | ||
291 | }; | ||
292 | |||
293 | struct hid_usage { | ||
294 | unsigned hid; /* hid usage code */ | ||
295 | unsigned collection_index; /* index into collection array */ | ||
296 | /* hidinput data */ | ||
297 | __u16 code; /* input driver code */ | ||
298 | __u8 type; /* input driver type */ | ||
299 | __s8 hat_min; /* hat switch fun */ | ||
300 | __s8 hat_max; /* ditto */ | ||
301 | __s8 hat_dir; /* ditto */ | ||
302 | }; | ||
303 | |||
304 | struct hid_input; | ||
305 | |||
306 | struct hid_field { | ||
307 | unsigned physical; /* physical usage for this field */ | ||
308 | unsigned logical; /* logical usage for this field */ | ||
309 | unsigned application; /* application usage for this field */ | ||
310 | struct hid_usage *usage; /* usage table for this function */ | ||
311 | unsigned maxusage; /* maximum usage index */ | ||
312 | unsigned flags; /* main-item flags (i.e. volatile,array,constant) */ | ||
313 | unsigned report_offset; /* bit offset in the report */ | ||
314 | unsigned report_size; /* size of this field in the report */ | ||
315 | unsigned report_count; /* number of this field in the report */ | ||
316 | unsigned report_type; /* (input,output,feature) */ | ||
317 | __s32 *value; /* last known value(s) */ | ||
318 | __s32 logical_minimum; | ||
319 | __s32 logical_maximum; | ||
320 | __s32 physical_minimum; | ||
321 | __s32 physical_maximum; | ||
322 | __s32 unit_exponent; | ||
323 | unsigned unit; | ||
324 | struct hid_report *report; /* associated report */ | ||
325 | unsigned index; /* index into report->field[] */ | ||
326 | /* hidinput data */ | ||
327 | struct hid_input *hidinput; /* associated input structure */ | ||
328 | __u16 dpad; /* dpad input code */ | ||
329 | }; | ||
330 | |||
331 | #define HID_MAX_FIELDS 64 | ||
332 | |||
333 | struct hid_report { | ||
334 | struct list_head list; | ||
335 | unsigned id; /* id of this report */ | ||
336 | unsigned type; /* report type */ | ||
337 | struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */ | ||
338 | unsigned maxfield; /* maximum valid field index */ | ||
339 | unsigned size; /* size of the report (bits) */ | ||
340 | struct hid_device *device; /* associated device */ | ||
341 | }; | ||
342 | |||
343 | struct hid_report_enum { | ||
344 | unsigned numbered; | ||
345 | struct list_head report_list; | ||
346 | struct hid_report *report_id_hash[256]; | ||
347 | }; | ||
348 | |||
349 | #define HID_REPORT_TYPES 3 | ||
350 | |||
351 | #define HID_BUFFER_SIZE 64 /* use 64 for compatibility with all possible packetlen */ | ||
352 | #define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */ | ||
353 | #define HID_OUTPUT_FIFO_SIZE 64 | ||
354 | |||
355 | struct hid_control_fifo { | ||
356 | unsigned char dir; | ||
357 | struct hid_report *report; | ||
358 | }; | ||
359 | |||
360 | #define HID_CLAIMED_INPUT 1 | ||
361 | #define HID_CLAIMED_HIDDEV 2 | ||
362 | |||
363 | #define HID_CTRL_RUNNING 1 | ||
364 | #define HID_OUT_RUNNING 2 | ||
365 | |||
366 | struct hid_input { | ||
367 | struct list_head list; | ||
368 | struct hid_report *report; | ||
369 | struct input_dev input; | ||
370 | }; | ||
371 | |||
372 | struct hid_device { /* device report descriptor */ | ||
373 | __u8 *rdesc; | ||
374 | unsigned rsize; | ||
375 | struct hid_collection *collection; /* List of HID collections */ | ||
376 | unsigned collection_size; /* Number of allocated hid_collections */ | ||
377 | unsigned maxcollection; /* Number of parsed collections */ | ||
378 | unsigned maxapplication; /* Number of applications */ | ||
379 | unsigned version; /* HID version */ | ||
380 | unsigned country; /* HID country */ | ||
381 | struct hid_report_enum report_enum[HID_REPORT_TYPES]; | ||
382 | |||
383 | struct usb_device *dev; /* USB device */ | ||
384 | struct usb_interface *intf; /* USB interface */ | ||
385 | int ifnum; /* USB interface number */ | ||
386 | |||
387 | unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ | ||
388 | |||
389 | struct urb *urbin; /* Input URB */ | ||
390 | char *inbuf; /* Input buffer */ | ||
391 | dma_addr_t inbuf_dma; /* Input buffer dma */ | ||
392 | |||
393 | struct urb *urbctrl; /* Control URB */ | ||
394 | struct usb_ctrlrequest *cr; /* Control request struct */ | ||
395 | dma_addr_t cr_dma; /* Control request struct dma */ | ||
396 | struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */ | ||
397 | unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */ | ||
398 | char *ctrlbuf; /* Control buffer */ | ||
399 | dma_addr_t ctrlbuf_dma; /* Control buffer dma */ | ||
400 | spinlock_t ctrllock; /* Control fifo spinlock */ | ||
401 | |||
402 | struct urb *urbout; /* Output URB */ | ||
403 | struct hid_report *out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */ | ||
404 | unsigned char outhead, outtail; /* Output pipe fifo head & tail */ | ||
405 | char *outbuf; /* Output buffer */ | ||
406 | dma_addr_t outbuf_dma; /* Output buffer dma */ | ||
407 | spinlock_t outlock; /* Output fifo spinlock */ | ||
408 | |||
409 | unsigned claimed; /* Claimed by hidinput, hiddev? */ | ||
410 | unsigned quirks; /* Various quirks the device can pull on us */ | ||
411 | |||
412 | struct list_head inputs; /* The list of inputs */ | ||
413 | void *hiddev; /* The hiddev structure */ | ||
414 | int minor; /* Hiddev minor number */ | ||
415 | |||
416 | wait_queue_head_t wait; /* For sleeping */ | ||
417 | |||
418 | int open; /* is the device open by anyone? */ | ||
419 | char name[128]; /* Device name */ | ||
420 | char phys[64]; /* Device physical location */ | ||
421 | char uniq[64]; /* Device unique identifier (serial #) */ | ||
422 | |||
423 | void *ff_private; /* Private data for the force-feedback driver */ | ||
424 | void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */ | ||
425 | int (*ff_event)(struct hid_device *hid, struct input_dev *input, | ||
426 | unsigned int type, unsigned int code, int value); | ||
427 | }; | ||
428 | |||
429 | #define HID_GLOBAL_STACK_SIZE 4 | ||
430 | #define HID_COLLECTION_STACK_SIZE 4 | ||
431 | |||
432 | struct hid_parser { | ||
433 | struct hid_global global; | ||
434 | struct hid_global global_stack[HID_GLOBAL_STACK_SIZE]; | ||
435 | unsigned global_stack_ptr; | ||
436 | struct hid_local local; | ||
437 | unsigned collection_stack[HID_COLLECTION_STACK_SIZE]; | ||
438 | unsigned collection_stack_ptr; | ||
439 | struct hid_device *device; | ||
440 | }; | ||
441 | |||
442 | struct hid_class_descriptor { | ||
443 | __u8 bDescriptorType; | ||
444 | __u16 wDescriptorLength; | ||
445 | } __attribute__ ((packed)); | ||
446 | |||
447 | struct hid_descriptor { | ||
448 | __u8 bLength; | ||
449 | __u8 bDescriptorType; | ||
450 | __u16 bcdHID; | ||
451 | __u8 bCountryCode; | ||
452 | __u8 bNumDescriptors; | ||
453 | |||
454 | struct hid_class_descriptor desc[1]; | ||
455 | } __attribute__ ((packed)); | ||
456 | |||
457 | #ifdef DEBUG | ||
458 | #include "hid-debug.h" | ||
459 | #else | ||
460 | #define hid_dump_input(a,b) do { } while (0) | ||
461 | #define hid_dump_device(c) do { } while (0) | ||
462 | #define hid_dump_field(a,b) do { } while (0) | ||
463 | #define resolv_usage(a) do { } while (0) | ||
464 | #define resolv_event(a,b) do { } while (0) | ||
465 | #endif | ||
466 | |||
467 | #endif | ||
468 | |||
469 | #ifdef CONFIG_USB_HIDINPUT | ||
470 | /* Applications from HID Usage Tables 4/8/99 Version 1.1 */ | ||
471 | /* We ignore a few input applications that are not widely used */ | ||
472 | #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001)) | ||
473 | extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32, struct pt_regs *regs); | ||
474 | extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report); | ||
475 | extern int hidinput_connect(struct hid_device *); | ||
476 | extern void hidinput_disconnect(struct hid_device *); | ||
477 | #else | ||
478 | #define IS_INPUT_APPLICATION(a) (0) | ||
479 | static inline void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, struct pt_regs *regs) { } | ||
480 | static inline void hidinput_report_event(struct hid_device *hid, struct hid_report *report) { } | ||
481 | static inline int hidinput_connect(struct hid_device *hid) { return -ENODEV; } | ||
482 | static inline void hidinput_disconnect(struct hid_device *hid) { } | ||
483 | #endif | ||
484 | |||
485 | int hid_open(struct hid_device *); | ||
486 | void hid_close(struct hid_device *); | ||
487 | int hid_set_field(struct hid_field *, unsigned, __s32); | ||
488 | void hid_submit_report(struct hid_device *, struct hid_report *, unsigned char dir); | ||
489 | void hid_init_reports(struct hid_device *hid); | ||
490 | struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type); | ||
491 | int hid_wait_io(struct hid_device* hid); | ||
492 | |||
493 | |||
494 | #ifdef CONFIG_HID_FF | ||
495 | int hid_ff_init(struct hid_device *hid); | ||
496 | #else | ||
497 | static inline int hid_ff_init(struct hid_device *hid) { return -1; } | ||
498 | #endif | ||
499 | static inline void hid_ff_exit(struct hid_device *hid) | ||
500 | { | ||
501 | if (hid->ff_exit) | ||
502 | hid->ff_exit(hid); | ||
503 | } | ||
504 | static inline int hid_ff_event(struct hid_device *hid, struct input_dev *input, | ||
505 | unsigned int type, unsigned int code, int value) | ||
506 | { | ||
507 | if (hid->ff_event) | ||
508 | return hid->ff_event(hid, input, type, code, value); | ||
509 | return -ENOSYS; | ||
510 | } | ||
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c new file mode 100644 index 000000000000..96b7c9067951 --- /dev/null +++ b/drivers/usb/input/hiddev.c | |||
@@ -0,0 +1,844 @@ | |||
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/config.h> | ||
29 | #include <linux/poll.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/smp_lock.h> | ||
34 | #include <linux/input.h> | ||
35 | #include <linux/usb.h> | ||
36 | #include "hid.h" | ||
37 | #include <linux/hiddev.h> | ||
38 | #include <linux/devfs_fs_kernel.h> | ||
39 | |||
40 | #ifdef CONFIG_USB_DYNAMIC_MINORS | ||
41 | #define HIDDEV_MINOR_BASE 0 | ||
42 | #define HIDDEV_MINORS 256 | ||
43 | #else | ||
44 | #define HIDDEV_MINOR_BASE 96 | ||
45 | #define HIDDEV_MINORS 16 | ||
46 | #endif | ||
47 | #define HIDDEV_BUFFER_SIZE 64 | ||
48 | |||
49 | struct hiddev { | ||
50 | int exist; | ||
51 | int open; | ||
52 | wait_queue_head_t wait; | ||
53 | struct hid_device *hid; | ||
54 | struct hiddev_list *list; | ||
55 | }; | ||
56 | |||
57 | struct hiddev_list { | ||
58 | struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE]; | ||
59 | int head; | ||
60 | int tail; | ||
61 | unsigned flags; | ||
62 | struct fasync_struct *fasync; | ||
63 | struct hiddev *hiddev; | ||
64 | struct hiddev_list *next; | ||
65 | }; | ||
66 | |||
67 | static struct hiddev *hiddev_table[HIDDEV_MINORS]; | ||
68 | |||
69 | /* | ||
70 | * Find a report, given the report's type and ID. The ID can be specified | ||
71 | * indirectly by REPORT_ID_FIRST (which returns the first report of the given | ||
72 | * type) or by (REPORT_ID_NEXT | old_id), which returns the next report of the | ||
73 | * given type which follows old_id. | ||
74 | */ | ||
75 | static struct hid_report * | ||
76 | hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) | ||
77 | { | ||
78 | unsigned flags = rinfo->report_id & ~HID_REPORT_ID_MASK; | ||
79 | struct hid_report_enum *report_enum; | ||
80 | struct list_head *list; | ||
81 | |||
82 | if (rinfo->report_type < HID_REPORT_TYPE_MIN || | ||
83 | rinfo->report_type > HID_REPORT_TYPE_MAX) return NULL; | ||
84 | |||
85 | report_enum = hid->report_enum + | ||
86 | (rinfo->report_type - HID_REPORT_TYPE_MIN); | ||
87 | |||
88 | switch (flags) { | ||
89 | case 0: /* Nothing to do -- report_id is already set correctly */ | ||
90 | break; | ||
91 | |||
92 | case HID_REPORT_ID_FIRST: | ||
93 | list = report_enum->report_list.next; | ||
94 | if (list == &report_enum->report_list) | ||
95 | return NULL; | ||
96 | rinfo->report_id = ((struct hid_report *) list)->id; | ||
97 | break; | ||
98 | |||
99 | case HID_REPORT_ID_NEXT: | ||
100 | list = (struct list_head *) | ||
101 | report_enum->report_id_hash[rinfo->report_id & HID_REPORT_ID_MASK]; | ||
102 | if (list == NULL) | ||
103 | return NULL; | ||
104 | list = list->next; | ||
105 | if (list == &report_enum->report_list) | ||
106 | return NULL; | ||
107 | rinfo->report_id = ((struct hid_report *) list)->id; | ||
108 | break; | ||
109 | |||
110 | default: | ||
111 | return NULL; | ||
112 | } | ||
113 | |||
114 | return report_enum->report_id_hash[rinfo->report_id]; | ||
115 | } | ||
116 | |||
117 | /* | ||
118 | * Perform an exhaustive search of the report table for a usage, given its | ||
119 | * type and usage id. | ||
120 | */ | ||
121 | static struct hid_field * | ||
122 | hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) | ||
123 | { | ||
124 | int i, j; | ||
125 | struct hid_report *report; | ||
126 | struct hid_report_enum *report_enum; | ||
127 | struct hid_field *field; | ||
128 | |||
129 | if (uref->report_type < HID_REPORT_TYPE_MIN || | ||
130 | uref->report_type > HID_REPORT_TYPE_MAX) return NULL; | ||
131 | |||
132 | report_enum = hid->report_enum + | ||
133 | (uref->report_type - HID_REPORT_TYPE_MIN); | ||
134 | |||
135 | list_for_each_entry(report, &report_enum->report_list, list) | ||
136 | for (i = 0; i < report->maxfield; i++) { | ||
137 | field = report->field[i]; | ||
138 | for (j = 0; j < field->maxusage; j++) { | ||
139 | if (field->usage[j].hid == uref->usage_code) { | ||
140 | uref->report_id = report->id; | ||
141 | uref->field_index = i; | ||
142 | uref->usage_index = j; | ||
143 | return field; | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | |||
148 | return NULL; | ||
149 | } | ||
150 | |||
151 | static void hiddev_send_event(struct hid_device *hid, | ||
152 | struct hiddev_usage_ref *uref) | ||
153 | { | ||
154 | struct hiddev *hiddev = hid->hiddev; | ||
155 | struct hiddev_list *list = hiddev->list; | ||
156 | |||
157 | while (list) { | ||
158 | if (uref->field_index != HID_FIELD_INDEX_NONE || | ||
159 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { | ||
160 | list->buffer[list->head] = *uref; | ||
161 | list->head = (list->head + 1) & | ||
162 | (HIDDEV_BUFFER_SIZE - 1); | ||
163 | kill_fasync(&list->fasync, SIGIO, POLL_IN); | ||
164 | } | ||
165 | |||
166 | list = list->next; | ||
167 | } | ||
168 | |||
169 | wake_up_interruptible(&hiddev->wait); | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * This is where hid.c calls into hiddev to pass an event that occurred over | ||
174 | * the interrupt pipe | ||
175 | */ | ||
176 | void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, | ||
177 | struct hid_usage *usage, __s32 value, struct pt_regs *regs) | ||
178 | { | ||
179 | unsigned type = field->report_type; | ||
180 | struct hiddev_usage_ref uref; | ||
181 | |||
182 | uref.report_type = | ||
183 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | ||
184 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | ||
185 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); | ||
186 | uref.report_id = field->report->id; | ||
187 | uref.field_index = field->index; | ||
188 | uref.usage_index = (usage - field->usage); | ||
189 | uref.usage_code = usage->hid; | ||
190 | uref.value = value; | ||
191 | |||
192 | hiddev_send_event(hid, &uref); | ||
193 | } | ||
194 | |||
195 | |||
196 | void hiddev_report_event(struct hid_device *hid, struct hid_report *report) | ||
197 | { | ||
198 | unsigned type = report->type; | ||
199 | struct hiddev_usage_ref uref; | ||
200 | |||
201 | memset(&uref, 0, sizeof(uref)); | ||
202 | uref.report_type = | ||
203 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | ||
204 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | ||
205 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); | ||
206 | uref.report_id = report->id; | ||
207 | uref.field_index = HID_FIELD_INDEX_NONE; | ||
208 | |||
209 | hiddev_send_event(hid, &uref); | ||
210 | } | ||
211 | /* | ||
212 | * fasync file op | ||
213 | */ | ||
214 | static int hiddev_fasync(int fd, struct file *file, int on) | ||
215 | { | ||
216 | int retval; | ||
217 | struct hiddev_list *list = file->private_data; | ||
218 | retval = fasync_helper(fd, file, on, &list->fasync); | ||
219 | return retval < 0 ? retval : 0; | ||
220 | } | ||
221 | |||
222 | |||
223 | /* | ||
224 | * release file op | ||
225 | */ | ||
226 | static int hiddev_release(struct inode * inode, struct file * file) | ||
227 | { | ||
228 | struct hiddev_list *list = file->private_data; | ||
229 | struct hiddev_list **listptr; | ||
230 | |||
231 | listptr = &list->hiddev->list; | ||
232 | hiddev_fasync(-1, file, 0); | ||
233 | |||
234 | while (*listptr && (*listptr != list)) | ||
235 | listptr = &((*listptr)->next); | ||
236 | *listptr = (*listptr)->next; | ||
237 | |||
238 | if (!--list->hiddev->open) { | ||
239 | if (list->hiddev->exist) | ||
240 | hid_close(list->hiddev->hid); | ||
241 | else | ||
242 | kfree(list->hiddev); | ||
243 | } | ||
244 | |||
245 | kfree(list); | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * open file op | ||
252 | */ | ||
253 | static int hiddev_open(struct inode * inode, struct file * file) { | ||
254 | struct hiddev_list *list; | ||
255 | |||
256 | int i = iminor(inode) - HIDDEV_MINOR_BASE; | ||
257 | |||
258 | if (i >= HIDDEV_MINORS || !hiddev_table[i]) | ||
259 | return -ENODEV; | ||
260 | |||
261 | if (!(list = kmalloc(sizeof(struct hiddev_list), GFP_KERNEL))) | ||
262 | return -ENOMEM; | ||
263 | memset(list, 0, sizeof(struct hiddev_list)); | ||
264 | |||
265 | list->hiddev = hiddev_table[i]; | ||
266 | list->next = hiddev_table[i]->list; | ||
267 | hiddev_table[i]->list = list; | ||
268 | |||
269 | file->private_data = list; | ||
270 | |||
271 | if (!list->hiddev->open++) | ||
272 | if (list->hiddev->exist) | ||
273 | hid_open(hiddev_table[i]->hid); | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | /* | ||
279 | * "write" file op | ||
280 | */ | ||
281 | static ssize_t hiddev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) | ||
282 | { | ||
283 | return -EINVAL; | ||
284 | } | ||
285 | |||
286 | /* | ||
287 | * "read" file op | ||
288 | */ | ||
289 | static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) | ||
290 | { | ||
291 | DECLARE_WAITQUEUE(wait, current); | ||
292 | struct hiddev_list *list = file->private_data; | ||
293 | int event_size; | ||
294 | int retval = 0; | ||
295 | |||
296 | event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ? | ||
297 | sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event); | ||
298 | |||
299 | if (count < event_size) | ||
300 | return 0; | ||
301 | |||
302 | while (retval == 0) { | ||
303 | if (list->head == list->tail) { | ||
304 | add_wait_queue(&list->hiddev->wait, &wait); | ||
305 | set_current_state(TASK_INTERRUPTIBLE); | ||
306 | |||
307 | while (list->head == list->tail) { | ||
308 | if (file->f_flags & O_NONBLOCK) { | ||
309 | retval = -EAGAIN; | ||
310 | break; | ||
311 | } | ||
312 | if (signal_pending(current)) { | ||
313 | retval = -ERESTARTSYS; | ||
314 | break; | ||
315 | } | ||
316 | if (!list->hiddev->exist) { | ||
317 | retval = -EIO; | ||
318 | break; | ||
319 | } | ||
320 | |||
321 | schedule(); | ||
322 | } | ||
323 | |||
324 | set_current_state(TASK_RUNNING); | ||
325 | remove_wait_queue(&list->hiddev->wait, &wait); | ||
326 | } | ||
327 | |||
328 | if (retval) | ||
329 | return retval; | ||
330 | |||
331 | |||
332 | while (list->head != list->tail && | ||
333 | retval + event_size <= count) { | ||
334 | if ((list->flags & HIDDEV_FLAG_UREF) == 0) { | ||
335 | if (list->buffer[list->tail].field_index != | ||
336 | HID_FIELD_INDEX_NONE) { | ||
337 | struct hiddev_event event; | ||
338 | event.hid = list->buffer[list->tail].usage_code; | ||
339 | event.value = list->buffer[list->tail].value; | ||
340 | if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) | ||
341 | return -EFAULT; | ||
342 | retval += sizeof(struct hiddev_event); | ||
343 | } | ||
344 | } else { | ||
345 | if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE || | ||
346 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { | ||
347 | if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) | ||
348 | return -EFAULT; | ||
349 | retval += sizeof(struct hiddev_usage_ref); | ||
350 | } | ||
351 | } | ||
352 | list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1); | ||
353 | } | ||
354 | |||
355 | } | ||
356 | |||
357 | return retval; | ||
358 | } | ||
359 | |||
360 | /* | ||
361 | * "poll" file op | ||
362 | * No kernel lock - fine | ||
363 | */ | ||
364 | static unsigned int hiddev_poll(struct file *file, poll_table *wait) | ||
365 | { | ||
366 | struct hiddev_list *list = file->private_data; | ||
367 | poll_wait(file, &list->hiddev->wait, wait); | ||
368 | if (list->head != list->tail) | ||
369 | return POLLIN | POLLRDNORM; | ||
370 | if (!list->hiddev->exist) | ||
371 | return POLLERR | POLLHUP; | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | /* | ||
376 | * "ioctl" file op | ||
377 | */ | ||
378 | static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | ||
379 | { | ||
380 | struct hiddev_list *list = file->private_data; | ||
381 | struct hiddev *hiddev = list->hiddev; | ||
382 | struct hid_device *hid = hiddev->hid; | ||
383 | struct usb_device *dev = hid->dev; | ||
384 | struct hiddev_collection_info cinfo; | ||
385 | struct hiddev_report_info rinfo; | ||
386 | struct hiddev_field_info finfo; | ||
387 | struct hiddev_usage_ref_multi *uref_multi=NULL; | ||
388 | struct hiddev_usage_ref *uref; | ||
389 | struct hiddev_devinfo dinfo; | ||
390 | struct hid_report *report; | ||
391 | struct hid_field *field; | ||
392 | void __user *user_arg = (void __user *)arg; | ||
393 | int i; | ||
394 | |||
395 | if (!hiddev->exist) | ||
396 | return -EIO; | ||
397 | |||
398 | switch (cmd) { | ||
399 | |||
400 | case HIDIOCGVERSION: | ||
401 | return put_user(HID_VERSION, (int __user *)arg); | ||
402 | |||
403 | case HIDIOCAPPLICATION: | ||
404 | if (arg < 0 || arg >= hid->maxapplication) | ||
405 | return -EINVAL; | ||
406 | |||
407 | for (i = 0; i < hid->maxcollection; i++) | ||
408 | if (hid->collection[i].type == | ||
409 | HID_COLLECTION_APPLICATION && arg-- == 0) | ||
410 | break; | ||
411 | |||
412 | if (i == hid->maxcollection) | ||
413 | return -EINVAL; | ||
414 | |||
415 | return hid->collection[i].usage; | ||
416 | |||
417 | case HIDIOCGDEVINFO: | ||
418 | dinfo.bustype = BUS_USB; | ||
419 | dinfo.busnum = dev->bus->busnum; | ||
420 | dinfo.devnum = dev->devnum; | ||
421 | dinfo.ifnum = hid->ifnum; | ||
422 | dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
423 | dinfo.product = le16_to_cpu(dev->descriptor.idProduct); | ||
424 | dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice); | ||
425 | dinfo.num_applications = hid->maxapplication; | ||
426 | if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) | ||
427 | return -EFAULT; | ||
428 | |||
429 | return 0; | ||
430 | |||
431 | case HIDIOCGFLAG: | ||
432 | if (put_user(list->flags, (int __user *)arg)) | ||
433 | return -EFAULT; | ||
434 | |||
435 | return 0; | ||
436 | |||
437 | case HIDIOCSFLAG: | ||
438 | { | ||
439 | int newflags; | ||
440 | if (get_user(newflags, (int __user *)arg)) | ||
441 | return -EFAULT; | ||
442 | |||
443 | if ((newflags & ~HIDDEV_FLAGS) != 0 || | ||
444 | ((newflags & HIDDEV_FLAG_REPORT) != 0 && | ||
445 | (newflags & HIDDEV_FLAG_UREF) == 0)) | ||
446 | return -EINVAL; | ||
447 | |||
448 | list->flags = newflags; | ||
449 | |||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | case HIDIOCGSTRING: | ||
454 | { | ||
455 | int idx, len; | ||
456 | char *buf; | ||
457 | |||
458 | if (get_user(idx, (int __user *)arg)) | ||
459 | return -EFAULT; | ||
460 | |||
461 | if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL) | ||
462 | return -ENOMEM; | ||
463 | |||
464 | if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) { | ||
465 | kfree(buf); | ||
466 | return -EINVAL; | ||
467 | } | ||
468 | |||
469 | if (copy_to_user(user_arg+sizeof(int), buf, len+1)) { | ||
470 | kfree(buf); | ||
471 | return -EFAULT; | ||
472 | } | ||
473 | |||
474 | kfree(buf); | ||
475 | |||
476 | return len; | ||
477 | } | ||
478 | |||
479 | case HIDIOCINITREPORT: | ||
480 | hid_init_reports(hid); | ||
481 | |||
482 | return 0; | ||
483 | |||
484 | case HIDIOCGREPORT: | ||
485 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | ||
486 | return -EFAULT; | ||
487 | |||
488 | if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT) | ||
489 | return -EINVAL; | ||
490 | |||
491 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
492 | return -EINVAL; | ||
493 | |||
494 | hid_submit_report(hid, report, USB_DIR_IN); | ||
495 | hid_wait_io(hid); | ||
496 | |||
497 | return 0; | ||
498 | |||
499 | case HIDIOCSREPORT: | ||
500 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | ||
501 | return -EFAULT; | ||
502 | |||
503 | if (rinfo.report_type == HID_REPORT_TYPE_INPUT) | ||
504 | return -EINVAL; | ||
505 | |||
506 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
507 | return -EINVAL; | ||
508 | |||
509 | hid_submit_report(hid, report, USB_DIR_OUT); | ||
510 | |||
511 | return 0; | ||
512 | |||
513 | case HIDIOCGREPORTINFO: | ||
514 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | ||
515 | return -EFAULT; | ||
516 | |||
517 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
518 | return -EINVAL; | ||
519 | |||
520 | rinfo.num_fields = report->maxfield; | ||
521 | |||
522 | if (copy_to_user(user_arg, &rinfo, sizeof(rinfo))) | ||
523 | return -EFAULT; | ||
524 | |||
525 | return 0; | ||
526 | |||
527 | case HIDIOCGFIELDINFO: | ||
528 | if (copy_from_user(&finfo, user_arg, sizeof(finfo))) | ||
529 | return -EFAULT; | ||
530 | rinfo.report_type = finfo.report_type; | ||
531 | rinfo.report_id = finfo.report_id; | ||
532 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
533 | return -EINVAL; | ||
534 | |||
535 | if (finfo.field_index >= report->maxfield) | ||
536 | return -EINVAL; | ||
537 | |||
538 | field = report->field[finfo.field_index]; | ||
539 | memset(&finfo, 0, sizeof(finfo)); | ||
540 | finfo.report_type = rinfo.report_type; | ||
541 | finfo.report_id = rinfo.report_id; | ||
542 | finfo.field_index = field->report_count - 1; | ||
543 | finfo.maxusage = field->maxusage; | ||
544 | finfo.flags = field->flags; | ||
545 | finfo.physical = field->physical; | ||
546 | finfo.logical = field->logical; | ||
547 | finfo.application = field->application; | ||
548 | finfo.logical_minimum = field->logical_minimum; | ||
549 | finfo.logical_maximum = field->logical_maximum; | ||
550 | finfo.physical_minimum = field->physical_minimum; | ||
551 | finfo.physical_maximum = field->physical_maximum; | ||
552 | finfo.unit_exponent = field->unit_exponent; | ||
553 | finfo.unit = field->unit; | ||
554 | |||
555 | if (copy_to_user(user_arg, &finfo, sizeof(finfo))) | ||
556 | return -EFAULT; | ||
557 | |||
558 | return 0; | ||
559 | |||
560 | case HIDIOCGUCODE: | ||
561 | uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL); | ||
562 | if (!uref_multi) | ||
563 | return -ENOMEM; | ||
564 | uref = &uref_multi->uref; | ||
565 | if (copy_from_user(uref, user_arg, sizeof(*uref))) | ||
566 | goto fault; | ||
567 | |||
568 | rinfo.report_type = uref->report_type; | ||
569 | rinfo.report_id = uref->report_id; | ||
570 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
571 | goto inval; | ||
572 | |||
573 | if (uref->field_index >= report->maxfield) | ||
574 | goto inval; | ||
575 | |||
576 | field = report->field[uref->field_index]; | ||
577 | if (uref->usage_index >= field->maxusage) | ||
578 | goto inval; | ||
579 | |||
580 | uref->usage_code = field->usage[uref->usage_index].hid; | ||
581 | |||
582 | if (copy_to_user(user_arg, uref, sizeof(*uref))) | ||
583 | goto fault; | ||
584 | |||
585 | kfree(uref_multi); | ||
586 | return 0; | ||
587 | |||
588 | case HIDIOCGUSAGE: | ||
589 | case HIDIOCSUSAGE: | ||
590 | case HIDIOCGUSAGES: | ||
591 | case HIDIOCSUSAGES: | ||
592 | case HIDIOCGCOLLECTIONINDEX: | ||
593 | uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL); | ||
594 | if (!uref_multi) | ||
595 | return -ENOMEM; | ||
596 | uref = &uref_multi->uref; | ||
597 | if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { | ||
598 | if (copy_from_user(uref_multi, user_arg, | ||
599 | sizeof(*uref_multi))) | ||
600 | goto fault; | ||
601 | } else { | ||
602 | if (copy_from_user(uref, user_arg, sizeof(*uref))) | ||
603 | goto fault; | ||
604 | } | ||
605 | |||
606 | if (cmd != HIDIOCGUSAGE && | ||
607 | cmd != HIDIOCGUSAGES && | ||
608 | uref->report_type == HID_REPORT_TYPE_INPUT) | ||
609 | goto inval; | ||
610 | |||
611 | if (uref->report_id == HID_REPORT_ID_UNKNOWN) { | ||
612 | field = hiddev_lookup_usage(hid, uref); | ||
613 | if (field == NULL) | ||
614 | goto inval; | ||
615 | } else { | ||
616 | rinfo.report_type = uref->report_type; | ||
617 | rinfo.report_id = uref->report_id; | ||
618 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
619 | goto inval; | ||
620 | |||
621 | if (uref->field_index >= report->maxfield) | ||
622 | goto inval; | ||
623 | |||
624 | field = report->field[uref->field_index]; | ||
625 | |||
626 | if (cmd == HIDIOCGCOLLECTIONINDEX) { | ||
627 | if (uref->usage_index >= field->maxusage) | ||
628 | goto inval; | ||
629 | } else if (uref->usage_index >= field->report_count) | ||
630 | goto inval; | ||
631 | |||
632 | else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && | ||
633 | (uref_multi->num_values > HID_MAX_MULTI_USAGES || | ||
634 | uref->usage_index + uref_multi->num_values >= field->report_count)) | ||
635 | goto inval; | ||
636 | } | ||
637 | |||
638 | switch (cmd) { | ||
639 | case HIDIOCGUSAGE: | ||
640 | uref->value = field->value[uref->usage_index]; | ||
641 | if (copy_to_user(user_arg, uref, sizeof(*uref))) | ||
642 | goto fault; | ||
643 | goto goodreturn; | ||
644 | |||
645 | case HIDIOCSUSAGE: | ||
646 | field->value[uref->usage_index] = uref->value; | ||
647 | goto goodreturn; | ||
648 | |||
649 | case HIDIOCGCOLLECTIONINDEX: | ||
650 | kfree(uref_multi); | ||
651 | return field->usage[uref->usage_index].collection_index; | ||
652 | case HIDIOCGUSAGES: | ||
653 | for (i = 0; i < uref_multi->num_values; i++) | ||
654 | uref_multi->values[i] = | ||
655 | field->value[uref->usage_index + i]; | ||
656 | if (copy_to_user(user_arg, uref_multi, | ||
657 | sizeof(*uref_multi))) | ||
658 | goto fault; | ||
659 | goto goodreturn; | ||
660 | case HIDIOCSUSAGES: | ||
661 | for (i = 0; i < uref_multi->num_values; i++) | ||
662 | field->value[uref->usage_index + i] = | ||
663 | uref_multi->values[i]; | ||
664 | goto goodreturn; | ||
665 | } | ||
666 | |||
667 | goodreturn: | ||
668 | kfree(uref_multi); | ||
669 | return 0; | ||
670 | fault: | ||
671 | kfree(uref_multi); | ||
672 | return -EFAULT; | ||
673 | inval: | ||
674 | kfree(uref_multi); | ||
675 | return -EINVAL; | ||
676 | |||
677 | case HIDIOCGCOLLECTIONINFO: | ||
678 | if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) | ||
679 | return -EFAULT; | ||
680 | |||
681 | if (cinfo.index >= hid->maxcollection) | ||
682 | return -EINVAL; | ||
683 | |||
684 | cinfo.type = hid->collection[cinfo.index].type; | ||
685 | cinfo.usage = hid->collection[cinfo.index].usage; | ||
686 | cinfo.level = hid->collection[cinfo.index].level; | ||
687 | |||
688 | if (copy_to_user(user_arg, &cinfo, sizeof(cinfo))) | ||
689 | return -EFAULT; | ||
690 | return 0; | ||
691 | |||
692 | default: | ||
693 | |||
694 | if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) | ||
695 | return -EINVAL; | ||
696 | |||
697 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) { | ||
698 | int len; | ||
699 | if (!hid->name) | ||
700 | return 0; | ||
701 | len = strlen(hid->name) + 1; | ||
702 | if (len > _IOC_SIZE(cmd)) | ||
703 | len = _IOC_SIZE(cmd); | ||
704 | return copy_to_user(user_arg, hid->name, len) ? | ||
705 | -EFAULT : len; | ||
706 | } | ||
707 | |||
708 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) { | ||
709 | int len; | ||
710 | if (!hid->phys) | ||
711 | return 0; | ||
712 | len = strlen(hid->phys) + 1; | ||
713 | if (len > _IOC_SIZE(cmd)) | ||
714 | len = _IOC_SIZE(cmd); | ||
715 | return copy_to_user(user_arg, hid->phys, len) ? | ||
716 | -EFAULT : len; | ||
717 | } | ||
718 | } | ||
719 | return -EINVAL; | ||
720 | } | ||
721 | |||
722 | static struct file_operations hiddev_fops = { | ||
723 | .owner = THIS_MODULE, | ||
724 | .read = hiddev_read, | ||
725 | .write = hiddev_write, | ||
726 | .poll = hiddev_poll, | ||
727 | .open = hiddev_open, | ||
728 | .release = hiddev_release, | ||
729 | .ioctl = hiddev_ioctl, | ||
730 | .fasync = hiddev_fasync, | ||
731 | }; | ||
732 | |||
733 | static struct usb_class_driver hiddev_class = { | ||
734 | .name = "usb/hid/hiddev%d", | ||
735 | .fops = &hiddev_fops, | ||
736 | .mode = S_IFCHR | S_IRUGO | S_IWUSR, | ||
737 | .minor_base = HIDDEV_MINOR_BASE, | ||
738 | }; | ||
739 | |||
740 | /* | ||
741 | * This is where hid.c calls us to connect a hid device to the hiddev driver | ||
742 | */ | ||
743 | int hiddev_connect(struct hid_device *hid) | ||
744 | { | ||
745 | struct hiddev *hiddev; | ||
746 | int i; | ||
747 | int retval; | ||
748 | |||
749 | for (i = 0; i < hid->maxcollection; i++) | ||
750 | if (hid->collection[i].type == | ||
751 | HID_COLLECTION_APPLICATION && | ||
752 | !IS_INPUT_APPLICATION(hid->collection[i].usage)) | ||
753 | break; | ||
754 | |||
755 | if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) | ||
756 | return -1; | ||
757 | |||
758 | if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) | ||
759 | return -1; | ||
760 | memset(hiddev, 0, sizeof(struct hiddev)); | ||
761 | |||
762 | retval = usb_register_dev(hid->intf, &hiddev_class); | ||
763 | if (retval) { | ||
764 | err("Not able to get a minor for this device."); | ||
765 | kfree(hiddev); | ||
766 | return -1; | ||
767 | } | ||
768 | |||
769 | init_waitqueue_head(&hiddev->wait); | ||
770 | |||
771 | hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | ||
772 | |||
773 | hiddev->hid = hid; | ||
774 | hiddev->exist = 1; | ||
775 | |||
776 | hid->minor = hid->intf->minor; | ||
777 | hid->hiddev = hiddev; | ||
778 | |||
779 | return 0; | ||
780 | } | ||
781 | |||
782 | /* | ||
783 | * This is where hid.c calls us to disconnect a hiddev device from the | ||
784 | * corresponding hid device (usually because the usb device has disconnected) | ||
785 | */ | ||
786 | static struct usb_class_driver hiddev_class; | ||
787 | void hiddev_disconnect(struct hid_device *hid) | ||
788 | { | ||
789 | struct hiddev *hiddev = hid->hiddev; | ||
790 | |||
791 | hiddev->exist = 0; | ||
792 | |||
793 | hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; | ||
794 | usb_deregister_dev(hiddev->hid->intf, &hiddev_class); | ||
795 | |||
796 | if (hiddev->open) { | ||
797 | hid_close(hiddev->hid); | ||
798 | wake_up_interruptible(&hiddev->wait); | ||
799 | } else { | ||
800 | kfree(hiddev); | ||
801 | } | ||
802 | } | ||
803 | |||
804 | /* Currently this driver is a USB driver. It's not a conventional one in | ||
805 | * the sense that it doesn't probe at the USB level. Instead it waits to | ||
806 | * be connected by HID through the hiddev_connect / hiddev_disconnect | ||
807 | * routines. The reason to register as a USB device is to gain part of the | ||
808 | * minor number space from the USB major. | ||
809 | * | ||
810 | * In theory, should the HID code be generalized to more than one physical | ||
811 | * medium (say, IEEE 1384), this driver will probably need to register its | ||
812 | * own major number, and in doing so, no longer need to register with USB. | ||
813 | * At that point the probe routine and hiddev_driver struct below will no | ||
814 | * longer be useful. | ||
815 | */ | ||
816 | |||
817 | |||
818 | /* We never attach in this manner, and rely on HID to connect us. This | ||
819 | * is why there is no disconnect routine defined in the usb_driver either. | ||
820 | */ | ||
821 | static int hiddev_usbd_probe(struct usb_interface *intf, | ||
822 | const struct usb_device_id *hiddev_info) | ||
823 | { | ||
824 | return -ENODEV; | ||
825 | } | ||
826 | |||
827 | |||
828 | static /* const */ struct usb_driver hiddev_driver = { | ||
829 | .owner = THIS_MODULE, | ||
830 | .name = "hiddev", | ||
831 | .probe = hiddev_usbd_probe, | ||
832 | }; | ||
833 | |||
834 | int __init hiddev_init(void) | ||
835 | { | ||
836 | devfs_mk_dir("usb/hid"); | ||
837 | return usb_register(&hiddev_driver); | ||
838 | } | ||
839 | |||
840 | void hiddev_exit(void) | ||
841 | { | ||
842 | usb_deregister(&hiddev_driver); | ||
843 | devfs_remove("usb/hid"); | ||
844 | } | ||
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c new file mode 100644 index 000000000000..a68c5b4e7b37 --- /dev/null +++ b/drivers/usb/input/kbtab.c | |||
@@ -0,0 +1,241 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/slab.h> | ||
3 | #include <linux/input.h> | ||
4 | #include <linux/module.h> | ||
5 | #include <linux/init.h> | ||
6 | #include <linux/usb.h> | ||
7 | #include <asm/unaligned.h> | ||
8 | #include <asm/byteorder.h> | ||
9 | |||
10 | /* | ||
11 | * Version Information | ||
12 | * v0.0.1 - Original, extremely basic version, 2.4.xx only | ||
13 | * v0.0.2 - Updated, works with 2.5.62 and 2.4.20; | ||
14 | * - added pressure-threshold modules param code from | ||
15 | * Alex Perry <alex.perry@ieee.org> | ||
16 | */ | ||
17 | |||
18 | #define DRIVER_VERSION "v0.0.2" | ||
19 | #define DRIVER_AUTHOR "Josh Myer <josh@joshisanerd.com>" | ||
20 | #define DRIVER_DESC "USB KB Gear JamStudio Tablet driver" | ||
21 | #define DRIVER_LICENSE "GPL" | ||
22 | |||
23 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
24 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
25 | MODULE_LICENSE(DRIVER_LICENSE); | ||
26 | |||
27 | #define USB_VENDOR_ID_KBGEAR 0x084e | ||
28 | |||
29 | static int kb_pressure_click = 0x10; | ||
30 | module_param(kb_pressure_click, int, 0); | ||
31 | MODULE_PARM_DESC(kb_pressure_click, "pressure threshold for clicks"); | ||
32 | |||
33 | struct kbtab { | ||
34 | signed char *data; | ||
35 | dma_addr_t data_dma; | ||
36 | struct input_dev dev; | ||
37 | struct usb_device *usbdev; | ||
38 | struct urb *irq; | ||
39 | int open; | ||
40 | int x, y; | ||
41 | int button; | ||
42 | int pressure; | ||
43 | __u32 serial[2]; | ||
44 | char phys[32]; | ||
45 | }; | ||
46 | |||
47 | static void kbtab_irq(struct urb *urb, struct pt_regs *regs) | ||
48 | { | ||
49 | struct kbtab *kbtab = urb->context; | ||
50 | unsigned char *data = kbtab->data; | ||
51 | struct input_dev *dev = &kbtab->dev; | ||
52 | int retval; | ||
53 | |||
54 | switch (urb->status) { | ||
55 | case 0: | ||
56 | /* success */ | ||
57 | break; | ||
58 | case -ECONNRESET: | ||
59 | case -ENOENT: | ||
60 | case -ESHUTDOWN: | ||
61 | /* this urb is terminated, clean up */ | ||
62 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
63 | return; | ||
64 | default: | ||
65 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
66 | goto exit; | ||
67 | } | ||
68 | |||
69 | kbtab->x = le16_to_cpu(get_unaligned((__le16 *) &data[1])); | ||
70 | kbtab->y = le16_to_cpu(get_unaligned((__le16 *) &data[3])); | ||
71 | |||
72 | kbtab->pressure = (data[5]); | ||
73 | |||
74 | input_report_key(dev, BTN_TOOL_PEN, 1); | ||
75 | |||
76 | input_report_abs(dev, ABS_X, kbtab->x); | ||
77 | input_report_abs(dev, ABS_Y, kbtab->y); | ||
78 | |||
79 | /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ | ||
80 | input_report_key(dev, BTN_RIGHT, data[0] & 0x02); | ||
81 | |||
82 | if( -1 == kb_pressure_click){ | ||
83 | input_report_abs(dev, ABS_PRESSURE, kbtab->pressure); | ||
84 | } else { | ||
85 | input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); | ||
86 | }; | ||
87 | |||
88 | input_sync(dev); | ||
89 | |||
90 | exit: | ||
91 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
92 | if (retval) | ||
93 | err ("%s - usb_submit_urb failed with result %d", | ||
94 | __FUNCTION__, retval); | ||
95 | } | ||
96 | |||
97 | static struct usb_device_id kbtab_ids[] = { | ||
98 | { USB_DEVICE(USB_VENDOR_ID_KBGEAR, 0x1001), .driver_info = 0 }, | ||
99 | { } | ||
100 | }; | ||
101 | |||
102 | MODULE_DEVICE_TABLE(usb, kbtab_ids); | ||
103 | |||
104 | static int kbtab_open(struct input_dev *dev) | ||
105 | { | ||
106 | struct kbtab *kbtab = dev->private; | ||
107 | |||
108 | if (kbtab->open++) | ||
109 | return 0; | ||
110 | |||
111 | kbtab->irq->dev = kbtab->usbdev; | ||
112 | if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) { | ||
113 | kbtab->open--; | ||
114 | return -EIO; | ||
115 | } | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static void kbtab_close(struct input_dev *dev) | ||
121 | { | ||
122 | struct kbtab *kbtab = dev->private; | ||
123 | |||
124 | if (!--kbtab->open) | ||
125 | usb_kill_urb(kbtab->irq); | ||
126 | } | ||
127 | |||
128 | static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
129 | { | ||
130 | struct usb_device *dev = interface_to_usbdev(intf); | ||
131 | struct usb_endpoint_descriptor *endpoint; | ||
132 | struct kbtab *kbtab; | ||
133 | char path[64]; | ||
134 | |||
135 | if (!(kbtab = kmalloc(sizeof(struct kbtab), GFP_KERNEL))) | ||
136 | return -ENOMEM; | ||
137 | memset(kbtab, 0, sizeof(struct kbtab)); | ||
138 | |||
139 | kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma); | ||
140 | if (!kbtab->data) { | ||
141 | kfree(kbtab); | ||
142 | return -ENOMEM; | ||
143 | } | ||
144 | |||
145 | kbtab->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
146 | if (!kbtab->irq) { | ||
147 | usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma); | ||
148 | kfree(kbtab); | ||
149 | return -ENOMEM; | ||
150 | } | ||
151 | |||
152 | kbtab->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC); | ||
153 | kbtab->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); | ||
154 | |||
155 | kbtab->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
156 | |||
157 | kbtab->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH); | ||
158 | |||
159 | kbtab->dev.mscbit[0] |= BIT(MSC_SERIAL); | ||
160 | |||
161 | kbtab->dev.absmax[ABS_X] = 0x2000; | ||
162 | kbtab->dev.absmax[ABS_Y] = 0x1750; | ||
163 | kbtab->dev.absmax[ABS_PRESSURE] = 0xff; | ||
164 | |||
165 | kbtab->dev.absfuzz[ABS_X] = 4; | ||
166 | kbtab->dev.absfuzz[ABS_Y] = 4; | ||
167 | |||
168 | kbtab->dev.private = kbtab; | ||
169 | kbtab->dev.open = kbtab_open; | ||
170 | kbtab->dev.close = kbtab_close; | ||
171 | |||
172 | usb_make_path(dev, path, 64); | ||
173 | sprintf(kbtab->phys, "%s/input0", path); | ||
174 | |||
175 | kbtab->dev.name = "KB Gear Tablet"; | ||
176 | kbtab->dev.phys = kbtab->phys; | ||
177 | kbtab->dev.id.bustype = BUS_USB; | ||
178 | kbtab->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
179 | kbtab->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); | ||
180 | kbtab->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); | ||
181 | kbtab->dev.dev = &intf->dev; | ||
182 | kbtab->usbdev = dev; | ||
183 | |||
184 | endpoint = &intf->cur_altsetting->endpoint[0].desc; | ||
185 | |||
186 | usb_fill_int_urb(kbtab->irq, dev, | ||
187 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), | ||
188 | kbtab->data, 8, | ||
189 | kbtab_irq, kbtab, endpoint->bInterval); | ||
190 | kbtab->irq->transfer_dma = kbtab->data_dma; | ||
191 | kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
192 | |||
193 | input_register_device(&kbtab->dev); | ||
194 | |||
195 | printk(KERN_INFO "input: KB Gear Tablet on %s\n", path); | ||
196 | |||
197 | usb_set_intfdata(intf, kbtab); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static void kbtab_disconnect(struct usb_interface *intf) | ||
203 | { | ||
204 | struct kbtab *kbtab = usb_get_intfdata (intf); | ||
205 | |||
206 | usb_set_intfdata(intf, NULL); | ||
207 | if (kbtab) { | ||
208 | usb_kill_urb(kbtab->irq); | ||
209 | input_unregister_device(&kbtab->dev); | ||
210 | usb_free_urb(kbtab->irq); | ||
211 | usb_buffer_free(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma); | ||
212 | kfree(kbtab); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | static struct usb_driver kbtab_driver = { | ||
217 | .owner = THIS_MODULE, | ||
218 | .name = "kbtab", | ||
219 | .probe = kbtab_probe, | ||
220 | .disconnect = kbtab_disconnect, | ||
221 | .id_table = kbtab_ids, | ||
222 | }; | ||
223 | |||
224 | static int __init kbtab_init(void) | ||
225 | { | ||
226 | int retval; | ||
227 | retval = usb_register(&kbtab_driver); | ||
228 | if (retval) | ||
229 | goto out; | ||
230 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
231 | out: | ||
232 | return retval; | ||
233 | } | ||
234 | |||
235 | static void __exit kbtab_exit(void) | ||
236 | { | ||
237 | usb_deregister(&kbtab_driver); | ||
238 | } | ||
239 | |||
240 | module_init(kbtab_init); | ||
241 | module_exit(kbtab_exit); | ||
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c new file mode 100644 index 000000000000..6b45a66d58c1 --- /dev/null +++ b/drivers/usb/input/mtouchusb.c | |||
@@ -0,0 +1,367 @@ | |||
1 | /****************************************************************************** | ||
2 | * mtouchusb.c -- Driver for Microtouch (Now 3M) USB Touchscreens | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation; either version 2 of the | ||
7 | * License, or (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | * | ||
18 | * Based upon original work by Radoslaw Garbacz (usb-support@ite.pl) | ||
19 | * (http://freshmeat.net/projects/3mtouchscreendriver) | ||
20 | * | ||
21 | * History | ||
22 | * | ||
23 | * 0.3 & 0.4 2002 (TEJ) tejohnson@yahoo.com | ||
24 | * Updated to 2.4.18, then 2.4.19 | ||
25 | * Old version still relied on stealing a minor | ||
26 | * | ||
27 | * 0.5 02/26/2004 (TEJ) tejohnson@yahoo.com | ||
28 | * Complete rewrite using Linux Input in 2.6.3 | ||
29 | * Unfortunately no calibration support at this time | ||
30 | * | ||
31 | * 1.4 04/25/2004 (TEJ) tejohnson@yahoo.com | ||
32 | * Changed reset from standard USB dev reset to vendor reset | ||
33 | * Changed data sent to host from compensated to raw coordinates | ||
34 | * Eliminated vendor/product module params | ||
35 | * Performed multiple successfull tests with an EXII-5010UC | ||
36 | * | ||
37 | * 1.5 02/27/2005 ddstreet@ieee.org | ||
38 | * Added module parameter to select raw or hw-calibrated coordinate reporting | ||
39 | * | ||
40 | *****************************************************************************/ | ||
41 | |||
42 | #include <linux/config.h> | ||
43 | |||
44 | #ifdef CONFIG_USB_DEBUG | ||
45 | #define DEBUG | ||
46 | #else | ||
47 | #undef DEBUG | ||
48 | #endif | ||
49 | |||
50 | #include <linux/kernel.h> | ||
51 | #include <linux/slab.h> | ||
52 | #include <linux/input.h> | ||
53 | #include <linux/module.h> | ||
54 | #include <linux/init.h> | ||
55 | #include <linux/usb.h> | ||
56 | |||
57 | #define MTOUCHUSB_MIN_XC 0x0 | ||
58 | #define MTOUCHUSB_MAX_RAW_XC 0x4000 | ||
59 | #define MTOUCHUSB_MAX_CALIB_XC 0xffff | ||
60 | #define MTOUCHUSB_XC_FUZZ 0x0 | ||
61 | #define MTOUCHUSB_XC_FLAT 0x0 | ||
62 | #define MTOUCHUSB_MIN_YC 0x0 | ||
63 | #define MTOUCHUSB_MAX_RAW_YC 0x4000 | ||
64 | #define MTOUCHUSB_MAX_CALIB_YC 0xffff | ||
65 | #define MTOUCHUSB_YC_FUZZ 0x0 | ||
66 | #define MTOUCHUSB_YC_FLAT 0x0 | ||
67 | |||
68 | #define MTOUCHUSB_ASYNC_REPORT 1 | ||
69 | #define MTOUCHUSB_RESET 7 | ||
70 | #define MTOUCHUSB_REPORT_DATA_SIZE 11 | ||
71 | #define MTOUCHUSB_REQ_CTRLLR_ID 10 | ||
72 | |||
73 | #define MTOUCHUSB_GET_RAW_XC(data) (data[8]<<8 | data[7]) | ||
74 | #define MTOUCHUSB_GET_CALIB_XC(data) (data[4]<<8 | data[3]) | ||
75 | #define MTOUCHUSB_GET_RAW_YC(data) (data[10]<<8 | data[9]) | ||
76 | #define MTOUCHUSB_GET_CALIB_YC(data) (data[6]<<8 | data[5]) | ||
77 | #define MTOUCHUSB_GET_XC(data) (raw_coordinates ? \ | ||
78 | MTOUCHUSB_GET_RAW_XC(data) : \ | ||
79 | MTOUCHUSB_GET_CALIB_XC(data)) | ||
80 | #define MTOUCHUSB_GET_YC(data) (raw_coordinates ? \ | ||
81 | MTOUCHUSB_GET_RAW_YC(data) : \ | ||
82 | MTOUCHUSB_GET_CALIB_YC(data)) | ||
83 | #define MTOUCHUSB_GET_TOUCHED(data) ((data[2] & 0x40) ? 1:0) | ||
84 | |||
85 | #define DRIVER_VERSION "v1.5" | ||
86 | #define DRIVER_AUTHOR "Todd E. Johnson, tejohnson@yahoo.com" | ||
87 | #define DRIVER_DESC "3M USB Touchscreen Driver" | ||
88 | #define DRIVER_LICENSE "GPL" | ||
89 | |||
90 | static int raw_coordinates = 1; | ||
91 | |||
92 | module_param(raw_coordinates, bool, S_IRUGO | S_IWUSR); | ||
93 | MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)"); | ||
94 | |||
95 | struct mtouch_usb { | ||
96 | unsigned char *data; | ||
97 | dma_addr_t data_dma; | ||
98 | struct urb *irq; | ||
99 | struct usb_device *udev; | ||
100 | struct input_dev input; | ||
101 | int open; | ||
102 | char name[128]; | ||
103 | char phys[64]; | ||
104 | }; | ||
105 | |||
106 | static struct usb_device_id mtouchusb_devices [] = { | ||
107 | { USB_DEVICE(0x0596, 0x0001) }, | ||
108 | { } | ||
109 | }; | ||
110 | |||
111 | static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs) | ||
112 | { | ||
113 | struct mtouch_usb *mtouch = urb->context; | ||
114 | int retval; | ||
115 | |||
116 | switch (urb->status) { | ||
117 | case 0: | ||
118 | /* success */ | ||
119 | break; | ||
120 | case -ETIMEDOUT: | ||
121 | /* this urb is timing out */ | ||
122 | dbg("%s - urb timed out - was the device unplugged?", | ||
123 | __FUNCTION__); | ||
124 | return; | ||
125 | case -ECONNRESET: | ||
126 | case -ENOENT: | ||
127 | case -ESHUTDOWN: | ||
128 | /* this urb is terminated, clean up */ | ||
129 | dbg("%s - urb shutting down with status: %d", | ||
130 | __FUNCTION__, urb->status); | ||
131 | return; | ||
132 | default: | ||
133 | dbg("%s - nonzero urb status received: %d", | ||
134 | __FUNCTION__, urb->status); | ||
135 | goto exit; | ||
136 | } | ||
137 | |||
138 | input_regs(&mtouch->input, regs); | ||
139 | input_report_key(&mtouch->input, BTN_TOUCH, | ||
140 | MTOUCHUSB_GET_TOUCHED(mtouch->data)); | ||
141 | input_report_abs(&mtouch->input, ABS_X, | ||
142 | MTOUCHUSB_GET_XC(mtouch->data)); | ||
143 | input_report_abs(&mtouch->input, ABS_Y, | ||
144 | (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC) | ||
145 | - MTOUCHUSB_GET_YC(mtouch->data)); | ||
146 | input_sync(&mtouch->input); | ||
147 | |||
148 | exit: | ||
149 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
150 | if (retval) | ||
151 | err ("%s - usb_submit_urb failed with result: %d", | ||
152 | __FUNCTION__, retval); | ||
153 | } | ||
154 | |||
155 | static int mtouchusb_open (struct input_dev *input) | ||
156 | { | ||
157 | struct mtouch_usb *mtouch = input->private; | ||
158 | |||
159 | if (mtouch->open++) | ||
160 | return 0; | ||
161 | |||
162 | mtouch->irq->dev = mtouch->udev; | ||
163 | |||
164 | if (usb_submit_urb (mtouch->irq, GFP_ATOMIC)) { | ||
165 | mtouch->open--; | ||
166 | return -EIO; | ||
167 | } | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static void mtouchusb_close (struct input_dev *input) | ||
173 | { | ||
174 | struct mtouch_usb *mtouch = input->private; | ||
175 | |||
176 | if (!--mtouch->open) | ||
177 | usb_kill_urb (mtouch->irq); | ||
178 | } | ||
179 | |||
180 | static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) | ||
181 | { | ||
182 | dbg("%s - called", __FUNCTION__); | ||
183 | |||
184 | mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE, | ||
185 | SLAB_ATOMIC, &mtouch->data_dma); | ||
186 | |||
187 | if (!mtouch->data) | ||
188 | return -1; | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) | ||
194 | { | ||
195 | dbg("%s - called", __FUNCTION__); | ||
196 | |||
197 | if (mtouch->data) | ||
198 | usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE, | ||
199 | mtouch->data, mtouch->data_dma); | ||
200 | } | ||
201 | |||
202 | static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
203 | { | ||
204 | struct mtouch_usb *mtouch; | ||
205 | struct usb_host_interface *interface; | ||
206 | struct usb_endpoint_descriptor *endpoint; | ||
207 | struct usb_device *udev = interface_to_usbdev (intf); | ||
208 | char path[64]; | ||
209 | int nRet; | ||
210 | |||
211 | dbg("%s - called", __FUNCTION__); | ||
212 | |||
213 | dbg("%s - setting interface", __FUNCTION__); | ||
214 | interface = intf->cur_altsetting; | ||
215 | |||
216 | dbg("%s - setting endpoint", __FUNCTION__); | ||
217 | endpoint = &interface->endpoint[0].desc; | ||
218 | |||
219 | if (!(mtouch = kmalloc (sizeof (struct mtouch_usb), GFP_KERNEL))) { | ||
220 | err("%s - Out of memory.", __FUNCTION__); | ||
221 | return -ENOMEM; | ||
222 | } | ||
223 | |||
224 | memset(mtouch, 0, sizeof(struct mtouch_usb)); | ||
225 | mtouch->udev = udev; | ||
226 | |||
227 | dbg("%s - allocating buffers", __FUNCTION__); | ||
228 | if (mtouchusb_alloc_buffers(udev, mtouch)) { | ||
229 | mtouchusb_free_buffers(udev, mtouch); | ||
230 | kfree(mtouch); | ||
231 | return -ENOMEM; | ||
232 | } | ||
233 | |||
234 | mtouch->input.private = mtouch; | ||
235 | mtouch->input.open = mtouchusb_open; | ||
236 | mtouch->input.close = mtouchusb_close; | ||
237 | |||
238 | usb_make_path(udev, path, 64); | ||
239 | sprintf(mtouch->phys, "%s/input0", path); | ||
240 | |||
241 | mtouch->input.name = mtouch->name; | ||
242 | mtouch->input.phys = mtouch->phys; | ||
243 | mtouch->input.id.bustype = BUS_USB; | ||
244 | mtouch->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); | ||
245 | mtouch->input.id.product = le16_to_cpu(udev->descriptor.idProduct); | ||
246 | mtouch->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); | ||
247 | mtouch->input.dev = &intf->dev; | ||
248 | |||
249 | mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
250 | mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); | ||
251 | mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
252 | |||
253 | /* Used to Scale Compensated Data and Flip Y */ | ||
254 | mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC; | ||
255 | mtouch->input.absmax[ABS_X] = raw_coordinates ? \ | ||
256 | MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC; | ||
257 | mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ; | ||
258 | mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT; | ||
259 | mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC; | ||
260 | mtouch->input.absmax[ABS_Y] = raw_coordinates ? \ | ||
261 | MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC; | ||
262 | mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ; | ||
263 | mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT; | ||
264 | |||
265 | if (udev->manufacturer) | ||
266 | strcat(mtouch->name, udev->manufacturer); | ||
267 | if (udev->product) | ||
268 | sprintf(mtouch->name, "%s %s", mtouch->name, udev->product); | ||
269 | |||
270 | if (!strlen(mtouch->name)) | ||
271 | sprintf(mtouch->name, "USB Touchscreen %04x:%04x", | ||
272 | mtouch->input.id.vendor, mtouch->input.id.product); | ||
273 | |||
274 | nRet = usb_control_msg(mtouch->udev, | ||
275 | usb_rcvctrlpipe(udev, 0), | ||
276 | MTOUCHUSB_RESET, | ||
277 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
278 | 1, | ||
279 | 0, | ||
280 | NULL, | ||
281 | 0, | ||
282 | USB_CTRL_SET_TIMEOUT); | ||
283 | dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", | ||
284 | __FUNCTION__, nRet); | ||
285 | |||
286 | dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__); | ||
287 | mtouch->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
288 | if (!mtouch->irq) { | ||
289 | dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__); | ||
290 | mtouchusb_free_buffers(udev, mtouch); | ||
291 | kfree(mtouch); | ||
292 | return -ENOMEM; | ||
293 | } | ||
294 | |||
295 | dbg("%s - usb_fill_int_urb", __FUNCTION__); | ||
296 | usb_fill_int_urb(mtouch->irq, | ||
297 | mtouch->udev, | ||
298 | usb_rcvintpipe(mtouch->udev, 0x81), | ||
299 | mtouch->data, | ||
300 | MTOUCHUSB_REPORT_DATA_SIZE, | ||
301 | mtouchusb_irq, | ||
302 | mtouch, | ||
303 | endpoint->bInterval); | ||
304 | |||
305 | dbg("%s - input_register_device", __FUNCTION__); | ||
306 | input_register_device(&mtouch->input); | ||
307 | |||
308 | nRet = usb_control_msg(mtouch->udev, | ||
309 | usb_rcvctrlpipe(udev, 0), | ||
310 | MTOUCHUSB_ASYNC_REPORT, | ||
311 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
312 | 1, | ||
313 | 1, | ||
314 | NULL, | ||
315 | 0, | ||
316 | USB_CTRL_SET_TIMEOUT); | ||
317 | dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", | ||
318 | __FUNCTION__, nRet); | ||
319 | |||
320 | printk(KERN_INFO "input: %s on %s\n", mtouch->name, path); | ||
321 | usb_set_intfdata(intf, mtouch); | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | static void mtouchusb_disconnect(struct usb_interface *intf) | ||
327 | { | ||
328 | struct mtouch_usb *mtouch = usb_get_intfdata (intf); | ||
329 | |||
330 | dbg("%s - called", __FUNCTION__); | ||
331 | usb_set_intfdata(intf, NULL); | ||
332 | if (mtouch) { | ||
333 | dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__); | ||
334 | usb_kill_urb(mtouch->irq); | ||
335 | input_unregister_device(&mtouch->input); | ||
336 | usb_free_urb(mtouch->irq); | ||
337 | mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch); | ||
338 | kfree(mtouch); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | MODULE_DEVICE_TABLE (usb, mtouchusb_devices); | ||
343 | |||
344 | static struct usb_driver mtouchusb_driver = { | ||
345 | .owner = THIS_MODULE, | ||
346 | .name = "mtouchusb", | ||
347 | .probe = mtouchusb_probe, | ||
348 | .disconnect = mtouchusb_disconnect, | ||
349 | .id_table = mtouchusb_devices, | ||
350 | }; | ||
351 | |||
352 | static int __init mtouchusb_init(void) { | ||
353 | dbg("%s - called", __FUNCTION__); | ||
354 | return usb_register(&mtouchusb_driver); | ||
355 | } | ||
356 | |||
357 | static void __exit mtouchusb_cleanup(void) { | ||
358 | dbg("%s - called", __FUNCTION__); | ||
359 | usb_deregister(&mtouchusb_driver); | ||
360 | } | ||
361 | |||
362 | module_init(mtouchusb_init); | ||
363 | module_exit(mtouchusb_cleanup); | ||
364 | |||
365 | MODULE_AUTHOR( DRIVER_AUTHOR ); | ||
366 | MODULE_DESCRIPTION( DRIVER_DESC ); | ||
367 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c new file mode 100644 index 000000000000..256963863478 --- /dev/null +++ b/drivers/usb/input/pid.c | |||
@@ -0,0 +1,295 @@ | |||
1 | /* | ||
2 | * PID Force feedback support for hid devices. | ||
3 | * | ||
4 | * Copyright (c) 2002 Rodrigo Damazio. | ||
5 | * Portions by Johann Deneux and Bjorn Augustson | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | * Should you need to contact me, the author, you can do so by | ||
24 | * e-mail - mail your message to <rdamazio@lsi.usp.br> | ||
25 | */ | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/mm.h> | ||
33 | #include <linux/smp_lock.h> | ||
34 | #include <linux/spinlock.h> | ||
35 | #include <linux/input.h> | ||
36 | #include <linux/usb.h> | ||
37 | #include "hid.h" | ||
38 | #include "pid.h" | ||
39 | |||
40 | #define DEBUG | ||
41 | |||
42 | #define CHECK_OWNERSHIP(i, hid_pid) \ | ||
43 | ((i) < FF_EFFECTS_MAX && i >= 0 && \ | ||
44 | test_bit(FF_PID_FLAGS_USED, &hid_pid->effects[(i)].flags) && \ | ||
45 | (current->pid == 0 || \ | ||
46 | (hid_pid)->effects[(i)].owner == current->pid)) | ||
47 | |||
48 | /* Called when a transfer is completed */ | ||
49 | static void hid_pid_ctrl_out(struct urb *u, struct pt_regs *regs) | ||
50 | { | ||
51 | dev_dbg(&u->dev->dev, "hid_pid_ctrl_out - Transfer Completed\n"); | ||
52 | } | ||
53 | |||
54 | static void hid_pid_exit(struct hid_device *hid) | ||
55 | { | ||
56 | struct hid_ff_pid *private = hid->ff_private; | ||
57 | |||
58 | if (private->urbffout) { | ||
59 | usb_kill_urb(private->urbffout); | ||
60 | usb_free_urb(private->urbffout); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | static int pid_upload_periodic(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) | ||
65 | { | ||
66 | dev_info(&pid->hid->dev->dev, "requested periodic force upload\n"); | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static int pid_upload_constant(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) | ||
71 | { | ||
72 | dev_info(&pid->hid->dev->dev, "requested constant force upload\n"); | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int pid_upload_condition(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) | ||
77 | { | ||
78 | dev_info(&pid->hid->dev->dev, "requested Condition force upload\n"); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int pid_upload_ramp(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) | ||
83 | { | ||
84 | dev_info(&pid->hid->dev->dev, "request ramp force upload\n"); | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static int hid_pid_event(struct hid_device *hid, struct input_dev *input, | ||
89 | unsigned int type, unsigned int code, int value) | ||
90 | { | ||
91 | dev_dbg(&hid->dev->dev, "PID event received: type=%d,code=%d,value=%d.\n", type, code, value); | ||
92 | |||
93 | if (type != EV_FF) | ||
94 | return -1; | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | /* Lock must be held by caller */ | ||
100 | static void hid_pid_ctrl_playback(struct hid_device *hid, struct hid_pid_effect *effect, int play) | ||
101 | { | ||
102 | if (play) | ||
103 | set_bit(FF_PID_FLAGS_PLAYING, &effect->flags); | ||
104 | else | ||
105 | clear_bit(FF_PID_FLAGS_PLAYING, &effect->flags); | ||
106 | } | ||
107 | |||
108 | static int hid_pid_erase(struct input_dev *dev, int id) | ||
109 | { | ||
110 | struct hid_device *hid = dev->private; | ||
111 | struct hid_ff_pid *pid = hid->ff_private; | ||
112 | struct hid_field *field; | ||
113 | unsigned long flags; | ||
114 | int ret; | ||
115 | |||
116 | if (!CHECK_OWNERSHIP(id, pid)) | ||
117 | return -EACCES; | ||
118 | |||
119 | /* Find report */ | ||
120 | field = hid_find_field_by_usage(hid, HID_UP_PID | FF_PID_USAGE_BLOCK_FREE, | ||
121 | HID_OUTPUT_REPORT); | ||
122 | if (!field) { | ||
123 | dev_err(&hid->dev->dev, "couldn't find report\n"); | ||
124 | return -EIO; | ||
125 | } | ||
126 | |||
127 | ret = hid_set_field(field, 0, pid->effects[id].device_id); | ||
128 | if (ret) { | ||
129 | dev_err(&hid->dev->dev, "couldn't set field\n"); | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | hid_submit_report(hid, field->report, USB_DIR_OUT); | ||
134 | |||
135 | spin_lock_irqsave(&pid->lock, flags); | ||
136 | hid_pid_ctrl_playback(hid, pid->effects + id, 0); | ||
137 | pid->effects[id].flags = 0; | ||
138 | spin_unlock_irqrestore(&pid->lock, flags); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | /* Erase all effects this process owns */ | ||
144 | static int hid_pid_flush(struct input_dev *dev, struct file *file) | ||
145 | { | ||
146 | struct hid_device *hid = dev->private; | ||
147 | struct hid_ff_pid *pid = hid->ff_private; | ||
148 | int i; | ||
149 | |||
150 | /*NOTE: no need to lock here. The only times EFFECT_USED is | ||
151 | modified is when effects are uploaded or when an effect is | ||
152 | erased. But a process cannot close its dev/input/eventX fd | ||
153 | and perform ioctls on the same fd all at the same time */ | ||
154 | /*FIXME: multiple threads, anyone? */ | ||
155 | for (i = 0; i < dev->ff_effects_max; ++i) | ||
156 | if (current->pid == pid->effects[i].owner | ||
157 | && test_bit(FF_PID_FLAGS_USED, &pid->effects[i].flags)) | ||
158 | if (hid_pid_erase(dev, i)) | ||
159 | dev_warn(&hid->dev->dev, "erase effect %d failed", i); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int hid_pid_upload_effect(struct input_dev *dev, | ||
165 | struct ff_effect *effect) | ||
166 | { | ||
167 | struct hid_ff_pid *pid_private = (struct hid_ff_pid *)(dev->private); | ||
168 | int ret; | ||
169 | int is_update; | ||
170 | unsigned long flags; | ||
171 | |||
172 | dev_dbg(&pid_private->hid->dev->dev, "upload effect called: effect_type=%x\n", effect->type); | ||
173 | /* Check this effect type is supported by this device */ | ||
174 | if (!test_bit(effect->type, dev->ffbit)) { | ||
175 | dev_dbg(&pid_private->hid->dev->dev, | ||
176 | "invalid kind of effect requested.\n"); | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | /* | ||
181 | * If we want to create a new effect, get a free id | ||
182 | */ | ||
183 | if (effect->id == -1) { | ||
184 | int id = 0; | ||
185 | |||
186 | // Spinlock so we don`t get a race condition when choosing IDs | ||
187 | spin_lock_irqsave(&pid_private->lock, flags); | ||
188 | |||
189 | while (id < FF_EFFECTS_MAX) | ||
190 | if (!test_and_set_bit(FF_PID_FLAGS_USED, &pid_private->effects[id++].flags)) | ||
191 | break; | ||
192 | |||
193 | if (id == FF_EFFECTS_MAX) { | ||
194 | spin_unlock_irqrestore(&pid_private->lock, flags); | ||
195 | // TEMP - We need to get ff_effects_max correctly first: || id >= dev->ff_effects_max) { | ||
196 | dev_dbg(&pid_private->hid->dev->dev, "Not enough device memory\n"); | ||
197 | return -ENOMEM; | ||
198 | } | ||
199 | |||
200 | effect->id = id; | ||
201 | dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d\n.", id); | ||
202 | pid_private->effects[id].owner = current->pid; | ||
203 | pid_private->effects[id].flags = (1 << FF_PID_FLAGS_USED); | ||
204 | spin_unlock_irqrestore(&pid_private->lock, flags); | ||
205 | |||
206 | is_update = FF_PID_FALSE; | ||
207 | } else { | ||
208 | /* We want to update an effect */ | ||
209 | if (!CHECK_OWNERSHIP(effect->id, pid_private)) | ||
210 | return -EACCES; | ||
211 | |||
212 | /* Parameter type cannot be updated */ | ||
213 | if (effect->type != pid_private->effects[effect->id].effect.type) | ||
214 | return -EINVAL; | ||
215 | |||
216 | /* Check the effect is not already being updated */ | ||
217 | if (test_bit(FF_PID_FLAGS_UPDATING, &pid_private->effects[effect->id].flags)) | ||
218 | return -EAGAIN; | ||
219 | |||
220 | is_update = FF_PID_TRUE; | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * Upload the effect | ||
225 | */ | ||
226 | switch (effect->type) { | ||
227 | case FF_PERIODIC: | ||
228 | ret = pid_upload_periodic(pid_private, effect, is_update); | ||
229 | break; | ||
230 | |||
231 | case FF_CONSTANT: | ||
232 | ret = pid_upload_constant(pid_private, effect, is_update); | ||
233 | break; | ||
234 | |||
235 | case FF_SPRING: | ||
236 | case FF_FRICTION: | ||
237 | case FF_DAMPER: | ||
238 | case FF_INERTIA: | ||
239 | ret = pid_upload_condition(pid_private, effect, is_update); | ||
240 | break; | ||
241 | |||
242 | case FF_RAMP: | ||
243 | ret = pid_upload_ramp(pid_private, effect, is_update); | ||
244 | break; | ||
245 | |||
246 | default: | ||
247 | dev_dbg(&pid_private->hid->dev->dev, | ||
248 | "invalid type of effect requested - %x.\n", | ||
249 | effect->type); | ||
250 | return -EINVAL; | ||
251 | } | ||
252 | /* If a packet was sent, forbid new updates until we are notified | ||
253 | * that the packet was updated | ||
254 | */ | ||
255 | if (ret == 0) | ||
256 | set_bit(FF_PID_FLAGS_UPDATING, &pid_private->effects[effect->id].flags); | ||
257 | pid_private->effects[effect->id].effect = *effect; | ||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | int hid_pid_init(struct hid_device *hid) | ||
262 | { | ||
263 | struct hid_ff_pid *private; | ||
264 | struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list); | ||
265 | |||
266 | private = hid->ff_private = kcalloc(1, sizeof(struct hid_ff_pid), GFP_KERNEL); | ||
267 | if (!private) | ||
268 | return -ENOMEM; | ||
269 | |||
270 | private->hid = hid; | ||
271 | |||
272 | hid->ff_exit = hid_pid_exit; | ||
273 | hid->ff_event = hid_pid_event; | ||
274 | |||
275 | /* Open output URB */ | ||
276 | if (!(private->urbffout = usb_alloc_urb(0, GFP_KERNEL))) { | ||
277 | kfree(private); | ||
278 | return -1; | ||
279 | } | ||
280 | |||
281 | usb_fill_control_urb(private->urbffout, hid->dev, 0, | ||
282 | (void *)&private->ffcr, private->ctrl_buffer, 8, | ||
283 | hid_pid_ctrl_out, hid); | ||
284 | hidinput->input.upload_effect = hid_pid_upload_effect; | ||
285 | hidinput->input.flush = hid_pid_flush; | ||
286 | hidinput->input.ff_effects_max = 8; // A random default | ||
287 | set_bit(EV_FF, hidinput->input.evbit); | ||
288 | set_bit(EV_FF_STATUS, hidinput->input.evbit); | ||
289 | |||
290 | spin_lock_init(&private->lock); | ||
291 | |||
292 | printk(KERN_INFO "Force feedback driver for PID devices by Rodrigo Damazio <rdamazio@lsi.usp.br>.\n"); | ||
293 | |||
294 | return 0; | ||
295 | } | ||
diff --git a/drivers/usb/input/pid.h b/drivers/usb/input/pid.h new file mode 100644 index 000000000000..a2cb9627ed0e --- /dev/null +++ b/drivers/usb/input/pid.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * PID Force feedback support for hid devices. | ||
3 | * | ||
4 | * Copyright (c) 2002 Rodrigo Damazio. | ||
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 | * Should you need to contact me, the author, you can do so by | ||
23 | * e-mail - mail your message to <rdamazio@lsi.usp.br> | ||
24 | */ | ||
25 | |||
26 | #define FF_EFFECTS_MAX 64 | ||
27 | |||
28 | #define FF_PID_FLAGS_USED 1 /* If the effect exists */ | ||
29 | #define FF_PID_FLAGS_UPDATING 2 /* If the effect is being updated */ | ||
30 | #define FF_PID_FLAGS_PLAYING 3 /* If the effect is currently being played */ | ||
31 | |||
32 | #define FF_PID_FALSE 0 | ||
33 | #define FF_PID_TRUE 1 | ||
34 | |||
35 | struct hid_pid_effect { | ||
36 | unsigned long flags; | ||
37 | pid_t owner; | ||
38 | unsigned int device_id; /* The device-assigned ID */ | ||
39 | struct ff_effect effect; | ||
40 | }; | ||
41 | |||
42 | struct hid_ff_pid { | ||
43 | struct hid_device *hid; | ||
44 | unsigned long gain; | ||
45 | |||
46 | struct urb *urbffout; | ||
47 | struct usb_ctrlrequest ffcr; | ||
48 | spinlock_t lock; | ||
49 | |||
50 | unsigned char ctrl_buffer[8]; | ||
51 | |||
52 | struct hid_pid_effect effects[FF_EFFECTS_MAX]; | ||
53 | }; | ||
54 | |||
55 | /* | ||
56 | * Constants from the PID usage table (still far from complete) | ||
57 | */ | ||
58 | |||
59 | #define FF_PID_USAGE_BLOCK_LOAD 0x89UL | ||
60 | #define FF_PID_USAGE_BLOCK_FREE 0x90UL | ||
61 | #define FF_PID_USAGE_NEW_EFFECT 0xABUL | ||
62 | #define FF_PID_USAGE_POOL_REPORT 0x7FUL | ||
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c new file mode 100644 index 000000000000..7fa2f9b9fb69 --- /dev/null +++ b/drivers/usb/input/powermate.c | |||
@@ -0,0 +1,464 @@ | |||
1 | /* | ||
2 | * A driver for the Griffin Technology, Inc. "PowerMate" USB controller dial. | ||
3 | * | ||
4 | * v1.1, (c)2002 William R Sowerbutts <will@sowerbutts.com> | ||
5 | * | ||
6 | * This device is a anodised aluminium knob which connects over USB. It can measure | ||
7 | * clockwise and anticlockwise rotation. The dial also acts as a pushbutton with | ||
8 | * a spring for automatic release. The base contains a pair of LEDs which illuminate | ||
9 | * the translucent base. It rotates without limit and reports its relative rotation | ||
10 | * back to the host when polled by the USB controller. | ||
11 | * | ||
12 | * Testing with the knob I have has shown that it measures approximately 94 "clicks" | ||
13 | * for one full rotation. Testing with my High Speed Rotation Actuator (ok, it was | ||
14 | * a variable speed cordless electric drill) has shown that the device can measure | ||
15 | * speeds of up to 7 clicks either clockwise or anticlockwise between pollings from | ||
16 | * the host. If it counts more than 7 clicks before it is polled, it will wrap back | ||
17 | * to zero and start counting again. This was at quite high speed, however, almost | ||
18 | * certainly faster than the human hand could turn it. Griffin say that it loses a | ||
19 | * pulse or two on a direction change; the granularity is so fine that I never | ||
20 | * noticed this in practice. | ||
21 | * | ||
22 | * The device's microcontroller can be programmed to set the LED to either a constant | ||
23 | * intensity, or to a rhythmic pulsing. Several patterns and speeds are available. | ||
24 | * | ||
25 | * Griffin were very happy to provide documentation and free hardware for development. | ||
26 | * | ||
27 | * Some userspace tools are available on the web: http://sowerbutts.com/powermate/ | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/input.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/spinlock.h> | ||
37 | #include <linux/usb.h> | ||
38 | |||
39 | #define POWERMATE_VENDOR 0x077d /* Griffin Technology, Inc. */ | ||
40 | #define POWERMATE_PRODUCT_NEW 0x0410 /* Griffin PowerMate */ | ||
41 | #define POWERMATE_PRODUCT_OLD 0x04AA /* Griffin soundKnob */ | ||
42 | |||
43 | #define CONTOUR_VENDOR 0x05f3 /* Contour Design, Inc. */ | ||
44 | #define CONTOUR_JOG 0x0240 /* Jog and Shuttle */ | ||
45 | |||
46 | /* these are the command codes we send to the device */ | ||
47 | #define SET_STATIC_BRIGHTNESS 0x01 | ||
48 | #define SET_PULSE_ASLEEP 0x02 | ||
49 | #define SET_PULSE_AWAKE 0x03 | ||
50 | #define SET_PULSE_MODE 0x04 | ||
51 | |||
52 | /* these refer to bits in the powermate_device's requires_update field. */ | ||
53 | #define UPDATE_STATIC_BRIGHTNESS (1<<0) | ||
54 | #define UPDATE_PULSE_ASLEEP (1<<1) | ||
55 | #define UPDATE_PULSE_AWAKE (1<<2) | ||
56 | #define UPDATE_PULSE_MODE (1<<3) | ||
57 | |||
58 | /* at least two versions of the hardware exist, with differing payload | ||
59 | sizes. the first three bytes always contain the "interesting" data in | ||
60 | the relevant format. */ | ||
61 | #define POWERMATE_PAYLOAD_SIZE_MAX 6 | ||
62 | #define POWERMATE_PAYLOAD_SIZE_MIN 3 | ||
63 | struct powermate_device { | ||
64 | signed char *data; | ||
65 | dma_addr_t data_dma; | ||
66 | struct urb *irq, *config; | ||
67 | struct usb_ctrlrequest *configcr; | ||
68 | dma_addr_t configcr_dma; | ||
69 | struct usb_device *udev; | ||
70 | struct input_dev input; | ||
71 | spinlock_t lock; | ||
72 | int static_brightness; | ||
73 | int pulse_speed; | ||
74 | int pulse_table; | ||
75 | int pulse_asleep; | ||
76 | int pulse_awake; | ||
77 | int requires_update; // physical settings which are out of sync | ||
78 | char phys[64]; | ||
79 | }; | ||
80 | |||
81 | static char pm_name_powermate[] = "Griffin PowerMate"; | ||
82 | static char pm_name_soundknob[] = "Griffin SoundKnob"; | ||
83 | |||
84 | static void powermate_config_complete(struct urb *urb, struct pt_regs *regs); | ||
85 | |||
86 | /* Callback for data arriving from the PowerMate over the USB interrupt pipe */ | ||
87 | static void powermate_irq(struct urb *urb, struct pt_regs *regs) | ||
88 | { | ||
89 | struct powermate_device *pm = urb->context; | ||
90 | int retval; | ||
91 | |||
92 | switch (urb->status) { | ||
93 | case 0: | ||
94 | /* success */ | ||
95 | break; | ||
96 | case -ECONNRESET: | ||
97 | case -ENOENT: | ||
98 | case -ESHUTDOWN: | ||
99 | /* this urb is terminated, clean up */ | ||
100 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
101 | return; | ||
102 | default: | ||
103 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
104 | goto exit; | ||
105 | } | ||
106 | |||
107 | /* handle updates to device state */ | ||
108 | input_regs(&pm->input, regs); | ||
109 | input_report_key(&pm->input, BTN_0, pm->data[0] & 0x01); | ||
110 | input_report_rel(&pm->input, REL_DIAL, pm->data[1]); | ||
111 | input_sync(&pm->input); | ||
112 | |||
113 | exit: | ||
114 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
115 | if (retval) | ||
116 | err ("%s - usb_submit_urb failed with result %d", | ||
117 | __FUNCTION__, retval); | ||
118 | } | ||
119 | |||
120 | /* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */ | ||
121 | static void powermate_sync_state(struct powermate_device *pm) | ||
122 | { | ||
123 | if (pm->requires_update == 0) | ||
124 | return; /* no updates are required */ | ||
125 | if (pm->config->status == -EINPROGRESS) | ||
126 | return; /* an update is already in progress; it'll issue this update when it completes */ | ||
127 | |||
128 | if (pm->requires_update & UPDATE_PULSE_ASLEEP){ | ||
129 | pm->configcr->wValue = cpu_to_le16( SET_PULSE_ASLEEP ); | ||
130 | pm->configcr->wIndex = cpu_to_le16( pm->pulse_asleep ? 1 : 0 ); | ||
131 | pm->requires_update &= ~UPDATE_PULSE_ASLEEP; | ||
132 | }else if (pm->requires_update & UPDATE_PULSE_AWAKE){ | ||
133 | pm->configcr->wValue = cpu_to_le16( SET_PULSE_AWAKE ); | ||
134 | pm->configcr->wIndex = cpu_to_le16( pm->pulse_awake ? 1 : 0 ); | ||
135 | pm->requires_update &= ~UPDATE_PULSE_AWAKE; | ||
136 | }else if (pm->requires_update & UPDATE_PULSE_MODE){ | ||
137 | int op, arg; | ||
138 | /* the powermate takes an operation and an argument for its pulse algorithm. | ||
139 | the operation can be: | ||
140 | 0: divide the speed | ||
141 | 1: pulse at normal speed | ||
142 | 2: multiply the speed | ||
143 | the argument only has an effect for operations 0 and 2, and ranges between | ||
144 | 1 (least effect) to 255 (maximum effect). | ||
145 | |||
146 | thus, several states are equivalent and are coalesced into one state. | ||
147 | |||
148 | we map this onto a range from 0 to 510, with: | ||
149 | 0 -- 254 -- use divide (0 = slowest) | ||
150 | 255 -- use normal speed | ||
151 | 256 -- 510 -- use multiple (510 = fastest). | ||
152 | |||
153 | Only values of 'arg' quite close to 255 are particularly useful/spectacular. | ||
154 | */ | ||
155 | if (pm->pulse_speed < 255){ | ||
156 | op = 0; // divide | ||
157 | arg = 255 - pm->pulse_speed; | ||
158 | } else if (pm->pulse_speed > 255){ | ||
159 | op = 2; // multiply | ||
160 | arg = pm->pulse_speed - 255; | ||
161 | } else { | ||
162 | op = 1; // normal speed | ||
163 | arg = 0; // can be any value | ||
164 | } | ||
165 | pm->configcr->wValue = cpu_to_le16( (pm->pulse_table << 8) | SET_PULSE_MODE ); | ||
166 | pm->configcr->wIndex = cpu_to_le16( (arg << 8) | op ); | ||
167 | pm->requires_update &= ~UPDATE_PULSE_MODE; | ||
168 | }else if (pm->requires_update & UPDATE_STATIC_BRIGHTNESS){ | ||
169 | pm->configcr->wValue = cpu_to_le16( SET_STATIC_BRIGHTNESS ); | ||
170 | pm->configcr->wIndex = cpu_to_le16( pm->static_brightness ); | ||
171 | pm->requires_update &= ~UPDATE_STATIC_BRIGHTNESS; | ||
172 | }else{ | ||
173 | printk(KERN_ERR "powermate: unknown update required"); | ||
174 | pm->requires_update = 0; /* fudge the bug */ | ||
175 | return; | ||
176 | } | ||
177 | |||
178 | /* printk("powermate: %04x %04x\n", pm->configcr->wValue, pm->configcr->wIndex); */ | ||
179 | |||
180 | pm->configcr->bRequestType = 0x41; /* vendor request */ | ||
181 | pm->configcr->bRequest = 0x01; | ||
182 | pm->configcr->wLength = 0; | ||
183 | |||
184 | usb_fill_control_urb(pm->config, pm->udev, usb_sndctrlpipe(pm->udev, 0), | ||
185 | (void *) pm->configcr, NULL, 0, | ||
186 | powermate_config_complete, pm); | ||
187 | pm->config->setup_dma = pm->configcr_dma; | ||
188 | pm->config->transfer_flags |= URB_NO_SETUP_DMA_MAP; | ||
189 | |||
190 | if (usb_submit_urb(pm->config, GFP_ATOMIC)) | ||
191 | printk(KERN_ERR "powermate: usb_submit_urb(config) failed"); | ||
192 | } | ||
193 | |||
194 | /* Called when our asynchronous control message completes. We may need to issue another immediately */ | ||
195 | static void powermate_config_complete(struct urb *urb, struct pt_regs *regs) | ||
196 | { | ||
197 | struct powermate_device *pm = urb->context; | ||
198 | unsigned long flags; | ||
199 | |||
200 | if (urb->status) | ||
201 | printk(KERN_ERR "powermate: config urb returned %d\n", urb->status); | ||
202 | |||
203 | spin_lock_irqsave(&pm->lock, flags); | ||
204 | powermate_sync_state(pm); | ||
205 | spin_unlock_irqrestore(&pm->lock, flags); | ||
206 | } | ||
207 | |||
208 | /* Set the LED up as described and begin the sync with the hardware if required */ | ||
209 | static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, | ||
210 | int pulse_table, int pulse_asleep, int pulse_awake) | ||
211 | { | ||
212 | unsigned long flags; | ||
213 | |||
214 | if (pulse_speed < 0) | ||
215 | pulse_speed = 0; | ||
216 | if (pulse_table < 0) | ||
217 | pulse_table = 0; | ||
218 | if (pulse_speed > 510) | ||
219 | pulse_speed = 510; | ||
220 | if (pulse_table > 2) | ||
221 | pulse_table = 2; | ||
222 | |||
223 | pulse_asleep = !!pulse_asleep; | ||
224 | pulse_awake = !!pulse_awake; | ||
225 | |||
226 | |||
227 | spin_lock_irqsave(&pm->lock, flags); | ||
228 | |||
229 | /* mark state updates which are required */ | ||
230 | if (static_brightness != pm->static_brightness){ | ||
231 | pm->static_brightness = static_brightness; | ||
232 | pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; | ||
233 | } | ||
234 | if (pulse_asleep != pm->pulse_asleep){ | ||
235 | pm->pulse_asleep = pulse_asleep; | ||
236 | pm->requires_update |= (UPDATE_PULSE_ASLEEP | UPDATE_STATIC_BRIGHTNESS); | ||
237 | } | ||
238 | if (pulse_awake != pm->pulse_awake){ | ||
239 | pm->pulse_awake = pulse_awake; | ||
240 | pm->requires_update |= (UPDATE_PULSE_AWAKE | UPDATE_STATIC_BRIGHTNESS); | ||
241 | } | ||
242 | if (pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table){ | ||
243 | pm->pulse_speed = pulse_speed; | ||
244 | pm->pulse_table = pulse_table; | ||
245 | pm->requires_update |= UPDATE_PULSE_MODE; | ||
246 | } | ||
247 | |||
248 | powermate_sync_state(pm); | ||
249 | |||
250 | spin_unlock_irqrestore(&pm->lock, flags); | ||
251 | } | ||
252 | |||
253 | /* Callback from the Input layer when an event arrives from userspace to configure the LED */ | ||
254 | static int powermate_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int _value) | ||
255 | { | ||
256 | unsigned int command = (unsigned int)_value; | ||
257 | struct powermate_device *pm = dev->private; | ||
258 | |||
259 | if (type == EV_MSC && code == MSC_PULSELED){ | ||
260 | /* | ||
261 | bits 0- 7: 8 bits: LED brightness | ||
262 | bits 8-16: 9 bits: pulsing speed modifier (0 ... 510); 0-254 = slower, 255 = standard, 256-510 = faster. | ||
263 | bits 17-18: 2 bits: pulse table (0, 1, 2 valid) | ||
264 | bit 19: 1 bit : pulse whilst asleep? | ||
265 | bit 20: 1 bit : pulse constantly? | ||
266 | */ | ||
267 | int static_brightness = command & 0xFF; // bits 0-7 | ||
268 | int pulse_speed = (command >> 8) & 0x1FF; // bits 8-16 | ||
269 | int pulse_table = (command >> 17) & 0x3; // bits 17-18 | ||
270 | int pulse_asleep = (command >> 19) & 0x1; // bit 19 | ||
271 | int pulse_awake = (command >> 20) & 0x1; // bit 20 | ||
272 | |||
273 | powermate_pulse_led(pm, static_brightness, pulse_speed, pulse_table, pulse_asleep, pulse_awake); | ||
274 | } | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm) | ||
280 | { | ||
281 | pm->data = usb_buffer_alloc(udev, POWERMATE_PAYLOAD_SIZE_MAX, | ||
282 | SLAB_ATOMIC, &pm->data_dma); | ||
283 | if (!pm->data) | ||
284 | return -1; | ||
285 | pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)), | ||
286 | SLAB_ATOMIC, &pm->configcr_dma); | ||
287 | if (!pm->configcr) | ||
288 | return -1; | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static void powermate_free_buffers(struct usb_device *udev, struct powermate_device *pm) | ||
294 | { | ||
295 | if (pm->data) | ||
296 | usb_buffer_free(udev, POWERMATE_PAYLOAD_SIZE_MAX, | ||
297 | pm->data, pm->data_dma); | ||
298 | if (pm->configcr) | ||
299 | usb_buffer_free(udev, sizeof(*(pm->configcr)), | ||
300 | pm->configcr, pm->configcr_dma); | ||
301 | } | ||
302 | |||
303 | /* Called whenever a USB device matching one in our supported devices table is connected */ | ||
304 | static int powermate_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
305 | { | ||
306 | struct usb_device *udev = interface_to_usbdev (intf); | ||
307 | struct usb_host_interface *interface; | ||
308 | struct usb_endpoint_descriptor *endpoint; | ||
309 | struct powermate_device *pm; | ||
310 | int pipe, maxp; | ||
311 | char path[64]; | ||
312 | |||
313 | interface = intf->cur_altsetting; | ||
314 | endpoint = &interface->endpoint[0].desc; | ||
315 | if (!(endpoint->bEndpointAddress & 0x80)) | ||
316 | return -EIO; | ||
317 | if ((endpoint->bmAttributes & 3) != 3) | ||
318 | return -EIO; | ||
319 | |||
320 | usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
321 | 0x0a, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
322 | 0, interface->desc.bInterfaceNumber, NULL, 0, | ||
323 | USB_CTRL_SET_TIMEOUT); | ||
324 | |||
325 | if (!(pm = kmalloc(sizeof(struct powermate_device), GFP_KERNEL))) | ||
326 | return -ENOMEM; | ||
327 | |||
328 | memset(pm, 0, sizeof(struct powermate_device)); | ||
329 | pm->udev = udev; | ||
330 | |||
331 | if (powermate_alloc_buffers(udev, pm)) { | ||
332 | powermate_free_buffers(udev, pm); | ||
333 | kfree(pm); | ||
334 | return -ENOMEM; | ||
335 | } | ||
336 | |||
337 | pm->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
338 | if (!pm->irq) { | ||
339 | powermate_free_buffers(udev, pm); | ||
340 | kfree(pm); | ||
341 | return -ENOMEM; | ||
342 | } | ||
343 | |||
344 | pm->config = usb_alloc_urb(0, GFP_KERNEL); | ||
345 | if (!pm->config) { | ||
346 | usb_free_urb(pm->irq); | ||
347 | powermate_free_buffers(udev, pm); | ||
348 | kfree(pm); | ||
349 | return -ENOMEM; | ||
350 | } | ||
351 | |||
352 | spin_lock_init(&pm->lock); | ||
353 | init_input_dev(&pm->input); | ||
354 | |||
355 | /* get a handle to the interrupt data pipe */ | ||
356 | pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); | ||
357 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
358 | |||
359 | if(maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX){ | ||
360 | printk("powermate: Expected payload of %d--%d bytes, found %d bytes!\n", | ||
361 | POWERMATE_PAYLOAD_SIZE_MIN, POWERMATE_PAYLOAD_SIZE_MAX, maxp); | ||
362 | maxp = POWERMATE_PAYLOAD_SIZE_MAX; | ||
363 | } | ||
364 | |||
365 | usb_fill_int_urb(pm->irq, udev, pipe, pm->data, | ||
366 | maxp, powermate_irq, | ||
367 | pm, endpoint->bInterval); | ||
368 | pm->irq->transfer_dma = pm->data_dma; | ||
369 | pm->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
370 | |||
371 | /* register our interrupt URB with the USB system */ | ||
372 | if (usb_submit_urb(pm->irq, GFP_KERNEL)) { | ||
373 | powermate_free_buffers(udev, pm); | ||
374 | kfree(pm); | ||
375 | return -EIO; /* failure */ | ||
376 | } | ||
377 | |||
378 | switch (le16_to_cpu(udev->descriptor.idProduct)) { | ||
379 | case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break; | ||
380 | case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break; | ||
381 | default: | ||
382 | pm->input.name = pm_name_soundknob; | ||
383 | printk(KERN_WARNING "powermate: unknown product id %04x\n", | ||
384 | le16_to_cpu(udev->descriptor.idProduct)); | ||
385 | } | ||
386 | |||
387 | pm->input.private = pm; | ||
388 | pm->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC); | ||
389 | pm->input.keybit[LONG(BTN_0)] = BIT(BTN_0); | ||
390 | pm->input.relbit[LONG(REL_DIAL)] = BIT(REL_DIAL); | ||
391 | pm->input.mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED); | ||
392 | pm->input.id.bustype = BUS_USB; | ||
393 | pm->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); | ||
394 | pm->input.id.product = le16_to_cpu(udev->descriptor.idProduct); | ||
395 | pm->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); | ||
396 | pm->input.event = powermate_input_event; | ||
397 | pm->input.dev = &intf->dev; | ||
398 | pm->input.phys = pm->phys; | ||
399 | |||
400 | input_register_device(&pm->input); | ||
401 | |||
402 | usb_make_path(udev, path, 64); | ||
403 | snprintf(pm->phys, 64, "%s/input0", path); | ||
404 | printk(KERN_INFO "input: %s on %s\n", pm->input.name, pm->input.phys); | ||
405 | |||
406 | /* force an update of everything */ | ||
407 | pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; | ||
408 | powermate_pulse_led(pm, 0x80, 255, 0, 1, 0); // set default pulse parameters | ||
409 | |||
410 | usb_set_intfdata(intf, pm); | ||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | /* Called when a USB device we've accepted ownership of is removed */ | ||
415 | static void powermate_disconnect(struct usb_interface *intf) | ||
416 | { | ||
417 | struct powermate_device *pm = usb_get_intfdata (intf); | ||
418 | |||
419 | usb_set_intfdata(intf, NULL); | ||
420 | if (pm) { | ||
421 | pm->requires_update = 0; | ||
422 | usb_kill_urb(pm->irq); | ||
423 | input_unregister_device(&pm->input); | ||
424 | usb_free_urb(pm->irq); | ||
425 | usb_free_urb(pm->config); | ||
426 | powermate_free_buffers(interface_to_usbdev(intf), pm); | ||
427 | |||
428 | kfree(pm); | ||
429 | } | ||
430 | } | ||
431 | |||
432 | static struct usb_device_id powermate_devices [] = { | ||
433 | { USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_NEW) }, | ||
434 | { USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_OLD) }, | ||
435 | { USB_DEVICE(CONTOUR_VENDOR, CONTOUR_JOG) }, | ||
436 | { } /* Terminating entry */ | ||
437 | }; | ||
438 | |||
439 | MODULE_DEVICE_TABLE (usb, powermate_devices); | ||
440 | |||
441 | static struct usb_driver powermate_driver = { | ||
442 | .owner = THIS_MODULE, | ||
443 | .name = "powermate", | ||
444 | .probe = powermate_probe, | ||
445 | .disconnect = powermate_disconnect, | ||
446 | .id_table = powermate_devices, | ||
447 | }; | ||
448 | |||
449 | static int __init powermate_init(void) | ||
450 | { | ||
451 | return usb_register(&powermate_driver); | ||
452 | } | ||
453 | |||
454 | static void __exit powermate_cleanup(void) | ||
455 | { | ||
456 | usb_deregister(&powermate_driver); | ||
457 | } | ||
458 | |||
459 | module_init(powermate_init); | ||
460 | module_exit(powermate_cleanup); | ||
461 | |||
462 | MODULE_AUTHOR( "William R Sowerbutts" ); | ||
463 | MODULE_DESCRIPTION( "Griffin Technology, Inc PowerMate driver" ); | ||
464 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c new file mode 100644 index 000000000000..a71f1bbd0a17 --- /dev/null +++ b/drivers/usb/input/touchkitusb.c | |||
@@ -0,0 +1,310 @@ | |||
1 | /****************************************************************************** | ||
2 | * touchkitusb.c -- Driver for eGalax TouchKit USB Touchscreens | ||
3 | * | ||
4 | * Copyright (C) 2004 by Daniel Ritz | ||
5 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of the | ||
10 | * License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | * Based upon mtouchusb.c | ||
22 | * | ||
23 | *****************************************************************************/ | ||
24 | |||
25 | //#define DEBUG | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/input.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | |||
34 | #if !defined(DEBUG) && defined(CONFIG_USB_DEBUG) | ||
35 | #define DEBUG | ||
36 | #endif | ||
37 | #include <linux/usb.h> | ||
38 | |||
39 | |||
40 | #define TOUCHKIT_MIN_XC 0x0 | ||
41 | #define TOUCHKIT_MAX_XC 0x07ff | ||
42 | #define TOUCHKIT_XC_FUZZ 0x0 | ||
43 | #define TOUCHKIT_XC_FLAT 0x0 | ||
44 | #define TOUCHKIT_MIN_YC 0x0 | ||
45 | #define TOUCHKIT_MAX_YC 0x07ff | ||
46 | #define TOUCHKIT_YC_FUZZ 0x0 | ||
47 | #define TOUCHKIT_YC_FLAT 0x0 | ||
48 | #define TOUCHKIT_REPORT_DATA_SIZE 8 | ||
49 | |||
50 | #define TOUCHKIT_DOWN 0x01 | ||
51 | #define TOUCHKIT_POINT_TOUCH 0x81 | ||
52 | #define TOUCHKIT_POINT_NOTOUCH 0x80 | ||
53 | |||
54 | #define TOUCHKIT_GET_TOUCHED(dat) ((((dat)[0]) & TOUCHKIT_DOWN) ? 1 : 0) | ||
55 | #define TOUCHKIT_GET_X(dat) (((dat)[3] << 7) | (dat)[4]) | ||
56 | #define TOUCHKIT_GET_Y(dat) (((dat)[1] << 7) | (dat)[2]) | ||
57 | |||
58 | #define DRIVER_VERSION "v0.1" | ||
59 | #define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" | ||
60 | #define DRIVER_DESC "eGalax TouchKit USB HID Touchscreen Driver" | ||
61 | |||
62 | static int swap_xy; | ||
63 | module_param(swap_xy, bool, 0644); | ||
64 | MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); | ||
65 | |||
66 | struct touchkit_usb { | ||
67 | unsigned char *data; | ||
68 | dma_addr_t data_dma; | ||
69 | struct urb *irq; | ||
70 | struct usb_device *udev; | ||
71 | struct input_dev input; | ||
72 | int open; | ||
73 | char name[128]; | ||
74 | char phys[64]; | ||
75 | }; | ||
76 | |||
77 | static struct usb_device_id touchkit_devices[] = { | ||
78 | {USB_DEVICE(0x3823, 0x0001)}, | ||
79 | {USB_DEVICE(0x0eef, 0x0001)}, | ||
80 | {} | ||
81 | }; | ||
82 | |||
83 | static void touchkit_irq(struct urb *urb, struct pt_regs *regs) | ||
84 | { | ||
85 | struct touchkit_usb *touchkit = urb->context; | ||
86 | int retval; | ||
87 | int x, y; | ||
88 | |||
89 | switch (urb->status) { | ||
90 | case 0: | ||
91 | /* success */ | ||
92 | break; | ||
93 | case -ETIMEDOUT: | ||
94 | /* this urb is timing out */ | ||
95 | dbg("%s - urb timed out - was the device unplugged?", | ||
96 | __FUNCTION__); | ||
97 | return; | ||
98 | case -ECONNRESET: | ||
99 | case -ENOENT: | ||
100 | case -ESHUTDOWN: | ||
101 | /* this urb is terminated, clean up */ | ||
102 | dbg("%s - urb shutting down with status: %d", | ||
103 | __FUNCTION__, urb->status); | ||
104 | return; | ||
105 | default: | ||
106 | dbg("%s - nonzero urb status received: %d", | ||
107 | __FUNCTION__, urb->status); | ||
108 | goto exit; | ||
109 | } | ||
110 | |||
111 | if (swap_xy) { | ||
112 | y = TOUCHKIT_GET_X(touchkit->data); | ||
113 | x = TOUCHKIT_GET_Y(touchkit->data); | ||
114 | } else { | ||
115 | x = TOUCHKIT_GET_X(touchkit->data); | ||
116 | y = TOUCHKIT_GET_Y(touchkit->data); | ||
117 | } | ||
118 | |||
119 | input_regs(&touchkit->input, regs); | ||
120 | input_report_key(&touchkit->input, BTN_TOUCH, | ||
121 | TOUCHKIT_GET_TOUCHED(touchkit->data)); | ||
122 | input_report_abs(&touchkit->input, ABS_X, x); | ||
123 | input_report_abs(&touchkit->input, ABS_Y, y); | ||
124 | input_sync(&touchkit->input); | ||
125 | |||
126 | exit: | ||
127 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
128 | if (retval) | ||
129 | err("%s - usb_submit_urb failed with result: %d", | ||
130 | __FUNCTION__, retval); | ||
131 | } | ||
132 | |||
133 | static int touchkit_open(struct input_dev *input) | ||
134 | { | ||
135 | struct touchkit_usb *touchkit = input->private; | ||
136 | |||
137 | if (touchkit->open++) | ||
138 | return 0; | ||
139 | |||
140 | touchkit->irq->dev = touchkit->udev; | ||
141 | |||
142 | if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) { | ||
143 | touchkit->open--; | ||
144 | return -EIO; | ||
145 | } | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static void touchkit_close(struct input_dev *input) | ||
151 | { | ||
152 | struct touchkit_usb *touchkit = input->private; | ||
153 | |||
154 | if (!--touchkit->open) | ||
155 | usb_kill_urb(touchkit->irq); | ||
156 | } | ||
157 | |||
158 | static int touchkit_alloc_buffers(struct usb_device *udev, | ||
159 | struct touchkit_usb *touchkit) | ||
160 | { | ||
161 | touchkit->data = usb_buffer_alloc(udev, TOUCHKIT_REPORT_DATA_SIZE, | ||
162 | SLAB_ATOMIC, &touchkit->data_dma); | ||
163 | |||
164 | if (!touchkit->data) | ||
165 | return -1; | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static void touchkit_free_buffers(struct usb_device *udev, | ||
171 | struct touchkit_usb *touchkit) | ||
172 | { | ||
173 | if (touchkit->data) | ||
174 | usb_buffer_free(udev, TOUCHKIT_REPORT_DATA_SIZE, | ||
175 | touchkit->data, touchkit->data_dma); | ||
176 | } | ||
177 | |||
178 | static int touchkit_probe(struct usb_interface *intf, | ||
179 | const struct usb_device_id *id) | ||
180 | { | ||
181 | int ret; | ||
182 | struct touchkit_usb *touchkit; | ||
183 | struct usb_host_interface *interface; | ||
184 | struct usb_endpoint_descriptor *endpoint; | ||
185 | struct usb_device *udev = interface_to_usbdev(intf); | ||
186 | char path[64]; | ||
187 | |||
188 | interface = intf->cur_altsetting; | ||
189 | endpoint = &interface->endpoint[0].desc; | ||
190 | |||
191 | touchkit = kmalloc(sizeof(struct touchkit_usb), GFP_KERNEL); | ||
192 | if (!touchkit) | ||
193 | return -ENOMEM; | ||
194 | |||
195 | memset(touchkit, 0, sizeof(struct touchkit_usb)); | ||
196 | touchkit->udev = udev; | ||
197 | |||
198 | if (touchkit_alloc_buffers(udev, touchkit)) { | ||
199 | ret = -ENOMEM; | ||
200 | goto out_free; | ||
201 | } | ||
202 | |||
203 | touchkit->input.private = touchkit; | ||
204 | touchkit->input.open = touchkit_open; | ||
205 | touchkit->input.close = touchkit_close; | ||
206 | |||
207 | usb_make_path(udev, path, 64); | ||
208 | sprintf(touchkit->phys, "%s/input0", path); | ||
209 | |||
210 | touchkit->input.name = touchkit->name; | ||
211 | touchkit->input.phys = touchkit->phys; | ||
212 | touchkit->input.id.bustype = BUS_USB; | ||
213 | touchkit->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); | ||
214 | touchkit->input.id.product = le16_to_cpu(udev->descriptor.idProduct); | ||
215 | touchkit->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); | ||
216 | touchkit->input.dev = &intf->dev; | ||
217 | |||
218 | touchkit->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
219 | touchkit->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); | ||
220 | touchkit->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
221 | |||
222 | /* Used to Scale Compensated Data */ | ||
223 | touchkit->input.absmin[ABS_X] = TOUCHKIT_MIN_XC; | ||
224 | touchkit->input.absmax[ABS_X] = TOUCHKIT_MAX_XC; | ||
225 | touchkit->input.absfuzz[ABS_X] = TOUCHKIT_XC_FUZZ; | ||
226 | touchkit->input.absflat[ABS_X] = TOUCHKIT_XC_FLAT; | ||
227 | touchkit->input.absmin[ABS_Y] = TOUCHKIT_MIN_YC; | ||
228 | touchkit->input.absmax[ABS_Y] = TOUCHKIT_MAX_YC; | ||
229 | touchkit->input.absfuzz[ABS_Y] = TOUCHKIT_YC_FUZZ; | ||
230 | touchkit->input.absflat[ABS_Y] = TOUCHKIT_YC_FLAT; | ||
231 | |||
232 | if (udev->manufacturer) | ||
233 | strcat(touchkit->name, udev->manufacturer); | ||
234 | if (udev->product) | ||
235 | sprintf(touchkit->name, "%s %s", touchkit->name, udev->product); | ||
236 | |||
237 | if (!strlen(touchkit->name)) | ||
238 | sprintf(touchkit->name, "USB Touchscreen %04x:%04x", | ||
239 | touchkit->input.id.vendor, touchkit->input.id.product); | ||
240 | |||
241 | touchkit->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
242 | if (!touchkit->irq) { | ||
243 | dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__); | ||
244 | ret = -ENOMEM; | ||
245 | goto out_free_buffers; | ||
246 | } | ||
247 | |||
248 | usb_fill_int_urb(touchkit->irq, touchkit->udev, | ||
249 | usb_rcvintpipe(touchkit->udev, 0x81), | ||
250 | touchkit->data, TOUCHKIT_REPORT_DATA_SIZE, | ||
251 | touchkit_irq, touchkit, endpoint->bInterval); | ||
252 | |||
253 | input_register_device(&touchkit->input); | ||
254 | |||
255 | printk(KERN_INFO "input: %s on %s\n", touchkit->name, path); | ||
256 | usb_set_intfdata(intf, touchkit); | ||
257 | |||
258 | return 0; | ||
259 | |||
260 | out_free_buffers: | ||
261 | touchkit_free_buffers(udev, touchkit); | ||
262 | out_free: | ||
263 | kfree(touchkit); | ||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | static void touchkit_disconnect(struct usb_interface *intf) | ||
268 | { | ||
269 | struct touchkit_usb *touchkit = usb_get_intfdata(intf); | ||
270 | |||
271 | dbg("%s - called", __FUNCTION__); | ||
272 | |||
273 | if (!touchkit) | ||
274 | return; | ||
275 | |||
276 | dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__); | ||
277 | usb_set_intfdata(intf, NULL); | ||
278 | input_unregister_device(&touchkit->input); | ||
279 | usb_kill_urb(touchkit->irq); | ||
280 | usb_free_urb(touchkit->irq); | ||
281 | touchkit_free_buffers(interface_to_usbdev(intf), touchkit); | ||
282 | kfree(touchkit); | ||
283 | } | ||
284 | |||
285 | MODULE_DEVICE_TABLE(usb, touchkit_devices); | ||
286 | |||
287 | static struct usb_driver touchkit_driver = { | ||
288 | .owner = THIS_MODULE, | ||
289 | .name = "touchkitusb", | ||
290 | .probe = touchkit_probe, | ||
291 | .disconnect = touchkit_disconnect, | ||
292 | .id_table = touchkit_devices, | ||
293 | }; | ||
294 | |||
295 | static int __init touchkit_init(void) | ||
296 | { | ||
297 | return usb_register(&touchkit_driver); | ||
298 | } | ||
299 | |||
300 | static void __exit touchkit_cleanup(void) | ||
301 | { | ||
302 | usb_deregister(&touchkit_driver); | ||
303 | } | ||
304 | |||
305 | module_init(touchkit_init); | ||
306 | module_exit(touchkit_cleanup); | ||
307 | |||
308 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
309 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
310 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c new file mode 100644 index 000000000000..01514b0551b8 --- /dev/null +++ b/drivers/usb/input/usbkbd.c | |||
@@ -0,0 +1,370 @@ | |||
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/input.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/usb.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 | int open; | ||
76 | |||
77 | unsigned char *new; | ||
78 | struct usb_ctrlrequest *cr; | ||
79 | unsigned char *leds; | ||
80 | dma_addr_t cr_dma; | ||
81 | dma_addr_t new_dma; | ||
82 | dma_addr_t leds_dma; | ||
83 | }; | ||
84 | |||
85 | static void usb_kbd_irq(struct urb *urb, struct pt_regs *regs) | ||
86 | { | ||
87 | struct usb_kbd *kbd = urb->context; | ||
88 | int i; | ||
89 | |||
90 | switch (urb->status) { | ||
91 | case 0: /* success */ | ||
92 | break; | ||
93 | case -ECONNRESET: /* unlink */ | ||
94 | case -ENOENT: | ||
95 | case -ESHUTDOWN: | ||
96 | return; | ||
97 | /* -EPIPE: should clear the halt */ | ||
98 | default: /* error */ | ||
99 | goto resubmit; | ||
100 | } | ||
101 | |||
102 | input_regs(&kbd->dev, regs); | ||
103 | |||
104 | for (i = 0; i < 8; i++) | ||
105 | input_report_key(&kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1); | ||
106 | |||
107 | for (i = 2; i < 8; i++) { | ||
108 | |||
109 | if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) { | ||
110 | if (usb_kbd_keycode[kbd->old[i]]) | ||
111 | input_report_key(&kbd->dev, usb_kbd_keycode[kbd->old[i]], 0); | ||
112 | else | ||
113 | info("Unknown key (scancode %#x) released.", kbd->old[i]); | ||
114 | } | ||
115 | |||
116 | if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) { | ||
117 | if (usb_kbd_keycode[kbd->new[i]]) | ||
118 | input_report_key(&kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); | ||
119 | else | ||
120 | info("Unknown key (scancode %#x) pressed.", kbd->new[i]); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | input_sync(&kbd->dev); | ||
125 | |||
126 | memcpy(kbd->old, kbd->new, 8); | ||
127 | |||
128 | resubmit: | ||
129 | i = usb_submit_urb (urb, SLAB_ATOMIC); | ||
130 | if (i) | ||
131 | err ("can't resubmit intr, %s-%s/input0, status %d", | ||
132 | kbd->usbdev->bus->bus_name, | ||
133 | kbd->usbdev->devpath, i); | ||
134 | } | ||
135 | |||
136 | int usb_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | ||
137 | { | ||
138 | struct usb_kbd *kbd = dev->private; | ||
139 | |||
140 | if (type != EV_LED) | ||
141 | return -1; | ||
142 | |||
143 | |||
144 | kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | | ||
145 | (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | | ||
146 | (!!test_bit(LED_NUML, dev->led)); | ||
147 | |||
148 | if (kbd->led->status == -EINPROGRESS) | ||
149 | return 0; | ||
150 | |||
151 | if (*(kbd->leds) == kbd->newleds) | ||
152 | return 0; | ||
153 | |||
154 | *(kbd->leds) = kbd->newleds; | ||
155 | kbd->led->dev = kbd->usbdev; | ||
156 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) | ||
157 | err("usb_submit_urb(leds) failed"); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static void usb_kbd_led(struct urb *urb, struct pt_regs *regs) | ||
163 | { | ||
164 | struct usb_kbd *kbd = urb->context; | ||
165 | |||
166 | if (urb->status) | ||
167 | warn("led urb status %d received", urb->status); | ||
168 | |||
169 | if (*(kbd->leds) == kbd->newleds) | ||
170 | return; | ||
171 | |||
172 | *(kbd->leds) = kbd->newleds; | ||
173 | kbd->led->dev = kbd->usbdev; | ||
174 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) | ||
175 | err("usb_submit_urb(leds) failed"); | ||
176 | } | ||
177 | |||
178 | static int usb_kbd_open(struct input_dev *dev) | ||
179 | { | ||
180 | struct usb_kbd *kbd = dev->private; | ||
181 | |||
182 | if (kbd->open++) | ||
183 | return 0; | ||
184 | |||
185 | kbd->irq->dev = kbd->usbdev; | ||
186 | if (usb_submit_urb(kbd->irq, GFP_KERNEL)) { | ||
187 | kbd->open--; | ||
188 | return -EIO; | ||
189 | } | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static void usb_kbd_close(struct input_dev *dev) | ||
195 | { | ||
196 | struct usb_kbd *kbd = dev->private; | ||
197 | |||
198 | if (!--kbd->open) | ||
199 | usb_kill_urb(kbd->irq); | ||
200 | } | ||
201 | |||
202 | static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) | ||
203 | { | ||
204 | if (!(kbd->irq = usb_alloc_urb(0, GFP_KERNEL))) | ||
205 | return -1; | ||
206 | if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL))) | ||
207 | return -1; | ||
208 | if (!(kbd->new = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kbd->new_dma))) | ||
209 | return -1; | ||
210 | if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), SLAB_ATOMIC, &kbd->cr_dma))) | ||
211 | return -1; | ||
212 | if (!(kbd->leds = usb_buffer_alloc(dev, 1, SLAB_ATOMIC, &kbd->leds_dma))) | ||
213 | return -1; | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) | ||
219 | { | ||
220 | if (kbd->irq) | ||
221 | usb_free_urb(kbd->irq); | ||
222 | if (kbd->led) | ||
223 | usb_free_urb(kbd->led); | ||
224 | if (kbd->new) | ||
225 | usb_buffer_free(dev, 8, kbd->new, kbd->new_dma); | ||
226 | if (kbd->cr) | ||
227 | usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma); | ||
228 | if (kbd->leds) | ||
229 | usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); | ||
230 | } | ||
231 | |||
232 | static int usb_kbd_probe(struct usb_interface *iface, | ||
233 | const struct usb_device_id *id) | ||
234 | { | ||
235 | struct usb_device * dev = interface_to_usbdev(iface); | ||
236 | struct usb_host_interface *interface; | ||
237 | struct usb_endpoint_descriptor *endpoint; | ||
238 | struct usb_kbd *kbd; | ||
239 | int i, pipe, maxp; | ||
240 | char path[64]; | ||
241 | |||
242 | interface = iface->cur_altsetting; | ||
243 | |||
244 | if (interface->desc.bNumEndpoints != 1) | ||
245 | return -ENODEV; | ||
246 | |||
247 | endpoint = &interface->endpoint[0].desc; | ||
248 | if (!(endpoint->bEndpointAddress & 0x80)) | ||
249 | return -ENODEV; | ||
250 | if ((endpoint->bmAttributes & 3) != 3) | ||
251 | return -ENODEV; | ||
252 | |||
253 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
254 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | ||
255 | |||
256 | if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) | ||
257 | return -ENOMEM; | ||
258 | memset(kbd, 0, sizeof(struct usb_kbd)); | ||
259 | |||
260 | if (usb_kbd_alloc_mem(dev, kbd)) { | ||
261 | usb_kbd_free_mem(dev, kbd); | ||
262 | kfree(kbd); | ||
263 | return -ENOMEM; | ||
264 | } | ||
265 | |||
266 | kbd->usbdev = dev; | ||
267 | |||
268 | kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); | ||
269 | kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA); | ||
270 | |||
271 | for (i = 0; i < 255; i++) | ||
272 | set_bit(usb_kbd_keycode[i], kbd->dev.keybit); | ||
273 | clear_bit(0, kbd->dev.keybit); | ||
274 | |||
275 | kbd->dev.private = kbd; | ||
276 | kbd->dev.event = usb_kbd_event; | ||
277 | kbd->dev.open = usb_kbd_open; | ||
278 | kbd->dev.close = usb_kbd_close; | ||
279 | |||
280 | usb_fill_int_urb(kbd->irq, dev, pipe, | ||
281 | kbd->new, (maxp > 8 ? 8 : maxp), | ||
282 | usb_kbd_irq, kbd, endpoint->bInterval); | ||
283 | kbd->irq->transfer_dma = kbd->new_dma; | ||
284 | kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
285 | |||
286 | kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||
287 | kbd->cr->bRequest = 0x09; | ||
288 | kbd->cr->wValue = cpu_to_le16(0x200); | ||
289 | kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); | ||
290 | kbd->cr->wLength = cpu_to_le16(1); | ||
291 | |||
292 | usb_make_path(dev, path, 64); | ||
293 | sprintf(kbd->phys, "%s/input0", path); | ||
294 | |||
295 | kbd->dev.name = kbd->name; | ||
296 | kbd->dev.phys = kbd->phys; | ||
297 | kbd->dev.id.bustype = BUS_USB; | ||
298 | kbd->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
299 | kbd->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); | ||
300 | kbd->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); | ||
301 | kbd->dev.dev = &iface->dev; | ||
302 | |||
303 | if (dev->manufacturer) | ||
304 | strcat(kbd->name, dev->manufacturer); | ||
305 | if (dev->product) | ||
306 | sprintf(kbd->name, "%s %s", kbd->name, dev->product); | ||
307 | |||
308 | if (!strlen(kbd->name)) | ||
309 | sprintf(kbd->name, "USB HIDBP Keyboard %04x:%04x", | ||
310 | kbd->dev.id.vendor, kbd->dev.id.product); | ||
311 | |||
312 | usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0), | ||
313 | (void *) kbd->cr, kbd->leds, 1, | ||
314 | usb_kbd_led, kbd); | ||
315 | kbd->led->setup_dma = kbd->cr_dma; | ||
316 | kbd->led->transfer_dma = kbd->leds_dma; | ||
317 | kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | ||
318 | | URB_NO_SETUP_DMA_MAP); | ||
319 | |||
320 | input_register_device(&kbd->dev); | ||
321 | |||
322 | printk(KERN_INFO "input: %s on %s\n", kbd->name, path); | ||
323 | |||
324 | usb_set_intfdata(iface, kbd); | ||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static void usb_kbd_disconnect(struct usb_interface *intf) | ||
329 | { | ||
330 | struct usb_kbd *kbd = usb_get_intfdata (intf); | ||
331 | |||
332 | usb_set_intfdata(intf, NULL); | ||
333 | if (kbd) { | ||
334 | usb_kill_urb(kbd->irq); | ||
335 | input_unregister_device(&kbd->dev); | ||
336 | usb_kbd_free_mem(interface_to_usbdev(intf), kbd); | ||
337 | kfree(kbd); | ||
338 | } | ||
339 | } | ||
340 | |||
341 | static struct usb_device_id usb_kbd_id_table [] = { | ||
342 | { USB_INTERFACE_INFO(3, 1, 1) }, | ||
343 | { } /* Terminating entry */ | ||
344 | }; | ||
345 | |||
346 | MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); | ||
347 | |||
348 | static struct usb_driver usb_kbd_driver = { | ||
349 | .owner = THIS_MODULE, | ||
350 | .name = "usbkbd", | ||
351 | .probe = usb_kbd_probe, | ||
352 | .disconnect = usb_kbd_disconnect, | ||
353 | .id_table = usb_kbd_id_table, | ||
354 | }; | ||
355 | |||
356 | static int __init usb_kbd_init(void) | ||
357 | { | ||
358 | int result = usb_register(&usb_kbd_driver); | ||
359 | if (result == 0) | ||
360 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
361 | return result; | ||
362 | } | ||
363 | |||
364 | static void __exit usb_kbd_exit(void) | ||
365 | { | ||
366 | usb_deregister(&usb_kbd_driver); | ||
367 | } | ||
368 | |||
369 | module_init(usb_kbd_init); | ||
370 | module_exit(usb_kbd_exit); | ||
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c new file mode 100644 index 000000000000..01155bbddd43 --- /dev/null +++ b/drivers/usb/input/usbmouse.c | |||
@@ -0,0 +1,252 @@ | |||
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/input.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/usb.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 | int open; | ||
55 | |||
56 | signed char *data; | ||
57 | dma_addr_t data_dma; | ||
58 | }; | ||
59 | |||
60 | static void usb_mouse_irq(struct urb *urb, struct pt_regs *regs) | ||
61 | { | ||
62 | struct usb_mouse *mouse = urb->context; | ||
63 | signed char *data = mouse->data; | ||
64 | struct input_dev *dev = &mouse->dev; | ||
65 | int status; | ||
66 | |||
67 | switch (urb->status) { | ||
68 | case 0: /* success */ | ||
69 | break; | ||
70 | case -ECONNRESET: /* unlink */ | ||
71 | case -ENOENT: | ||
72 | case -ESHUTDOWN: | ||
73 | return; | ||
74 | /* -EPIPE: should clear the halt */ | ||
75 | default: /* error */ | ||
76 | goto resubmit; | ||
77 | } | ||
78 | |||
79 | input_regs(dev, regs); | ||
80 | |||
81 | input_report_key(dev, BTN_LEFT, data[0] & 0x01); | ||
82 | input_report_key(dev, BTN_RIGHT, data[0] & 0x02); | ||
83 | input_report_key(dev, BTN_MIDDLE, data[0] & 0x04); | ||
84 | input_report_key(dev, BTN_SIDE, data[0] & 0x08); | ||
85 | input_report_key(dev, BTN_EXTRA, data[0] & 0x10); | ||
86 | |||
87 | input_report_rel(dev, REL_X, data[1]); | ||
88 | input_report_rel(dev, REL_Y, data[2]); | ||
89 | input_report_rel(dev, REL_WHEEL, data[3]); | ||
90 | |||
91 | input_sync(dev); | ||
92 | resubmit: | ||
93 | status = usb_submit_urb (urb, SLAB_ATOMIC); | ||
94 | if (status) | ||
95 | err ("can't resubmit intr, %s-%s/input0, status %d", | ||
96 | mouse->usbdev->bus->bus_name, | ||
97 | mouse->usbdev->devpath, status); | ||
98 | } | ||
99 | |||
100 | static int usb_mouse_open(struct input_dev *dev) | ||
101 | { | ||
102 | struct usb_mouse *mouse = dev->private; | ||
103 | |||
104 | if (mouse->open++) | ||
105 | return 0; | ||
106 | |||
107 | mouse->irq->dev = mouse->usbdev; | ||
108 | if (usb_submit_urb(mouse->irq, GFP_KERNEL)) { | ||
109 | mouse->open--; | ||
110 | return -EIO; | ||
111 | } | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static void usb_mouse_close(struct input_dev *dev) | ||
117 | { | ||
118 | struct usb_mouse *mouse = dev->private; | ||
119 | |||
120 | if (!--mouse->open) | ||
121 | usb_kill_urb(mouse->irq); | ||
122 | } | ||
123 | |||
124 | static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id) | ||
125 | { | ||
126 | struct usb_device * dev = interface_to_usbdev(intf); | ||
127 | struct usb_host_interface *interface; | ||
128 | struct usb_endpoint_descriptor *endpoint; | ||
129 | struct usb_mouse *mouse; | ||
130 | int pipe, maxp; | ||
131 | char path[64]; | ||
132 | |||
133 | interface = intf->cur_altsetting; | ||
134 | |||
135 | if (interface->desc.bNumEndpoints != 1) | ||
136 | return -ENODEV; | ||
137 | |||
138 | endpoint = &interface->endpoint[0].desc; | ||
139 | if (!(endpoint->bEndpointAddress & 0x80)) | ||
140 | return -ENODEV; | ||
141 | if ((endpoint->bmAttributes & 3) != 3) | ||
142 | return -ENODEV; | ||
143 | |||
144 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
145 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | ||
146 | |||
147 | if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) | ||
148 | return -ENOMEM; | ||
149 | memset(mouse, 0, sizeof(struct usb_mouse)); | ||
150 | |||
151 | mouse->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &mouse->data_dma); | ||
152 | if (!mouse->data) { | ||
153 | kfree(mouse); | ||
154 | return -ENOMEM; | ||
155 | } | ||
156 | |||
157 | mouse->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
158 | if (!mouse->irq) { | ||
159 | usb_buffer_free(dev, 8, mouse->data, mouse->data_dma); | ||
160 | kfree(mouse); | ||
161 | return -ENODEV; | ||
162 | } | ||
163 | |||
164 | mouse->usbdev = dev; | ||
165 | |||
166 | mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
167 | mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
168 | mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
169 | mouse->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA); | ||
170 | mouse->dev.relbit[0] |= BIT(REL_WHEEL); | ||
171 | |||
172 | mouse->dev.private = mouse; | ||
173 | mouse->dev.open = usb_mouse_open; | ||
174 | mouse->dev.close = usb_mouse_close; | ||
175 | |||
176 | usb_make_path(dev, path, 64); | ||
177 | sprintf(mouse->phys, "%s/input0", path); | ||
178 | |||
179 | mouse->dev.name = mouse->name; | ||
180 | mouse->dev.phys = mouse->phys; | ||
181 | mouse->dev.id.bustype = BUS_USB; | ||
182 | mouse->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
183 | mouse->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); | ||
184 | mouse->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); | ||
185 | mouse->dev.dev = &intf->dev; | ||
186 | |||
187 | if (dev->manufacturer) | ||
188 | strcat(mouse->name, dev->manufacturer); | ||
189 | if (dev->product) | ||
190 | sprintf(mouse->name, "%s %s", mouse->name, dev->product); | ||
191 | |||
192 | if (!strlen(mouse->name)) | ||
193 | sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x", | ||
194 | mouse->dev.id.vendor, mouse->dev.id.product); | ||
195 | |||
196 | usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data, | ||
197 | (maxp > 8 ? 8 : maxp), | ||
198 | usb_mouse_irq, mouse, endpoint->bInterval); | ||
199 | mouse->irq->transfer_dma = mouse->data_dma; | ||
200 | mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
201 | |||
202 | input_register_device(&mouse->dev); | ||
203 | printk(KERN_INFO "input: %s on %s\n", mouse->name, path); | ||
204 | |||
205 | usb_set_intfdata(intf, mouse); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static void usb_mouse_disconnect(struct usb_interface *intf) | ||
210 | { | ||
211 | struct usb_mouse *mouse = usb_get_intfdata (intf); | ||
212 | |||
213 | usb_set_intfdata(intf, NULL); | ||
214 | if (mouse) { | ||
215 | usb_kill_urb(mouse->irq); | ||
216 | input_unregister_device(&mouse->dev); | ||
217 | usb_free_urb(mouse->irq); | ||
218 | usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma); | ||
219 | kfree(mouse); | ||
220 | } | ||
221 | } | ||
222 | |||
223 | static struct usb_device_id usb_mouse_id_table [] = { | ||
224 | { USB_INTERFACE_INFO(3, 1, 2) }, | ||
225 | { } /* Terminating entry */ | ||
226 | }; | ||
227 | |||
228 | MODULE_DEVICE_TABLE (usb, usb_mouse_id_table); | ||
229 | |||
230 | static struct usb_driver usb_mouse_driver = { | ||
231 | .owner = THIS_MODULE, | ||
232 | .name = "usbmouse", | ||
233 | .probe = usb_mouse_probe, | ||
234 | .disconnect = usb_mouse_disconnect, | ||
235 | .id_table = usb_mouse_id_table, | ||
236 | }; | ||
237 | |||
238 | static int __init usb_mouse_init(void) | ||
239 | { | ||
240 | int retval = usb_register(&usb_mouse_driver); | ||
241 | if (retval == 0) | ||
242 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
243 | return retval; | ||
244 | } | ||
245 | |||
246 | static void __exit usb_mouse_exit(void) | ||
247 | { | ||
248 | usb_deregister(&usb_mouse_driver); | ||
249 | } | ||
250 | |||
251 | module_init(usb_mouse_init); | ||
252 | module_exit(usb_mouse_exit); | ||
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c new file mode 100644 index 000000000000..fec04dda088e --- /dev/null +++ b/drivers/usb/input/wacom.c | |||
@@ -0,0 +1,951 @@ | |||
1 | /* | ||
2 | * USB Wacom Graphire and Wacom Intuos tablet support | ||
3 | * | ||
4 | * Copyright (c) 2000-2004 Vojtech Pavlik <vojtech@ucw.cz> | ||
5 | * Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk> | ||
6 | * Copyright (c) 2000 Clifford Wolf <clifford@clifford.at> | ||
7 | * Copyright (c) 2000 Sam Mosel <sam.mosel@computer.org> | ||
8 | * Copyright (c) 2000 James E. Blair <corvus@gnu.org> | ||
9 | * Copyright (c) 2000 Daniel Egger <egger@suse.de> | ||
10 | * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> | ||
11 | * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> | ||
12 | * Copyright (c) 2002-2004 Ping Cheng <pingc@wacom.com> | ||
13 | * | ||
14 | * ChangeLog: | ||
15 | * v0.1 (vp) - Initial release | ||
16 | * v0.2 (aba) - Support for all buttons / combinations | ||
17 | * v0.3 (vp) - Support for Intuos added | ||
18 | * v0.4 (sm) - Support for more Intuos models, menustrip | ||
19 | * relative mode, proximity. | ||
20 | * v0.5 (vp) - Big cleanup, nifty features removed, | ||
21 | * they belong in userspace | ||
22 | * v1.8 (vp) - Submit URB only when operating, moved to CVS, | ||
23 | * use input_report_key instead of report_btn and | ||
24 | * other cleanups | ||
25 | * v1.11 (vp) - Add URB ->dev setting for new kernels | ||
26 | * v1.11 (jb) - Add support for the 4D Mouse & Lens | ||
27 | * v1.12 (de) - Add support for two more inking pen IDs | ||
28 | * v1.14 (vp) - Use new USB device id probing scheme. | ||
29 | * Fix Wacom Graphire mouse wheel | ||
30 | * v1.18 (vp) - Fix mouse wheel direction | ||
31 | * Make mouse relative | ||
32 | * v1.20 (fl) - Report tool id for Intuos devices | ||
33 | * - Multi tools support | ||
34 | * - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...) | ||
35 | * - Add PL models support | ||
36 | * - Fix Wacom Graphire mouse wheel again | ||
37 | * v1.21 (vp) - Removed protocol descriptions | ||
38 | * - Added MISC_SERIAL for tool serial numbers | ||
39 | * (gb) - Identify version on module load. | ||
40 | * v1.21.1 (fl) - added Graphire2 support | ||
41 | * v1.21.2 (fl) - added Intuos2 support | ||
42 | * - added all the PL ids | ||
43 | * v1.21.3 (fl) - added another eraser id from Neil Okamoto | ||
44 | * - added smooth filter for Graphire from Peri Hankey | ||
45 | * - added PenPartner support from Olaf van Es | ||
46 | * - new tool ids from Ole Martin Bjoerndalen | ||
47 | * v1.29 (pc) - Add support for more tablets | ||
48 | * - Fix pressure reporting | ||
49 | * v1.30 (vp) - Merge 2.4 and 2.5 drivers | ||
50 | * - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse | ||
51 | * - Cleanups here and there | ||
52 | * v1.30.1 (pi) - Added Graphire3 support | ||
53 | * v1.40 (pc) - Add support for several new devices, fix eraser reporting, ... | ||
54 | */ | ||
55 | |||
56 | /* | ||
57 | * This program is free software; you can redistribute it and/or modify | ||
58 | * it under the terms of the GNU General Public License as published by | ||
59 | * the Free Software Foundation; either version 2 of the License, or | ||
60 | * (at your option) any later version. | ||
61 | */ | ||
62 | |||
63 | #include <linux/kernel.h> | ||
64 | #include <linux/slab.h> | ||
65 | #include <linux/input.h> | ||
66 | #include <linux/module.h> | ||
67 | #include <linux/init.h> | ||
68 | #include <linux/usb.h> | ||
69 | #include <asm/unaligned.h> | ||
70 | #include <asm/byteorder.h> | ||
71 | |||
72 | /* | ||
73 | * Version Information | ||
74 | */ | ||
75 | #define DRIVER_VERSION "v1.40" | ||
76 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | ||
77 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" | ||
78 | #define DRIVER_LICENSE "GPL" | ||
79 | |||
80 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
81 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
82 | MODULE_LICENSE(DRIVER_LICENSE); | ||
83 | |||
84 | #define USB_VENDOR_ID_WACOM 0x056a | ||
85 | |||
86 | struct wacom_features { | ||
87 | char *name; | ||
88 | int pktlen; | ||
89 | int x_max; | ||
90 | int y_max; | ||
91 | int pressure_max; | ||
92 | int distance_max; | ||
93 | int type; | ||
94 | usb_complete_t irq; | ||
95 | }; | ||
96 | |||
97 | struct wacom { | ||
98 | signed char *data; | ||
99 | dma_addr_t data_dma; | ||
100 | struct input_dev dev; | ||
101 | struct usb_device *usbdev; | ||
102 | struct urb *irq; | ||
103 | struct wacom_features *features; | ||
104 | int tool[2]; | ||
105 | int open; | ||
106 | __u32 serial[2]; | ||
107 | char phys[32]; | ||
108 | }; | ||
109 | |||
110 | #define USB_REQ_SET_REPORT 0x09 | ||
111 | static int usb_set_report(struct usb_interface *intf, unsigned char type, | ||
112 | unsigned char id, void *buf, int size) | ||
113 | { | ||
114 | return usb_control_msg(interface_to_usbdev(intf), | ||
115 | usb_sndctrlpipe(interface_to_usbdev(intf), 0), | ||
116 | USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
117 | (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, | ||
118 | buf, size, 1000); | ||
119 | } | ||
120 | |||
121 | static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | ||
122 | { | ||
123 | struct wacom *wacom = urb->context; | ||
124 | unsigned char *data = wacom->data; | ||
125 | struct input_dev *dev = &wacom->dev; | ||
126 | int prox, pressure; | ||
127 | int retval; | ||
128 | |||
129 | switch (urb->status) { | ||
130 | case 0: | ||
131 | /* success */ | ||
132 | break; | ||
133 | case -ECONNRESET: | ||
134 | case -ENOENT: | ||
135 | case -ESHUTDOWN: | ||
136 | /* this urb is terminated, clean up */ | ||
137 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
138 | return; | ||
139 | default: | ||
140 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
141 | goto exit; | ||
142 | } | ||
143 | |||
144 | if (data[0] != 2) { | ||
145 | dbg("wacom_pl_irq: received unknown report #%d", data[0]); | ||
146 | goto exit; | ||
147 | } | ||
148 | |||
149 | prox = data[1] & 0x40; | ||
150 | |||
151 | input_regs(dev, regs); | ||
152 | |||
153 | if (prox) { | ||
154 | |||
155 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); | ||
156 | if (wacom->features->pressure_max > 255) | ||
157 | pressure = (pressure << 1) | ((data[4] >> 6) & 1); | ||
158 | pressure += (wacom->features->pressure_max + 1) / 2; | ||
159 | |||
160 | /* | ||
161 | * if going from out of proximity into proximity select between the eraser | ||
162 | * and the pen based on the state of the stylus2 button, choose eraser if | ||
163 | * pressed else choose pen. if not a proximity change from out to in, send | ||
164 | * an out of proximity for previous tool then a in for new tool. | ||
165 | */ | ||
166 | if (!wacom->tool[0]) { | ||
167 | /* Going into proximity select tool */ | ||
168 | wacom->tool[1] = (data[4] & 0x20)? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
169 | } | ||
170 | else { | ||
171 | /* was entered with stylus2 pressed */ | ||
172 | if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20) ) { | ||
173 | /* report out proximity for previous tool */ | ||
174 | input_report_key(dev, wacom->tool[1], 0); | ||
175 | input_sync(dev); | ||
176 | wacom->tool[1] = BTN_TOOL_PEN; | ||
177 | goto exit; | ||
178 | } | ||
179 | } | ||
180 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | ||
181 | /* Unknown tool selected default to pen tool */ | ||
182 | wacom->tool[1] = BTN_TOOL_PEN; | ||
183 | } | ||
184 | input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */ | ||
185 | input_report_abs(dev, ABS_X, data[3] | ((__u32)data[2] << 7) | ((__u32)(data[1] & 0x03) << 14)); | ||
186 | input_report_abs(dev, ABS_Y, data[6] | ((__u32)data[5] << 7) | ((__u32)(data[4] & 0x03) << 14)); | ||
187 | input_report_abs(dev, ABS_PRESSURE, pressure); | ||
188 | |||
189 | input_report_key(dev, BTN_TOUCH, data[4] & 0x08); | ||
190 | input_report_key(dev, BTN_STYLUS, data[4] & 0x10); | ||
191 | /* Only allow the stylus2 button to be reported for the pen tool. */ | ||
192 | input_report_key(dev, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); | ||
193 | } | ||
194 | else { | ||
195 | /* report proximity-out of a (valid) tool */ | ||
196 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | ||
197 | /* Unknown tool selected default to pen tool */ | ||
198 | wacom->tool[1] = BTN_TOOL_PEN; | ||
199 | } | ||
200 | input_report_key(dev, wacom->tool[1], prox); | ||
201 | } | ||
202 | |||
203 | wacom->tool[0] = prox; /* Save proximity state */ | ||
204 | input_sync(dev); | ||
205 | |||
206 | exit: | ||
207 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
208 | if (retval) | ||
209 | err ("%s - usb_submit_urb failed with result %d", | ||
210 | __FUNCTION__, retval); | ||
211 | } | ||
212 | |||
213 | static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs) | ||
214 | { | ||
215 | struct wacom *wacom = urb->context; | ||
216 | unsigned char *data = wacom->data; | ||
217 | struct input_dev *dev = &wacom->dev; | ||
218 | int retval; | ||
219 | |||
220 | switch (urb->status) { | ||
221 | case 0: | ||
222 | /* success */ | ||
223 | break; | ||
224 | case -ECONNRESET: | ||
225 | case -ENOENT: | ||
226 | case -ESHUTDOWN: | ||
227 | /* this urb is terminated, clean up */ | ||
228 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
229 | return; | ||
230 | default: | ||
231 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
232 | goto exit; | ||
233 | } | ||
234 | |||
235 | if (data[0] != 2) | ||
236 | { | ||
237 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); | ||
238 | goto exit; | ||
239 | } | ||
240 | |||
241 | input_regs(dev, regs); | ||
242 | if (data[1] & 0x04) | ||
243 | { | ||
244 | input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20); | ||
245 | input_report_key(dev, BTN_TOUCH, data[1] & 0x08); | ||
246 | } | ||
247 | else | ||
248 | { | ||
249 | input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20); | ||
250 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); | ||
251 | } | ||
252 | input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[2])); | ||
253 | input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[4])); | ||
254 | input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); | ||
255 | input_report_key(dev, BTN_STYLUS, data[1] & 0x02); | ||
256 | input_report_key(dev, BTN_STYLUS2, data[1] & 0x10); | ||
257 | |||
258 | input_sync(dev); | ||
259 | |||
260 | exit: | ||
261 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
262 | if (retval) | ||
263 | err ("%s - usb_submit_urb failed with result %d", | ||
264 | __FUNCTION__, retval); | ||
265 | } | ||
266 | |||
267 | static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs) | ||
268 | { | ||
269 | struct wacom *wacom = urb->context; | ||
270 | unsigned char *data = wacom->data; | ||
271 | struct input_dev *dev = &wacom->dev; | ||
272 | int retval; | ||
273 | |||
274 | switch (urb->status) { | ||
275 | case 0: | ||
276 | /* success */ | ||
277 | break; | ||
278 | case -ECONNRESET: | ||
279 | case -ENOENT: | ||
280 | case -ESHUTDOWN: | ||
281 | /* this urb is terminated, clean up */ | ||
282 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
283 | return; | ||
284 | default: | ||
285 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
286 | goto exit; | ||
287 | } | ||
288 | |||
289 | if (data[0] != 2) { | ||
290 | printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); | ||
291 | goto exit; | ||
292 | } | ||
293 | |||
294 | input_regs(dev, regs); | ||
295 | input_report_key(dev, BTN_TOOL_PEN, 1); | ||
296 | input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[1])); | ||
297 | input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[3])); | ||
298 | input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127); | ||
299 | input_report_key(dev, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); | ||
300 | input_report_key(dev, BTN_STYLUS, (data[5] & 0x40)); | ||
301 | input_sync(dev); | ||
302 | |||
303 | exit: | ||
304 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
305 | if (retval) | ||
306 | err ("%s - usb_submit_urb failed with result %d", | ||
307 | __FUNCTION__, retval); | ||
308 | } | ||
309 | |||
310 | static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | ||
311 | { | ||
312 | struct wacom *wacom = urb->context; | ||
313 | unsigned char *data = wacom->data; | ||
314 | struct input_dev *dev = &wacom->dev; | ||
315 | int x, y; | ||
316 | int retval; | ||
317 | |||
318 | switch (urb->status) { | ||
319 | case 0: | ||
320 | /* success */ | ||
321 | break; | ||
322 | case -ECONNRESET: | ||
323 | case -ENOENT: | ||
324 | case -ESHUTDOWN: | ||
325 | /* this urb is terminated, clean up */ | ||
326 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
327 | return; | ||
328 | default: | ||
329 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
330 | goto exit; | ||
331 | } | ||
332 | |||
333 | if (data[0] != 2) { | ||
334 | dbg("wacom_graphire_irq: received unknown report #%d", data[0]); | ||
335 | goto exit; | ||
336 | } | ||
337 | |||
338 | x = le16_to_cpu(*(__le16 *) &data[2]); | ||
339 | y = le16_to_cpu(*(__le16 *) &data[4]); | ||
340 | |||
341 | input_regs(dev, regs); | ||
342 | |||
343 | switch ((data[1] >> 5) & 3) { | ||
344 | |||
345 | case 0: /* Pen */ | ||
346 | input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x80); | ||
347 | break; | ||
348 | |||
349 | case 1: /* Rubber */ | ||
350 | input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x80); | ||
351 | break; | ||
352 | |||
353 | case 2: /* Mouse with wheel */ | ||
354 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); | ||
355 | input_report_rel(dev, REL_WHEEL, (signed char) data[6]); | ||
356 | /* fall through */ | ||
357 | |||
358 | case 3: /* Mouse without wheel */ | ||
359 | input_report_key(dev, BTN_TOOL_MOUSE, data[7] > 24); | ||
360 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); | ||
361 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); | ||
362 | input_report_abs(dev, ABS_DISTANCE, data[7]); | ||
363 | |||
364 | input_report_abs(dev, ABS_X, x); | ||
365 | input_report_abs(dev, ABS_Y, y); | ||
366 | |||
367 | input_sync(dev); | ||
368 | goto exit; | ||
369 | } | ||
370 | |||
371 | if (data[1] & 0x80) { | ||
372 | input_report_abs(dev, ABS_X, x); | ||
373 | input_report_abs(dev, ABS_Y, y); | ||
374 | } | ||
375 | |||
376 | input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); | ||
377 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); | ||
378 | input_report_key(dev, BTN_STYLUS, data[1] & 0x02); | ||
379 | input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); | ||
380 | |||
381 | input_sync(dev); | ||
382 | |||
383 | exit: | ||
384 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
385 | if (retval) | ||
386 | err ("%s - usb_submit_urb failed with result %d", | ||
387 | __FUNCTION__, retval); | ||
388 | } | ||
389 | |||
390 | static int wacom_intuos_inout(struct urb *urb) | ||
391 | { | ||
392 | struct wacom *wacom = urb->context; | ||
393 | unsigned char *data = wacom->data; | ||
394 | struct input_dev *dev = &wacom->dev; | ||
395 | int idx; | ||
396 | |||
397 | /* tool number */ | ||
398 | idx = data[1] & 0x01; | ||
399 | |||
400 | /* Enter report */ | ||
401 | if ((data[1] & 0xfc) == 0xc0) | ||
402 | { | ||
403 | /* serial number of the tool */ | ||
404 | wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 28) + | ||
405 | ((__u32)data[4] << 20) + ((__u32)data[5] << 12) + | ||
406 | ((__u32)data[6] << 4) + (data[7] >> 4); | ||
407 | |||
408 | switch (((__u32)data[2] << 4) | (data[3] >> 4)) { | ||
409 | case 0x812: /* Inking pen */ | ||
410 | case 0x801: /* Intuos3 Inking pen */ | ||
411 | case 0x012: | ||
412 | wacom->tool[idx] = BTN_TOOL_PENCIL; | ||
413 | break; | ||
414 | case 0x822: /* Pen */ | ||
415 | case 0x842: | ||
416 | case 0x852: | ||
417 | case 0x823: /* Intuos3 Grip Pen */ | ||
418 | case 0x813: /* Intuos3 Classic Pen */ | ||
419 | case 0x885: /* Intuos3 Marker Pen */ | ||
420 | case 0x022: | ||
421 | wacom->tool[idx] = BTN_TOOL_PEN; | ||
422 | break; | ||
423 | case 0x832: /* Stroke pen */ | ||
424 | case 0x032: | ||
425 | wacom->tool[idx] = BTN_TOOL_BRUSH; | ||
426 | break; | ||
427 | case 0x007: /* Mouse 4D and 2D */ | ||
428 | case 0x09c: | ||
429 | case 0x094: | ||
430 | case 0x017: /* Intuos3 2D Mouse */ | ||
431 | wacom->tool[idx] = BTN_TOOL_MOUSE; | ||
432 | break; | ||
433 | case 0x096: /* Lens cursor */ | ||
434 | case 0x097: /* Intuos3 Lens cursor */ | ||
435 | wacom->tool[idx] = BTN_TOOL_LENS; | ||
436 | break; | ||
437 | case 0x82a: /* Eraser */ | ||
438 | case 0x85a: | ||
439 | case 0x91a: | ||
440 | case 0xd1a: | ||
441 | case 0x0fa: | ||
442 | case 0x82b: /* Intuos3 Grip Pen Eraser */ | ||
443 | case 0x81b: /* Intuos3 Classic Pen Eraser */ | ||
444 | case 0x91b: /* Intuos3 Airbrush Eraser */ | ||
445 | wacom->tool[idx] = BTN_TOOL_RUBBER; | ||
446 | break; | ||
447 | case 0xd12: | ||
448 | case 0x912: | ||
449 | case 0x112: | ||
450 | case 0x913: /* Intuos3 Airbrush */ | ||
451 | wacom->tool[idx] = BTN_TOOL_AIRBRUSH; | ||
452 | break; /* Airbrush */ | ||
453 | default: /* Unknown tool */ | ||
454 | wacom->tool[idx] = BTN_TOOL_PEN; | ||
455 | } | ||
456 | input_report_key(dev, wacom->tool[idx], 1); | ||
457 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
458 | input_sync(dev); | ||
459 | return 1; | ||
460 | } | ||
461 | |||
462 | /* Exit report */ | ||
463 | if ((data[1] & 0xfe) == 0x80) { | ||
464 | input_report_key(dev, wacom->tool[idx], 0); | ||
465 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
466 | input_sync(dev); | ||
467 | return 1; | ||
468 | } | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static void wacom_intuos_general(struct urb *urb) | ||
474 | { | ||
475 | struct wacom *wacom = urb->context; | ||
476 | unsigned char *data = wacom->data; | ||
477 | struct input_dev *dev = &wacom->dev; | ||
478 | unsigned int t; | ||
479 | |||
480 | /* general pen packet */ | ||
481 | if ((data[1] & 0xb8) == 0xa0) | ||
482 | { | ||
483 | t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3); | ||
484 | input_report_abs(dev, ABS_PRESSURE, t); | ||
485 | input_report_abs(dev, ABS_TILT_X, | ||
486 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | ||
487 | input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); | ||
488 | input_report_key(dev, BTN_STYLUS, data[1] & 2); | ||
489 | input_report_key(dev, BTN_STYLUS2, data[1] & 4); | ||
490 | input_report_key(dev, BTN_TOUCH, t > 10); | ||
491 | } | ||
492 | |||
493 | /* airbrush second packet */ | ||
494 | if ((data[1] & 0xbc) == 0xb4) | ||
495 | { | ||
496 | input_report_abs(dev, ABS_WHEEL, | ||
497 | ((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); | ||
498 | input_report_abs(dev, ABS_TILT_X, | ||
499 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | ||
500 | input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); | ||
501 | } | ||
502 | return; | ||
503 | } | ||
504 | |||
505 | static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) | ||
506 | { | ||
507 | struct wacom *wacom = urb->context; | ||
508 | unsigned char *data = wacom->data; | ||
509 | struct input_dev *dev = &wacom->dev; | ||
510 | unsigned int t; | ||
511 | int idx; | ||
512 | int retval; | ||
513 | |||
514 | switch (urb->status) { | ||
515 | case 0: | ||
516 | /* success */ | ||
517 | break; | ||
518 | case -ECONNRESET: | ||
519 | case -ENOENT: | ||
520 | case -ESHUTDOWN: | ||
521 | /* this urb is terminated, clean up */ | ||
522 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
523 | return; | ||
524 | default: | ||
525 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
526 | goto exit; | ||
527 | } | ||
528 | |||
529 | if (data[0] != 2 && data[0] != 5 && data[0] != 6) { | ||
530 | dbg("wacom_intuos_irq: received unknown report #%d", data[0]); | ||
531 | goto exit; | ||
532 | } | ||
533 | |||
534 | input_regs(dev, regs); | ||
535 | |||
536 | /* tool number */ | ||
537 | idx = data[1] & 0x01; | ||
538 | |||
539 | /* process in/out prox events */ | ||
540 | if (wacom_intuos_inout(urb)) goto exit; | ||
541 | |||
542 | input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2])); | ||
543 | input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4])); | ||
544 | input_report_abs(dev, ABS_DISTANCE, data[9]); | ||
545 | |||
546 | /* process general packets */ | ||
547 | wacom_intuos_general(urb); | ||
548 | |||
549 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { /* 4D mouse or Lens cursor packets */ | ||
550 | |||
551 | if (data[1] & 0x02) { /* Rotation packet */ | ||
552 | |||
553 | t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7); | ||
554 | input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? ((t - 1) / 2) : -t / 2); | ||
555 | |||
556 | } else { | ||
557 | |||
558 | if ((data[1] & 0x10) == 0) { /* 4D mouse packets */ | ||
559 | |||
560 | input_report_key(dev, BTN_LEFT, data[8] & 0x01); | ||
561 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); | ||
562 | input_report_key(dev, BTN_RIGHT, data[8] & 0x04); | ||
563 | |||
564 | input_report_key(dev, BTN_SIDE, data[8] & 0x20); | ||
565 | input_report_key(dev, BTN_EXTRA, data[8] & 0x10); | ||
566 | t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3); | ||
567 | input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); | ||
568 | |||
569 | } else { | ||
570 | if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* 2D mouse packets */ | ||
571 | input_report_key(dev, BTN_LEFT, data[8] & 0x04); | ||
572 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); | ||
573 | input_report_key(dev, BTN_RIGHT, data[8] & 0x10); | ||
574 | input_report_rel(dev, REL_WHEEL, | ||
575 | (-(__u32)(data[8] & 0x01) + (__u32)((data[8] & 0x02) >> 1))); | ||
576 | } | ||
577 | else { /* Lens cursor packets */ | ||
578 | input_report_key(dev, BTN_LEFT, data[8] & 0x01); | ||
579 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); | ||
580 | input_report_key(dev, BTN_RIGHT, data[8] & 0x04); | ||
581 | input_report_key(dev, BTN_SIDE, data[8] & 0x10); | ||
582 | input_report_key(dev, BTN_EXTRA, data[8] & 0x08); | ||
583 | } | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | |||
588 | input_report_key(dev, wacom->tool[idx], 1); | ||
589 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
590 | input_sync(dev); | ||
591 | |||
592 | exit: | ||
593 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
594 | if (retval) | ||
595 | err ("%s - usb_submit_urb failed with result %d", | ||
596 | __FUNCTION__, retval); | ||
597 | } | ||
598 | |||
599 | static void wacom_intuos3_irq(struct urb *urb, struct pt_regs *regs) | ||
600 | { | ||
601 | struct wacom *wacom = urb->context; | ||
602 | unsigned char *data = wacom->data; | ||
603 | struct input_dev *dev = &wacom->dev; | ||
604 | unsigned int t; | ||
605 | int idx, retval; | ||
606 | |||
607 | switch (urb->status) { | ||
608 | case 0: | ||
609 | /* success */ | ||
610 | break; | ||
611 | case -ECONNRESET: | ||
612 | case -ENOENT: | ||
613 | case -ESHUTDOWN: | ||
614 | /* this urb is terminated, clean up */ | ||
615 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
616 | return; | ||
617 | default: | ||
618 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
619 | goto exit; | ||
620 | } | ||
621 | |||
622 | /* check for valid report */ | ||
623 | if (data[0] != 2 && data[0] != 5 && data[0] != 12) | ||
624 | { | ||
625 | printk(KERN_INFO "wacom_intuos3_irq: received unknown report #%d\n", data[0]); | ||
626 | goto exit; | ||
627 | } | ||
628 | |||
629 | input_regs(dev, regs); | ||
630 | |||
631 | /* tool index is always 0 here since there is no dual input tool */ | ||
632 | idx = data[1] & 0x01; | ||
633 | |||
634 | /* pad packets. Works as a second tool and is always in prox */ | ||
635 | if (data[0] == 12) | ||
636 | { | ||
637 | /* initiate the pad as a device */ | ||
638 | if (wacom->tool[1] != BTN_TOOL_FINGER) | ||
639 | { | ||
640 | wacom->tool[1] = BTN_TOOL_FINGER; | ||
641 | input_report_key(dev, wacom->tool[1], 1); | ||
642 | } | ||
643 | input_report_key(dev, BTN_0, (data[5] & 0x01)); | ||
644 | input_report_key(dev, BTN_1, (data[5] & 0x02)); | ||
645 | input_report_key(dev, BTN_2, (data[5] & 0x04)); | ||
646 | input_report_key(dev, BTN_3, (data[5] & 0x08)); | ||
647 | input_report_key(dev, BTN_4, (data[6] & 0x01)); | ||
648 | input_report_key(dev, BTN_5, (data[6] & 0x02)); | ||
649 | input_report_key(dev, BTN_6, (data[6] & 0x04)); | ||
650 | input_report_key(dev, BTN_7, (data[6] & 0x08)); | ||
651 | input_report_abs(dev, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); | ||
652 | input_report_abs(dev, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); | ||
653 | input_event(dev, EV_MSC, MSC_SERIAL, 0xffffffff); | ||
654 | input_sync(dev); | ||
655 | goto exit; | ||
656 | } | ||
657 | |||
658 | /* process in/out prox events */ | ||
659 | if (wacom_intuos_inout(urb)) goto exit; | ||
660 | |||
661 | input_report_abs(dev, ABS_X, ((__u32)data[2] << 9) | ((__u32)data[3] << 1) | ((data[9] >> 1) & 1)); | ||
662 | input_report_abs(dev, ABS_Y, ((__u32)data[4] << 9) | ((__u32)data[5] << 1) | (data[9] & 1)); | ||
663 | input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); | ||
664 | |||
665 | /* process general packets */ | ||
666 | wacom_intuos_general(urb); | ||
667 | |||
668 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) | ||
669 | { | ||
670 | /* Marker pen rotation packet. Reported as wheel due to valuator limitation */ | ||
671 | if (data[1] & 0x02) | ||
672 | { | ||
673 | t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7); | ||
674 | t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : | ||
675 | ((t-1) / 2 + 450)) : (450 - t / 2) ; | ||
676 | input_report_abs(dev, ABS_WHEEL, t); | ||
677 | } | ||
678 | |||
679 | /* 2D mouse packets */ | ||
680 | if (wacom->tool[idx] == BTN_TOOL_MOUSE) | ||
681 | { | ||
682 | input_report_key(dev, BTN_LEFT, data[8] & 0x04); | ||
683 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); | ||
684 | input_report_key(dev, BTN_RIGHT, data[8] & 0x10); | ||
685 | input_report_key(dev, BTN_SIDE, data[8] & 0x40); | ||
686 | input_report_key(dev, BTN_EXTRA, data[8] & 0x20); | ||
687 | /* mouse wheel is positive when rolled backwards */ | ||
688 | input_report_rel(dev, REL_WHEEL, ((__u32)((data[8] & 0x02) >> 1) | ||
689 | - (__u32)(data[8] & 0x01))); | ||
690 | } | ||
691 | } | ||
692 | |||
693 | input_report_key(dev, wacom->tool[idx], 1); | ||
694 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
695 | input_sync(dev); | ||
696 | |||
697 | exit: | ||
698 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
699 | if (retval) | ||
700 | err ("%s - usb_submit_urb failed with result %d", | ||
701 | __FUNCTION__, retval); | ||
702 | } | ||
703 | |||
704 | static struct wacom_features wacom_features[] = { | ||
705 | { "Wacom Penpartner", 7, 5040, 3780, 255, 32, 0, wacom_penpartner_irq }, | ||
706 | { "Wacom Graphire", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, | ||
707 | { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, | ||
708 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, 1, wacom_graphire_irq }, | ||
709 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, 1, wacom_graphire_irq }, | ||
710 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, 1, wacom_graphire_irq }, | ||
711 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq }, | ||
712 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, | ||
713 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq }, | ||
714 | { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq }, | ||
715 | { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq }, | ||
716 | { "Wacom PL400", 8, 5408, 4056, 255, 32, 3, wacom_pl_irq }, | ||
717 | { "Wacom PL500", 8, 6144, 4608, 255, 32, 3, wacom_pl_irq }, | ||
718 | { "Wacom PL600", 8, 6126, 4604, 255, 32, 3, wacom_pl_irq }, | ||
719 | { "Wacom PL600SX", 8, 6260, 5016, 255, 32, 3, wacom_pl_irq }, | ||
720 | { "Wacom PL550", 8, 6144, 4608, 511, 32, 3, wacom_pl_irq }, | ||
721 | { "Wacom PL800", 8, 7220, 5780, 511, 32, 3, wacom_pl_irq }, | ||
722 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq }, | ||
723 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, | ||
724 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq }, | ||
725 | { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq }, | ||
726 | { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq }, | ||
727 | { "Wacom Volito", 8, 5104, 3712, 511, 32, 1, wacom_graphire_irq }, | ||
728 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, 3, wacom_ptu_irq }, | ||
729 | { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, 4, wacom_intuos3_irq }, | ||
730 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, 4, wacom_intuos3_irq }, | ||
731 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, 4, wacom_intuos3_irq }, | ||
732 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, | ||
733 | { } | ||
734 | }; | ||
735 | |||
736 | static struct usb_device_id wacom_ids[] = { | ||
737 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) }, | ||
738 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) }, | ||
739 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) }, | ||
740 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) }, | ||
741 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) }, | ||
742 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) }, | ||
743 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) }, | ||
744 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) }, | ||
745 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) }, | ||
746 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) }, | ||
747 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) }, | ||
748 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) }, | ||
749 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) }, | ||
750 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) }, | ||
751 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) }, | ||
752 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) }, | ||
753 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) }, | ||
754 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, | ||
755 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, | ||
756 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) }, | ||
757 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) }, | ||
758 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) }, | ||
759 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) }, | ||
760 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, | ||
761 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, | ||
762 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, | ||
763 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, | ||
764 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, | ||
765 | { } | ||
766 | }; | ||
767 | |||
768 | MODULE_DEVICE_TABLE(usb, wacom_ids); | ||
769 | |||
770 | static int wacom_open(struct input_dev *dev) | ||
771 | { | ||
772 | struct wacom *wacom = dev->private; | ||
773 | |||
774 | if (wacom->open++) | ||
775 | return 0; | ||
776 | |||
777 | wacom->irq->dev = wacom->usbdev; | ||
778 | if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { | ||
779 | wacom->open--; | ||
780 | return -EIO; | ||
781 | } | ||
782 | |||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | static void wacom_close(struct input_dev *dev) | ||
787 | { | ||
788 | struct wacom *wacom = dev->private; | ||
789 | |||
790 | if (!--wacom->open) | ||
791 | usb_kill_urb(wacom->irq); | ||
792 | } | ||
793 | |||
794 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
795 | { | ||
796 | struct usb_device *dev = interface_to_usbdev(intf); | ||
797 | struct usb_endpoint_descriptor *endpoint; | ||
798 | char rep_data[2] = {0x02, 0x02}; | ||
799 | struct wacom *wacom; | ||
800 | char path[64]; | ||
801 | |||
802 | if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL))) | ||
803 | return -ENOMEM; | ||
804 | memset(wacom, 0, sizeof(struct wacom)); | ||
805 | |||
806 | wacom->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma); | ||
807 | if (!wacom->data) { | ||
808 | kfree(wacom); | ||
809 | return -ENOMEM; | ||
810 | } | ||
811 | |||
812 | wacom->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
813 | if (!wacom->irq) { | ||
814 | usb_buffer_free(dev, 10, wacom->data, wacom->data_dma); | ||
815 | kfree(wacom); | ||
816 | return -ENOMEM; | ||
817 | } | ||
818 | |||
819 | wacom->features = wacom_features + (id - wacom_ids); | ||
820 | |||
821 | wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS); | ||
822 | wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); | ||
823 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); | ||
824 | |||
825 | switch (wacom->features->type) { | ||
826 | case 1: | ||
827 | wacom->dev.evbit[0] |= BIT(EV_REL); | ||
828 | wacom->dev.relbit[0] |= BIT(REL_WHEEL); | ||
829 | wacom->dev.absbit[0] |= BIT(ABS_DISTANCE); | ||
830 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
831 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); | ||
832 | break; | ||
833 | |||
834 | case 4: /* new functions for Intuos3 */ | ||
835 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | ||
836 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); | ||
837 | wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY); | ||
838 | /* fall through */ | ||
839 | |||
840 | case 2: | ||
841 | wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); | ||
842 | wacom->dev.mscbit[0] |= BIT(MSC_SERIAL); | ||
843 | wacom->dev.relbit[0] |= BIT(REL_WHEEL); | ||
844 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); | ||
845 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) | ||
846 | | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2); | ||
847 | wacom->dev.absbit[0] |= BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE); | ||
848 | break; | ||
849 | |||
850 | case 3: | ||
851 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); | ||
852 | break; | ||
853 | } | ||
854 | |||
855 | wacom->dev.absmax[ABS_X] = wacom->features->x_max; | ||
856 | wacom->dev.absmax[ABS_Y] = wacom->features->y_max; | ||
857 | wacom->dev.absmax[ABS_PRESSURE] = wacom->features->pressure_max; | ||
858 | wacom->dev.absmax[ABS_DISTANCE] = wacom->features->distance_max; | ||
859 | wacom->dev.absmax[ABS_TILT_X] = 127; | ||
860 | wacom->dev.absmax[ABS_TILT_Y] = 127; | ||
861 | wacom->dev.absmax[ABS_WHEEL] = 1023; | ||
862 | |||
863 | wacom->dev.absmax[ABS_RX] = 4097; | ||
864 | wacom->dev.absmax[ABS_RY] = 4097; | ||
865 | wacom->dev.absmin[ABS_RZ] = -900; | ||
866 | wacom->dev.absmax[ABS_RZ] = 899; | ||
867 | wacom->dev.absmin[ABS_THROTTLE] = -1023; | ||
868 | wacom->dev.absmax[ABS_THROTTLE] = 1023; | ||
869 | |||
870 | wacom->dev.absfuzz[ABS_X] = 4; | ||
871 | wacom->dev.absfuzz[ABS_Y] = 4; | ||
872 | |||
873 | wacom->dev.private = wacom; | ||
874 | wacom->dev.open = wacom_open; | ||
875 | wacom->dev.close = wacom_close; | ||
876 | |||
877 | usb_make_path(dev, path, 64); | ||
878 | sprintf(wacom->phys, "%s/input0", path); | ||
879 | |||
880 | wacom->dev.name = wacom->features->name; | ||
881 | wacom->dev.phys = wacom->phys; | ||
882 | wacom->dev.id.bustype = BUS_USB; | ||
883 | wacom->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
884 | wacom->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); | ||
885 | wacom->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); | ||
886 | wacom->dev.dev = &intf->dev; | ||
887 | wacom->usbdev = dev; | ||
888 | |||
889 | endpoint = &intf->cur_altsetting->endpoint[0].desc; | ||
890 | |||
891 | if (wacom->features->pktlen > 10) | ||
892 | BUG(); | ||
893 | |||
894 | usb_fill_int_urb(wacom->irq, dev, | ||
895 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), | ||
896 | wacom->data, wacom->features->pktlen, | ||
897 | wacom->features->irq, wacom, endpoint->bInterval); | ||
898 | wacom->irq->transfer_dma = wacom->data_dma; | ||
899 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
900 | |||
901 | input_register_device(&wacom->dev); | ||
902 | |||
903 | /* ask the tablet to report tablet data */ | ||
904 | usb_set_report(intf, 3, 2, rep_data, 2); | ||
905 | /* repeat once (not sure why the first call often fails) */ | ||
906 | usb_set_report(intf, 3, 2, rep_data, 2); | ||
907 | |||
908 | printk(KERN_INFO "input: %s on %s\n", wacom->features->name, path); | ||
909 | |||
910 | usb_set_intfdata(intf, wacom); | ||
911 | |||
912 | return 0; | ||
913 | } | ||
914 | |||
915 | static void wacom_disconnect(struct usb_interface *intf) | ||
916 | { | ||
917 | struct wacom *wacom = usb_get_intfdata (intf); | ||
918 | |||
919 | usb_set_intfdata(intf, NULL); | ||
920 | if (wacom) { | ||
921 | usb_kill_urb(wacom->irq); | ||
922 | input_unregister_device(&wacom->dev); | ||
923 | usb_free_urb(wacom->irq); | ||
924 | usb_buffer_free(interface_to_usbdev(intf), 10, wacom->data, wacom->data_dma); | ||
925 | kfree(wacom); | ||
926 | } | ||
927 | } | ||
928 | |||
929 | static struct usb_driver wacom_driver = { | ||
930 | .owner = THIS_MODULE, | ||
931 | .name = "wacom", | ||
932 | .probe = wacom_probe, | ||
933 | .disconnect = wacom_disconnect, | ||
934 | .id_table = wacom_ids, | ||
935 | }; | ||
936 | |||
937 | static int __init wacom_init(void) | ||
938 | { | ||
939 | int result = usb_register(&wacom_driver); | ||
940 | if (result == 0) | ||
941 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
942 | return result; | ||
943 | } | ||
944 | |||
945 | static void __exit wacom_exit(void) | ||
946 | { | ||
947 | usb_deregister(&wacom_driver); | ||
948 | } | ||
949 | |||
950 | module_init(wacom_init); | ||
951 | module_exit(wacom_exit); | ||
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c new file mode 100644 index 000000000000..d65edb22e545 --- /dev/null +++ b/drivers/usb/input/xpad.c | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | * X-Box gamepad - v0.0.5 | ||
3 | * | ||
4 | * Copyright (c) 2002 Marko Friedemann <mfr@bmx-chemnitz.de> | ||
5 | * | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | * | ||
22 | * This driver is based on: | ||
23 | * - information from http://euc.jp/periphs/xbox-controller.ja.html | ||
24 | * - the iForce driver drivers/char/joystick/iforce.c | ||
25 | * - the skeleton-driver drivers/usb/usb-skeleton.c | ||
26 | * | ||
27 | * Thanks to: | ||
28 | * - ITO Takayuki for providing essential xpad information on his website | ||
29 | * - Vojtech Pavlik - iforce driver / input subsystem | ||
30 | * - Greg Kroah-Hartman - usb-skeleton driver | ||
31 | * | ||
32 | * TODO: | ||
33 | * - fine tune axes | ||
34 | * - fix "analog" buttons (reported as digital now) | ||
35 | * - get rumble working | ||
36 | * | ||
37 | * History: | ||
38 | * | ||
39 | * 2002-06-27 - 0.0.1 : first version, just said "XBOX HID controller" | ||
40 | * | ||
41 | * 2002-07-02 - 0.0.2 : basic working version | ||
42 | * - all axes and 9 of the 10 buttons work (german InterAct device) | ||
43 | * - the black button does not work | ||
44 | * | ||
45 | * 2002-07-14 - 0.0.3 : rework by Vojtech Pavlik | ||
46 | * - indentation fixes | ||
47 | * - usb + input init sequence fixes | ||
48 | * | ||
49 | * 2002-07-16 - 0.0.4 : minor changes, merge with Vojtech's v0.0.3 | ||
50 | * - verified the lack of HID and report descriptors | ||
51 | * - verified that ALL buttons WORK | ||
52 | * - fixed d-pad to axes mapping | ||
53 | * | ||
54 | * 2002-07-17 - 0.0.5 : simplified d-pad handling | ||
55 | */ | ||
56 | |||
57 | #include <linux/config.h> | ||
58 | #include <linux/kernel.h> | ||
59 | #include <linux/input.h> | ||
60 | #include <linux/init.h> | ||
61 | #include <linux/slab.h> | ||
62 | #include <linux/module.h> | ||
63 | #include <linux/smp_lock.h> | ||
64 | #include <linux/usb.h> | ||
65 | |||
66 | #define DRIVER_VERSION "v0.0.5" | ||
67 | #define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>" | ||
68 | #define DRIVER_DESC "X-Box pad driver" | ||
69 | |||
70 | #define XPAD_PKT_LEN 32 | ||
71 | |||
72 | static struct xpad_device { | ||
73 | u16 idVendor; | ||
74 | u16 idProduct; | ||
75 | char *name; | ||
76 | } xpad_device[] = { | ||
77 | { 0x045e, 0x0202, "Microsoft X-Box pad (US)" }, | ||
78 | { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)" }, | ||
79 | { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)" }, | ||
80 | { 0x0000, 0x0000, "X-Box pad" } | ||
81 | }; | ||
82 | |||
83 | static signed short xpad_btn[] = { | ||
84 | BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, /* "analog" buttons */ | ||
85 | BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */ | ||
86 | -1 /* terminating entry */ | ||
87 | }; | ||
88 | |||
89 | static signed short xpad_abs[] = { | ||
90 | ABS_X, ABS_Y, /* left stick */ | ||
91 | ABS_RX, ABS_RY, /* right stick */ | ||
92 | ABS_Z, ABS_RZ, /* triggers left/right */ | ||
93 | ABS_HAT0X, ABS_HAT0Y, /* digital pad */ | ||
94 | -1 /* terminating entry */ | ||
95 | }; | ||
96 | |||
97 | static struct usb_device_id xpad_table [] = { | ||
98 | { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ | ||
99 | { } | ||
100 | }; | ||
101 | |||
102 | MODULE_DEVICE_TABLE (usb, xpad_table); | ||
103 | |||
104 | struct usb_xpad { | ||
105 | struct input_dev dev; /* input device interface */ | ||
106 | struct usb_device *udev; /* usb device */ | ||
107 | |||
108 | struct urb *irq_in; /* urb for interrupt in report */ | ||
109 | unsigned char *idata; /* input data */ | ||
110 | dma_addr_t idata_dma; | ||
111 | |||
112 | char phys[65]; /* physical device path */ | ||
113 | int open_count; /* reference count */ | ||
114 | }; | ||
115 | |||
116 | /* | ||
117 | * xpad_process_packet | ||
118 | * | ||
119 | * Completes a request by converting the data into events for the | ||
120 | * input subsystem. | ||
121 | * | ||
122 | * The used report descriptor was taken from ITO Takayukis website: | ||
123 | * http://euc.jp/periphs/xbox-controller.ja.html | ||
124 | */ | ||
125 | |||
126 | static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data, struct pt_regs *regs) | ||
127 | { | ||
128 | struct input_dev *dev = &xpad->dev; | ||
129 | |||
130 | input_regs(dev, regs); | ||
131 | |||
132 | /* left stick */ | ||
133 | input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12])); | ||
134 | input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14])); | ||
135 | |||
136 | /* right stick */ | ||
137 | input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16])); | ||
138 | input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18])); | ||
139 | |||
140 | /* triggers left/right */ | ||
141 | input_report_abs(dev, ABS_Z, data[10]); | ||
142 | input_report_abs(dev, ABS_RZ, data[11]); | ||
143 | |||
144 | /* digital pad */ | ||
145 | input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); | ||
146 | input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); | ||
147 | |||
148 | /* start/back buttons and stick press left/right */ | ||
149 | input_report_key(dev, BTN_START, (data[2] & 0x10) >> 4); | ||
150 | input_report_key(dev, BTN_BACK, (data[2] & 0x20) >> 5); | ||
151 | input_report_key(dev, BTN_THUMBL, (data[2] & 0x40) >> 6); | ||
152 | input_report_key(dev, BTN_THUMBR, data[2] >> 7); | ||
153 | |||
154 | /* "analog" buttons A, B, X, Y */ | ||
155 | input_report_key(dev, BTN_A, data[4]); | ||
156 | input_report_key(dev, BTN_B, data[5]); | ||
157 | input_report_key(dev, BTN_X, data[6]); | ||
158 | input_report_key(dev, BTN_Y, data[7]); | ||
159 | |||
160 | /* "analog" buttons black, white */ | ||
161 | input_report_key(dev, BTN_C, data[8]); | ||
162 | input_report_key(dev, BTN_Z, data[9]); | ||
163 | |||
164 | input_sync(dev); | ||
165 | } | ||
166 | |||
167 | static void xpad_irq_in(struct urb *urb, struct pt_regs *regs) | ||
168 | { | ||
169 | struct usb_xpad *xpad = urb->context; | ||
170 | int retval; | ||
171 | |||
172 | switch (urb->status) { | ||
173 | case 0: | ||
174 | /* success */ | ||
175 | break; | ||
176 | case -ECONNRESET: | ||
177 | case -ENOENT: | ||
178 | case -ESHUTDOWN: | ||
179 | /* this urb is terminated, clean up */ | ||
180 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
181 | return; | ||
182 | default: | ||
183 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
184 | goto exit; | ||
185 | } | ||
186 | |||
187 | xpad_process_packet(xpad, 0, xpad->idata, regs); | ||
188 | |||
189 | exit: | ||
190 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
191 | if (retval) | ||
192 | err ("%s - usb_submit_urb failed with result %d", | ||
193 | __FUNCTION__, retval); | ||
194 | } | ||
195 | |||
196 | static int xpad_open (struct input_dev *dev) | ||
197 | { | ||
198 | struct usb_xpad *xpad = dev->private; | ||
199 | |||
200 | if (xpad->open_count++) | ||
201 | return 0; | ||
202 | |||
203 | xpad->irq_in->dev = xpad->udev; | ||
204 | if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) { | ||
205 | xpad->open_count--; | ||
206 | return -EIO; | ||
207 | } | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static void xpad_close (struct input_dev *dev) | ||
213 | { | ||
214 | struct usb_xpad *xpad = dev->private; | ||
215 | |||
216 | if (!--xpad->open_count) | ||
217 | usb_kill_urb(xpad->irq_in); | ||
218 | } | ||
219 | |||
220 | static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
221 | { | ||
222 | struct usb_device *udev = interface_to_usbdev (intf); | ||
223 | struct usb_xpad *xpad = NULL; | ||
224 | struct usb_endpoint_descriptor *ep_irq_in; | ||
225 | char path[64]; | ||
226 | int i; | ||
227 | |||
228 | for (i = 0; xpad_device[i].idVendor; i++) { | ||
229 | if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && | ||
230 | (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) | ||
231 | break; | ||
232 | } | ||
233 | |||
234 | if ((xpad = kmalloc (sizeof(struct usb_xpad), GFP_KERNEL)) == NULL) { | ||
235 | err("cannot allocate memory for new pad"); | ||
236 | return -ENOMEM; | ||
237 | } | ||
238 | memset(xpad, 0, sizeof(struct usb_xpad)); | ||
239 | |||
240 | xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, | ||
241 | SLAB_ATOMIC, &xpad->idata_dma); | ||
242 | if (!xpad->idata) { | ||
243 | kfree(xpad); | ||
244 | return -ENOMEM; | ||
245 | } | ||
246 | |||
247 | xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); | ||
248 | if (!xpad->irq_in) { | ||
249 | err("cannot allocate memory for new pad irq urb"); | ||
250 | usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); | ||
251 | kfree(xpad); | ||
252 | return -ENOMEM; | ||
253 | } | ||
254 | |||
255 | ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; | ||
256 | |||
257 | usb_fill_int_urb(xpad->irq_in, udev, | ||
258 | usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), | ||
259 | xpad->idata, XPAD_PKT_LEN, xpad_irq_in, | ||
260 | xpad, ep_irq_in->bInterval); | ||
261 | xpad->irq_in->transfer_dma = xpad->idata_dma; | ||
262 | xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
263 | |||
264 | xpad->udev = udev; | ||
265 | |||
266 | xpad->dev.id.bustype = BUS_USB; | ||
267 | xpad->dev.id.vendor = le16_to_cpu(udev->descriptor.idVendor); | ||
268 | xpad->dev.id.product = le16_to_cpu(udev->descriptor.idProduct); | ||
269 | xpad->dev.id.version = le16_to_cpu(udev->descriptor.bcdDevice); | ||
270 | xpad->dev.dev = &intf->dev; | ||
271 | xpad->dev.private = xpad; | ||
272 | xpad->dev.name = xpad_device[i].name; | ||
273 | xpad->dev.phys = xpad->phys; | ||
274 | xpad->dev.open = xpad_open; | ||
275 | xpad->dev.close = xpad_close; | ||
276 | |||
277 | usb_make_path(udev, path, 64); | ||
278 | snprintf(xpad->phys, 64, "%s/input0", path); | ||
279 | |||
280 | xpad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
281 | |||
282 | for (i = 0; xpad_btn[i] >= 0; i++) | ||
283 | set_bit(xpad_btn[i], xpad->dev.keybit); | ||
284 | |||
285 | for (i = 0; xpad_abs[i] >= 0; i++) { | ||
286 | |||
287 | signed short t = xpad_abs[i]; | ||
288 | |||
289 | set_bit(t, xpad->dev.absbit); | ||
290 | |||
291 | switch (t) { | ||
292 | case ABS_X: | ||
293 | case ABS_Y: | ||
294 | case ABS_RX: | ||
295 | case ABS_RY: /* the two sticks */ | ||
296 | xpad->dev.absmax[t] = 32767; | ||
297 | xpad->dev.absmin[t] = -32768; | ||
298 | xpad->dev.absflat[t] = 128; | ||
299 | xpad->dev.absfuzz[t] = 16; | ||
300 | break; | ||
301 | case ABS_Z: | ||
302 | case ABS_RZ: /* the triggers */ | ||
303 | xpad->dev.absmax[t] = 255; | ||
304 | xpad->dev.absmin[t] = 0; | ||
305 | break; | ||
306 | case ABS_HAT0X: | ||
307 | case ABS_HAT0Y: /* the d-pad */ | ||
308 | xpad->dev.absmax[t] = 1; | ||
309 | xpad->dev.absmin[t] = -1; | ||
310 | break; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | input_register_device(&xpad->dev); | ||
315 | |||
316 | printk(KERN_INFO "input: %s on %s", xpad->dev.name, path); | ||
317 | |||
318 | usb_set_intfdata(intf, xpad); | ||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static void xpad_disconnect(struct usb_interface *intf) | ||
323 | { | ||
324 | struct usb_xpad *xpad = usb_get_intfdata (intf); | ||
325 | |||
326 | usb_set_intfdata(intf, NULL); | ||
327 | if (xpad) { | ||
328 | usb_kill_urb(xpad->irq_in); | ||
329 | input_unregister_device(&xpad->dev); | ||
330 | usb_free_urb(xpad->irq_in); | ||
331 | usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); | ||
332 | kfree(xpad); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | static struct usb_driver xpad_driver = { | ||
337 | .owner = THIS_MODULE, | ||
338 | .name = "xpad", | ||
339 | .probe = xpad_probe, | ||
340 | .disconnect = xpad_disconnect, | ||
341 | .id_table = xpad_table, | ||
342 | }; | ||
343 | |||
344 | static int __init usb_xpad_init(void) | ||
345 | { | ||
346 | int result = usb_register(&xpad_driver); | ||
347 | if (result == 0) | ||
348 | info(DRIVER_DESC ":" DRIVER_VERSION); | ||
349 | return result; | ||
350 | } | ||
351 | |||
352 | static void __exit usb_xpad_exit(void) | ||
353 | { | ||
354 | usb_deregister(&xpad_driver); | ||
355 | } | ||
356 | |||
357 | module_init(usb_xpad_init); | ||
358 | module_exit(usb_xpad_exit); | ||
359 | |||
360 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
361 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
362 | MODULE_LICENSE("GPL"); | ||