linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Dmitry Torokhov" <dmitry.torokhov@gmail.com>
To: Gerald Folcher <geraldf2@free.fr>
Cc: linux-input@atrey.karlin.mff.cuni.cz
Subject: Re: Force Feedback: Thrustmaster FGT Wheel quick-and-dirty in hid-lgff.c or hid-tmff.c
Date: Mon, 16 Jul 2007 16:50:14 -0400	[thread overview]
Message-ID: <d120d5000707161350v782563e8na7ae4f593e0daf83@mail.gmail.com> (raw)
In-Reply-To: <469BA787.8080700@free.fr>

[-- Attachment #1: Type: text/plain, Size: 1240 bytes --]

On 7/16/07, Gerald Folcher <geraldf2@free.fr> wrote:
> Dmitry Torokhov wrote:
> > I wonder if the attached is all that is needed for your wheel to work...
>
> No, but I think I understand where is the confusion:
> It won't work because my wheel is the "Force Feedback" model, not the
> "Rumble Force" model which is cheaper but looks exactly the same. With
> your patch applied as is, my wheel will neither do rumble effects nor
> constant force effects, the force feedback test utilities 'ffcfstress'
> and 'ffmvforce' will spit an error message on startup and exit. And
> 'fftest' will think my wheel can do Rumble but trying such effects will
> effectively trigger hazardous constant forces on my wheel.
>
> But your patch would maybe work for the actual Rumble wheel if you
> change the id to 0x651, which is the id of the Rumble version according
> to the MS-Windows registry on a machine where I installed the
> Thrustmaster drivers (the registry is full of id's of the wheels
> supported by the driver).
>
> While the id of my wheel (Force Feedback) is: 0x654 (and according to
> the aforementioned MS-Windows registry there is also an id 0x652 for a
> Thrustmaster wheel with the same name).
>

OK, how about this then?

-- 
Dmitry

[-- Attachment #2: hid-add-thrustmaster-fgt-wheel.patch --]
[-- Type: application/octet-stream, Size: 6463 bytes --]

Input: HID - add support for Thrustmaster FGT Force Feedback wheel

Rework thrustmaster force-feedback module to support devices having
different types of force feedback effects. Add signatures of
Thrustmaster FGT Rumble Force and Thrustmaster FGT Force Feedback
wheels to the list of devices dupported by tthe module.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
 drivers/hid/usbhid/hid-ff.c   |    2 
 drivers/hid/usbhid/hid-tmff.c |  136 +++++++++++++++++++++++++++++-------------
 2 files changed, 99 insertions(+), 39 deletions(-)

Index: linux/drivers/hid/usbhid/hid-ff.c
===================================================================
--- linux.orig/drivers/hid/usbhid/hid-ff.c
+++ linux/drivers/hid/usbhid/hid-ff.c
@@ -67,6 +67,8 @@ static struct hid_ff_initializer inits[]
 #ifdef CONFIG_THRUSTMASTER_FF
 	{ 0x44f, 0xb300, hid_tmff_init },
 	{ 0x44f, 0xb304, hid_tmff_init },
+	{ 0x44f, 0xb651, hid_tmff_init }, /* FGT Rumble Force Wheel */
+	{ 0x44f, 0xb654, hid_tmff_init }, /* FGT Force Feedback Wheel */
 #endif
 #ifdef CONFIG_ZEROPLUS_FF
 	{ 0xc12, 0x0005, hid_zpff_init },
Index: linux/drivers/hid/usbhid/hid-tmff.c
===================================================================
--- linux.orig/drivers/hid/usbhid/hid-tmff.c
+++ linux/drivers/hid/usbhid/hid-tmff.c
@@ -36,16 +36,39 @@
 #include "usbhid.h"
 
 /* Usages for thrustmaster devices I know about */
-#define THRUSTMASTER_USAGE_RUMBLE_LR	(HID_UP_GENDESK | 0xbb)
+#define THRUSTMASTER_USAGE_FORCEFEEDBACK	(HID_UP_GENDESK | 0xbb)
 
+struct dev_type {
+	u16 idVendor;
+	u16 idProduct;
+	const signed short *ff;
+};
+
+static const signed short ff_rumble[] = {
+	FF_RUMBLE,
+	-1
+};
+
+static const signed short ff_joystick[] = {
+	FF_CONSTANT,
+	-1
+};
+
+static const struct dev_type devices[] = {
+	{ 0x44f, 0xb300, ff_rumble },
+	{ 0x44f, 0xb304, ff_rumble },
+	{ 0x44f, 0xb651, ff_rumble },	/* FGT Rumble Force Wheel */
+	{ 0x44f, 0xb654, ff_joystick },	/* FGT Force Feedback Wheel */
+};
 
 struct tmff_device {
 	struct hid_report *report;
-	struct hid_field *rumble;
+	struct hid_field *ff_field;
 };
 
 /* Changes values from 0 to 0xffff into values from minimum to maximum */
-static inline int hid_tmff_scale(unsigned int in, int minimum, int maximum)
+static inline int hid_tmff_scale_u16(unsigned int in,
+				int minimum, int maximum)
 {
 	int ret;
 
@@ -57,22 +80,57 @@ static inline int hid_tmff_scale(unsigne
 	return ret;
 }
 
+/* Changes values from -0x80 to 0x7f into values from minimum to maximum */
+static inline int hid_tmff_scale_s8(int in,
+				    int minimum, int maximum)
+{
+	int ret;
+
+	ret = (((in + 0x80) * (maximum - minimum)) / 0xff) + minimum;
+	if (ret < minimum)
+		return minimum;
+	if (ret > maximum)
+		return maximum;
+	return ret;
+}
+
 static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
 {
 	struct hid_device *hid = input_get_drvdata(dev);
 	struct tmff_device *tmff = data;
+	struct hid_field *ff_field = tmff->ff_field;
+	int x, y;
 	int left, right;	/* Rumbling */
 
-	left = hid_tmff_scale(effect->u.rumble.weak_magnitude,
-		tmff->rumble->logical_minimum, tmff->rumble->logical_maximum);
-	right = hid_tmff_scale(effect->u.rumble.strong_magnitude,
-		tmff->rumble->logical_minimum, tmff->rumble->logical_maximum);
-
-	tmff->rumble->value[0] = left;
-	tmff->rumble->value[1] = right;
-	dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
-	usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
-
+	switch (effect->type) {
+	case FF_CONSTANT:
+		x = hid_tmff_scale_s8(effect->u.ramp.start_level,
+					ff_field->logical_minimum,
+					ff_field->logical_maximum);
+		y = hid_tmff_scale_s8(effect->u.ramp.end_level,
+					ff_field->logical_minimum,
+					ff_field->logical_maximum);
+
+		dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
+		ff_field->value[0] = x;
+		ff_field->value[1] = y;
+		usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
+		break;
+
+	case FF_RUMBLE:
+		left = hid_tmff_scale_u16(effect->u.rumble.weak_magnitude,
+					ff_field->logical_minimum,
+					ff_field->logical_maximum);
+		right = hid_tmff_scale_u16(effect->u.rumble.strong_magnitude,
+					ff_field->logical_minimum,
+					ff_field->logical_maximum);
+
+		dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
+		ff_field->value[0] = left;
+		ff_field->value[1] = right;
+		usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
+		break;
+	}
 	return 0;
 }
 
@@ -89,7 +147,7 @@ int hid_tmff_init(struct hid_device *hid
 		return -ENOMEM;
 
 	/* Find the report to use */
-	__list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) {
+	list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) {
 		struct hid_report *report = (struct hid_report *)pos;
 		int fieldnum;
 
@@ -100,36 +158,36 @@ int hid_tmff_init(struct hid_device *hid
 				continue;
 
 			switch (field->usage[0].hid) {
-				case THRUSTMASTER_USAGE_RUMBLE_LR:
-					if (field->report_count < 2) {
-						warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with report_count < 2");
-						continue;
-					}
-
-					if (field->logical_maximum == field->logical_minimum) {
-						warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with logical_maximum == logical_minimum");
-						continue;
-					}
-
-					if (tmff->report && tmff->report != report) {
-						warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR in other report");
-						continue;
-					}
-
-					if (tmff->rumble && tmff->rumble != field) {
-						warn("ignoring duplicate THRUSTMASTER_USAGE_RUMBLE_LR");
-						continue;
-					}
+			case THRUSTMASTER_USAGE_FORCEFEEDBACK:
+				if (field->report_count < 2) {
+					warn("ignoring FF field with report_count < 2");
+					continue;
+				}
+
+				if (field->logical_maximum == field->logical_minimum) {
+					warn("ignoring FF field with logical_maximum == logical_minimum");
+					continue;
+				}
+
+				if (tmff->report && tmff->report != report) {
+					warn("ignoring FF field in other report");
+					continue;
+				}
 
-					tmff->report = report;
-					tmff->rumble = field;
+				if (tmff->ff_field && tmff->ff_field != field) {
+					warn("ignoring duplicate FF field");
+					continue;
+				}
+
+				tmff->report = report;
+				tmff->ff_field = field;
 
 					set_bit(FF_RUMBLE, input_dev->ffbit);
 					break;
 
-				default:
-					warn("ignoring unknown output usage %08x", field->usage[0].hid);
-					continue;
+			default:
+				warn("ignoring unknown output usage %08x", field->usage[0].hid);
+				continue;
 			}
 		}
 	}

  parent reply	other threads:[~2007-07-16 20:50 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-07-16 13:48 Force Feedback: Thrustmaster FGT Wheel quick-and-dirty in hid-lgff.c or hid-tmff.c Gerald Folcher
2007-07-16 16:05 ` Dmitry Torokhov
2007-07-16 17:14   ` Gerald Folcher
2007-07-16 17:21     ` Anssi Hannula
2007-07-16 18:37       ` Gerald Folcher
2007-07-16 21:00         ` Anssi Hannula
2007-07-16 20:50     ` Dmitry Torokhov [this message]
2007-07-16 21:03       ` Dmitry Torokhov
2007-07-16 21:21         ` Dmitry Torokhov
2007-07-17  9:14           ` Gerald Folcher
2007-07-17 13:50             ` Dmitry Torokhov
2007-07-30 13:13               ` Jiri Kosina
2007-08-22  2:30                 ` Gerald Folcher
2007-08-22  8:16                   ` Jiri Kosina
2007-08-22 10:30                     ` Gerald Folcher
2007-07-17 13:14     ` Gerald Folcher

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d120d5000707161350v782563e8na7ae4f593e0daf83@mail.gmail.com \
    --to=dmitry.torokhov@gmail.com \
    --cc=geraldf2@free.fr \
    --cc=linux-input@atrey.karlin.mff.cuni.cz \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).