Skip to content

Commit 740c84e

Browse files
author
Jiri Kosina
committed
Merge branch 'for-4.16/wacom' into for-linus
Pull Wacom device driver updates. These don't have to go on top of the hid_have_special_driver[] revamp, as the whole group is assumed to have a special driver based on VID.
2 parents a44f3ec + c947218 commit 740c84e

File tree

3 files changed

+178
-29
lines changed

3 files changed

+178
-29
lines changed

drivers/hid/wacom_sys.c

Lines changed: 122 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,107 @@ static int wacom_set_report(struct hid_device *hdev, u8 type, u8 *buf,
5656
return retval;
5757
}
5858

59+
static void wacom_wac_queue_insert(struct hid_device *hdev,
60+
struct kfifo_rec_ptr_2 *fifo,
61+
u8 *raw_data, int size)
62+
{
63+
bool warned = false;
64+
65+
while (kfifo_avail(fifo) < size) {
66+
if (!warned)
67+
hid_warn(hdev, "%s: kfifo has filled, starting to drop events\n", __func__);
68+
warned = true;
69+
70+
kfifo_skip(fifo);
71+
}
72+
73+
kfifo_in(fifo, raw_data, size);
74+
}
75+
76+
static void wacom_wac_queue_flush(struct hid_device *hdev,
77+
struct kfifo_rec_ptr_2 *fifo)
78+
{
79+
while (!kfifo_is_empty(fifo)) {
80+
u8 buf[WACOM_PKGLEN_MAX];
81+
int size;
82+
int err;
83+
84+
size = kfifo_out(fifo, buf, sizeof(buf));
85+
err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, false);
86+
if (err) {
87+
hid_warn(hdev, "%s: unable to flush event due to error %d\n",
88+
__func__, err);
89+
}
90+
}
91+
}
92+
93+
static int wacom_wac_pen_serial_enforce(struct hid_device *hdev,
94+
struct hid_report *report, u8 *raw_data, int size)
95+
{
96+
struct wacom *wacom = hid_get_drvdata(hdev);
97+
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
98+
struct wacom_features *features = &wacom_wac->features;
99+
bool flush = false;
100+
bool insert = false;
101+
int i, j;
102+
103+
if (wacom_wac->serial[0] || !(features->quirks & WACOM_QUIRK_TOOLSERIAL))
104+
return 0;
105+
106+
/* Queue events which have invalid tool type or serial number */
107+
for (i = 0; i < report->maxfield; i++) {
108+
for (j = 0; j < report->field[i]->maxusage; j++) {
109+
struct hid_field *field = report->field[i];
110+
struct hid_usage *usage = &field->usage[j];
111+
unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
112+
unsigned int offset;
113+
unsigned int size;
114+
unsigned int value;
115+
116+
if (equivalent_usage != HID_DG_INRANGE &&
117+
equivalent_usage != HID_DG_TOOLSERIALNUMBER &&
118+
equivalent_usage != WACOM_HID_WD_SERIALHI &&
119+
equivalent_usage != WACOM_HID_WD_TOOLTYPE)
120+
continue;
121+
122+
offset = field->report_offset;
123+
size = field->report_size;
124+
value = hid_field_extract(hdev, raw_data+1, offset + j * size, size);
125+
126+
/* If we go out of range, we need to flush the queue ASAP */
127+
if (equivalent_usage == HID_DG_INRANGE)
128+
value = !value;
129+
130+
if (value) {
131+
flush = true;
132+
switch (equivalent_usage) {
133+
case HID_DG_TOOLSERIALNUMBER:
134+
wacom_wac->serial[0] = value;
135+
break;
136+
137+
case WACOM_HID_WD_SERIALHI:
138+
wacom_wac->serial[0] |= ((__u64)value) << 32;
139+
break;
140+
141+
case WACOM_HID_WD_TOOLTYPE:
142+
wacom_wac->id[0] = value;
143+
break;
144+
}
145+
}
146+
else {
147+
insert = true;
148+
}
149+
}
150+
}
151+
152+
if (flush)
153+
wacom_wac_queue_flush(hdev, &wacom_wac->pen_fifo);
154+
else if (insert)
155+
wacom_wac_queue_insert(hdev, &wacom_wac->pen_fifo, raw_data, size);
156+
157+
return insert && !flush;
158+
}
159+
59160
static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
60161
u8 *raw_data, int size)
61162
{
@@ -64,6 +165,9 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
64165
if (size > WACOM_PKGLEN_MAX)
65166
return 1;
66167

168+
if (wacom_wac_pen_serial_enforce(hdev, report, raw_data, size))
169+
return -1;
170+
67171
memcpy(wacom->wacom_wac.data, raw_data, size);
68172

69173
wacom_wac_irq(&wacom->wacom_wac, size);
@@ -2347,23 +2451,23 @@ static void wacom_remote_destroy_one(struct wacom *wacom, unsigned int index)
23472451
int i;
23482452
unsigned long flags;
23492453

2350-
spin_lock_irqsave(&remote->remote_lock, flags);
2351-
remote->remotes[index].registered = false;
2352-
spin_unlock_irqrestore(&remote->remote_lock, flags);
2454+
for (i = 0; i < WACOM_MAX_REMOTES; i++) {
2455+
if (remote->remotes[i].serial == serial) {
23532456

2354-
if (remote->remotes[index].battery.battery)
2355-
devres_release_group(&wacom->hdev->dev,
2356-
&remote->remotes[index].battery.bat_desc);
2457+
spin_lock_irqsave(&remote->remote_lock, flags);
2458+
remote->remotes[i].registered = false;
2459+
spin_unlock_irqrestore(&remote->remote_lock, flags);
23572460

2358-
if (remote->remotes[index].group.name)
2359-
devres_release_group(&wacom->hdev->dev,
2360-
&remote->remotes[index]);
2461+
if (remote->remotes[i].battery.battery)
2462+
devres_release_group(&wacom->hdev->dev,
2463+
&remote->remotes[i].battery.bat_desc);
2464+
2465+
if (remote->remotes[i].group.name)
2466+
devres_release_group(&wacom->hdev->dev,
2467+
&remote->remotes[i]);
23612468

2362-
for (i = 0; i < WACOM_MAX_REMOTES; i++) {
2363-
if (remote->remotes[i].serial == serial) {
23642469
remote->remotes[i].serial = 0;
23652470
remote->remotes[i].group.name = NULL;
2366-
remote->remotes[i].registered = false;
23672471
remote->remotes[i].battery.battery = NULL;
23682472
wacom->led.groups[i].select = WACOM_STATUS_UNKNOWN;
23692473
}
@@ -2580,6 +2684,10 @@ static int wacom_probe(struct hid_device *hdev,
25802684
goto fail;
25812685
}
25822686

2687+
error = kfifo_alloc(&wacom_wac->pen_fifo, WACOM_PKGLEN_MAX, GFP_KERNEL);
2688+
if (error)
2689+
goto fail;
2690+
25832691
wacom_wac->hid_data.inputmode = -1;
25842692
wacom_wac->mode_report = -1;
25852693

@@ -2643,6 +2751,8 @@ static void wacom_remove(struct hid_device *hdev)
26432751
if (wacom->wacom_wac.features.type != REMOTE)
26442752
wacom_release_resources(wacom);
26452753

2754+
kfifo_free(&wacom_wac->pen_fifo);
2755+
26462756
hid_set_drvdata(hdev, NULL);
26472757
}
26482758

drivers/hid/wacom_wac.c

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,7 +1924,6 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
19241924
struct wacom_features *features = &wacom_wac->features;
19251925
unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
19261926
int i;
1927-
bool is_touch_on = value;
19281927
bool do_report = false;
19291928

19301929
/*
@@ -1969,16 +1968,17 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
19691968
break;
19701969

19711970
case WACOM_HID_WD_MUTE_DEVICE:
1972-
if (wacom_wac->shared->touch_input && value) {
1973-
wacom_wac->shared->is_touch_on = !wacom_wac->shared->is_touch_on;
1974-
is_touch_on = wacom_wac->shared->is_touch_on;
1975-
}
1976-
1977-
/* fall through*/
19781971
case WACOM_HID_WD_TOUCHONOFF:
19791972
if (wacom_wac->shared->touch_input) {
1973+
bool *is_touch_on = &wacom_wac->shared->is_touch_on;
1974+
1975+
if (equivalent_usage == WACOM_HID_WD_MUTE_DEVICE && value)
1976+
*is_touch_on = !(*is_touch_on);
1977+
else if (equivalent_usage == WACOM_HID_WD_TOUCHONOFF)
1978+
*is_touch_on = value;
1979+
19801980
input_report_switch(wacom_wac->shared->touch_input,
1981-
SW_MUTE_DEVICE, !is_touch_on);
1981+
SW_MUTE_DEVICE, !(*is_touch_on));
19821982
input_sync(wacom_wac->shared->touch_input);
19831983
}
19841984
break;
@@ -2085,23 +2085,48 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
20852085
wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS2, 0);
20862086
break;
20872087
case HID_DG_TOOLSERIALNUMBER:
2088+
features->quirks |= WACOM_QUIRK_TOOLSERIAL;
20882089
wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
2090+
2091+
/* Adjust AES usages to match modern convention */
2092+
if (usage->hid == WACOM_HID_WT_SERIALNUMBER && field->report_size == 16) {
2093+
if (field->index + 2 < field->report->maxfield) {
2094+
struct hid_field *a = field->report->field[field->index + 1];
2095+
struct hid_field *b = field->report->field[field->index + 2];
2096+
2097+
if (a->maxusage > 0 && a->usage[0].hid == HID_DG_TOOLSERIALNUMBER && a->report_size == 32 &&
2098+
b->maxusage > 0 && b->usage[0].hid == 0xFF000000 && b->report_size == 8) {
2099+
features->quirks |= WACOM_QUIRK_AESPEN;
2100+
usage->hid = WACOM_HID_WD_TOOLTYPE;
2101+
field->logical_minimum = S16_MIN;
2102+
field->logical_maximum = S16_MAX;
2103+
a->logical_minimum = S32_MIN;
2104+
a->logical_maximum = S32_MAX;
2105+
b->usage[0].hid = WACOM_HID_WD_SERIALHI;
2106+
b->logical_minimum = 0;
2107+
b->logical_maximum = U8_MAX;
2108+
}
2109+
}
2110+
}
20892111
break;
20902112
case WACOM_HID_WD_SENSE:
20912113
features->quirks |= WACOM_QUIRK_SENSE;
20922114
wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
20932115
break;
20942116
case WACOM_HID_WD_SERIALHI:
20952117
wacom_map_usage(input, usage, field, EV_ABS, ABS_MISC, 0);
2096-
set_bit(EV_KEY, input->evbit);
2097-
input_set_capability(input, EV_KEY, BTN_TOOL_PEN);
2098-
input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER);
2099-
input_set_capability(input, EV_KEY, BTN_TOOL_BRUSH);
2100-
input_set_capability(input, EV_KEY, BTN_TOOL_PENCIL);
2101-
input_set_capability(input, EV_KEY, BTN_TOOL_AIRBRUSH);
2102-
if (!(features->device_type & WACOM_DEVICETYPE_DIRECT)) {
2103-
input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE);
2104-
input_set_capability(input, EV_KEY, BTN_TOOL_LENS);
2118+
2119+
if (!(features->quirks & WACOM_QUIRK_AESPEN)) {
2120+
set_bit(EV_KEY, input->evbit);
2121+
input_set_capability(input, EV_KEY, BTN_TOOL_PEN);
2122+
input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER);
2123+
input_set_capability(input, EV_KEY, BTN_TOOL_BRUSH);
2124+
input_set_capability(input, EV_KEY, BTN_TOOL_PENCIL);
2125+
input_set_capability(input, EV_KEY, BTN_TOOL_AIRBRUSH);
2126+
if (!(features->device_type & WACOM_DEVICETYPE_DIRECT)) {
2127+
input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE);
2128+
input_set_capability(input, EV_KEY, BTN_TOOL_LENS);
2129+
}
21052130
}
21062131
break;
21072132
case WACOM_HID_WD_FINGERWHEEL:
@@ -4390,6 +4415,12 @@ static const struct wacom_features wacom_features_0x360 =
43904415
static const struct wacom_features wacom_features_0x361 =
43914416
{ "Wacom Intuos Pro L", 62200, 43200, 8191, 63,
43924417
INTUOSP2_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 10 };
4418+
static const struct wacom_features wacom_features_0x37A =
4419+
{ "Wacom One by Wacom S", 15200, 9500, 2047, 63,
4420+
BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
4421+
static const struct wacom_features wacom_features_0x37B =
4422+
{ "Wacom One by Wacom M", 21600, 13500, 2047, 63,
4423+
BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
43934424

43944425
static const struct wacom_features wacom_features_HID_ANY_ID =
43954426
{ "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID };
@@ -4558,6 +4589,8 @@ const struct hid_device_id wacom_ids[] = {
45584589
{ USB_DEVICE_WACOM(0x343) },
45594590
{ BT_DEVICE_WACOM(0x360) },
45604591
{ BT_DEVICE_WACOM(0x361) },
4592+
{ USB_DEVICE_WACOM(0x37A) },
4593+
{ USB_DEVICE_WACOM(0x37B) },
45614594
{ USB_DEVICE_WACOM(0x4001) },
45624595
{ USB_DEVICE_WACOM(0x4004) },
45634596
{ USB_DEVICE_WACOM(0x5000) },

drivers/hid/wacom_wac.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <linux/types.h>
1313
#include <linux/hid.h>
14+
#include <linux/kfifo.h>
1415

1516
/* maximum packet length for USB/BT devices */
1617
#define WACOM_PKGLEN_MAX 361
@@ -86,7 +87,9 @@
8687
/* device quirks */
8788
#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001
8889
#define WACOM_QUIRK_SENSE 0x0002
90+
#define WACOM_QUIRK_AESPEN 0x0004
8991
#define WACOM_QUIRK_BATTERY 0x0008
92+
#define WACOM_QUIRK_TOOLSERIAL 0x0010
9093

9194
/* device types */
9295
#define WACOM_DEVICETYPE_NONE 0x0000
@@ -107,6 +110,7 @@
107110
#define WACOM_HID_WD_PEN (WACOM_HID_UP_WACOMDIGITIZER | 0x02)
108111
#define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36)
109112
#define WACOM_HID_WD_DIGITIZERFNKEYS (WACOM_HID_UP_WACOMDIGITIZER | 0x39)
113+
#define WACOM_HID_WD_SERIALNUMBER (WACOM_HID_UP_WACOMDIGITIZER | 0x5b)
110114
#define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)
111115
#define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77)
112116
#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
@@ -150,6 +154,7 @@
150154
#define WACOM_HID_WT_TOUCHSCREEN (WACOM_HID_UP_WACOMTOUCH | 0x04)
151155
#define WACOM_HID_WT_TOUCHPAD (WACOM_HID_UP_WACOMTOUCH | 0x05)
152156
#define WACOM_HID_WT_CONTACTMAX (WACOM_HID_UP_WACOMTOUCH | 0x55)
157+
#define WACOM_HID_WT_SERIALNUMBER (WACOM_HID_UP_WACOMTOUCH | 0x5b)
153158
#define WACOM_HID_WT_X (WACOM_HID_UP_WACOMTOUCH | 0x130)
154159
#define WACOM_HID_WT_Y (WACOM_HID_UP_WACOMTOUCH | 0x131)
155160

@@ -336,6 +341,7 @@ struct wacom_wac {
336341
struct input_dev *pen_input;
337342
struct input_dev *touch_input;
338343
struct input_dev *pad_input;
344+
struct kfifo_rec_ptr_2 pen_fifo;
339345
int pid;
340346
int num_contacts_left;
341347
u8 bt_features;

0 commit comments

Comments
 (0)