From ea08eeccae9297f7aabd2ef7f0c2517ac4549acc Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 20 Feb 2024 01:18:26 +0000
Subject: [PATCH] write in 30M
---
kernel/drivers/hid/wacom_wac.c | 417 +++++++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 302 insertions(+), 115 deletions(-)
diff --git a/kernel/drivers/hid/wacom_wac.c b/kernel/drivers/hid/wacom_wac.c
index 254afea..1b5e5e9 100644
--- a/kernel/drivers/hid/wacom_wac.c
+++ b/kernel/drivers/hid/wacom_wac.c
@@ -1,20 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* drivers/input/tablet/wacom_wac.c
*
* USB Wacom tablet support - Wacom specific code
- *
*/
/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
*/
#include "wacom_wac.h"
#include "wacom.h"
#include <linux/input/mt.h>
+#include <linux/jiffies.h>
/* resolution for penabled devices */
#define WACOM_PL_RES 20
@@ -45,6 +42,43 @@
static void wacom_update_led(struct wacom *wacom, int button_count, int mask,
int group);
+
+static void wacom_force_proxout(struct wacom_wac *wacom_wac)
+{
+ struct input_dev *input = wacom_wac->pen_input;
+
+ wacom_wac->shared->stylus_in_proximity = 0;
+
+ input_report_key(input, BTN_TOUCH, 0);
+ input_report_key(input, BTN_STYLUS, 0);
+ input_report_key(input, BTN_STYLUS2, 0);
+ input_report_key(input, BTN_STYLUS3, 0);
+ input_report_key(input, wacom_wac->tool[0], 0);
+ if (wacom_wac->serial[0]) {
+ input_report_abs(input, ABS_MISC, 0);
+ }
+ input_report_abs(input, ABS_PRESSURE, 0);
+
+ wacom_wac->tool[0] = 0;
+ wacom_wac->id[0] = 0;
+ wacom_wac->serial[0] = 0;
+
+ input_sync(input);
+}
+
+void wacom_idleprox_timeout(struct timer_list *list)
+{
+ struct wacom *wacom = from_timer(wacom, list, idleprox_timer);
+ struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+
+ if (!wacom_wac->hid_data.sense_state) {
+ return;
+ }
+
+ hid_warn(wacom->hdev, "%s: tool appears to be hung in-prox. forcing it out.\n", __func__);
+ wacom_force_proxout(wacom_wac);
+}
+
/*
* Percent of battery capacity for Graphire.
* 8th value means AC online and show 100% capacity.
@@ -345,7 +379,7 @@
case 2: /* Mouse with wheel */
input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
- /* fall through */
+ fallthrough;
case 3: /* Mouse without wheel */
wacom->tool[0] = BTN_TOOL_MOUSE;
@@ -487,6 +521,8 @@
int ring1 = 0, ring2 = 0;
int strip1 = 0, strip2 = 0;
bool prox = false;
+ bool wrench = false, keyboard = false, mute_touch = false, menu = false,
+ info = false;
/* pad packets. Works as a second tool and is always in prox */
if (!(data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD ||
@@ -516,10 +552,32 @@
keys = ((data[3] & 0x1C) ? 1<<2 : 0) |
((data[4] & 0xE0) ? 1<<1 : 0) |
((data[4] & 0x07) ? 1<<0 : 0);
+ keyboard = !!(data[4] & 0xE0);
+ info = !!(data[3] & 0x1C);
+
+ if (features->oPid) {
+ mute_touch = !!(data[4] & 0x07);
+ if (mute_touch)
+ wacom->shared->is_touch_on =
+ !wacom->shared->is_touch_on;
+ } else {
+ wrench = !!(data[4] & 0x07);
+ }
} else if (features->type == WACOM_27QHD) {
nkeys = 3;
keys = data[2] & 0x07;
+ wrench = !!(data[2] & 0x01);
+ keyboard = !!(data[2] & 0x02);
+
+ if (features->oPid) {
+ mute_touch = !!(data[2] & 0x04);
+ if (mute_touch)
+ wacom->shared->is_touch_on =
+ !wacom->shared->is_touch_on;
+ } else {
+ menu = !!(data[2] & 0x04);
+ }
input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[4]));
input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[6]));
input_report_abs(input, ABS_Z, be16_to_cpup((__be16 *)&data[8]));
@@ -565,6 +623,9 @@
if (features->type == WACOM_22HD) {
nkeys = 3;
keys = data[9] & 0x07;
+
+ info = !!(data[9] & 0x01);
+ wrench = !!(data[9] & 0x02);
}
} else {
buttons = ((data[6] & 0x10) << 5) |
@@ -583,6 +644,18 @@
for (i = 0; i < nkeys; i++)
input_report_key(input, KEY_PROG1 + i, keys & (1 << i));
+
+ input_report_key(input, KEY_BUTTONCONFIG, wrench);
+ input_report_key(input, KEY_ONSCREEN_KEYBOARD, keyboard);
+ input_report_key(input, KEY_CONTROLPANEL, menu);
+ input_report_key(input, KEY_INFO, info);
+
+ if (wacom->shared && wacom->shared->touch_input) {
+ input_report_switch(wacom->shared->touch_input,
+ SW_MUTE_DEVICE,
+ !wacom->shared->is_touch_on);
+ input_sync(wacom->shared->touch_input);
+ }
input_report_abs(input, ABS_RX, strip1);
input_report_abs(input, ABS_RY, strip2);
@@ -603,9 +676,26 @@
return (tool_id & ~0xFFF) << 4 | (tool_id & 0xFFF);
}
+static bool wacom_is_art_pen(int tool_id)
+{
+ bool is_art_pen = false;
+
+ switch (tool_id) {
+ case 0x885: /* Intuos3 Marker Pen */
+ case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */
+ case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */
+ is_art_pen = true;
+ break;
+ }
+ return is_art_pen;
+}
+
static int wacom_intuos_get_tool_type(int tool_id)
{
- int tool_type;
+ int tool_type = BTN_TOOL_PEN;
+
+ if (wacom_is_art_pen(tool_id))
+ return tool_type;
switch (tool_id) {
case 0x812: /* Inking pen */
@@ -620,16 +710,17 @@
case 0x852:
case 0x823: /* Intuos3 Grip Pen */
case 0x813: /* Intuos3 Classic Pen */
- case 0x885: /* Intuos3 Marker Pen */
case 0x802: /* Intuos4/5 13HD/24HD General Pen */
- case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */
case 0x8e2: /* IntuosHT2 pen */
case 0x022:
- case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */
+ case 0x200: /* Pro Pen 3 */
+ case 0x04200: /* Pro Pen 3 */
+ case 0x10842: /* MobileStudio Pro Pro Pen slim */
case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */
case 0x16802: /* Cintiq 13HD Pro Pen */
case 0x18802: /* DTH2242 Pen */
case 0x10802: /* Intuos4/5 13HD/24HD General Pen */
+ case 0x80842: /* Intuos Pro and Cintiq Pro 3D Pen */
tool_type = BTN_TOOL_PEN;
break;
@@ -667,6 +758,7 @@
case 0x1480a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */
case 0x1090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
case 0x1080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */
+ case 0x1084a: /* MobileStudio Pro Pro Pen slim Eraser */
case 0x1680a: /* Cintiq 13HD Pro Pen Eraser */
case 0x1880a: /* DTH2242 Eraser */
case 0x1080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
@@ -680,10 +772,6 @@
case 0x902: /* Intuos4/5 13HD/24HD Airbrush */
case 0x10902: /* Intuos4/5 13HD/24HD Airbrush */
tool_type = BTN_TOOL_AIRBRUSH;
- break;
-
- default: /* Unknown tool */
- tool_type = BTN_TOOL_PEN;
break;
}
return tool_type;
@@ -743,7 +831,7 @@
/* Enter report */
if ((data[1] & 0xfc) == 0xc0) {
/* serial number of the tool */
- wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
+ wacom->serial[idx] = ((__u64)(data[3] & 0x0f) << 28) +
(data[4] << 20) + (data[5] << 12) +
(data[6] << 4) + (data[7] >> 4);
@@ -1039,6 +1127,7 @@
if (index < 0 || !remote->remotes[index].registered)
goto out;
+ remote->remotes[i].active_time = ktime_get();
input = remote->remotes[index].input;
input_report_key(input, BTN_0, (data[9] & 0x01));
@@ -1164,7 +1253,7 @@
case 0x04:
wacom_intuos_bt_process_data(wacom, data + i);
i += 10;
- /* fall through */
+ fallthrough;
case 0x03:
wacom_intuos_bt_process_data(wacom, data + i);
i += 10;
@@ -1218,9 +1307,13 @@
struct input_dev *pen_input = wacom->pen_input;
unsigned char *data = wacom->data;
+ int number_of_valid_frames = 0;
+ ktime_t time_interval = 15000000;
+ ktime_t time_packet_received = ktime_get();
int i;
- if (wacom->features.type == INTUOSP2_BT) {
+ if (wacom->features.type == INTUOSP2_BT ||
+ wacom->features.type == INTUOSP2S_BT) {
wacom->serial[0] = get_unaligned_le64(&data[99]);
wacom->id[0] = get_unaligned_le16(&data[107]);
pen_frame_len = 14;
@@ -1237,12 +1330,30 @@
wacom->id[0] |= (wacom->serial[0] >> 32) & 0xFFFFF;
}
+ /* number of valid frames */
for (i = 0; i < pen_frames; i++) {
+ unsigned char *frame = &data[i*pen_frame_len + 1];
+ bool valid = frame[0] & 0x80;
+
+ if (valid)
+ number_of_valid_frames++;
+ }
+
+ if (number_of_valid_frames) {
+ if (wacom->hid_data.time_delayed)
+ time_interval = ktime_get() - wacom->hid_data.time_delayed;
+ time_interval = div_u64(time_interval, number_of_valid_frames);
+ wacom->hid_data.time_delayed = time_packet_received;
+ }
+
+ for (i = 0; i < number_of_valid_frames; i++) {
unsigned char *frame = &data[i*pen_frame_len + 1];
bool valid = frame[0] & 0x80;
bool prox = frame[0] & 0x40;
bool range = frame[0] & 0x20;
bool invert = frame[0] & 0x10;
+ int frames_number_reversed = number_of_valid_frames - i - 1;
+ ktime_t event_timestamp = time_packet_received - frames_number_reversed * time_interval;
if (!valid)
continue;
@@ -1255,6 +1366,7 @@
wacom->tool[0] = 0;
wacom->id[0] = 0;
wacom->serial[0] = 0;
+ wacom->hid_data.time_delayed = 0;
return;
}
@@ -1272,7 +1384,8 @@
input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1]));
input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3]));
- if (wacom->features.type == INTUOSP2_BT) {
+ if (wacom->features.type == INTUOSP2_BT ||
+ wacom->features.type == INTUOSP2S_BT) {
/* Fix rotation alignment: userspace expects zero at left */
int16_t rotation =
(int16_t)get_unaligned_le16(&frame[9]);
@@ -1293,7 +1406,8 @@
if (wacom->tool[0]) {
input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5]));
- if (wacom->features.type == INTUOSP2_BT) {
+ if (wacom->features.type == INTUOSP2_BT ||
+ wacom->features.type == INTUOSP2S_BT) {
input_report_abs(pen_input, ABS_DISTANCE,
range ? frame[13] : wacom->features.distance_max);
} else {
@@ -1312,6 +1426,9 @@
}
wacom->shared->stylus_in_proximity = prox;
+
+ /* add timestamp to unpack the frames */
+ input_set_timestamp(pen_input, event_timestamp);
input_sync(pen_input);
}
@@ -1388,11 +1505,13 @@
{
struct input_dev *pad_input = wacom->pad_input;
unsigned char *data = wacom->data;
+ int nbuttons = wacom->features.numbered_buttons;
- int buttons = data[282] | ((data[281] & 0x40) << 2);
+ int expresskeys = data[282];
+ int center = (data[281] & 0x40) >> 6;
int ring = data[285] & 0x7F;
bool ringstatus = data[285] & 0x80;
- bool prox = buttons || ringstatus;
+ bool prox = expresskeys || center || ringstatus;
/* Fix touchring data: userspace expects 0 at left and increasing clockwise */
ring = 71 - ring;
@@ -1400,7 +1519,8 @@
if (ring > 71)
ring -= 72;
- wacom_report_numbered_buttons(pad_input, 9, buttons);
+ wacom_report_numbered_buttons(pad_input, nbuttons,
+ expresskeys | (center << (nbuttons - 1)));
input_report_abs(pad_input, ABS_WHEEL, ringstatus ? ring : 0);
@@ -1460,7 +1580,8 @@
}
wacom_intuos_pro2_bt_pen(wacom);
- if (wacom->features.type == INTUOSP2_BT) {
+ if (wacom->features.type == INTUOSP2_BT ||
+ wacom->features.type == INTUOSP2S_BT) {
wacom_intuos_pro2_bt_touch(wacom);
wacom_intuos_pro2_bt_pad(wacom);
wacom_intuos_pro2_bt_battery(wacom);
@@ -1481,6 +1602,12 @@
int num_contacts_left = 4; /* maximum contacts per packet */
int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET;
int y_offset = 2;
+
+ if (wacom->shared->has_mute_touch_switch &&
+ !wacom->shared->is_touch_on) {
+ if (!wacom->shared->touch_down)
+ return 0;
+ }
if (wacom->features.type == WACOM_27QHDT) {
current_num_contacts = data[63];
@@ -1772,6 +1899,9 @@
int subpage = (usage & 0xFF00) << 8;
int subusage = (usage & 0xFF);
+ if (usage == WACOM_HID_WT_REPORT_VALID)
+ return usage;
+
if (subpage == HID_UP_UNDEFINED)
subpage = WACOM_HID_SP_DIGITIZER;
@@ -1791,6 +1921,7 @@
int fmax = field->logical_maximum;
unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
int resolution_code = code;
+ int resolution = hidinput_calc_abs_res(field, resolution_code);
if (equivalent_usage == HID_DG_TWIST) {
resolution_code = ABS_RZ;
@@ -1813,8 +1944,15 @@
switch (type) {
case EV_ABS:
input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
- input_abs_set_res(input, code,
- hidinput_calc_abs_res(field, resolution_code));
+
+ /* older tablet may miss physical usage */
+ if ((code == ABS_X || code == ABS_Y) && !resolution) {
+ resolution = WACOM_INTUOS_RES;
+ hid_warn(input,
+ "Wacom usage (%d) missing resolution \n",
+ code);
+ }
+ input_abs_set_res(input, code, resolution);
break;
case EV_KEY:
input_set_capability(input, EV_KEY, code);
@@ -1831,18 +1969,7 @@
static void wacom_wac_battery_usage_mapping(struct hid_device *hdev,
struct hid_field *field, struct hid_usage *usage)
{
- struct wacom *wacom = hid_get_drvdata(hdev);
- struct wacom_wac *wacom_wac = &wacom->wacom_wac;
- struct wacom_features *features = &wacom_wac->features;
- unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
-
- switch (equivalent_usage) {
- case HID_DG_BATTERYSTRENGTH:
- case WACOM_HID_WD_BATTERY_LEVEL:
- case WACOM_HID_WD_BATTERY_CHARGING:
- features->quirks |= WACOM_QUIRK_BATTERY;
- break;
- }
+ return;
}
static void wacom_wac_battery_event(struct hid_device *hdev, struct hid_field *field,
@@ -1863,18 +1990,21 @@
wacom_wac->hid_data.bat_connected = 1;
wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO;
}
+ wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY;
break;
case WACOM_HID_WD_BATTERY_LEVEL:
value = value * 100 / (field->logical_maximum - field->logical_minimum);
wacom_wac->hid_data.battery_capacity = value;
wacom_wac->hid_data.bat_connected = 1;
wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO;
+ wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY;
break;
case WACOM_HID_WD_BATTERY_CHARGING:
wacom_wac->hid_data.bat_charging = value;
wacom_wac->hid_data.ps_connected = value;
wacom_wac->hid_data.bat_connected = 1;
wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO;
+ wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY;
break;
}
}
@@ -1890,18 +2020,15 @@
{
struct wacom *wacom = hid_get_drvdata(hdev);
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
- struct wacom_features *features = &wacom_wac->features;
- if (features->quirks & WACOM_QUIRK_BATTERY) {
- int status = wacom_wac->hid_data.bat_status;
- int capacity = wacom_wac->hid_data.battery_capacity;
- bool charging = wacom_wac->hid_data.bat_charging;
- bool connected = wacom_wac->hid_data.bat_connected;
- bool powered = wacom_wac->hid_data.ps_connected;
+ int status = wacom_wac->hid_data.bat_status;
+ int capacity = wacom_wac->hid_data.battery_capacity;
+ bool charging = wacom_wac->hid_data.bat_charging;
+ bool connected = wacom_wac->hid_data.bat_connected;
+ bool powered = wacom_wac->hid_data.ps_connected;
- wacom_notify_battery(wacom_wac, status, capacity, charging,
- connected, powered);
- }
+ wacom_notify_battery(wacom_wac, status, capacity, charging,
+ connected, powered);
}
static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
@@ -1954,7 +2081,6 @@
wacom_wac->has_mute_touch_switch = true;
usage->type = EV_SW;
usage->code = SW_MUTE_DEVICE;
- features->device_type |= WACOM_DEVICETYPE_PAD;
break;
case WACOM_HID_WD_TOUCHSTRIP:
wacom_map_usage(input, usage, field, EV_ABS, ABS_RX, 0);
@@ -2034,37 +2160,12 @@
wacom_wac->hid_data.inrange_state |= value;
}
- switch (equivalent_usage) {
- case WACOM_HID_WD_TOUCHRING:
- /*
- * Userspace expects touchrings to increase in value with
- * clockwise gestures and have their zero point at the
- * tablet's left. HID events "should" be clockwise-
- * increasing and zero at top, though the MobileStudio
- * Pro and 2nd-gen Intuos Pro don't do this...
- */
- if (hdev->vendor == 0x56a &&
- (hdev->product == 0x34d || hdev->product == 0x34e || /* MobileStudio Pro */
- hdev->product == 0x357 || hdev->product == 0x358)) { /* Intuos Pro 2 */
- value = (field->logical_maximum - value);
-
- if (hdev->product == 0x357 || hdev->product == 0x358)
- value = wacom_offset_rotation(input, usage, value, 3, 16);
- else if (hdev->product == 0x34d || hdev->product == 0x34e)
- value = wacom_offset_rotation(input, usage, value, 1, 2);
- }
- else {
- value = wacom_offset_rotation(input, usage, value, 1, 4);
- }
- do_report = true;
- break;
- case WACOM_HID_WD_TOUCHRINGSTATUS:
- if (!value)
- input_event(input, usage->type, usage->code, 0);
- break;
-
- case WACOM_HID_WD_MUTE_DEVICE:
- case WACOM_HID_WD_TOUCHONOFF:
+ /* Process touch switch state first since it is reported through touch interface,
+ * which is indepentent of pad interface. In the case when there are no other pad
+ * events, the pad interface will not even be created.
+ */
+ if ((equivalent_usage == WACOM_HID_WD_MUTE_DEVICE) ||
+ (equivalent_usage == WACOM_HID_WD_TOUCHONOFF)) {
if (wacom_wac->shared->touch_input) {
bool *is_touch_on = &wacom_wac->shared->is_touch_on;
@@ -2077,6 +2178,45 @@
SW_MUTE_DEVICE, !(*is_touch_on));
input_sync(wacom_wac->shared->touch_input);
}
+ return;
+ }
+
+ if (!input)
+ return;
+
+ switch (equivalent_usage) {
+ case WACOM_HID_WD_TOUCHRING:
+ /*
+ * Userspace expects touchrings to increase in value with
+ * clockwise gestures and have their zero point at the
+ * tablet's left. HID events "should" be clockwise-
+ * increasing and zero at top, though the MobileStudio
+ * Pro and 2nd-gen Intuos Pro don't do this...
+ */
+ if (hdev->vendor == 0x56a &&
+ (hdev->product == 0x34d || hdev->product == 0x34e || /* MobileStudio Pro */
+ hdev->product == 0x357 || hdev->product == 0x358 || /* Intuos Pro 2 */
+ hdev->product == 0x392 || /* Intuos Pro 2 */
+ hdev->product == 0x398 || hdev->product == 0x399 || /* MobileStudio Pro */
+ hdev->product == 0x3AA)) { /* MobileStudio Pro */
+ value = (field->logical_maximum - value);
+
+ if (hdev->product == 0x357 || hdev->product == 0x358 ||
+ hdev->product == 0x392)
+ value = wacom_offset_rotation(input, usage, value, 3, 16);
+ else if (hdev->product == 0x34d || hdev->product == 0x34e ||
+ hdev->product == 0x398 || hdev->product == 0x399 ||
+ hdev->product == 0x3AA)
+ value = wacom_offset_rotation(input, usage, value, 1, 2);
+ }
+ else {
+ value = wacom_offset_rotation(input, usage, value, 1, 4);
+ }
+ do_report = true;
+ break;
+ case WACOM_HID_WD_TOUCHRINGSTATUS:
+ if (!value)
+ input_event(input, usage->type, usage->code, 0);
break;
case WACOM_HID_WD_MODE_CHANGE:
@@ -2090,7 +2230,7 @@
for (i = 0; i < wacom->led.count; i++)
wacom_update_led(wacom, features->numbered_buttons,
value, i);
- /* fall through*/
+ fallthrough;
default:
do_report = true;
break;
@@ -2181,27 +2321,6 @@
case HID_DG_TOOLSERIALNUMBER:
features->quirks |= WACOM_QUIRK_TOOLSERIAL;
wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
-
- /* Adjust AES usages to match modern convention */
- if (usage->hid == WACOM_HID_WT_SERIALNUMBER && field->report_size == 16) {
- if (field->index + 2 < field->report->maxfield) {
- struct hid_field *a = field->report->field[field->index + 1];
- struct hid_field *b = field->report->field[field->index + 2];
-
- if (a->maxusage > 0 && a->usage[0].hid == HID_DG_TOOLSERIALNUMBER && a->report_size == 32 &&
- b->maxusage > 0 && b->usage[0].hid == 0xFF000000 && b->report_size == 8) {
- features->quirks |= WACOM_QUIRK_AESPEN;
- usage->hid = WACOM_HID_WD_TOOLTYPE;
- field->logical_minimum = S16_MIN;
- field->logical_maximum = S16_MAX;
- a->logical_minimum = S32_MIN;
- a->logical_maximum = S32_MAX;
- b->usage[0].hid = WACOM_HID_WD_SERIALHI;
- b->logical_minimum = 0;
- b->logical_maximum = U8_MAX;
- }
- }
- }
break;
case WACOM_HID_WD_SENSE:
features->quirks |= WACOM_QUIRK_SENSE;
@@ -2251,6 +2370,7 @@
value = field->logical_maximum - value;
break;
case HID_DG_INRANGE:
+ mod_timer(&wacom->idleprox_timer, jiffies + msecs_to_jiffies(100));
wacom_wac->hid_data.inrange_state = value;
if (!(features->quirks & WACOM_QUIRK_SENSE))
wacom_wac->hid_data.sense_state = value;
@@ -2275,6 +2395,9 @@
}
return;
case HID_DG_TWIST:
+ /* don't modify the value if the pen doesn't support the feature */
+ if (!wacom_is_art_pen(wacom_wac->id[0])) return;
+
/*
* Userspace expects pen twist to have its zero point when
* the buttons/finger is on the tablet's left. HID values
@@ -2555,6 +2678,9 @@
unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
struct wacom_features *features = &wacom->wacom_wac.features;
+ if (wacom_wac->is_invalid_bt_frame)
+ return;
+
switch (equivalent_usage) {
case HID_DG_CONFIDENCE:
wacom_wac->hid_data.confidence = value;
@@ -2577,6 +2703,9 @@
case HID_DG_TIPSWITCH:
wacom_wac->hid_data.tipswitch = value;
break;
+ case WACOM_HID_WT_REPORT_VALID:
+ wacom_wac->is_invalid_bt_frame = !value;
+ return;
case HID_DG_CONTACTMAX:
if (!features->touch_max) {
features->touch_max = value;
@@ -2586,7 +2715,6 @@
}
return;
}
-
if (usage->usage_index + 1 == field->report_count) {
if (equivalent_usage == wacom_wac->hid_data.last_slot_field) {
@@ -2607,6 +2735,8 @@
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
struct hid_data* hid_data = &wacom_wac->hid_data;
int i;
+
+ wacom_wac->is_invalid_bt_frame = false;
hid_data->confidence = true;
@@ -2719,7 +2849,7 @@
/* usage tests must precede field tests */
if (WACOM_BATTERY_USAGE(usage))
wacom_wac_battery_event(hdev, field, usage, value);
- else if (WACOM_PAD_FIELD(field) && wacom->wacom_wac.pad_input)
+ else if (WACOM_PAD_FIELD(field))
wacom_wac_pad_event(hdev, field, usage, value);
else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
wacom_wac_pen_event(hdev, field, usage, value);
@@ -3299,6 +3429,7 @@
break;
case INTUOSP2_BT:
+ case INTUOSP2S_BT:
case INTUOSHT3_BT:
sync = wacom_intuos_pro2_bt_irq(wacom_wac, len);
break;
@@ -3479,7 +3610,8 @@
if (features->type == REMOTE)
features->device_type = WACOM_DEVICETYPE_PAD;
- if (features->type == INTUOSP2_BT) {
+ if (features->type == INTUOSP2_BT ||
+ features->type == INTUOSP2S_BT) {
features->device_type |= WACOM_DEVICETYPE_PEN |
WACOM_DEVICETYPE_PAD |
WACOM_DEVICETYPE_TOUCH;
@@ -3599,13 +3731,14 @@
switch (features->type) {
case GRAPHIRE_BT:
__clear_bit(ABS_MISC, input_dev->absbit);
+ fallthrough;
case WACOM_MO:
case WACOM_G4:
input_set_abs_params(input_dev, ABS_DISTANCE, 0,
features->distance_max,
features->distance_fuzz, 0);
- /* fall through */
+ fallthrough;
case GRAPHIRE:
input_set_capability(input_dev, EV_REL, REL_WHEEL);
@@ -3645,7 +3778,7 @@
case INTUOS4S:
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
input_abs_set_res(input_dev, ABS_Z, 287);
- /* fall through */
+ fallthrough;
case INTUOS:
wacom_setup_intuos(wacom_wac);
@@ -3658,6 +3791,7 @@
case INTUOS5S:
case INTUOSPS:
case INTUOSP2_BT:
+ case INTUOSP2S_BT:
input_set_abs_params(input_dev, ABS_DISTANCE, 0,
features->distance_max,
features->distance_fuzz, 0);
@@ -3677,7 +3811,7 @@
case TABLETPC:
case TABLETPCE:
__clear_bit(ABS_MISC, input_dev->absbit);
- /* fall through */
+ fallthrough;
case DTUS:
case DTUSX:
@@ -3691,7 +3825,7 @@
case PTU:
__set_bit(BTN_STYLUS2, input_dev->keybit);
- /* fall through */
+ fallthrough;
case PENPARTNER:
__set_bit(BTN_TOOL_PEN, input_dev->keybit);
@@ -3768,6 +3902,7 @@
switch (features->type) {
case INTUOSP2_BT:
+ case INTUOSP2S_BT:
input_dev->evbit[0] |= BIT_MASK(EV_SW);
__set_bit(SW_MUTE_DEVICE, input_dev->swbit);
@@ -3783,10 +3918,16 @@
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
0, 5920, 4, 0);
}
+ else if (wacom_wac->shared->touch->product == 0x393) {
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+ 0, 6400, 4, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+ 0, 4000, 4, 0);
+ }
input_abs_set_res(input_dev, ABS_MT_POSITION_X, 40);
input_abs_set_res(input_dev, ABS_MT_POSITION_Y, 40);
- /* fall through */
+ fallthrough;
case INTUOS5:
case INTUOS5L:
@@ -3804,15 +3945,23 @@
input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
- /* fall through */
+ fallthrough;
case WACOM_27QHDT:
+ if (wacom_wac->shared->touch->product == 0x32C ||
+ wacom_wac->shared->touch->product == 0xF6) {
+ input_dev->evbit[0] |= BIT_MASK(EV_SW);
+ __set_bit(SW_MUTE_DEVICE, input_dev->swbit);
+ wacom_wac->has_mute_touch_switch = true;
+ }
+ fallthrough;
+
case MTSCREEN:
case MTTPC:
case MTTPC_B:
case TABLETPC2FG:
input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_DIRECT);
- /*fall through */
+ fallthrough;
case TABLETPC:
case TABLETPCE:
@@ -3822,7 +3971,7 @@
case INTUOSHT2:
input_dev->evbit[0] |= BIT_MASK(EV_SW);
__set_bit(SW_MUTE_DEVICE, input_dev->swbit);
- /* fall through */
+ fallthrough;
case BAMBOO_PT:
case BAMBOO_TOUCH:
@@ -4042,6 +4191,12 @@
__set_bit(KEY_PROG2, input_dev->keybit);
__set_bit(KEY_PROG3, input_dev->keybit);
+ __set_bit(KEY_ONSCREEN_KEYBOARD, input_dev->keybit);
+ __set_bit(KEY_INFO, input_dev->keybit);
+
+ if (!features->oPid)
+ __set_bit(KEY_BUTTONCONFIG, input_dev->keybit);
+
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
break;
@@ -4050,6 +4205,12 @@
__set_bit(KEY_PROG1, input_dev->keybit);
__set_bit(KEY_PROG2, input_dev->keybit);
__set_bit(KEY_PROG3, input_dev->keybit);
+
+ __set_bit(KEY_ONSCREEN_KEYBOARD, input_dev->keybit);
+ __set_bit(KEY_BUTTONCONFIG, input_dev->keybit);
+
+ if (!features->oPid)
+ __set_bit(KEY_CONTROLPANEL, input_dev->keybit);
input_set_abs_params(input_dev, ABS_X, -2048, 2048, 0, 0);
input_abs_set_res(input_dev, ABS_X, 1024); /* points/g */
input_set_abs_params(input_dev, ABS_Y, -2048, 2048, 0, 0);
@@ -4063,7 +4224,10 @@
__set_bit(KEY_PROG1, input_dev->keybit);
__set_bit(KEY_PROG2, input_dev->keybit);
__set_bit(KEY_PROG3, input_dev->keybit);
- /* fall through */
+
+ __set_bit(KEY_BUTTONCONFIG, input_dev->keybit);
+ __set_bit(KEY_INFO, input_dev->keybit);
+ fallthrough;
case WACOM_21UX2:
case WACOM_BEE:
@@ -4079,7 +4243,7 @@
case INTUOS3:
case INTUOS3L:
input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
- /* fall through */
+ fallthrough;
case INTUOS3S:
input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
@@ -4092,6 +4256,7 @@
case INTUOS5S:
case INTUOSPS:
case INTUOSP2_BT:
+ case INTUOSP2S_BT:
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
break;
@@ -4102,7 +4267,7 @@
* ID_INPUT_TABLET to be set.
*/
__set_bit(BTN_STYLUS, input_dev->keybit);
- /* fall through */
+ fallthrough;
case INTUOS4:
case INTUOS4L:
@@ -4669,9 +4834,26 @@
static const struct wacom_features wacom_features_0x37B =
{ "Wacom One by Wacom M", 21600, 13500, 2047, 63,
BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x393 =
+ { "Wacom Intuos Pro S", 31920, 19950, 8191, 63,
+ INTUOSP2S_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7,
+ .touch_max = 10 };
+static const struct wacom_features wacom_features_0x3c6 =
+ { "Wacom Intuos BT S", 15200, 9500, 4095, 63,
+ INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
+static const struct wacom_features wacom_features_0x3c8 =
+ { "Wacom Intuos BT M", 21600, 13500, 4095, 63,
+ INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
+static const struct wacom_features wacom_features_0x3dd =
+ { "Wacom Intuos Pro S", 31920, 19950, 8191, 63,
+ INTUOSP2S_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7,
+ .touch_max = 10 };
static const struct wacom_features wacom_features_HID_ANY_ID =
{ "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID };
+
+static const struct wacom_features wacom_features_0x94 =
+ { "Wacom Bootloader", .type = BOOTLOADER };
#define USB_DEVICE_WACOM(prod) \
HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
@@ -4746,6 +4928,7 @@
{ USB_DEVICE_WACOM(0x84) },
{ USB_DEVICE_WACOM(0x90) },
{ USB_DEVICE_WACOM(0x93) },
+ { USB_DEVICE_WACOM(0x94) },
{ USB_DEVICE_WACOM(0x97) },
{ USB_DEVICE_WACOM(0x9A) },
{ USB_DEVICE_WACOM(0x9F) },
@@ -4841,6 +5024,10 @@
{ BT_DEVICE_WACOM(0x379) },
{ USB_DEVICE_WACOM(0x37A) },
{ USB_DEVICE_WACOM(0x37B) },
+ { BT_DEVICE_WACOM(0x393) },
+ { BT_DEVICE_WACOM(0x3c6) },
+ { BT_DEVICE_WACOM(0x3c8) },
+ { BT_DEVICE_WACOM(0x3dd) },
{ USB_DEVICE_WACOM(0x4001) },
{ USB_DEVICE_WACOM(0x4004) },
{ USB_DEVICE_WACOM(0x5000) },
--
Gitblit v1.6.2