Re: [PATCH 1/1] HID: wiimote: invert Y-Axis and add automatic calibration for Wii U Pro Controller

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi

On Sun, Oct 6, 2013 at 8:44 PM, Rafael Brune <mail@xxxxxxxxx> wrote:
> With these changes the Wii U Pro Controller fully complies
> to the gamepad-API and with the calibration is fully usable
> out-of-the-box without any user-space tools. This potentially
> breaks compatibility with software that relies on the two
> inverted Y-Axis but since current bluez 4.x and 5.x versions
> don't even support pairing with the controller yet the amount
> of people affected should be rather small.

Did anyone try to read the calibration values from the EEPROM? Doing
calibration in the kernel is fine, but I'd rather have the
hardware-calibration values instead. Even if we cannot figure it out
now, we should try to stay as compatible to the real values as we can.

So how about keeping the min/max and neutral point as we have it know
and instead adjusting the reported values by scaling/moving them?

> Signed-off-by: Rafael Brune <mail@xxxxxxxxx>
> ---
>  drivers/hid/hid-wiimote-modules.c | 45 +++++++++++++++++++++++++++++++++++----
>  1 file changed, 41 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
> index 2e7d644..1422b0b 100644
> --- a/drivers/hid/hid-wiimote-modules.c
> +++ b/drivers/hid/hid-wiimote-modules.c
> @@ -1640,10 +1640,41 @@ static void wiimod_pro_in_ext(struct wiimote_data *wdata, const __u8 *ext)
>         ly = (ext[4] & 0xff) | ((ext[5] & 0x0f) << 8);
>         ry = (ext[6] & 0xff) | ((ext[7] & 0x0f) << 8);
>
> -       input_report_abs(wdata->extension.input, ABS_X, lx - 0x800);
> -       input_report_abs(wdata->extension.input, ABS_Y, ly - 0x800);
> -       input_report_abs(wdata->extension.input, ABS_RX, rx - 0x800);
> -       input_report_abs(wdata->extension.input, ABS_RY, ry - 0x800);
> +       /* Calibrating the sticks by saving the global min/max per axis */
> +       if (lx < wdata->state.calib_bboard[0][0])
> +               wdata->state.calib_bboard[0][0] = lx;
> +       if (lx > wdata->state.calib_bboard[0][1])
> +               wdata->state.calib_bboard[0][1] = lx;
> +
> +       if (ly < wdata->state.calib_bboard[1][0])
> +               wdata->state.calib_bboard[1][0] = ly;
> +       if (ly > wdata->state.calib_bboard[1][1])
> +               wdata->state.calib_bboard[1][1] = ly;
> +
> +       if (rx < wdata->state.calib_bboard[2][0])
> +               wdata->state.calib_bboard[2][0] = rx;
> +       if (rx > wdata->state.calib_bboard[2][1])
> +               wdata->state.calib_bboard[2][1] = rx;
> +
> +       if (ry < wdata->state.calib_bboard[3][0])
> +               wdata->state.calib_bboard[3][0] = ry;
> +       if (ry > wdata->state.calib_bboard[3][1])
> +               wdata->state.calib_bboard[3][1] = ry;
> +
> +       /* Normalize using int math to prevent conversion to/from float */
> +       lx = -2048 + (((__s32)(lx - wdata->state.calib_bboard[0][0]) * 4096)/
> +          (wdata->state.calib_bboard[0][1]-wdata->state.calib_bboard[0][0]));
> +       ly = -2048 + (((__s32)(ly - wdata->state.calib_bboard[1][0]) * 4096)/
> +          (wdata->state.calib_bboard[1][1]-wdata->state.calib_bboard[1][0]));
> +       rx = -2048 + (((__s32)(rx - wdata->state.calib_bboard[2][0]) * 4096)/
> +          (wdata->state.calib_bboard[2][1]-wdata->state.calib_bboard[2][0]));
> +       ry = -2048 + (((__s32)(ry - wdata->state.calib_bboard[3][0]) * 4096)/
> +          (wdata->state.calib_bboard[3][1]-wdata->state.calib_bboard[3][0]));

Don't use calib_bboard. Add a new array (or use a union). This is confusing.

> +
> +       input_report_abs(wdata->extension.input, ABS_X,  lx);
> +       input_report_abs(wdata->extension.input, ABS_Y, -ly);
> +       input_report_abs(wdata->extension.input, ABS_RX,  rx);
> +       input_report_abs(wdata->extension.input, ABS_RY, -ry);
>
>         input_report_key(wdata->extension.input,
>                          wiimod_pro_map[WIIMOD_PRO_KEY_RIGHT],
> @@ -1760,6 +1791,12 @@ static int wiimod_pro_probe(const struct wiimod_ops *ops,
>         if (!wdata->extension.input)
>                 return -ENOMEM;
>
> +       /* Initialize min/max values for all Axis with reasonable values */
> +       for (i = 0; i < 4; ++i) {
> +               wdata->state.calib_bboard[i][0] = 0x780;
> +               wdata->state.calib_bboard[i][1] = 0x880;

Ugh, these values look weird. We have a reported range of -0x400 to
+0x400 but you limit it to a virtual range of 0x100. That's a loss of
precision of 80%. Where are these values from?

> +       }
> +
>         set_bit(FF_RUMBLE, wdata->extension.input->ffbit);
>         input_set_drvdata(wdata->extension.input, wdata);

Thanks for hacking this up. Could you give me some values from your
device so I can see how big the deviation is? My device reports:

Range: 0-4095 (0x0fff)
Neutral-Point: 2048 (0x800)

I haven't seen any big deviations from these values. I can try to take
this over if you want, just let me know.

Thanks
David
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux