linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Gary Stein <lordcnidarian@gmail.com>
To: Jiri Kosina <jkosina@suse.cz>
Cc: linux-input@vger.kernel.org, dmitry.torokhov@gmail.com
Subject: Re: [PATCH] Add Driver for Logitech Flight System G940
Date: Thu, 10 Dec 2009 15:37:18 -0500	[thread overview]
Message-ID: <fce72f9b0912101237x5f38300bxcd0fbb815ad5ea9c@mail.gmail.com> (raw)
In-Reply-To: <alpine.LNX.2.00.0912091416010.3755@pobox.suse.cz>

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

This is a cleaned up and updated driver for the G940.  I followed most
of the checkpatch notes except for some of the 80 column stuff, the
sections of where most of that code is hid-core.c also doesn't seem to
care about it.

I stripped out my custom X,Y interface using FF_RAMP, so this should
be just a drop in replacement for userland code that does force
feedback.

However, also in this code is the (int) cast fix that I send before to
linux-kernel in ff-memless.  Without this, my driver or the normal
logitech driver for other sticks seems to work for me.

It is sent as an attachment, if it truely needs to be inline, I'll set
up thunderbird for gmail IMAP.

gary

[-- Attachment #2: logitech-g940.patch --]
[-- Type: application/octet-stream, Size: 11792 bytes --]

diff -uprN -X linux-2.6.31.next/Documentation/dontdiff linux-2.6.31.orig/drivers/hid/Kconfig linux-2.6.31.next/drivers/hid/Kconfig
--- linux-2.6.31.orig/drivers/hid/Kconfig	2009-09-09 17:13:59.000000000 -0500
+++ linux-2.6.31.next/drivers/hid/Kconfig	2009-12-01 12:29:44.000000000 -0500
@@ -190,6 +190,14 @@ config LOGIRUMBLEPAD2_FF
 	  Say Y here if you want to enable force feedback support for Logitech
 	  Rumblepad 2 devices.
 
+config LOGIG940_FF
+	bool "Logitech Flight System G940 force feedback support"
+	depends on HID_LOGITECH
+	select INPUT_FF_MEMLESS
+	help
+	  Say Y here if you want to enable force feedback support for Logitech
+	  Flight System G940 devices.
+
 config HID_MICROSOFT
 	tristate "Microsoft" if EMBEDDED
 	depends on USB_HID
diff -uprN -X linux-2.6.31.next/Documentation/dontdiff linux-2.6.31.orig/drivers/hid/Makefile linux-2.6.31.next/drivers/hid/Makefile
--- linux-2.6.31.orig/drivers/hid/Makefile	2009-09-09 17:13:59.000000000 -0500
+++ linux-2.6.31.next/drivers/hid/Makefile	2009-12-01 12:29:44.000000000 -0500
@@ -15,6 +15,9 @@ endif
 ifdef CONFIG_LOGIRUMBLEPAD2_FF
 	hid-logitech-objs	+= hid-lg2ff.o
 endif
+ifdef CONFIG_LOGIG940_FF
+	hid-logitech-objs	+= hid-lg3ff.o
+endif
 
 obj-$(CONFIG_HID_A4TECH)	+= hid-a4tech.o
 obj-$(CONFIG_HID_APPLE)		+= hid-apple.o
diff -uprN -X linux-2.6.31.next/Documentation/dontdiff linux-2.6.31.orig/drivers/hid/hid-core.c linux-2.6.31.next/drivers/hid/hid-core.c
--- linux-2.6.31.orig/drivers/hid/hid-core.c	2009-09-09 17:13:59.000000000 -0500
+++ linux-2.6.31.next/drivers/hid/hid-core.c	2009-12-01 12:29:44.000000000 -0500
@@ -1293,6 +1293,7 @@ static const struct hid_device_id hid_bl
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) },
diff -uprN -X linux-2.6.31.next/Documentation/dontdiff linux-2.6.31.orig/drivers/hid/hid-ids.h linux-2.6.31.next/drivers/hid/hid-ids.h
--- linux-2.6.31.orig/drivers/hid/hid-ids.h	2009-09-09 17:13:59.000000000 -0500
+++ linux-2.6.31.next/drivers/hid/hid-ids.h	2009-12-01 12:29:44.000000000 -0500
@@ -295,6 +295,7 @@
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2	0xc219
 #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D	0xc283
 #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO	0xc286
+#define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940	0xc287
 #define USB_DEVICE_ID_LOGITECH_WHEEL	0xc294
 #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL	0xc295
 #define USB_DEVICE_ID_LOGITECH_G25_WHEEL	0xc299
diff -uprN -X linux-2.6.31.next/Documentation/dontdiff linux-2.6.31.orig/drivers/hid/hid-lg.c linux-2.6.31.next/drivers/hid/hid-lg.c
--- linux-2.6.31.orig/drivers/hid/hid-lg.c	2009-09-09 17:13:59.000000000 -0500
+++ linux-2.6.31.next/drivers/hid/hid-lg.c	2009-12-01 12:29:44.000000000 -0500
@@ -33,6 +33,7 @@
 #define LG_NOGET		0x100
 #define LG_FF			0x200
 #define LG_FF2			0x400
+#define LG_FF3			0x800
 
 /*
  * Certain Logitech keyboards send in report #3 keys which are far
@@ -238,7 +239,7 @@ static int lg_probe(struct hid_device *h
 		goto err_free;
 	}
 
-	if (quirks & (LG_FF | LG_FF2))
+	if (quirks & (LG_FF | LG_FF2 | LG_FF3))
 		connect_mask &= ~HID_CONNECT_FF;
 
 	ret = hid_hw_start(hdev, connect_mask);
@@ -251,6 +252,8 @@ static int lg_probe(struct hid_device *h
 		lgff_init(hdev);
 	if (quirks & LG_FF2)
 		lg2ff_init(hdev);
+	if (quirks & LG_FF3)
+		lg3ff_init(hdev);
 
 	return 0;
 err_free:
@@ -301,6 +304,8 @@ static const struct hid_device_id lg_dev
 		.driver_data = LG_FF },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
 		.driver_data = LG_FF2 },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940),
+		.driver_data = LG_FF3 },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, lg_devices);
diff -uprN -X linux-2.6.31.next/Documentation/dontdiff linux-2.6.31.orig/drivers/hid/hid-lg.h linux-2.6.31.next/drivers/hid/hid-lg.h
--- linux-2.6.31.orig/drivers/hid/hid-lg.h	2009-09-09 17:13:59.000000000 -0500
+++ linux-2.6.31.next/drivers/hid/hid-lg.h	2009-12-01 12:29:44.000000000 -0500
@@ -15,4 +15,10 @@ int lg2ff_init(struct hid_device *hdev);
 static inline int lg2ff_init(struct hid_device *hdev) { return -1; }
 #endif
 
+#ifdef CONFIG_LOGIG940_FF
+int lg3ff_init(struct hid_device *hdev);
+#else
+static inline int lg3ff_init(struct hid_device *hdev) { return -1; }
+#endif
+
 #endif
diff -uprN -X linux-2.6.31.next/Documentation/dontdiff linux-2.6.31.orig/drivers/hid/hid-lg3ff.c linux-2.6.31.next/drivers/hid/hid-lg3ff.c
--- linux-2.6.31.orig/drivers/hid/hid-lg3ff.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.31.next/drivers/hid/hid-lg3ff.c	2009-12-10 15:03:39.000000000 -0500
@@ -0,0 +1,168 @@
+/*
+ *  Force feedback support for Logitech Flight System G940
+ *
+ *  Copyright (c) 2009 Gary Stein <LordCnidarian@gmail.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+
+#include "usbhid/usbhid.h"
+#include "hid-lg.h"
+
+/*
+	G940 Theory of Operation (from experimentation)
+
+	There are 63 fields (only 3 of them currently used)
+	0 - seems to be command field
+	1 - 30 deal with the x axis
+	31 -60 deal with the y axis
+
+	Field 1 is x axis constant force
+	Field 31 is y axis constant force
+
+	other interesting fields 1,2,3,4 on x axis
+		(same for 31,32,33,34 on y axis)
+
+	0 0 127 127 makes the joystick autocenter hard
+
+	127 0 127 127 makes the joystick loose on the right,
+		but stops all movemnt left
+
+	-127 0 -127 -127 makes the joystick loose on the left,
+		but stops all movement right
+
+	0 0 -127 -127 makes the joystick rattle very hard
+
+	I'm sure these are effects that I don't know enough about them
+*/
+
+struct lg3ff_device {
+	struct hid_report *report;
+};
+
+static int hid_lg3ff_play(struct input_dev *dev, void *data,
+			 struct ff_effect *effect)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	int x, y;
+
+	/* maxusage should be 63, maximum fields
+		likely a better way to ensure this data is clean */
+	memset(report->field[0]->value, 0, sizeof(__s32)*report->field[0]->maxusage);
+
+	switch (effect->type) {
+	case FF_CONSTANT:
+		/* Already clamped in ff_memless */
+		/* 0 is center (different then other logitech) */
+		x = effect->u.ramp.start_level;
+		y = effect->u.ramp.end_level;
+
+		/* send command byte */
+		report->field[0]->value[0] = 0x51;
+
+		/* sign backwards from other Force3d pro
+			which get recast here in two's complement 8 bits */
+		report->field[0]->value[1] = (unsigned char)(-x);
+		report->field[0]->value[31] = (unsigned char)(-y);
+
+		usbhid_submit_report(hid, report, USB_DIR_OUT);
+		break;
+	}
+	return 0;
+}
+static void hid_lg3ff_set_autocenter(struct input_dev *dev, u16 magnitude)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+
+	/* Auto Centering probed from device
+		note: deadman's switch on G940 must be covered
+		for effects to work */
+	report->field[0]->value[0] = 0x51;
+	report->field[0]->value[1] = 0x00;
+	report->field[0]->value[2] = 0x00;
+	report->field[0]->value[3] = 0x7F;
+	report->field[0]->value[4] = 0x7F;
+	report->field[0]->value[31] = 0x00;
+	report->field[0]->value[32] = 0x00;
+	report->field[0]->value[33] = 0x7F;
+	report->field[0]->value[34] = 0x7F;
+
+	usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+
+static const signed short ff3_joystick_ac[] = {
+	FF_CONSTANT,
+	FF_AUTOCENTER,
+	-1
+};
+
+int lg3ff_init(struct hid_device *hid)
+{
+	struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct input_dev *dev = hidinput->input;
+	struct hid_report *report;
+	struct hid_field *field;
+	const signed short *ff_bits = ff3_joystick_ac;
+	int error;
+	int i;
+
+	/* Find the report to use */
+	if (list_empty(report_list)) {
+		err_hid("No output report found");
+		return -1;
+	}
+
+	/* Check that the report looks ok */
+	report = list_entry(report_list->next, struct hid_report, list);
+	if (!report) {
+		err_hid("NULL output report");
+		return -1;
+	}
+
+	field = report->field[0];
+	if (!field) {
+		err_hid("NULL field");
+		return -1;
+	}
+
+	/* Assume single fixed device G940 */
+	for (i = 0; ff_bits[i] >= 0; i++)
+		set_bit(ff_bits[i], dev->ffbit);
+
+	error = input_ff_create_memless(dev, NULL, hid_lg3ff_play);
+	if (error)
+		return error;
+
+	if (test_bit(FF_AUTOCENTER, dev->ffbit))
+		dev->ff->set_autocenter = hid_lg3ff_set_autocenter;
+
+	dev_info(&hid->dev, "Force feedback for Logitech Flight System G940 by "
+			"Gary Stein <LordCnidarian@gmail.com>\n");
+	return 0;
+}
+
diff -uprN -X linux-2.6.31.next/Documentation/dontdiff linux-2.6.31.orig/drivers/hid/hid-lgff.c linux-2.6.31.next/drivers/hid/hid-lgff.c
--- linux-2.6.31.orig/drivers/hid/hid-lgff.c	2009-09-09 17:13:59.000000000 -0500
+++ linux-2.6.31.next/drivers/hid/hid-lgff.c	2009-12-01 15:19:49.000000000 -0500
@@ -67,6 +67,7 @@ static const struct dev_type devices[] =
 	{ 0x046d, 0xc219, ff_rumble },
 	{ 0x046d, 0xc283, ff_joystick },
 	{ 0x046d, 0xc286, ff_joystick_ac },
+	{ 0x046d, 0xc287, ff_joystick_ac },
 	{ 0x046d, 0xc294, ff_wheel },
 	{ 0x046d, 0xc295, ff_joystick },
 	{ 0x046d, 0xca03, ff_wheel },
@@ -95,7 +96,6 @@ static int hid_lgff_play(struct input_de
 		dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
 		usbhid_submit_report(hid, report, USB_DIR_OUT);
 		break;
-
 	case FF_RUMBLE:
 		right = effect->u.rumble.strong_magnitude;
 		left = effect->u.rumble.weak_magnitude;
diff -uprN -X linux-2.6.31.next/Documentation/dontdiff linux-2.6.31.orig/drivers/input/ff-memless.c linux-2.6.31.next/drivers/input/ff-memless.c
--- linux-2.6.31.orig/drivers/input/ff-memless.c	2009-09-09 17:13:59.000000000 -0500
+++ linux-2.6.31.next/drivers/input/ff-memless.c	2009-12-10 15:06:09.000000000 -0500
@@ -239,8 +239,8 @@ static void ml_combine_effects(struct ff
 		level = fixp_new16(apply_envelope(state,
 					new->u.constant.level,
 					&new->u.constant.envelope));
-		x = fixp_mult(fixp_sin(i), level) * gain / 0xffff;
-		y = fixp_mult(-fixp_cos(i), level) * gain / 0xffff;
+		x = (int)(fixp_mult(fixp_sin(i), level) * gain) / 0xffff;
+		y = (int)(fixp_mult(-fixp_cos(i), level) * gain) / 0xffff;
 		/*
 		 * here we abuse ff_ramp to hold x and y of constant force
 		 * If in future any driver wants something else than x and y

  parent reply	other threads:[~2009-12-10 20:37 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-08 22:39 [PATCH] Add Driver for Logitech Flight System G940 Gary Stein
2009-12-09  6:36 ` Dmitry Torokhov
2009-12-09 13:24 ` Jiri Kosina
2009-12-10 17:47   ` Gary Stein
2009-12-10 18:12     ` Dmitry Torokhov
2009-12-10 20:37   ` Gary Stein [this message]
2009-12-15 13:53     ` Jiri Kosina
2009-12-19  8:53       ` Dmitry Torokhov
2009-12-25  0:17         ` Anssi Hannula
2009-12-23 13:23       ` Jiri Kosina

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=fce72f9b0912101237x5f38300bxcd0fbb815ad5ea9c@mail.gmail.com \
    --to=lordcnidarian@gmail.com \
    --cc=dmitry.torokhov@gmail.com \
    --cc=jkosina@suse.cz \
    --cc=linux-input@vger.kernel.org \
    /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).