aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2015-02-26 11:28:50 -0500
committerJiri Kosina <jkosina@suse.cz>2015-02-27 02:37:52 -0500
commit8c97a765467c5d58682e85f103899ec2355fc393 (patch)
treef974f0053ad6f09131d16d2be7b6a96299f79334
parenta97ac10401fe86fa30ef73315241e31d8594a651 (diff)
HID: wacom: add full support of the Wacom Bamboo PAD
The stylus of this device works just fine out of the box. The touch is seen by default as a mouse with relative events and some gestures. The wireless and the wired version have slightly different firmwares, but the debug mode 2 on the feature 2 is common to the 2 devices. In this mode, all the reports are emitted through the debug interface (pen, raw touch and mouse emulation), so we have to re-route manually the events. We keep the Pen interface as a HID_GENERIC one because it works, and only parse the raw touches while discarding the mouse emulation & gestures. Switching the default in raw mode allows us to have a consistent user experience accross all the multitouch touchpads (and enable the touch part of the devices). Note that the buttons of this devices are reported through the touch interface. There is no 'Pad' interface. It seemed more natural to have the BTN_LEFT and BTN_RIGHT reported with the touch because they are placed under the touch interface and it looks like they belong to the touch part. Tested-by: Josep Sanchez Ferreres <josep.sanchez.ferreres@est.fib.upc.edu> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Acked-by: Ping Cheng <pingc@wacom.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/wacom_sys.c24
-rw-r--r--drivers/hid/wacom_wac.c104
-rw-r--r--drivers/hid/wacom_wac.h5
3 files changed, 133 insertions, 0 deletions
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index b3c2395aef3b..957699fb70b5 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -406,6 +406,9 @@ static int wacom_query_tablet_data(struct hid_device *hdev,
406 else if (features->type == WACOM_27QHDT) { 406 else if (features->type == WACOM_27QHDT) {
407 return wacom_set_device_mode(hdev, 131, 3, 2); 407 return wacom_set_device_mode(hdev, 131, 3, 2);
408 } 408 }
409 else if (features->type == BAMBOO_PAD) {
410 return wacom_set_device_mode(hdev, 2, 2, 2);
411 }
409 } else if (features->device_type == BTN_TOOL_PEN) { 412 } else if (features->device_type == BTN_TOOL_PEN) {
410 if (features->type <= BAMBOO_PT && features->type != WIRELESS) { 413 if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
411 return wacom_set_device_mode(hdev, 2, 2, 2); 414 return wacom_set_device_mode(hdev, 2, 2, 2);
@@ -1425,6 +1428,21 @@ static int wacom_probe(struct hid_device *hdev,
1425 goto fail_allocate_inputs; 1428 goto fail_allocate_inputs;
1426 } 1429 }
1427 1430
1431 /*
1432 * Bamboo Pad has a generic hid handling for the Pen, and we switch it
1433 * into debug mode for the touch part.
1434 * We ignore the other interfaces.
1435 */
1436 if (features->type == BAMBOO_PAD) {
1437 if (features->pktlen == WACOM_PKGLEN_PENABLED) {
1438 features->type = HID_GENERIC;
1439 } else if ((features->pktlen != WACOM_PKGLEN_BPAD_TOUCH) &&
1440 (features->pktlen != WACOM_PKGLEN_BPAD_TOUCH_USB)) {
1441 error = -ENODEV;
1442 goto fail_shared_data;
1443 }
1444 }
1445
1428 /* set the default size in case we do not get them from hid */ 1446 /* set the default size in case we do not get them from hid */
1429 wacom_set_default_phy(features); 1447 wacom_set_default_phy(features);
1430 1448
@@ -1459,6 +1477,12 @@ static int wacom_probe(struct hid_device *hdev,
1459 features->y_max = 4096; 1477 features->y_max = 4096;
1460 } 1478 }
1461 1479
1480 /*
1481 * Same thing for Bamboo PAD
1482 */
1483 if (features->type == BAMBOO_PAD)
1484 features->device_type = BTN_TOOL_FINGER;
1485
1462 if (hdev->bus == BUS_BLUETOOTH) 1486 if (hdev->bus == BUS_BLUETOOTH)
1463 features->quirks |= WACOM_QUIRK_BATTERY; 1487 features->quirks |= WACOM_QUIRK_BATTERY;
1464 1488
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 16e8d288e913..bbf72f94c91d 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1826,6 +1826,91 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
1826 return 0; 1826 return 0;
1827} 1827}
1828 1828
1829static void wacom_bamboo_pad_pen_event(struct wacom_wac *wacom,
1830 unsigned char *data)
1831{
1832 unsigned char prefix;
1833
1834 /*
1835 * We need to reroute the event from the debug interface to the
1836 * pen interface.
1837 * We need to add the report ID to the actual pen report, so we
1838 * temporary overwrite the first byte to prevent having to kzalloc/kfree
1839 * and memcpy the report.
1840 */
1841 prefix = data[0];
1842 data[0] = WACOM_REPORT_BPAD_PEN;
1843
1844 /*
1845 * actually reroute the event.
1846 * No need to check if wacom->shared->pen is valid, hid_input_report()
1847 * will check for us.
1848 */
1849 hid_input_report(wacom->shared->pen, HID_INPUT_REPORT, data,
1850 WACOM_PKGLEN_PENABLED, 1);
1851
1852 data[0] = prefix;
1853}
1854
1855static int wacom_bamboo_pad_touch_event(struct wacom_wac *wacom,
1856 unsigned char *data)
1857{
1858 struct input_dev *input = wacom->input;
1859 unsigned char *finger_data, prefix;
1860 unsigned id;
1861 int x, y;
1862 bool valid;
1863
1864 prefix = data[0];
1865
1866 for (id = 0; id < wacom->features.touch_max; id++) {
1867 valid = !!(prefix & BIT(id)) &&
1868 !wacom->shared->stylus_in_proximity;
1869
1870 input_mt_slot(input, id);
1871 input_mt_report_slot_state(input, MT_TOOL_FINGER, valid);
1872
1873 if (!valid)
1874 continue;
1875
1876 finger_data = data + 1 + id * 3;
1877 x = finger_data[0] | ((finger_data[1] & 0x0f) << 8);
1878 y = (finger_data[2] << 4) | (finger_data[1] >> 4);
1879
1880 input_report_abs(input, ABS_MT_POSITION_X, x);
1881 input_report_abs(input, ABS_MT_POSITION_Y, y);
1882 }
1883
1884 input_mt_sync_frame(input);
1885
1886 input_report_key(input, BTN_LEFT, prefix & 0x40);
1887 input_report_key(input, BTN_RIGHT, prefix & 0x80);
1888
1889 /* keep touch state for pen event */
1890 wacom->shared->touch_down = !!prefix &&
1891 !wacom->shared->stylus_in_proximity;
1892
1893 return 1;
1894}
1895
1896static int wacom_bamboo_pad_irq(struct wacom_wac *wacom, size_t len)
1897{
1898 unsigned char *data = wacom->data;
1899
1900 if (!((len == WACOM_PKGLEN_BPAD_TOUCH) ||
1901 (len == WACOM_PKGLEN_BPAD_TOUCH_USB)) ||
1902 (data[0] != WACOM_REPORT_BPAD_TOUCH))
1903 return 0;
1904
1905 if (data[1] & 0x01)
1906 wacom_bamboo_pad_pen_event(wacom, &data[1]);
1907
1908 if (data[1] & 0x02)
1909 return wacom_bamboo_pad_touch_event(wacom, &data[9]);
1910
1911 return 0;
1912}
1913
1829static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) 1914static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
1830{ 1915{
1831 unsigned char *data = wacom->data; 1916 unsigned char *data = wacom->data;
@@ -1962,6 +2047,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
1962 sync = wacom_bpt_irq(wacom_wac, len); 2047 sync = wacom_bpt_irq(wacom_wac, len);
1963 break; 2048 break;
1964 2049
2050 case BAMBOO_PAD:
2051 sync = wacom_bamboo_pad_irq(wacom_wac, len);
2052 break;
2053
1965 case WIRELESS: 2054 case WIRELESS:
1966 sync = wacom_wireless_irq(wacom_wac, len); 2055 sync = wacom_wireless_irq(wacom_wac, len);
1967 break; 2056 break;
@@ -2300,6 +2389,13 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
2300 0, 0); 2389 0, 0);
2301 } 2390 }
2302 break; 2391 break;
2392 case BAMBOO_PAD:
2393 __clear_bit(ABS_MISC, input_dev->absbit);
2394 input_mt_init_slots(input_dev, features->touch_max,
2395 INPUT_MT_POINTER);
2396 __set_bit(BTN_LEFT, input_dev->keybit);
2397 __set_bit(BTN_RIGHT, input_dev->keybit);
2398 break;
2303 } 2399 }
2304 return 0; 2400 return 0;
2305} 2401}
@@ -2953,6 +3049,12 @@ static const struct wacom_features wacom_features_0x30C =
2953 { "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */ 3049 { "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */
2954 .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30A, .touch_max = 10, 3050 .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30A, .touch_max = 10,
2955 .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; 3051 .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
3052static const struct wacom_features wacom_features_0x318 =
3053 { "Wacom USB Bamboo PAD", 4095, 4095, /* Touch */
3054 .type = BAMBOO_PAD, 35, 48, .touch_max = 4 };
3055static const struct wacom_features wacom_features_0x319 =
3056 { "Wacom Wireless Bamboo PAD", 4095, 4095, /* Touch */
3057 .type = BAMBOO_PAD, 35, 48, .touch_max = 4 };
2956static const struct wacom_features wacom_features_0x323 = 3058static const struct wacom_features wacom_features_0x323 =
2957 { "Wacom Intuos P M", 21600, 13500, 1023, 31, 3059 { "Wacom Intuos P M", 21600, 13500, 1023, 31,
2958 INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 3060 INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
@@ -3105,6 +3207,8 @@ const struct hid_device_id wacom_ids[] = {
3105 { USB_DEVICE_WACOM(0x314) }, 3207 { USB_DEVICE_WACOM(0x314) },
3106 { USB_DEVICE_WACOM(0x315) }, 3208 { USB_DEVICE_WACOM(0x315) },
3107 { USB_DEVICE_WACOM(0x317) }, 3209 { USB_DEVICE_WACOM(0x317) },
3210 { USB_DEVICE_WACOM(0x318) },
3211 { USB_DEVICE_WACOM(0x319) },
3108 { USB_DEVICE_WACOM(0x323) }, 3212 { USB_DEVICE_WACOM(0x323) },
3109 { USB_DEVICE_WACOM(0x32A) }, 3213 { USB_DEVICE_WACOM(0x32A) },
3110 { USB_DEVICE_WACOM(0x32B) }, 3214 { USB_DEVICE_WACOM(0x32B) },
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index e42efbe3338c..a3d0828ff8b1 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -33,6 +33,8 @@
33#define WACOM_PKGLEN_MTTPC 40 33#define WACOM_PKGLEN_MTTPC 40
34#define WACOM_PKGLEN_DTUS 68 34#define WACOM_PKGLEN_DTUS 68
35#define WACOM_PKGLEN_PENABLED 8 35#define WACOM_PKGLEN_PENABLED 8
36#define WACOM_PKGLEN_BPAD_TOUCH 32
37#define WACOM_PKGLEN_BPAD_TOUCH_USB 64
36 38
37/* wacom data size per MT contact */ 39/* wacom data size per MT contact */
38#define WACOM_BYTES_PER_MT_PACKET 11 40#define WACOM_BYTES_PER_MT_PACKET 11
@@ -67,6 +69,8 @@
67#define WACOM_REPORT_24HDT 1 69#define WACOM_REPORT_24HDT 1
68#define WACOM_REPORT_WL 128 70#define WACOM_REPORT_WL 128
69#define WACOM_REPORT_USB 192 71#define WACOM_REPORT_USB 192
72#define WACOM_REPORT_BPAD_PEN 3
73#define WACOM_REPORT_BPAD_TOUCH 16
70 74
71/* device quirks */ 75/* device quirks */
72#define WACOM_QUIRK_MULTI_INPUT 0x0001 76#define WACOM_QUIRK_MULTI_INPUT 0x0001
@@ -122,6 +126,7 @@ enum {
122 BAMBOO_PT, 126 BAMBOO_PT,
123 WACOM_24HDT, 127 WACOM_24HDT,
124 WACOM_27QHDT, 128 WACOM_27QHDT,
129 BAMBOO_PAD,
125 TABLETPC, /* add new TPC below */ 130 TABLETPC, /* add new TPC below */
126 TABLETPCE, 131 TABLETPCE,
127 TABLETPC2FG, 132 TABLETPC2FG,