Hi On Oct 10, 2013, at 11:16 AM, David Herrmann wrote: > 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? > After googling a little bit it seems like their might actually be no calibration data for the Classic Controller and Wii U Pro Controller. The midpoint is supposedly just detected when the device connects. http://wiibrew.org/wiki/Classic_Controller My code did not change what we output as the min/max/mid values it's still -0x800,0x000,0x800. As you suggest it scales/moves the raw values so that the reported values fall into that range. >> 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. I agree, will do that. >> + >> + 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? I picked these values arbitrarily as starting points since they will update during use of the gamepad as soon as lower/higher values are observed. As soon as the sticks have been moved to their extreme positions once everything is perfect. We could also set those values in a similar fashion as to what Nintendo seems to be doing. Wait for a first report of raw values, use them as the mid point and set these min/max values as midpoint +/- ~0x800. >> + } >> + >> 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 When I write out the observed raw min/max values of all Axis I get these: LX: 1033 - 3326 (center~=2179 (0x883)) LY: 857 - 3211 (center~=2034 (0x7F2)) RX: 944 - 3176 (center~=2060 (0x80C)) RY: 853 - 3159 (center~=2006 (0x7D6)) So not really the whole range of 0x0FFF is actually used and offsets due to manufacturing differences are present. Regards, Rafael -- 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