aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-10-28 12:49:20 -0400
committerJiri Kosina <jkosina@suse.cz>2013-10-30 09:13:29 -0400
commit08072dde333c2f09114a01b0bd32be52ecce195b (patch)
tree9f6841827abd53f5445052951ff2b1a64a925bb8 /drivers/hid
parent0abda6fa81dced031e3df31ac29bfb253549c2d1 (diff)
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>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-wiimote-modules.c117
-rw-r--r--drivers/hid/hid-wiimote.h2
2 files changed, 110 insertions, 9 deletions
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index e30567af42ed..6b61f01e01e7 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -1655,10 +1655,39 @@ static void wiimod_pro_in_ext(struct wiimote_data *wdata, const __u8 *ext)
1655 ly = (ext[4] & 0xff) | ((ext[5] & 0x0f) << 8); 1655 ly = (ext[4] & 0xff) | ((ext[5] & 0x0f) << 8);
1656 ry = (ext[6] & 0xff) | ((ext[7] & 0x0f) << 8); 1656 ry = (ext[6] & 0xff) | ((ext[7] & 0x0f) << 8);
1657 1657
1658 input_report_abs(wdata->extension.input, ABS_X, lx - 0x800); 1658 /* zero-point offsets */
1659 input_report_abs(wdata->extension.input, ABS_Y, 0x800 - ly); 1659 lx -= 0x800;
1660 input_report_abs(wdata->extension.input, ABS_RX, rx - 0x800); 1660 ly = 0x800 - ly;
1661 input_report_abs(wdata->extension.input, ABS_RY, 0x800 - ry); 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 input_report_key(wdata->extension.input, 1692 input_report_key(wdata->extension.input,
1664 wiimod_pro_map[WIIMOD_PRO_KEY_RIGHT], 1693 wiimod_pro_map[WIIMOD_PRO_KEY_RIGHT],
@@ -1766,12 +1795,70 @@ static int wiimod_pro_play(struct input_dev *dev, void *data,
1766 return 0; 1795 return 0;
1767} 1796}
1768 1797
1798static ssize_t wiimod_pro_calib_show(struct device *dev,
1799 struct device_attribute *attr,
1800 char *out)
1801{
1802 struct wiimote_data *wdata = dev_to_wii(dev);
1803 int r;
1804
1805 r = 0;
1806 r += sprintf(&out[r], "%+06hd:", wdata->state.calib_pro_sticks[0]);
1807 r += sprintf(&out[r], "%+06hd ", wdata->state.calib_pro_sticks[1]);
1808 r += sprintf(&out[r], "%+06hd:", wdata->state.calib_pro_sticks[2]);
1809 r += sprintf(&out[r], "%+06hd\n", wdata->state.calib_pro_sticks[3]);
1810
1811 return r;
1812}
1813
1814static ssize_t wiimod_pro_calib_store(struct device *dev,
1815 struct device_attribute *attr,
1816 const char *buf, size_t count)
1817{
1818 struct wiimote_data *wdata = dev_to_wii(dev);
1819 int r;
1820 s16 x1, y1, x2, y2;
1821
1822 if (!strncmp(buf, "scan\n", 5)) {
1823 spin_lock_irq(&wdata->state.lock);
1824 wdata->state.flags &= ~WIIPROTO_FLAG_PRO_CALIB_DONE;
1825 spin_unlock_irq(&wdata->state.lock);
1826 } else {
1827 r = sscanf(buf, "%hd:%hd %hd:%hd", &x1, &y1, &x2, &y2);
1828 if (r != 4)
1829 return -EINVAL;
1830
1831 spin_lock_irq(&wdata->state.lock);
1832 wdata->state.flags |= WIIPROTO_FLAG_PRO_CALIB_DONE;
1833 spin_unlock_irq(&wdata->state.lock);
1834
1835 wdata->state.calib_pro_sticks[0] = x1;
1836 wdata->state.calib_pro_sticks[1] = y1;
1837 wdata->state.calib_pro_sticks[2] = x2;
1838 wdata->state.calib_pro_sticks[3] = y2;
1839 }
1840
1841 return strnlen(buf, PAGE_SIZE);
1842}
1843
1844static DEVICE_ATTR(pro_calib, S_IRUGO|S_IWUSR|S_IWGRP, wiimod_pro_calib_show,
1845 wiimod_pro_calib_store);
1846
1769static int wiimod_pro_probe(const struct wiimod_ops *ops, 1847static int wiimod_pro_probe(const struct wiimod_ops *ops,
1770 struct wiimote_data *wdata) 1848 struct wiimote_data *wdata)
1771{ 1849{
1772 int ret, i; 1850 int ret, i;
1851 unsigned long flags;
1773 1852
1774 INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker); 1853 INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker);
1854 wdata->state.calib_pro_sticks[0] = 0;
1855 wdata->state.calib_pro_sticks[1] = 0;
1856 wdata->state.calib_pro_sticks[2] = 0;
1857 wdata->state.calib_pro_sticks[3] = 0;
1858
1859 spin_lock_irqsave(&wdata->state.lock, flags);
1860 wdata->state.flags &= ~WIIPROTO_FLAG_PRO_CALIB_DONE;
1861 spin_unlock_irqrestore(&wdata->state.lock, flags);
1775 1862
1776 wdata->extension.input = input_allocate_device(); 1863 wdata->extension.input = input_allocate_device();
1777 if (!wdata->extension.input) 1864 if (!wdata->extension.input)
@@ -1786,6 +1873,13 @@ static int wiimod_pro_probe(const struct wiimod_ops *ops,
1786 goto err_free; 1873 goto err_free;
1787 } 1874 }
1788 1875
1876 ret = device_create_file(&wdata->hdev->dev,
1877 &dev_attr_pro_calib);
1878 if (ret) {
1879 hid_err(wdata->hdev, "cannot create sysfs attribute\n");
1880 goto err_free;
1881 }
1882
1789 wdata->extension.input->open = wiimod_pro_open; 1883 wdata->extension.input->open = wiimod_pro_open;
1790 wdata->extension.input->close = wiimod_pro_close; 1884 wdata->extension.input->close = wiimod_pro_close;
1791 wdata->extension.input->dev.parent = &wdata->hdev->dev; 1885 wdata->extension.input->dev.parent = &wdata->hdev->dev;
@@ -1806,20 +1900,23 @@ static int wiimod_pro_probe(const struct wiimod_ops *ops,
1806 set_bit(ABS_RX, wdata->extension.input->absbit); 1900 set_bit(ABS_RX, wdata->extension.input->absbit);
1807 set_bit(ABS_RY, wdata->extension.input->absbit); 1901 set_bit(ABS_RY, wdata->extension.input->absbit);
1808 input_set_abs_params(wdata->extension.input, 1902 input_set_abs_params(wdata->extension.input,
1809 ABS_X, -0x800, 0x800, 2, 4); 1903 ABS_X, -0x400, 0x400, 4, 100);
1810 input_set_abs_params(wdata->extension.input, 1904 input_set_abs_params(wdata->extension.input,
1811 ABS_Y, -0x800, 0x800, 2, 4); 1905 ABS_Y, -0x400, 0x400, 4, 100);
1812 input_set_abs_params(wdata->extension.input, 1906 input_set_abs_params(wdata->extension.input,
1813 ABS_RX, -0x800, 0x800, 2, 4); 1907 ABS_RX, -0x400, 0x400, 4, 100);
1814 input_set_abs_params(wdata->extension.input, 1908 input_set_abs_params(wdata->extension.input,
1815 ABS_RY, -0x800, 0x800, 2, 4); 1909 ABS_RY, -0x400, 0x400, 4, 100);
1816 1910
1817 ret = input_register_device(wdata->extension.input); 1911 ret = input_register_device(wdata->extension.input);
1818 if (ret) 1912 if (ret)
1819 goto err_free; 1913 goto err_file;
1820 1914
1821 return 0; 1915 return 0;
1822 1916
1917err_file:
1918 device_remove_file(&wdata->hdev->dev,
1919 &dev_attr_pro_calib);
1823err_free: 1920err_free:
1824 input_free_device(wdata->extension.input); 1921 input_free_device(wdata->extension.input);
1825 wdata->extension.input = NULL; 1922 wdata->extension.input = NULL;
@@ -1837,6 +1934,8 @@ static void wiimod_pro_remove(const struct wiimod_ops *ops,
1837 input_unregister_device(wdata->extension.input); 1934 input_unregister_device(wdata->extension.input);
1838 wdata->extension.input = NULL; 1935 wdata->extension.input = NULL;
1839 cancel_work_sync(&wdata->rumble_worker); 1936 cancel_work_sync(&wdata->rumble_worker);
1937 device_remove_file(&wdata->hdev->dev,
1938 &dev_attr_pro_calib);
1840 1939
1841 spin_lock_irqsave(&wdata->state.lock, flags); 1940 spin_lock_irqsave(&wdata->state.lock, flags);
1842 wiiproto_req_rumble(wdata, 0); 1941 wiiproto_req_rumble(wdata, 0);
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 75db0c400037..03065f1917fc 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -46,6 +46,7 @@
46#define WIIPROTO_FLAG_DRM_LOCKED 0x8000 46#define WIIPROTO_FLAG_DRM_LOCKED 0x8000
47#define WIIPROTO_FLAG_BUILTIN_MP 0x010000 47#define WIIPROTO_FLAG_BUILTIN_MP 0x010000
48#define WIIPROTO_FLAG_NO_MP 0x020000 48#define WIIPROTO_FLAG_NO_MP 0x020000
49#define WIIPROTO_FLAG_PRO_CALIB_DONE 0x040000
49 50
50#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ 51#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
51 WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) 52 WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
@@ -135,6 +136,7 @@ struct wiimote_state {
135 136
136 /* calibration/cache data */ 137 /* calibration/cache data */
137 __u16 calib_bboard[4][3]; 138 __u16 calib_bboard[4][3];
139 __s16 calib_pro_sticks[4];
138 __u8 cache_rumble; 140 __u8 cache_rumble;
139}; 141};
140 142