xref: /OK3568_Linux_fs/kernel/drivers/hid/hid-tmff.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Force feedback support for various HID compliant devices by ThrustMaster:
4*4882a593Smuzhiyun  *    ThrustMaster FireStorm Dual Power 2
5*4882a593Smuzhiyun  * and possibly others whose device ids haven't been added.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  *  Modified to support ThrustMaster devices by Zinx Verituse
8*4882a593Smuzhiyun  *  on 2003-01-25 from the Logitech force feedback driver,
9*4882a593Smuzhiyun  *  which is by Johann Deneux.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  *  Copyright (c) 2003 Zinx Verituse <zinx@epicsol.org>
12*4882a593Smuzhiyun  *  Copyright (c) 2002 Johann Deneux
13*4882a593Smuzhiyun  */
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun /*
16*4882a593Smuzhiyun  */
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #include <linux/hid.h>
19*4882a593Smuzhiyun #include <linux/input.h>
20*4882a593Smuzhiyun #include <linux/slab.h>
21*4882a593Smuzhiyun #include <linux/module.h>
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include "hid-ids.h"
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define THRUSTMASTER_DEVICE_ID_2_IN_1_DT	0xb320
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun static const signed short ff_rumble[] = {
28*4882a593Smuzhiyun 	FF_RUMBLE,
29*4882a593Smuzhiyun 	-1
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun static const signed short ff_joystick[] = {
33*4882a593Smuzhiyun 	FF_CONSTANT,
34*4882a593Smuzhiyun 	-1
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #ifdef CONFIG_THRUSTMASTER_FF
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun /* Usages for thrustmaster devices I know about */
40*4882a593Smuzhiyun #define THRUSTMASTER_USAGE_FF	(HID_UP_GENDESK | 0xbb)
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun struct tmff_device {
43*4882a593Smuzhiyun 	struct hid_report *report;
44*4882a593Smuzhiyun 	struct hid_field *ff_field;
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun /* Changes values from 0 to 0xffff into values from minimum to maximum */
tmff_scale_u16(unsigned int in,int minimum,int maximum)48*4882a593Smuzhiyun static inline int tmff_scale_u16(unsigned int in, int minimum, int maximum)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun 	int ret;
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	ret = (in * (maximum - minimum) / 0xffff) + minimum;
53*4882a593Smuzhiyun 	if (ret < minimum)
54*4882a593Smuzhiyun 		return minimum;
55*4882a593Smuzhiyun 	if (ret > maximum)
56*4882a593Smuzhiyun 		return maximum;
57*4882a593Smuzhiyun 	return ret;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun /* Changes values from -0x80 to 0x7f into values from minimum to maximum */
tmff_scale_s8(int in,int minimum,int maximum)61*4882a593Smuzhiyun static inline int tmff_scale_s8(int in, int minimum, int maximum)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	int ret;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	ret = (((in + 0x80) * (maximum - minimum)) / 0xff) + minimum;
66*4882a593Smuzhiyun 	if (ret < minimum)
67*4882a593Smuzhiyun 		return minimum;
68*4882a593Smuzhiyun 	if (ret > maximum)
69*4882a593Smuzhiyun 		return maximum;
70*4882a593Smuzhiyun 	return ret;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
tmff_play(struct input_dev * dev,void * data,struct ff_effect * effect)73*4882a593Smuzhiyun static int tmff_play(struct input_dev *dev, void *data,
74*4882a593Smuzhiyun 		struct ff_effect *effect)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun 	struct hid_device *hid = input_get_drvdata(dev);
77*4882a593Smuzhiyun 	struct tmff_device *tmff = data;
78*4882a593Smuzhiyun 	struct hid_field *ff_field = tmff->ff_field;
79*4882a593Smuzhiyun 	int x, y;
80*4882a593Smuzhiyun 	int left, right;	/* Rumbling */
81*4882a593Smuzhiyun 	int motor_swap;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	switch (effect->type) {
84*4882a593Smuzhiyun 	case FF_CONSTANT:
85*4882a593Smuzhiyun 		x = tmff_scale_s8(effect->u.ramp.start_level,
86*4882a593Smuzhiyun 					ff_field->logical_minimum,
87*4882a593Smuzhiyun 					ff_field->logical_maximum);
88*4882a593Smuzhiyun 		y = tmff_scale_s8(effect->u.ramp.end_level,
89*4882a593Smuzhiyun 					ff_field->logical_minimum,
90*4882a593Smuzhiyun 					ff_field->logical_maximum);
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 		dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
93*4882a593Smuzhiyun 		ff_field->value[0] = x;
94*4882a593Smuzhiyun 		ff_field->value[1] = y;
95*4882a593Smuzhiyun 		hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT);
96*4882a593Smuzhiyun 		break;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	case FF_RUMBLE:
99*4882a593Smuzhiyun 		left = tmff_scale_u16(effect->u.rumble.weak_magnitude,
100*4882a593Smuzhiyun 					ff_field->logical_minimum,
101*4882a593Smuzhiyun 					ff_field->logical_maximum);
102*4882a593Smuzhiyun 		right = tmff_scale_u16(effect->u.rumble.strong_magnitude,
103*4882a593Smuzhiyun 					ff_field->logical_minimum,
104*4882a593Smuzhiyun 					ff_field->logical_maximum);
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 		/* 2-in-1 strong motor is left */
107*4882a593Smuzhiyun 		if (hid->product == THRUSTMASTER_DEVICE_ID_2_IN_1_DT) {
108*4882a593Smuzhiyun 			motor_swap = left;
109*4882a593Smuzhiyun 			left = right;
110*4882a593Smuzhiyun 			right = motor_swap;
111*4882a593Smuzhiyun 		}
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 		dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
114*4882a593Smuzhiyun 		ff_field->value[0] = left;
115*4882a593Smuzhiyun 		ff_field->value[1] = right;
116*4882a593Smuzhiyun 		hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT);
117*4882a593Smuzhiyun 		break;
118*4882a593Smuzhiyun 	}
119*4882a593Smuzhiyun 	return 0;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
tmff_init(struct hid_device * hid,const signed short * ff_bits)122*4882a593Smuzhiyun static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun 	struct tmff_device *tmff;
125*4882a593Smuzhiyun 	struct hid_report *report;
126*4882a593Smuzhiyun 	struct list_head *report_list;
127*4882a593Smuzhiyun 	struct hid_input *hidinput;
128*4882a593Smuzhiyun 	struct input_dev *input_dev;
129*4882a593Smuzhiyun 	int error;
130*4882a593Smuzhiyun 	int i;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	if (list_empty(&hid->inputs)) {
133*4882a593Smuzhiyun 		hid_err(hid, "no inputs found\n");
134*4882a593Smuzhiyun 		return -ENODEV;
135*4882a593Smuzhiyun 	}
136*4882a593Smuzhiyun 	hidinput = list_entry(hid->inputs.next, struct hid_input, list);
137*4882a593Smuzhiyun 	input_dev = hidinput->input;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL);
140*4882a593Smuzhiyun 	if (!tmff)
141*4882a593Smuzhiyun 		return -ENOMEM;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	/* Find the report to use */
144*4882a593Smuzhiyun 	report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
145*4882a593Smuzhiyun 	list_for_each_entry(report, report_list, list) {
146*4882a593Smuzhiyun 		int fieldnum;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 		for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) {
149*4882a593Smuzhiyun 			struct hid_field *field = report->field[fieldnum];
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 			if (field->maxusage <= 0)
152*4882a593Smuzhiyun 				continue;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 			switch (field->usage[0].hid) {
155*4882a593Smuzhiyun 			case THRUSTMASTER_USAGE_FF:
156*4882a593Smuzhiyun 				if (field->report_count < 2) {
157*4882a593Smuzhiyun 					hid_warn(hid, "ignoring FF field with report_count < 2\n");
158*4882a593Smuzhiyun 					continue;
159*4882a593Smuzhiyun 				}
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 				if (field->logical_maximum ==
162*4882a593Smuzhiyun 						field->logical_minimum) {
163*4882a593Smuzhiyun 					hid_warn(hid, "ignoring FF field with logical_maximum == logical_minimum\n");
164*4882a593Smuzhiyun 					continue;
165*4882a593Smuzhiyun 				}
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 				if (tmff->report && tmff->report != report) {
168*4882a593Smuzhiyun 					hid_warn(hid, "ignoring FF field in other report\n");
169*4882a593Smuzhiyun 					continue;
170*4882a593Smuzhiyun 				}
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 				if (tmff->ff_field && tmff->ff_field != field) {
173*4882a593Smuzhiyun 					hid_warn(hid, "ignoring duplicate FF field\n");
174*4882a593Smuzhiyun 					continue;
175*4882a593Smuzhiyun 				}
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 				tmff->report = report;
178*4882a593Smuzhiyun 				tmff->ff_field = field;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 				for (i = 0; ff_bits[i] >= 0; i++)
181*4882a593Smuzhiyun 					set_bit(ff_bits[i], input_dev->ffbit);
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 				break;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 			default:
186*4882a593Smuzhiyun 				hid_warn(hid, "ignoring unknown output usage %08x\n",
187*4882a593Smuzhiyun 					 field->usage[0].hid);
188*4882a593Smuzhiyun 				continue;
189*4882a593Smuzhiyun 			}
190*4882a593Smuzhiyun 		}
191*4882a593Smuzhiyun 	}
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	if (!tmff->report) {
194*4882a593Smuzhiyun 		hid_err(hid, "can't find FF field in output reports\n");
195*4882a593Smuzhiyun 		error = -ENODEV;
196*4882a593Smuzhiyun 		goto fail;
197*4882a593Smuzhiyun 	}
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	error = input_ff_create_memless(input_dev, tmff, tmff_play);
200*4882a593Smuzhiyun 	if (error)
201*4882a593Smuzhiyun 		goto fail;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	hid_info(hid, "force feedback for ThrustMaster devices by Zinx Verituse <zinx@epicsol.org>\n");
204*4882a593Smuzhiyun 	return 0;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun fail:
207*4882a593Smuzhiyun 	kfree(tmff);
208*4882a593Smuzhiyun 	return error;
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun #else
tmff_init(struct hid_device * hid,const signed short * ff_bits)211*4882a593Smuzhiyun static inline int tmff_init(struct hid_device *hid, const signed short *ff_bits)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun 	return 0;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun #endif
216*4882a593Smuzhiyun 
tm_probe(struct hid_device * hdev,const struct hid_device_id * id)217*4882a593Smuzhiyun static int tm_probe(struct hid_device *hdev, const struct hid_device_id *id)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun 	int ret;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	ret = hid_parse(hdev);
222*4882a593Smuzhiyun 	if (ret) {
223*4882a593Smuzhiyun 		hid_err(hdev, "parse failed\n");
224*4882a593Smuzhiyun 		goto err;
225*4882a593Smuzhiyun 	}
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
228*4882a593Smuzhiyun 	if (ret) {
229*4882a593Smuzhiyun 		hid_err(hdev, "hw start failed\n");
230*4882a593Smuzhiyun 		goto err;
231*4882a593Smuzhiyun 	}
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	tmff_init(hdev, (void *)id->driver_data);
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	return 0;
236*4882a593Smuzhiyun err:
237*4882a593Smuzhiyun 	return ret;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun static const struct hid_device_id tm_devices[] = {
241*4882a593Smuzhiyun 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300),
242*4882a593Smuzhiyun 		.driver_data = (unsigned long)ff_rumble },
243*4882a593Smuzhiyun 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304),   /* FireStorm Dual Power 2 (and 3) */
244*4882a593Smuzhiyun 		.driver_data = (unsigned long)ff_rumble },
245*4882a593Smuzhiyun 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, THRUSTMASTER_DEVICE_ID_2_IN_1_DT),   /* Dual Trigger 2-in-1 */
246*4882a593Smuzhiyun 		.driver_data = (unsigned long)ff_rumble },
247*4882a593Smuzhiyun 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323),   /* Dual Trigger 3-in-1 (PC Mode) */
248*4882a593Smuzhiyun 		.driver_data = (unsigned long)ff_rumble },
249*4882a593Smuzhiyun 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324),   /* Dual Trigger 3-in-1 (PS3 Mode) */
250*4882a593Smuzhiyun 		.driver_data = (unsigned long)ff_rumble },
251*4882a593Smuzhiyun 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb605),   /* NASCAR PRO FF2 Wheel */
252*4882a593Smuzhiyun 		.driver_data = (unsigned long)ff_joystick },
253*4882a593Smuzhiyun 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651),	/* FGT Rumble Force Wheel */
254*4882a593Smuzhiyun 		.driver_data = (unsigned long)ff_rumble },
255*4882a593Smuzhiyun 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653),	/* RGT Force Feedback CLUTCH Raging Wheel */
256*4882a593Smuzhiyun 		.driver_data = (unsigned long)ff_joystick },
257*4882a593Smuzhiyun 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654),	/* FGT Force Feedback Wheel */
258*4882a593Smuzhiyun 		.driver_data = (unsigned long)ff_joystick },
259*4882a593Smuzhiyun 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a),	/* F430 Force Feedback Wheel */
260*4882a593Smuzhiyun 		.driver_data = (unsigned long)ff_joystick },
261*4882a593Smuzhiyun 	{ }
262*4882a593Smuzhiyun };
263*4882a593Smuzhiyun MODULE_DEVICE_TABLE(hid, tm_devices);
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun static struct hid_driver tm_driver = {
266*4882a593Smuzhiyun 	.name = "thrustmaster",
267*4882a593Smuzhiyun 	.id_table = tm_devices,
268*4882a593Smuzhiyun 	.probe = tm_probe,
269*4882a593Smuzhiyun };
270*4882a593Smuzhiyun module_hid_driver(tm_driver);
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun MODULE_LICENSE("GPL");
273