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 ==
(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
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
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);
}
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
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
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
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.
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