Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HID: wiimote: add pro-controller analog stick calibration

The analog sticks of the pro-controller might report slightly off values.
To guarantee a uniform setup, we now calibrate analog-stick values during
pro-controller setup.

Unfortunately, the pro-controller fails during normal EEPROM reads and I
couldn't figure out whether there are any calibration values stored on the
device. Therefore, we now use the first values reported by the device (iff
they are not _way_ off, which would indicate movement) to initialize the
calibration values. To allow users to change this calibration data, we
provide a pro_calib sysfs attribute.

We also change the "flat" values so user-space correctly smoothes our
data. It makes slightly off zero-positions less visible while still
guaranteeing highly precise movement reports. Note that the pro controller
reports zero-positions in a quite huge range (at least: -100 to +100).

Reported-by: Rafael Brune <mail@rbrune.de>
Tested-by: Rafael Brune <mail@rbrune.de>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

authored by

David Herrmann and committed by
Jiri Kosina
08072dde 0abda6fa

+128 -9
+18
Documentation/ABI/testing/sysfs-driver-hid-wiimote
··· 57 57 Calibration data is already applied by the kernel to all input 58 58 values but may be used by user-space to perform other 59 59 transformations. 60 + 61 + What: /sys/bus/hid/drivers/wiimote/<dev>/pro_calib 62 + Date: October 2013 63 + KernelVersion: 3.13 64 + Contact: David Herrmann <dh.herrmann@gmail.com> 65 + Description: This attribute is only provided if the device was detected as a 66 + pro-controller. It provides a single line with 4 calibration 67 + values for all 4 analog sticks. Format is: "x1:y1 x2:y2". Data 68 + is prefixed with a +/-. Each value is a signed 16bit number. 69 + Data is encoded as decimal numbers and specifies the offsets of 70 + the analog sticks of the pro-controller. 71 + Calibration data is already applied by the kernel to all input 72 + values but may be used by user-space to perform other 73 + transformations. 74 + Calibration data is detected by the kernel during device setup. 75 + You can write "scan\n" into this file to re-trigger calibration. 76 + You can also write data directly in the form "x1:y1 x2:y2" to 77 + set the calibration values manually.
+108 -9
drivers/hid/hid-wiimote-modules.c
··· 1655 1655 ly = (ext[4] & 0xff) | ((ext[5] & 0x0f) << 8); 1656 1656 ry = (ext[6] & 0xff) | ((ext[7] & 0x0f) << 8); 1657 1657 1658 - input_report_abs(wdata->extension.input, ABS_X, lx - 0x800); 1659 - input_report_abs(wdata->extension.input, ABS_Y, 0x800 - ly); 1660 - input_report_abs(wdata->extension.input, ABS_RX, rx - 0x800); 1661 - input_report_abs(wdata->extension.input, ABS_RY, 0x800 - ry); 1658 + /* zero-point offsets */ 1659 + lx -= 0x800; 1660 + ly = 0x800 - ly; 1661 + rx -= 0x800; 1662 + ry = 0x800 - ry; 1663 + 1664 + /* Trivial automatic calibration. We don't know any calibration data 1665 + * in the EEPROM so we must use the first report to calibrate the 1666 + * null-position of the analog sticks. Users can retrigger calibration 1667 + * via sysfs, or set it explicitly. If data is off more than abs(500), 1668 + * we skip calibration as the sticks are likely to be moved already. */ 1669 + if (!(wdata->state.flags & WIIPROTO_FLAG_PRO_CALIB_DONE)) { 1670 + wdata->state.flags |= WIIPROTO_FLAG_PRO_CALIB_DONE; 1671 + if (abs(lx) < 500) 1672 + wdata->state.calib_pro_sticks[0] = -lx; 1673 + if (abs(ly) < 500) 1674 + wdata->state.calib_pro_sticks[1] = -ly; 1675 + if (abs(rx) < 500) 1676 + wdata->state.calib_pro_sticks[2] = -rx; 1677 + if (abs(ry) < 500) 1678 + wdata->state.calib_pro_sticks[3] = -ry; 1679 + } 1680 + 1681 + /* apply calibration data */ 1682 + lx += wdata->state.calib_pro_sticks[0]; 1683 + ly += wdata->state.calib_pro_sticks[1]; 1684 + rx += wdata->state.calib_pro_sticks[2]; 1685 + ry += wdata->state.calib_pro_sticks[3]; 1686 + 1687 + input_report_abs(wdata->extension.input, ABS_X, lx); 1688 + input_report_abs(wdata->extension.input, ABS_Y, ly); 1689 + input_report_abs(wdata->extension.input, ABS_RX, rx); 1690 + input_report_abs(wdata->extension.input, ABS_RY, ry); 1662 1691 1663 1692 input_report_key(wdata->extension.input, 1664 1693 wiimod_pro_map[WIIMOD_PRO_KEY_RIGHT], ··· 1795 1766 return 0; 1796 1767 } 1797 1768 1769 + static ssize_t wiimod_pro_calib_show(struct device *dev, 1770 + struct device_attribute *attr, 1771 + char *out) 1772 + { 1773 + struct wiimote_data *wdata = dev_to_wii(dev); 1774 + int r; 1775 + 1776 + r = 0; 1777 + r += sprintf(&out[r], "%+06hd:", wdata->state.calib_pro_sticks[0]); 1778 + r += sprintf(&out[r], "%+06hd ", wdata->state.calib_pro_sticks[1]); 1779 + r += sprintf(&out[r], "%+06hd:", wdata->state.calib_pro_sticks[2]); 1780 + r += sprintf(&out[r], "%+06hd\n", wdata->state.calib_pro_sticks[3]); 1781 + 1782 + return r; 1783 + } 1784 + 1785 + static ssize_t wiimod_pro_calib_store(struct device *dev, 1786 + struct device_attribute *attr, 1787 + const char *buf, size_t count) 1788 + { 1789 + struct wiimote_data *wdata = dev_to_wii(dev); 1790 + int r; 1791 + s16 x1, y1, x2, y2; 1792 + 1793 + if (!strncmp(buf, "scan\n", 5)) { 1794 + spin_lock_irq(&wdata->state.lock); 1795 + wdata->state.flags &= ~WIIPROTO_FLAG_PRO_CALIB_DONE; 1796 + spin_unlock_irq(&wdata->state.lock); 1797 + } else { 1798 + r = sscanf(buf, "%hd:%hd %hd:%hd", &x1, &y1, &x2, &y2); 1799 + if (r != 4) 1800 + return -EINVAL; 1801 + 1802 + spin_lock_irq(&wdata->state.lock); 1803 + wdata->state.flags |= WIIPROTO_FLAG_PRO_CALIB_DONE; 1804 + spin_unlock_irq(&wdata->state.lock); 1805 + 1806 + wdata->state.calib_pro_sticks[0] = x1; 1807 + wdata->state.calib_pro_sticks[1] = y1; 1808 + wdata->state.calib_pro_sticks[2] = x2; 1809 + wdata->state.calib_pro_sticks[3] = y2; 1810 + } 1811 + 1812 + return strnlen(buf, PAGE_SIZE); 1813 + } 1814 + 1815 + static DEVICE_ATTR(pro_calib, S_IRUGO|S_IWUSR|S_IWGRP, wiimod_pro_calib_show, 1816 + wiimod_pro_calib_store); 1817 + 1798 1818 static int wiimod_pro_probe(const struct wiimod_ops *ops, 1799 1819 struct wiimote_data *wdata) 1800 1820 { 1801 1821 int ret, i; 1822 + unsigned long flags; 1802 1823 1803 1824 INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker); 1825 + wdata->state.calib_pro_sticks[0] = 0; 1826 + wdata->state.calib_pro_sticks[1] = 0; 1827 + wdata->state.calib_pro_sticks[2] = 0; 1828 + wdata->state.calib_pro_sticks[3] = 0; 1829 + 1830 + spin_lock_irqsave(&wdata->state.lock, flags); 1831 + wdata->state.flags &= ~WIIPROTO_FLAG_PRO_CALIB_DONE; 1832 + spin_unlock_irqrestore(&wdata->state.lock, flags); 1804 1833 1805 1834 wdata->extension.input = input_allocate_device(); 1806 1835 if (!wdata->extension.input) ··· 1870 1783 if (input_ff_create_memless(wdata->extension.input, NULL, 1871 1784 wiimod_pro_play)) { 1872 1785 ret = -ENOMEM; 1786 + goto err_free; 1787 + } 1788 + 1789 + ret = device_create_file(&wdata->hdev->dev, 1790 + &dev_attr_pro_calib); 1791 + if (ret) { 1792 + hid_err(wdata->hdev, "cannot create sysfs attribute\n"); 1873 1793 goto err_free; 1874 1794 } 1875 1795 ··· 1900 1806 set_bit(ABS_RX, wdata->extension.input->absbit); 1901 1807 set_bit(ABS_RY, wdata->extension.input->absbit); 1902 1808 input_set_abs_params(wdata->extension.input, 1903 - ABS_X, -0x800, 0x800, 2, 4); 1809 + ABS_X, -0x400, 0x400, 4, 100); 1904 1810 input_set_abs_params(wdata->extension.input, 1905 - ABS_Y, -0x800, 0x800, 2, 4); 1811 + ABS_Y, -0x400, 0x400, 4, 100); 1906 1812 input_set_abs_params(wdata->extension.input, 1907 - ABS_RX, -0x800, 0x800, 2, 4); 1813 + ABS_RX, -0x400, 0x400, 4, 100); 1908 1814 input_set_abs_params(wdata->extension.input, 1909 - ABS_RY, -0x800, 0x800, 2, 4); 1815 + ABS_RY, -0x400, 0x400, 4, 100); 1910 1816 1911 1817 ret = input_register_device(wdata->extension.input); 1912 1818 if (ret) 1913 - goto err_free; 1819 + goto err_file; 1914 1820 1915 1821 return 0; 1916 1822 1823 + err_file: 1824 + device_remove_file(&wdata->hdev->dev, 1825 + &dev_attr_pro_calib); 1917 1826 err_free: 1918 1827 input_free_device(wdata->extension.input); 1919 1828 wdata->extension.input = NULL; ··· 1934 1837 input_unregister_device(wdata->extension.input); 1935 1838 wdata->extension.input = NULL; 1936 1839 cancel_work_sync(&wdata->rumble_worker); 1840 + device_remove_file(&wdata->hdev->dev, 1841 + &dev_attr_pro_calib); 1937 1842 1938 1843 spin_lock_irqsave(&wdata->state.lock, flags); 1939 1844 wiiproto_req_rumble(wdata, 0);
+2
drivers/hid/hid-wiimote.h
··· 46 46 #define WIIPROTO_FLAG_DRM_LOCKED 0x8000 47 47 #define WIIPROTO_FLAG_BUILTIN_MP 0x010000 48 48 #define WIIPROTO_FLAG_NO_MP 0x020000 49 + #define WIIPROTO_FLAG_PRO_CALIB_DONE 0x040000 49 50 50 51 #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ 51 52 WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) ··· 136 135 137 136 /* calibration/cache data */ 138 137 __u16 calib_bboard[4][3]; 138 + __s16 calib_pro_sticks[4]; 139 139 __u8 cache_rumble; 140 140 }; 141 141