linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Benjamin Franzke <benjaminfranzke@googlemail.com>
To: linux-input@vger.kernel.org
Cc: Benjamin Franzke <benjaminfranzke@googlemail.com>
Subject: [PATCH 1/2] joydev: Map ABS_{THROTTLE,GAS,BREAK} to positive values.
Date: Wed, 11 Dec 2013 09:15:30 +0100	[thread overview]
Message-ID: <1386749731-6500-1-git-send-email-benjaminfranzke@googlemail.com> (raw)

Gamepads like XInput devices have triggers with a range from
e.g. 0 to 255.
When the conventional joydev AXES correction/mapping method is used,
the default state 0 (i.e. when the user does not press a button or trigger)
is mapped to -32767 (and 255 to 32767).
You'll get 0 only when pressing the trigger half-way down.
This has several drawbacks:
 - A trigger is not usable at all when configured to have 2 directions
   when there is physically only one.
 - Applications that let the user configure joystick input assignments
   may register the mapped non-zero default state as a press,
   preventing the user from configuring any sensible value.

Traditonal calibration e.g. with jscal does not help to get a usable
experience either, it'll map the default state to -32767 as well.
Only manually editing the calibration data does work currently.

This patch tries to fix this issue by calculating a positive-only range for
the throttle break and gas ABS bits.
Maybe other ABS types need to be added to this scheme as well(?)

Note:
Although joydev is considered obsolete and people are encouraged to just
use evdev, joydev should still be fixed, because
 1. many applications still use it.
 2. userspace already copies the joydev correction code to evdev (e.g. libSDL).

This bug should be fixed here in joydev first, and when we have a good
sensible state, this should be propagated to the application/libraries
that copied the joydev correction code.

Gamepad drivers will need to advertise triggers as THROTTLE,GAS,BREAK instead
of e.g. ABS_{RZ,Z} where phyisically appropriate, to make use of this.

I've considered changing the current joydev correction calculation for all ABS
types, to have only a scaling functionality by default, no translation
(all positive values remain positive, negatives negative and zero remains zero),
so that drivers would need to expose zero-centered ABS values.
It turned out to many drivers would need to be adjusted, which i cant
test.

Signed-off-by: Benjamin Franzke <benjaminfranzke@googlemail.com>
---
 drivers/input/joydev.c | 59 +++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 44 insertions(+), 15 deletions(-)

diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index f362883..8352bee 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -761,11 +761,50 @@ static bool joydev_match(struct input_handler *handler, struct input_dev *dev)
 	return true;
 }
 
+static void joydev_calculate_correction(struct input_dev *dev, __u8 abs,
+					struct js_corr *corr)
+{
+	int t;
+
+	corr->type = JS_CORR_BROKEN;
+	corr->prec = input_abs_get_fuzz(dev, abs);
+
+	switch (abs) {
+	/* Map [min - max] => [0 - 32767]. */
+	case ABS_THROTTLE:
+	case ABS_GAS:
+	case ABS_BRAKE:
+		corr->coef[0] = input_abs_get_min(dev, abs);
+		corr->coef[1] = corr->coef[0] + input_abs_get_flat(dev, abs);
+		corr->coef[2] = 0;
+
+		t = input_abs_get_max(dev, abs) - input_abs_get_min(dev, abs)
+			- input_abs_get_flat(dev, abs);
+		if (t)
+			corr->coef[3] = (1 << 29) / t;
+		break;
+	/* Map [min - max] => [-32768 - 32767]. */
+	default:
+		t = (input_abs_get_max(dev, abs) +
+		     input_abs_get_min(dev, abs)) / 2;
+		corr->coef[0] = t - input_abs_get_flat(dev, abs);
+		corr->coef[1] = t + input_abs_get_flat(dev, abs);
+		t = (input_abs_get_max(dev, abs) -
+		     input_abs_get_min(dev, abs)) / 2
+			- 2 * input_abs_get_flat(dev, abs);
+		if (t) {
+			corr->coef[2] = (1 << 29) / t;
+			corr->coef[3] = (1 << 29) / t;
+		}
+		break;
+	}
+}
+
 static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
 			  const struct input_device_id *id)
 {
 	struct joydev *joydev;
-	int i, j, t, minor, dev_no;
+	int i, j, minor, dev_no;
 	int error;
 
 	minor = input_get_new_minor(JOYDEV_MINOR_BASE, JOYDEV_MINORS, true);
@@ -826,23 +865,13 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
 			joydev->abs[i] = input_abs_get_val(dev, j);
 			continue;
 		}
-		joydev->corr[i].type = JS_CORR_BROKEN;
-		joydev->corr[i].prec = input_abs_get_fuzz(dev, j);
 
-		t = (input_abs_get_max(dev, j) + input_abs_get_min(dev, j)) / 2;
-		joydev->corr[i].coef[0] = t - input_abs_get_flat(dev, j);
-		joydev->corr[i].coef[1] = t + input_abs_get_flat(dev, j);
+		joydev_calculate_correction(dev, j, &joydev->corr[i]);
 
-		t = (input_abs_get_max(dev, j) - input_abs_get_min(dev, j)) / 2
-			- 2 * input_abs_get_flat(dev, j);
-		if (t) {
-			joydev->corr[i].coef[2] = (1 << 29) / t;
-			joydev->corr[i].coef[3] = (1 << 29) / t;
+		joydev->abs[i] =
+			joydev_correct(input_abs_get_val(dev, j),
+				       joydev->corr + i);
 
-			joydev->abs[i] =
-				joydev_correct(input_abs_get_val(dev, j),
-					       joydev->corr + i);
-		}
 	}
 
 	joydev->dev.devt = MKDEV(INPUT_MAJOR, minor);
-- 
1.8.1.5


             reply	other threads:[~2013-12-11  8:16 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-11  8:15 Benjamin Franzke [this message]
2013-12-11  8:15 ` [PATCH 2/2] joystick/xpad: Advertise the triggers as throttle/break Benjamin Franzke
2013-12-14  5:13 ` [PATCH 1/2] joydev: Map ABS_{THROTTLE,GAS,BREAK} to positive values Ken Phillis Jr
2013-12-14  6:22   ` Benjamin Franzke
2013-12-14  6:56     ` Ken Phillis Jr
2013-12-14  8:16       ` Benjamin Franzke
2013-12-19 12:50 ` Benjamin Franzke

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=1386749731-6500-1-git-send-email-benjaminfranzke@googlemail.com \
    --to=benjaminfranzke@googlemail.com \
    --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).