2007-05-23 00:33:24

by Renato Golin

[permalink] [raw]
Subject: [PATCH] joydev.c automatic re-calibration

This small patch adds the automatic recalibration feature without
spoiling previously calibrated devices. It's a fix for those joysticks
that report faulty range, specially Saitek Cyborg Evo Force.

File: drivers/input/joydev.c
Fix:
- extracted code from joydev_connect to method
joydev_calculate_correction to be able to call it from both
joydev_event upon recalibration and joydev_connect during first
connection.
- on joydev_connect check ranges and zero calibration if found out of range
- on joydev_event, every time found out of range, update min/max and
recalculate the correction

Patch below and attached.

cheers,
--renato

== PATCH BEGIN ==

--- joydev.c.original 2007-05-22 22:23:43.000000000 +0100
+++ joydev.c 2007-05-23 01:24:04.000000000 +0100
@@ -53,6 +53,8 @@
__u8 absmap[ABS_MAX + 1];
__u8 abspam[ABS_MAX + 1];
__s16 abs[ABS_MAX + 1];
+ __s16 absmin[ABS_MAX + 1];
+ __s16 absmax[ABS_MAX + 1];
};

struct joydev_list {
@@ -67,6 +69,19 @@

static struct joydev *joydev_table[JOYDEV_MINORS];

+static void joydev_calculate_correction(int min, int max, int axis,
struct joydev *joydev)
+{
+ int t, j = joydev->abspam[axis];
+ int flat = joydev->handle.dev->absflat[j];
+
+ joydev->corr[axis].coef[0] = (max + min) / 2 - flat;
+ joydev->corr[axis].coef[1] = (max + min) / 2 + flat;
+ if (!(t = ((max - min) / 2 - 2 * flat)))
+ return;
+ joydev->corr[axis].coef[2] = (1 << 29) / t;
+ joydev->corr[axis].coef[3] = (1 << 29) / t;
+}
+
static int joydev_correct(int value, struct js_corr *corr)
{
switch (corr->type) {
@@ -103,6 +118,14 @@
case EV_ABS:
event.type = JS_EVENT_AXIS;
event.number = joydev->absmap[code];
+ /* recalibration if needed */
+ if (value < joydev->absmin[code]) {
+ joydev->absmin[code] = value;
+ joydev_calculate_correction(value,
joydev->absmax[code], code, joydev);
+ } else if (value > joydev->absmax[code]) {
+ joydev->absmax[code] = value;
+
joydev_calculate_correction(joydev->absmin[code], value, code,
joydev);
+ }
event.value = joydev_correct(value,
joydev->corr + event.number);
if (event.value == joydev->abs[event.number])
return;
@@ -470,7 +493,7 @@
{
struct joydev *joydev;
struct class_device *cdev;
- int i, j, t, minor;
+ int i, j, minor;

for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
if (minor == JOYDEV_MINORS) {
@@ -515,19 +538,21 @@

for (i = 0; i < joydev->nabs; i++) {
j = joydev->abspam[i];
- if (dev->absmax[j] == dev->absmin[j]) {
+ joydev->absmin[i] = dev->absmin[j];
+ joydev->absmax[i] = dev->absmax[j];
+ if (joydev->absmax[i] == joydev->absmin[i]) {
joydev->corr[i].type = JS_CORR_NONE;
joydev->abs[i] = dev->abs[j];
continue;
}
joydev->corr[i].type = JS_CORR_BROKEN;
joydev->corr[i].prec = dev->absfuzz[j];
- joydev->corr[i].coef[0] = (dev->absmax[j] +
dev->absmin[j]) / 2 - dev->absflat[j];
- joydev->corr[i].coef[1] = (dev->absmax[j] +
dev->absmin[j]) / 2 + dev->absflat[j];
- if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 *
dev->absflat[j])))
- continue;
- joydev->corr[i].coef[2] = (1 << 29) / t;
- joydev->corr[i].coef[3] = (1 << 29) / t;
+
+ if (dev->abs[j] > joydev->absmax[i] || dev->abs[j] <
joydev->absmin[i]) {
+ printk("Joydev: Bad axis range, recalibrating
automatically\n");
+ joydev_calculate_correction(0, 0, i, joydev);
+ } else
+ joydev_calculate_correction(joydev->absmin[i],
joydev->absmax[i], i, joydev);

joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
}

== PATCH END ==


Attachments:
(No filename) (4.20 kB)
joydev.patch (2.80 kB)
Download all attachments

2007-05-23 09:38:22

by Jiri Kosina

[permalink] [raw]
Subject: Re: [PATCH] joydev.c automatic re-calibration

(Adding Dmitry to CC so that he doesn't miss it.

Also, if you'd like to get your patch merged, you should add proper
Signed-off-by line.

Thanks)

On Wed, 23 May 2007, Renato Golin wrote:

> This small patch adds the automatic recalibration feature without
> spoiling previously calibrated devices. It's a fix for those joysticks
> that report faulty range, specially Saitek Cyborg Evo Force.
>
> File: drivers/input/joydev.c
> Fix:
> - extracted code from joydev_connect to method
> joydev_calculate_correction to be able to call it from both
> joydev_event upon recalibration and joydev_connect during first
> connection.
> - on joydev_connect check ranges and zero calibration if found out of range
> - on joydev_event, every time found out of range, update min/max and
> recalculate the correction
>
> Patch below and attached.
>
> cheers,
> --renato
>
> == PATCH BEGIN ==
>
> --- joydev.c.original 2007-05-22 22:23:43.000000000 +0100
> +++ joydev.c 2007-05-23 01:24:04.000000000 +0100
> @@ -53,6 +53,8 @@
> __u8 absmap[ABS_MAX + 1];
> __u8 abspam[ABS_MAX + 1];
> __s16 abs[ABS_MAX + 1];
> + __s16 absmin[ABS_MAX + 1];
> + __s16 absmax[ABS_MAX + 1];
> };
>
> struct joydev_list {
> @@ -67,6 +69,19 @@
>
> static struct joydev *joydev_table[JOYDEV_MINORS];
>
> +static void joydev_calculate_correction(int min, int max, int axis,
> struct joydev *joydev)
> +{
> + int t, j = joydev->abspam[axis];
> + int flat = joydev->handle.dev->absflat[j];
> +
> + joydev->corr[axis].coef[0] = (max + min) / 2 - flat;
> + joydev->corr[axis].coef[1] = (max + min) / 2 + flat;
> + if (!(t = ((max - min) / 2 - 2 * flat)))
> + return;
> + joydev->corr[axis].coef[2] = (1 << 29) / t;
> + joydev->corr[axis].coef[3] = (1 << 29) / t;
> +}
> +
> static int joydev_correct(int value, struct js_corr *corr)
> {
> switch (corr->type) {
> @@ -103,6 +118,14 @@
> case EV_ABS:
> event.type = JS_EVENT_AXIS;
> event.number = joydev->absmap[code];
> + /* recalibration if needed */
> + if (value < joydev->absmin[code]) {
> + joydev->absmin[code] = value;
> + joydev_calculate_correction(value,
> joydev->absmax[code], code, joydev);
> + } else if (value > joydev->absmax[code]) {
> + joydev->absmax[code] = value;
> +
> joydev_calculate_correction(joydev->absmin[code], value, code,
> joydev);
> + }
> event.value = joydev_correct(value,
> joydev->corr + event.number);
> if (event.value == joydev->abs[event.number])
> return;
> @@ -470,7 +493,7 @@
> {
> struct joydev *joydev;
> struct class_device *cdev;
> - int i, j, t, minor;
> + int i, j, minor;
>
> for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
> if (minor == JOYDEV_MINORS) {
> @@ -515,19 +538,21 @@
>
> for (i = 0; i < joydev->nabs; i++) {
> j = joydev->abspam[i];
> - if (dev->absmax[j] == dev->absmin[j]) {
> + joydev->absmin[i] = dev->absmin[j];
> + joydev->absmax[i] = dev->absmax[j];
> + if (joydev->absmax[i] == joydev->absmin[i]) {
> joydev->corr[i].type = JS_CORR_NONE;
> joydev->abs[i] = dev->abs[j];
> continue;
> }
> joydev->corr[i].type = JS_CORR_BROKEN;
> joydev->corr[i].prec = dev->absfuzz[j];
> - joydev->corr[i].coef[0] = (dev->absmax[j] +
> dev->absmin[j]) / 2 - dev->absflat[j];
> - joydev->corr[i].coef[1] = (dev->absmax[j] +
> dev->absmin[j]) / 2 + dev->absflat[j];
> - if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 *
> dev->absflat[j])))
> - continue;
> - joydev->corr[i].coef[2] = (1 << 29) / t;
> - joydev->corr[i].coef[3] = (1 << 29) / t;
> +
> + if (dev->abs[j] > joydev->absmax[i] || dev->abs[j] <
> joydev->absmin[i]) {
> + printk("Joydev: Bad axis range, recalibrating
> automatically\n");
> + joydev_calculate_correction(0, 0, i, joydev);
> + } else
> + joydev_calculate_correction(joydev->absmin[i],
> joydev->absmax[i], i, joydev);
>
> joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
> }
>
> == PATCH END ==
>
>

--
Jiri Kosina

2007-05-23 10:01:18

by Renato Golin

[permalink] [raw]
Subject: Re: [PATCH] joydev.c automatic re-calibration

On 23/05/07, Jiri Kosina <[email protected]> wrote:
> (Adding Dmitry to CC so that he doesn't miss it.
>
> Also, if you'd like to get your patch merged, you should add proper
> Signed-off-by line.

Hi Jiri,

Sorry, it's my first kernel patch, how do I add Signed-off-by line?

I did with:

$ diff -u original changed

cheers,
--renato

Reclaim your digital rights, eliminate DRM, learn more at
http://www.defectivebydesign.org/what_is_drm

2007-05-23 10:09:57

by Renato Golin

[permalink] [raw]
Subject: Re: [PATCH] joydev.c automatic re-calibration

This small patch adds the automatic recalibration feature without
spoiling previously calibrated devices. It's a fix for those joysticks
that report faulty range, specially Saitek Cyborg Evo Force.

File: drivers/input/joydev.c
Fix:
- extracted code from joydev_connect to method
joydev_calculate_correction to be able to call it from both
joydev_event upon recalibration and joydev_connect during first
connection.
- on joydev_connect check ranges and zero calibration if found out of range
- on joydev_event, every time found out of range, update min/max and
recalculate the correction

PS: adding Signed-off-by line (is that it?)

Signed-off-by: Renato Golin <[email protected]>
$ diff -u joydev.c.original joydev.c
--- joydev.c.original 2007-05-22 22:23:43.000000000 +0100
+++ joydev.c 2007-05-23 01:24:04.000000000 +0100
@@ -53,6 +53,8 @@
__u8 absmap[ABS_MAX + 1];
__u8 abspam[ABS_MAX + 1];
__s16 abs[ABS_MAX + 1];
+ __s16 absmin[ABS_MAX + 1];
+ __s16 absmax[ABS_MAX + 1];
};

struct joydev_list {
@@ -67,6 +69,19 @@

static struct joydev *joydev_table[JOYDEV_MINORS];

+static void joydev_calculate_correction(int min, int max, int axis,
struct joydev *joydev)
+{
+ int t, j = joydev->abspam[axis];
+ int flat = joydev->handle.dev->absflat[j];
+
+ joydev->corr[axis].coef[0] = (max + min) / 2 - flat;
+ joydev->corr[axis].coef[1] = (max + min) / 2 + flat;
+ if (!(t = ((max - min) / 2 - 2 * flat)))
+ return;
+ joydev->corr[axis].coef[2] = (1 << 29) / t;
+ joydev->corr[axis].coef[3] = (1 << 29) / t;
+}
+
static int joydev_correct(int value, struct js_corr *corr)
{
switch (corr->type) {
@@ -103,6 +118,14 @@
case EV_ABS:
event.type = JS_EVENT_AXIS;
event.number = joydev->absmap[code];
+ /* recalibration if needed */
+ if (value < joydev->absmin[code]) {
+ joydev->absmin[code] = value;
+ joydev_calculate_correction(value,
joydev->absmax[code], code, joydev);
+ } else if (value > joydev->absmax[code]) {
+ joydev->absmax[code] = value;
+
joydev_calculate_correction(joydev->absmin[code], value, code,
joydev);
+ }
event.value = joydev_correct(value,
joydev->corr + event.number);
if (event.value == joydev->abs[event.number])
return;
@@ -470,7 +493,7 @@
{
struct joydev *joydev;
struct class_device *cdev;
- int i, j, t, minor;
+ int i, j, minor;

for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
if (minor == JOYDEV_MINORS) {
@@ -515,19 +538,21 @@

for (i = 0; i < joydev->nabs; i++) {
j = joydev->abspam[i];
- if (dev->absmax[j] == dev->absmin[j]) {
+ joydev->absmin[i] = dev->absmin[j];
+ joydev->absmax[i] = dev->absmax[j];
+ if (joydev->absmax[i] == joydev->absmin[i]) {
joydev->corr[i].type = JS_CORR_NONE;
joydev->abs[i] = dev->abs[j];
continue;
}
joydev->corr[i].type = JS_CORR_BROKEN;
joydev->corr[i].prec = dev->absfuzz[j];
- joydev->corr[i].coef[0] = (dev->absmax[j] +
dev->absmin[j]) / 2 - dev->absflat[j];
- joydev->corr[i].coef[1] = (dev->absmax[j] +
dev->absmin[j]) / 2 + dev->absflat[j];
- if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 *
dev->absflat[j])))
- continue;
- joydev->corr[i].coef[2] = (1 << 29) / t;
- joydev->corr[i].coef[3] = (1 << 29) / t;
+
+ if (dev->abs[j] > joydev->absmax[i] || dev->abs[j] <
joydev->absmin[i]) {
+ printk("Joydev: Bad axis range, recalibrating
automatically\n");
+ joydev_calculate_correction(0, 0, i, joydev);
+ } else
+ joydev_calculate_correction(joydev->absmin[i],
joydev->absmax[i], i, joydev);

joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
}

2007-05-23 14:37:49

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [PATCH] joydev.c automatic re-calibration

Hi,

On 5/23/07, Jiri Kosina <[email protected]> wrote:
> (Adding Dmitry to CC so that he doesn't miss it.
>
> Also, if you'd like to get your patch merged, you should add proper
> Signed-off-by line.
>

So did you come to the conclusion that HID can't set up true (or real)
range for some of Saitek's axes upon input device registration?

--
Dmitry

2007-05-23 14:46:59

by Jiri Kosina

[permalink] [raw]
Subject: Re: [PATCH] joydev.c automatic re-calibration

On Wed, 23 May 2007, Dmitry Torokhov wrote:

> > Also, if you'd like to get your patch merged, you should add proper
> > Signed-off-by line.
> So did you come to the conclusion that HID can't set up true (or real)
> range for some of Saitek's axes upon input device registration?

I have asked Renato to provide HID debugging output a few days ago - see
http://lkml.org/lkml/2007/5/21/201 - but that was without reply.

Renato, do you think you could try this, so that we can understand better
if we can't put a HID quirk to normalize the values on HID-level somehow?

Thanks a lot,

--
Jiri Kosina

2007-05-23 15:25:28

by Renato Golin

[permalink] [raw]
Subject: Re: [PATCH] joydev.c automatic re-calibration

On 23/05/07, Jiri Kosina <[email protected]> wrote:
> I have asked Renato to provide HID debugging output a few days ago - see
> http://lkml.org/lkml/2007/5/21/201 - but that was without reply.

Sorry, didn't get the email.


> Renato, do you think you could try this, so that we can understand better
> if we can't put a HID quirk to normalize the values on HID-level somehow?

Good idea. I've put some debugging (but posted in the wrong list)
about the values my joystick is reporting. Will turn on HID debugging
and post the results.

cheers,
--renato

Reclaim your digital rights, eliminate DRM, learn more at
http://www.defectivebydesign.org/what_is_drm

2007-05-23 18:00:42

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] joydev.c automatic re-calibration

On Wed, 23 May 2007 01:33:14 +0100 "Renato Golin" <[email protected]> wrote:

> This small patch adds the automatic recalibration feature without
> spoiling previously calibrated devices. It's a fix for those joysticks
> that report faulty range, specially Saitek Cyborg Evo Force.
>
> File: drivers/input/joydev.c
> Fix:
> - extracted code from joydev_connect to method
> joydev_calculate_correction to be able to call it from both
> joydev_event upon recalibration and joydev_connect during first
> connection.
> - on joydev_connect check ranges and zero calibration if found out of range
> - on joydev_event, every time found out of range, update min/max and
> recalculate the correction

A few patch protocol things:

- Please always prepare patches in `patch -p1' form

- Include a Signed-off-by: as per Documentation/SubmittingPatches,
section 11.

- Avoid including two copies of the patch in the one email. Inlined plain
text is preferred, ext/plain attachments are grudgingly accepted.

I descrambled the patch, fixed a reject and queued it up in the -mm tree
for Dmitry's consideration, thanks.

2007-05-23 18:20:59

by Renato Golin

[permalink] [raw]
Subject: Re: [PATCH] joydev.c automatic re-calibration

On 23/05/07, Andrew Morton <[email protected]> wrote:
> A few patch protocol things:
>
> - Please always prepare patches in `patch -p1' form
>
> - Include a Signed-off-by: as per Documentation/SubmittingPatches,
> section 11.
>
> - Avoid including two copies of the patch in the one email. Inlined plain
> text is preferred, ext/plain attachments are grudgingly accepted.
>
> I descrambled the patch, fixed a reject and queued it up in the -mm tree
> for Dmitry's consideration, thanks.

Hi Andrew,

sorry for the confusion, I'm following up with Dimitri and Jiri and
hopefully will have a patch following the protocol next time. ;)

cheers,
--renato

Reclaim your digital rights, eliminate DRM, learn more at
http://www.defectivebydesign.org/what_is_drm