From 4eb220cb35a9c4f69a2438b987bb3d509d56cc80 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Tue, 14 Feb 2017 21:26:21 -0800 Subject: HID: wacom: generic: add 3 tablet touch keys This patch add support to the 3 touch keys on Wacom Cintiq Pro. These touch keys are in the middle of the other two keys on the top edge of the tablet. Signed-off-by: Ping Cheng Reviewed-by: Benjamin Tissoires Tested-by: Aaron Armstrong Skomra Acked-by: Dmitry Torokhov Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 4aa3de9f1163..dbda99272374 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1768,6 +1768,18 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); features->device_type |= WACOM_DEVICETYPE_PAD; break; + case WACOM_HID_WD_BUTTONCONFIG: + wacom_map_usage(input, usage, field, EV_KEY, KEY_BUTTONCONFIG, 0); + features->device_type |= WACOM_DEVICETYPE_PAD; + break; + case WACOM_HID_WD_ONSCREEN_KEYBOARD: + wacom_map_usage(input, usage, field, EV_KEY, KEY_ONSCREEN_KEYBOARD, 0); + features->device_type |= WACOM_DEVICETYPE_PAD; + break; + case WACOM_HID_WD_CONTROLPANEL: + wacom_map_usage(input, usage, field, EV_KEY, KEY_CONTROLPANEL, 0); + features->device_type |= WACOM_DEVICETYPE_PAD; + break; } switch (equivalent_usage & 0xfffffff0) { -- cgit v1.2.3 From 4082da80f46a6683439bb0357faadb18f0f5b2a6 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 14 Feb 2017 21:27:18 -0800 Subject: HID: wacom: generic: add mode change touch key Wacom Cintiq Pro added a touch key to switch the tablet between display and opaque mode. This patch informs the change by removing the old devices and creating new ones with proper properties. Signed-off-by: Benjamin Tissoires Signed-off-by: Ping Cheng Tested-by: Aaron Armstrong Skomra Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index dbda99272374..2c399a423957 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1780,6 +1780,14 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, wacom_map_usage(input, usage, field, EV_KEY, KEY_CONTROLPANEL, 0); features->device_type |= WACOM_DEVICETYPE_PAD; break; + case WACOM_HID_WD_MODE_CHANGE: + /* do not overwrite previous data */ + if (!wacom_wac->has_mode_change) { + wacom_wac->has_mode_change = true; + wacom_wac->is_direct_mode = true; + } + features->device_type |= WACOM_DEVICETYPE_PAD; + break; } switch (equivalent_usage & 0xfffffff0) { @@ -1828,7 +1836,7 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field * Avoid reporting this event and setting inrange_state if this usage * hasn't been mapped. */ - if (!usage->type) + if (!usage->type && equivalent_usage != WACOM_HID_WD_MODE_CHANGE) return; if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) { @@ -1850,6 +1858,13 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field } break; + case WACOM_HID_WD_MODE_CHANGE: + if (wacom_wac->is_direct_mode != value) { + wacom_wac->is_direct_mode = value; + wacom_schedule_work(&wacom->wacom_wac, WACOM_WORKER_MODE_CHANGE); + } + break; + case WACOM_HID_WD_BUTTONCENTER: for (i = 0; i < wacom->led.count; i++) wacom_update_led(wacom, features->numbered_buttons, -- cgit v1.2.3 From d793ff81879a5747109f3106bd18e77662cb5187 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Tue, 14 Feb 2017 21:27:45 -0800 Subject: HID: wacom: generic: support touch on/off softkey Wacom Cintiq Pro has a softkey to turn touch on/off. Since it is a softkey, hardware/firmware still reports touch events no matter what state the softkey is. We need to ignore touch events when the key is in off mode. Signed-off-by: Ping Cheng Reviewed-by: Benjamin Tissoires Tested-by: Aaron Armstrong Skomra Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 2c399a423957..68fb9e114a0b 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1739,6 +1739,7 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, features->device_type |= WACOM_DEVICETYPE_PAD; break; case WACOM_HID_WD_TOUCHONOFF: + case WACOM_HID_WD_MUTE_DEVICE: /* * This usage, which is used to mute touch events, comes * from the pad packet, but is reported on the touch @@ -1831,6 +1832,7 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field struct wacom_features *features = &wacom_wac->features; unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); int i; + bool is_touch_on = value; /* * Avoid reporting this event and setting inrange_state if this usage @@ -1850,10 +1852,17 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field input_event(input, usage->type, usage->code, 0); break; + case WACOM_HID_WD_MUTE_DEVICE: + if (wacom_wac->shared->touch_input && value) { + wacom_wac->shared->is_touch_on = !wacom_wac->shared->is_touch_on; + is_touch_on = wacom_wac->shared->is_touch_on; + } + + /* fall through*/ case WACOM_HID_WD_TOUCHONOFF: if (wacom_wac->shared->touch_input) { input_report_switch(wacom_wac->shared->touch_input, - SW_MUTE_DEVICE, !value); + SW_MUTE_DEVICE, !is_touch_on); input_sync(wacom_wac->shared->touch_input); } break; @@ -2212,6 +2221,13 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac, bool prox = hid_data->tipswitch && report_touch_events(wacom_wac); + if (wacom_wac->shared->has_mute_touch_switch && + !wacom_wac->shared->is_touch_on) { + if (!wacom_wac->shared->touch_down) + return; + prox = 0; + } + wacom_wac->hid_data.num_received++; if (wacom_wac->hid_data.num_received > wacom_wac->hid_data.num_expected) return; -- cgit v1.2.3 From b79cbc55481ddc0b7cc68fb2072d93ee7eefbf8f Mon Sep 17 00:00:00 2001 From: Aaron Armstrong Skomra Date: Wed, 29 Mar 2017 13:07:36 -0700 Subject: HID: wacom: Bamboo One Medium does not have touch Commit 3b164a00a9fc ("HID: wacom: Cleanup unsupported device_type for BAMBOO_PT") cleaned up Bamboo devices which our driver falsely claimed had touch. Bamboo One Medium also does not have touch. Signed-off-by: Aaron Armstrong Skomra Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 68fb9e114a0b..f1360381c8f5 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -4158,7 +4158,7 @@ static const struct wacom_features wacom_features_0x300 = BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x301 = { "Wacom Bamboo One M", 21648, 13530, 1023, 31, - BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x302 = { "Wacom Intuos PT S", 15200, 9500, 1023, 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, -- cgit v1.2.3 From ed1fa736839eb97b1d066e36150df28251095eef Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Tue, 4 Apr 2017 12:31:07 -0700 Subject: HID: wacom: generic: sync pad events only for actual packets Commits d793ff8 and 4082da8 introduced two pad usages which do not actually send pad input events. To make sure we do not post empty pad packets, pad_input_event_flag is introduced. Turn on the flag for real pad input events so we can synchronize them properly. Signed-off-by: Ping Cheng Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index f1360381c8f5..037a9962d053 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1881,6 +1881,8 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field /* fall through*/ default: input_event(input, usage->type, usage->code, value); + if (value) + wacom_wac->hid_data.pad_input_event_flag = true; break; } } @@ -1921,9 +1923,12 @@ static void wacom_wac_pad_report(struct hid_device *hdev, bool active = wacom_wac->hid_data.inrange_state != 0; /* report prox for expresskey events */ - if (wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY) { + if ((wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY) && + wacom_wac->hid_data.pad_input_event_flag) { input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0); input_sync(input); + if (!active) + wacom_wac->hid_data.pad_input_event_flag = false; } } -- cgit v1.2.3 From 149f6f6b8ff3288a88dc34755de7719637cc8cc4 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Fri, 31 Mar 2017 10:02:05 -0700 Subject: HID: wacom: Move wacom_remote_irq and wacom_remote_status_irq These two functions awkwardly break up the otherwise-contiguous chunk of related Intuos IRQ functions with a 500 line tangent about the operation of the EKR. Their presence makes it difficult to read/navigate through the the Intuos code. Since there is no dependency between these functions, it is possible to simply move them down somewhat. This commit moves them to be after the final Intuos IRQ function. Signed-off-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 250 ++++++++++++++++++++++++------------------------ 1 file changed, 125 insertions(+), 125 deletions(-) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 037a9962d053..6b8f6b816195 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -773,131 +773,6 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) return 0; } -static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) -{ - unsigned char *data = wacom_wac->data; - struct input_dev *input; - struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); - struct wacom_remote *remote = wacom->remote; - int bat_charging, bat_percent, touch_ring_mode; - __u32 serial; - int i, index = -1; - unsigned long flags; - - if (data[0] != WACOM_REPORT_REMOTE) { - hid_dbg(wacom->hdev, "%s: received unknown report #%d", - __func__, data[0]); - return 0; - } - - serial = data[3] + (data[4] << 8) + (data[5] << 16); - wacom_wac->id[0] = PAD_DEVICE_ID; - - spin_lock_irqsave(&remote->remote_lock, flags); - - for (i = 0; i < WACOM_MAX_REMOTES; i++) { - if (remote->remotes[i].serial == serial) { - index = i; - break; - } - } - - if (index < 0 || !remote->remotes[index].registered) - goto out; - - input = remote->remotes[index].input; - - input_report_key(input, BTN_0, (data[9] & 0x01)); - input_report_key(input, BTN_1, (data[9] & 0x02)); - input_report_key(input, BTN_2, (data[9] & 0x04)); - input_report_key(input, BTN_3, (data[9] & 0x08)); - input_report_key(input, BTN_4, (data[9] & 0x10)); - input_report_key(input, BTN_5, (data[9] & 0x20)); - input_report_key(input, BTN_6, (data[9] & 0x40)); - input_report_key(input, BTN_7, (data[9] & 0x80)); - - input_report_key(input, BTN_8, (data[10] & 0x01)); - input_report_key(input, BTN_9, (data[10] & 0x02)); - input_report_key(input, BTN_A, (data[10] & 0x04)); - input_report_key(input, BTN_B, (data[10] & 0x08)); - input_report_key(input, BTN_C, (data[10] & 0x10)); - input_report_key(input, BTN_X, (data[10] & 0x20)); - input_report_key(input, BTN_Y, (data[10] & 0x40)); - input_report_key(input, BTN_Z, (data[10] & 0x80)); - - input_report_key(input, BTN_BASE, (data[11] & 0x01)); - input_report_key(input, BTN_BASE2, (data[11] & 0x02)); - - if (data[12] & 0x80) - input_report_abs(input, ABS_WHEEL, (data[12] & 0x7f)); - else - input_report_abs(input, ABS_WHEEL, 0); - - bat_percent = data[7] & 0x7f; - bat_charging = !!(data[7] & 0x80); - - if (data[9] | data[10] | (data[11] & 0x03) | data[12]) - input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); - else - input_report_abs(input, ABS_MISC, 0); - - input_event(input, EV_MSC, MSC_SERIAL, serial); - - input_sync(input); - - /*Which mode select (LED light) is currently on?*/ - touch_ring_mode = (data[11] & 0xC0) >> 6; - - for (i = 0; i < WACOM_MAX_REMOTES; i++) { - if (remote->remotes[i].serial == serial) - wacom->led.groups[i].select = touch_ring_mode; - } - - __wacom_notify_battery(&remote->remotes[index].battery, bat_percent, - bat_charging, 1, bat_charging); - -out: - spin_unlock_irqrestore(&remote->remote_lock, flags); - return 0; -} - -static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) -{ - struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); - unsigned char *data = wacom_wac->data; - struct wacom_remote *remote = wacom->remote; - struct wacom_remote_data remote_data; - unsigned long flags; - int i, ret; - - if (data[0] != WACOM_REPORT_DEVICE_LIST) - return; - - memset(&remote_data, 0, sizeof(struct wacom_remote_data)); - - for (i = 0; i < WACOM_MAX_REMOTES; i++) { - int j = i * 6; - int serial = (data[j+6] << 16) + (data[j+5] << 8) + data[j+4]; - bool connected = data[j+2]; - - remote_data.remote[i].serial = serial; - remote_data.remote[i].connected = connected; - } - - spin_lock_irqsave(&remote->remote_lock, flags); - - ret = kfifo_in(&remote->remote_fifo, &remote_data, sizeof(remote_data)); - if (ret != sizeof(remote_data)) { - spin_unlock_irqrestore(&remote->remote_lock, flags); - hid_err(wacom->hdev, "Can't queue Remote status event.\n"); - return; - } - - spin_unlock_irqrestore(&remote->remote_lock, flags); - - wacom_schedule_work(wacom_wac, WACOM_WORKER_REMOTE); -} - static inline bool report_touch_events(struct wacom_wac *wacom) { return (touch_arbitration ? !wacom->shared->stylus_in_proximity : 1); @@ -1116,6 +991,131 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) return 0; } +static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) +{ + unsigned char *data = wacom_wac->data; + struct input_dev *input; + struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); + struct wacom_remote *remote = wacom->remote; + int bat_charging, bat_percent, touch_ring_mode; + __u32 serial; + int i, index = -1; + unsigned long flags; + + if (data[0] != WACOM_REPORT_REMOTE) { + hid_dbg(wacom->hdev, "%s: received unknown report #%d", + __func__, data[0]); + return 0; + } + + serial = data[3] + (data[4] << 8) + (data[5] << 16); + wacom_wac->id[0] = PAD_DEVICE_ID; + + spin_lock_irqsave(&remote->remote_lock, flags); + + for (i = 0; i < WACOM_MAX_REMOTES; i++) { + if (remote->remotes[i].serial == serial) { + index = i; + break; + } + } + + if (index < 0 || !remote->remotes[index].registered) + goto out; + + input = remote->remotes[index].input; + + input_report_key(input, BTN_0, (data[9] & 0x01)); + input_report_key(input, BTN_1, (data[9] & 0x02)); + input_report_key(input, BTN_2, (data[9] & 0x04)); + input_report_key(input, BTN_3, (data[9] & 0x08)); + input_report_key(input, BTN_4, (data[9] & 0x10)); + input_report_key(input, BTN_5, (data[9] & 0x20)); + input_report_key(input, BTN_6, (data[9] & 0x40)); + input_report_key(input, BTN_7, (data[9] & 0x80)); + + input_report_key(input, BTN_8, (data[10] & 0x01)); + input_report_key(input, BTN_9, (data[10] & 0x02)); + input_report_key(input, BTN_A, (data[10] & 0x04)); + input_report_key(input, BTN_B, (data[10] & 0x08)); + input_report_key(input, BTN_C, (data[10] & 0x10)); + input_report_key(input, BTN_X, (data[10] & 0x20)); + input_report_key(input, BTN_Y, (data[10] & 0x40)); + input_report_key(input, BTN_Z, (data[10] & 0x80)); + + input_report_key(input, BTN_BASE, (data[11] & 0x01)); + input_report_key(input, BTN_BASE2, (data[11] & 0x02)); + + if (data[12] & 0x80) + input_report_abs(input, ABS_WHEEL, (data[12] & 0x7f)); + else + input_report_abs(input, ABS_WHEEL, 0); + + bat_percent = data[7] & 0x7f; + bat_charging = !!(data[7] & 0x80); + + if (data[9] | data[10] | (data[11] & 0x03) | data[12]) + input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); + else + input_report_abs(input, ABS_MISC, 0); + + input_event(input, EV_MSC, MSC_SERIAL, serial); + + input_sync(input); + + /*Which mode select (LED light) is currently on?*/ + touch_ring_mode = (data[11] & 0xC0) >> 6; + + for (i = 0; i < WACOM_MAX_REMOTES; i++) { + if (remote->remotes[i].serial == serial) + wacom->led.groups[i].select = touch_ring_mode; + } + + __wacom_notify_battery(&remote->remotes[index].battery, bat_percent, + bat_charging, 1, bat_charging); + +out: + spin_unlock_irqrestore(&remote->remote_lock, flags); + return 0; +} + +static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) +{ + struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); + unsigned char *data = wacom_wac->data; + struct wacom_remote *remote = wacom->remote; + struct wacom_remote_data remote_data; + unsigned long flags; + int i, ret; + + if (data[0] != WACOM_REPORT_DEVICE_LIST) + return; + + memset(&remote_data, 0, sizeof(struct wacom_remote_data)); + + for (i = 0; i < WACOM_MAX_REMOTES; i++) { + int j = i * 6; + int serial = (data[j+6] << 16) + (data[j+5] << 8) + data[j+4]; + bool connected = data[j+2]; + + remote_data.remote[i].serial = serial; + remote_data.remote[i].connected = connected; + } + + spin_lock_irqsave(&remote->remote_lock, flags); + + ret = kfifo_in(&remote->remote_fifo, &remote_data, sizeof(remote_data)); + if (ret != sizeof(remote_data)) { + spin_unlock_irqrestore(&remote->remote_lock, flags); + hid_err(wacom->hdev, "Can't queue Remote status event.\n"); + return; + } + + spin_unlock_irqrestore(&remote->remote_lock, flags); + + wacom_schedule_work(wacom_wac, WACOM_WORKER_REMOTE); +} + static int int_dist(int x1, int y1, int x2, int y2) { int x = x2 - x1; -- cgit v1.2.3