diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2008-09-18 06:23:31 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2008-10-14 17:51:00 -0400 |
commit | 10e41a711e55f485709b4ca157e587cf36ef5a69 (patch) | |
tree | 5e7e31db5f0127370ab2cc7250b16061ec7fc3cb /drivers/hid/usbhid | |
parent | 5f022298aab58ddff9bccdb28b82a59109789da9 (diff) |
HID: move thrustmaster FF processing
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/usbhid')
-rw-r--r-- | drivers/hid/usbhid/Kconfig | 11 | ||||
-rw-r--r-- | drivers/hid/usbhid/Makefile | 3 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-ff.c | 6 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-tmff.c | 225 |
4 files changed, 0 insertions, 245 deletions
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig index 02c8228ed7ee..c236fb3deb59 100644 --- a/drivers/hid/usbhid/Kconfig +++ b/drivers/hid/usbhid/Kconfig | |||
@@ -44,17 +44,6 @@ config HID_PID | |||
44 | feedback for it. Microsoft Sidewinder Force Feedback 2 is one of such | 44 | feedback for it. Microsoft Sidewinder Force Feedback 2 is one of such |
45 | devices. | 45 | devices. |
46 | 46 | ||
47 | config THRUSTMASTER_FF | ||
48 | bool "ThrustMaster devices support" | ||
49 | depends on HID_FF | ||
50 | select INPUT_FF_MEMLESS if USB_HID | ||
51 | help | ||
52 | Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or | ||
53 | a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel, | ||
54 | and want to enable force feedback support for it. | ||
55 | Note: if you say N here, this device will still be supported, but without | ||
56 | force feedback. | ||
57 | |||
58 | config ZEROPLUS_FF | 47 | config ZEROPLUS_FF |
59 | bool "Zeroplus based game controller support" | 48 | bool "Zeroplus based game controller support" |
60 | depends on HID_FF | 49 | depends on HID_FF |
diff --git a/drivers/hid/usbhid/Makefile b/drivers/hid/usbhid/Makefile index 0ee4803375b2..dd3b8634800f 100644 --- a/drivers/hid/usbhid/Makefile +++ b/drivers/hid/usbhid/Makefile | |||
@@ -13,9 +13,6 @@ endif | |||
13 | ifeq ($(CONFIG_HID_PID),y) | 13 | ifeq ($(CONFIG_HID_PID),y) |
14 | usbhid-objs += hid-pidff.o | 14 | usbhid-objs += hid-pidff.o |
15 | endif | 15 | endif |
16 | ifeq ($(CONFIG_THRUSTMASTER_FF),y) | ||
17 | usbhid-objs += hid-tmff.o | ||
18 | endif | ||
19 | ifeq ($(CONFIG_ZEROPLUS_FF),y) | 16 | ifeq ($(CONFIG_ZEROPLUS_FF),y) |
20 | usbhid-objs += hid-zpff.o | 17 | usbhid-objs += hid-zpff.o |
21 | endif | 18 | endif |
diff --git a/drivers/hid/usbhid/hid-ff.c b/drivers/hid/usbhid/hid-ff.c index a868eef06189..ed3a869d54e3 100644 --- a/drivers/hid/usbhid/hid-ff.c +++ b/drivers/hid/usbhid/hid-ff.c | |||
@@ -50,12 +50,6 @@ struct hid_ff_initializer { | |||
50 | * be a PID device | 50 | * be a PID device |
51 | */ | 51 | */ |
52 | static struct hid_ff_initializer inits[] = { | 52 | static struct hid_ff_initializer inits[] = { |
53 | #ifdef CONFIG_THRUSTMASTER_FF | ||
54 | { 0x44f, 0xb300, hid_tmff_init }, | ||
55 | { 0x44f, 0xb304, hid_tmff_init }, | ||
56 | { 0x44f, 0xb651, hid_tmff_init }, /* FGT Rumble Force Wheel */ | ||
57 | { 0x44f, 0xb654, hid_tmff_init }, /* FGT Force Feedback Wheel */ | ||
58 | #endif | ||
59 | #ifdef CONFIG_ZEROPLUS_FF | 53 | #ifdef CONFIG_ZEROPLUS_FF |
60 | { 0xc12, 0x0005, hid_zpff_init }, | 54 | { 0xc12, 0x0005, hid_zpff_init }, |
61 | { 0xc12, 0x0030, hid_zpff_init }, | 55 | { 0xc12, 0x0030, hid_zpff_init }, |
diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c deleted file mode 100644 index 144578b1a00c..000000000000 --- a/drivers/hid/usbhid/hid-tmff.c +++ /dev/null | |||
@@ -1,225 +0,0 @@ | |||
1 | /* | ||
2 | * Force feedback support for various HID compliant devices by ThrustMaster: | ||
3 | * ThrustMaster FireStorm Dual Power 2 | ||
4 | * and possibly others whose device ids haven't been added. | ||
5 | * | ||
6 | * Modified to support ThrustMaster devices by Zinx Verituse | ||
7 | * on 2003-01-25 from the Logitech force feedback driver, | ||
8 | * which is by Johann Deneux. | ||
9 | * | ||
10 | * Copyright (c) 2003 Zinx Verituse <zinx@epicsol.org> | ||
11 | * Copyright (c) 2002 Johann Deneux | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
28 | */ | ||
29 | |||
30 | #include <linux/input.h> | ||
31 | |||
32 | #undef DEBUG | ||
33 | #include <linux/usb.h> | ||
34 | |||
35 | #include <linux/hid.h> | ||
36 | #include "usbhid.h" | ||
37 | |||
38 | /* Usages for thrustmaster devices I know about */ | ||
39 | #define THRUSTMASTER_USAGE_FF (HID_UP_GENDESK | 0xbb) | ||
40 | |||
41 | struct dev_type { | ||
42 | u16 idVendor; | ||
43 | u16 idProduct; | ||
44 | const signed short *ff; | ||
45 | }; | ||
46 | |||
47 | static const signed short ff_rumble[] = { | ||
48 | FF_RUMBLE, | ||
49 | -1 | ||
50 | }; | ||
51 | |||
52 | static const signed short ff_joystick[] = { | ||
53 | FF_CONSTANT, | ||
54 | -1 | ||
55 | }; | ||
56 | |||
57 | static const struct dev_type devices[] = { | ||
58 | { 0x44f, 0xb300, ff_rumble }, | ||
59 | { 0x44f, 0xb304, ff_rumble }, | ||
60 | { 0x44f, 0xb651, ff_rumble }, /* FGT Rumble Force Wheel */ | ||
61 | { 0x44f, 0xb654, ff_joystick }, /* FGT Force Feedback Wheel */ | ||
62 | }; | ||
63 | |||
64 | struct tmff_device { | ||
65 | struct hid_report *report; | ||
66 | struct hid_field *ff_field; | ||
67 | }; | ||
68 | |||
69 | /* Changes values from 0 to 0xffff into values from minimum to maximum */ | ||
70 | static inline int hid_tmff_scale_u16(unsigned int in, | ||
71 | int minimum, int maximum) | ||
72 | { | ||
73 | int ret; | ||
74 | |||
75 | ret = (in * (maximum - minimum) / 0xffff) + minimum; | ||
76 | if (ret < minimum) | ||
77 | return minimum; | ||
78 | if (ret > maximum) | ||
79 | return maximum; | ||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | /* Changes values from -0x80 to 0x7f into values from minimum to maximum */ | ||
84 | static inline int hid_tmff_scale_s8(int in, | ||
85 | int minimum, int maximum) | ||
86 | { | ||
87 | int ret; | ||
88 | |||
89 | ret = (((in + 0x80) * (maximum - minimum)) / 0xff) + minimum; | ||
90 | if (ret < minimum) | ||
91 | return minimum; | ||
92 | if (ret > maximum) | ||
93 | return maximum; | ||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect) | ||
98 | { | ||
99 | struct hid_device *hid = input_get_drvdata(dev); | ||
100 | struct tmff_device *tmff = data; | ||
101 | struct hid_field *ff_field = tmff->ff_field; | ||
102 | int x, y; | ||
103 | int left, right; /* Rumbling */ | ||
104 | |||
105 | switch (effect->type) { | ||
106 | case FF_CONSTANT: | ||
107 | x = hid_tmff_scale_s8(effect->u.ramp.start_level, | ||
108 | ff_field->logical_minimum, | ||
109 | ff_field->logical_maximum); | ||
110 | y = hid_tmff_scale_s8(effect->u.ramp.end_level, | ||
111 | ff_field->logical_minimum, | ||
112 | ff_field->logical_maximum); | ||
113 | |||
114 | dbg_hid("(x, y)=(%04x, %04x)\n", x, y); | ||
115 | ff_field->value[0] = x; | ||
116 | ff_field->value[1] = y; | ||
117 | usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); | ||
118 | break; | ||
119 | |||
120 | case FF_RUMBLE: | ||
121 | left = hid_tmff_scale_u16(effect->u.rumble.weak_magnitude, | ||
122 | ff_field->logical_minimum, | ||
123 | ff_field->logical_maximum); | ||
124 | right = hid_tmff_scale_u16(effect->u.rumble.strong_magnitude, | ||
125 | ff_field->logical_minimum, | ||
126 | ff_field->logical_maximum); | ||
127 | |||
128 | dbg_hid("(left,right)=(%08x, %08x)\n", left, right); | ||
129 | ff_field->value[0] = left; | ||
130 | ff_field->value[1] = right; | ||
131 | usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); | ||
132 | break; | ||
133 | } | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | int hid_tmff_init(struct hid_device *hid) | ||
138 | { | ||
139 | struct tmff_device *tmff; | ||
140 | struct hid_report *report; | ||
141 | struct list_head *report_list; | ||
142 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
143 | struct input_dev *input_dev = hidinput->input; | ||
144 | const signed short *ff_bits = ff_joystick; | ||
145 | int error; | ||
146 | int i; | ||
147 | |||
148 | tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); | ||
149 | if (!tmff) | ||
150 | return -ENOMEM; | ||
151 | |||
152 | /* Find the report to use */ | ||
153 | report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
154 | list_for_each_entry(report, report_list, list) { | ||
155 | int fieldnum; | ||
156 | |||
157 | for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) { | ||
158 | struct hid_field *field = report->field[fieldnum]; | ||
159 | |||
160 | if (field->maxusage <= 0) | ||
161 | continue; | ||
162 | |||
163 | switch (field->usage[0].hid) { | ||
164 | case THRUSTMASTER_USAGE_FF: | ||
165 | if (field->report_count < 2) { | ||
166 | warn("ignoring FF field with report_count < 2"); | ||
167 | continue; | ||
168 | } | ||
169 | |||
170 | if (field->logical_maximum == field->logical_minimum) { | ||
171 | warn("ignoring FF field with logical_maximum == logical_minimum"); | ||
172 | continue; | ||
173 | } | ||
174 | |||
175 | if (tmff->report && tmff->report != report) { | ||
176 | warn("ignoring FF field in other report"); | ||
177 | continue; | ||
178 | } | ||
179 | |||
180 | if (tmff->ff_field && tmff->ff_field != field) { | ||
181 | warn("ignoring duplicate FF field"); | ||
182 | continue; | ||
183 | } | ||
184 | |||
185 | tmff->report = report; | ||
186 | tmff->ff_field = field; | ||
187 | |||
188 | for (i = 0; i < ARRAY_SIZE(devices); i++) { | ||
189 | if (input_dev->id.vendor == devices[i].idVendor && | ||
190 | input_dev->id.product == devices[i].idProduct) { | ||
191 | ff_bits = devices[i].ff; | ||
192 | break; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | for (i = 0; ff_bits[i] >= 0; i++) | ||
197 | set_bit(ff_bits[i], input_dev->ffbit); | ||
198 | |||
199 | break; | ||
200 | |||
201 | default: | ||
202 | warn("ignoring unknown output usage %08x", field->usage[0].hid); | ||
203 | continue; | ||
204 | } | ||
205 | } | ||
206 | } | ||
207 | |||
208 | if (!tmff->report) { | ||
209 | err("cant find FF field in output reports\n"); | ||
210 | error = -ENODEV; | ||
211 | goto fail; | ||
212 | } | ||
213 | |||
214 | error = input_ff_create_memless(input_dev, tmff, hid_tmff_play); | ||
215 | if (error) | ||
216 | goto fail; | ||
217 | |||
218 | info("Force feedback for ThrustMaster devices by Zinx Verituse <zinx@epicsol.org>"); | ||
219 | return 0; | ||
220 | |||
221 | fail: | ||
222 | kfree(tmff); | ||
223 | return error; | ||
224 | } | ||
225 | |||