summaryrefslogtreecommitdiffstats
path: root/drivers/hid/wacom_wac.c
diff options
context:
space:
mode:
authorBenjamin Tissoires2015-02-26 17:28:50 +0100
committerJiri Kosina2015-02-27 08:37:52 +0100
commit8c97a765467c5d58682e85f103899ec2355fc393 (patch)
treef974f0053ad6f09131d16d2be7b6a96299f79334 /drivers/hid/wacom_wac.c
parentHID: wacom: store the hid_device pointers of the sibling devices (diff)
downloadkernel-qcow2-linux-8c97a765467c5d58682e85f103899ec2355fc393.tar.gz
kernel-qcow2-linux-8c97a765467c5d58682e85f103899ec2355fc393.tar.xz
kernel-qcow2-linux-8c97a765467c5d58682e85f103899ec2355fc393.zip
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>
Diffstat (limited to 'drivers/hid/wacom_wac.c')
-rw-r--r--drivers/hid/wacom_wac.c104
1 files changed, 104 insertions, 0 deletions
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)
return 0;
}
+static void wacom_bamboo_pad_pen_event(struct wacom_wac *wacom,
+ unsigned char *data)
+{
+ unsigned char prefix;
+
+ /*
+ * We need to reroute the event from the debug interface to the
+ * pen interface.
+ * We need to add the report ID to the actual pen report, so we
+ * temporary overwrite the first byte to prevent having to kzalloc/kfree
+ * and memcpy the report.
+ */
+ prefix = data[0];
+ data[0] = WACOM_REPORT_BPAD_PEN;
+
+ /*
+ * actually reroute the event.
+ * No need to check if wacom->shared->pen is valid, hid_input_report()
+ * will check for us.
+ */
+ hid_input_report(wacom->shared->pen, HID_INPUT_REPORT, data,
+ WACOM_PKGLEN_PENABLED, 1);
+
+ data[0] = prefix;
+}
+
+static int wacom_bamboo_pad_touch_event(struct wacom_wac *wacom,
+ unsigned char *data)
+{
+ struct input_dev *input = wacom->input;
+ unsigned char *finger_data, prefix;
+ unsigned id;
+ int x, y;
+ bool valid;
+
+ prefix = data[0];
+
+ for (id = 0; id < wacom->features.touch_max; id++) {
+ valid = !!(prefix & BIT(id)) &&
+ !wacom->shared->stylus_in_proximity;
+
+ input_mt_slot(input, id);
+ input_mt_report_slot_state(input, MT_TOOL_FINGER, valid);
+
+ if (!valid)
+ continue;
+
+ finger_data = data + 1 + id * 3;
+ x = finger_data[0] | ((finger_data[1] & 0x0f) << 8);
+ y = (finger_data[2] << 4) | (finger_data[1] >> 4);
+
+ input_report_abs(input, ABS_MT_POSITION_X, x);
+ input_report_abs(input, ABS_MT_POSITION_Y, y);
+ }
+
+ input_mt_sync_frame(input);
+
+ input_report_key(input, BTN_LEFT, prefix & 0x40);
+ input_report_key(input, BTN_RIGHT, prefix & 0x80);
+
+ /* keep touch state for pen event */
+ wacom->shared->touch_down = !!prefix &&
+ !wacom->shared->stylus_in_proximity;
+
+ return 1;
+}
+
+static int wacom_bamboo_pad_irq(struct wacom_wac *wacom, size_t len)
+{
+ unsigned char *data = wacom->data;
+
+ if (!((len == WACOM_PKGLEN_BPAD_TOUCH) ||
+ (len == WACOM_PKGLEN_BPAD_TOUCH_USB)) ||
+ (data[0] != WACOM_REPORT_BPAD_TOUCH))
+ return 0;
+
+ if (data[1] & 0x01)
+ wacom_bamboo_pad_pen_event(wacom, &data[1]);
+
+ if (data[1] & 0x02)
+ return wacom_bamboo_pad_touch_event(wacom, &data[9]);
+
+ return 0;
+}
+
static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
{
unsigned char *data = wacom->data;
@@ -1962,6 +2047,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
sync = wacom_bpt_irq(wacom_wac, len);
break;
+ case BAMBOO_PAD:
+ sync = wacom_bamboo_pad_irq(wacom_wac, len);
+ break;
+
case WIRELESS:
sync = wacom_wireless_irq(wacom_wac, len);
break;
@@ -2300,6 +2389,13 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
0, 0);
}
break;
+ case BAMBOO_PAD:
+ __clear_bit(ABS_MISC, input_dev->absbit);
+ input_mt_init_slots(input_dev, features->touch_max,
+ INPUT_MT_POINTER);
+ __set_bit(BTN_LEFT, input_dev->keybit);
+ __set_bit(BTN_RIGHT, input_dev->keybit);
+ break;
}
return 0;
}
@@ -2953,6 +3049,12 @@ static const struct wacom_features wacom_features_0x30C =
{ "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30A, .touch_max = 10,
.check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x318 =
+ { "Wacom USB Bamboo PAD", 4095, 4095, /* Touch */
+ .type = BAMBOO_PAD, 35, 48, .touch_max = 4 };
+static const struct wacom_features wacom_features_0x319 =
+ { "Wacom Wireless Bamboo PAD", 4095, 4095, /* Touch */
+ .type = BAMBOO_PAD, 35, 48, .touch_max = 4 };
static const struct wacom_features wacom_features_0x323 =
{ "Wacom Intuos P M", 21600, 13500, 1023, 31,
INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
@@ -3105,6 +3207,8 @@ const struct hid_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x314) },
{ USB_DEVICE_WACOM(0x315) },
{ USB_DEVICE_WACOM(0x317) },
+ { USB_DEVICE_WACOM(0x318) },
+ { USB_DEVICE_WACOM(0x319) },
{ USB_DEVICE_WACOM(0x323) },
{ USB_DEVICE_WACOM(0x32A) },
{ USB_DEVICE_WACOM(0x32B) },