Skip to content

Commit 9931753

Browse files
author
Jiri Kosina
committed
Merge branch 'for-4.17/wacom' into for-linus
Pull support for 3rd generation Intuos BT device
2 parents e2d39e0 + 7ba8fc0 commit 9931753

File tree

2 files changed

+179
-48
lines changed

2 files changed

+179
-48
lines changed

drivers/hid/wacom_wac.c

Lines changed: 176 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,15 +1202,24 @@ static int wacom_wac_finger_count_touches(struct wacom_wac *wacom)
12021202

12031203
static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
12041204
{
1205-
const int pen_frame_len = 14;
1206-
const int pen_frames = 7;
1205+
int pen_frame_len, pen_frames;
12071206

12081207
struct input_dev *pen_input = wacom->pen_input;
12091208
unsigned char *data = wacom->data;
12101209
int i;
12111210

1212-
wacom->serial[0] = get_unaligned_le64(&data[99]);
1213-
wacom->id[0] = get_unaligned_le16(&data[107]);
1211+
if (wacom->features.type == INTUOSP2_BT) {
1212+
wacom->serial[0] = get_unaligned_le64(&data[99]);
1213+
wacom->id[0] = get_unaligned_le16(&data[107]);
1214+
pen_frame_len = 14;
1215+
pen_frames = 7;
1216+
} else {
1217+
wacom->serial[0] = get_unaligned_le64(&data[33]);
1218+
wacom->id[0] = get_unaligned_le16(&data[41]);
1219+
pen_frame_len = 8;
1220+
pen_frames = 4;
1221+
}
1222+
12141223
if (wacom->serial[0] >> 52 == 1) {
12151224
/* Add back in missing bits of ID for non-USI pens */
12161225
wacom->id[0] |= (wacom->serial[0] >> 32) & 0xFFFFF;
@@ -1227,21 +1236,35 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
12271236
continue;
12281237

12291238
if (range) {
1230-
/* Fix rotation alignment: userspace expects zero at left */
1231-
int16_t rotation = (int16_t)get_unaligned_le16(&frame[9]);
1232-
rotation += 1800/4;
1233-
if (rotation > 899)
1234-
rotation -= 1800;
1235-
12361239
input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1]));
12371240
input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3]));
1238-
input_report_abs(pen_input, ABS_TILT_X, (char)frame[7]);
1239-
input_report_abs(pen_input, ABS_TILT_Y, (char)frame[8]);
1240-
input_report_abs(pen_input, ABS_Z, rotation);
1241-
input_report_abs(pen_input, ABS_WHEEL, get_unaligned_le16(&frame[11]));
1241+
1242+
if (wacom->features.type == INTUOSP2_BT) {
1243+
/* Fix rotation alignment: userspace expects zero at left */
1244+
int16_t rotation =
1245+
(int16_t)get_unaligned_le16(&frame[9]);
1246+
rotation += 1800/4;
1247+
1248+
if (rotation > 899)
1249+
rotation -= 1800;
1250+
1251+
input_report_abs(pen_input, ABS_TILT_X,
1252+
(char)frame[7]);
1253+
input_report_abs(pen_input, ABS_TILT_Y,
1254+
(char)frame[8]);
1255+
input_report_abs(pen_input, ABS_Z, rotation);
1256+
input_report_abs(pen_input, ABS_WHEEL,
1257+
get_unaligned_le16(&frame[11]));
1258+
}
12421259
}
12431260
input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5]));
1244-
input_report_abs(pen_input, ABS_DISTANCE, range ? frame[13] : wacom->features.distance_max);
1261+
if (wacom->features.type == INTUOSP2_BT) {
1262+
input_report_abs(pen_input, ABS_DISTANCE,
1263+
range ? frame[13] : wacom->features.distance_max);
1264+
} else {
1265+
input_report_abs(pen_input, ABS_DISTANCE,
1266+
range ? frame[7] : wacom->features.distance_max);
1267+
}
12451268

12461269
input_report_key(pen_input, BTN_TOUCH, frame[0] & 0x01);
12471270
input_report_key(pen_input, BTN_STYLUS, frame[0] & 0x02);
@@ -1357,20 +1380,52 @@ static void wacom_intuos_pro2_bt_battery(struct wacom_wac *wacom)
13571380
battery_status, chg, 1, chg);
13581381
}
13591382

1383+
static void wacom_intuos_gen3_bt_pad(struct wacom_wac *wacom)
1384+
{
1385+
struct input_dev *pad_input = wacom->pad_input;
1386+
unsigned char *data = wacom->data;
1387+
1388+
int buttons = data[44];
1389+
1390+
wacom_report_numbered_buttons(pad_input, 4, buttons);
1391+
1392+
input_report_key(pad_input, wacom->tool[1], buttons ? 1 : 0);
1393+
input_report_abs(pad_input, ABS_MISC, buttons ? PAD_DEVICE_ID : 0);
1394+
input_event(pad_input, EV_MSC, MSC_SERIAL, 0xffffffff);
1395+
1396+
input_sync(pad_input);
1397+
}
1398+
1399+
static void wacom_intuos_gen3_bt_battery(struct wacom_wac *wacom)
1400+
{
1401+
unsigned char *data = wacom->data;
1402+
1403+
bool chg = data[45] & 0x80;
1404+
int battery_status = data[45] & 0x7F;
1405+
1406+
wacom_notify_battery(wacom, WACOM_POWER_SUPPLY_STATUS_AUTO,
1407+
battery_status, chg, 1, chg);
1408+
}
1409+
13601410
static int wacom_intuos_pro2_bt_irq(struct wacom_wac *wacom, size_t len)
13611411
{
13621412
unsigned char *data = wacom->data;
13631413

1364-
if (data[0] != 0x80) {
1414+
if (data[0] != 0x80 && data[0] != 0x81) {
13651415
dev_dbg(wacom->pen_input->dev.parent,
13661416
"%s: received unknown report #%d\n", __func__, data[0]);
13671417
return 0;
13681418
}
13691419

13701420
wacom_intuos_pro2_bt_pen(wacom);
1371-
wacom_intuos_pro2_bt_touch(wacom);
1372-
wacom_intuos_pro2_bt_pad(wacom);
1373-
wacom_intuos_pro2_bt_battery(wacom);
1421+
if (wacom->features.type == INTUOSP2_BT) {
1422+
wacom_intuos_pro2_bt_touch(wacom);
1423+
wacom_intuos_pro2_bt_pad(wacom);
1424+
wacom_intuos_pro2_bt_battery(wacom);
1425+
} else {
1426+
wacom_intuos_gen3_bt_pad(wacom);
1427+
wacom_intuos_gen3_bt_battery(wacom);
1428+
}
13741429
return 0;
13751430
}
13761431

@@ -1660,7 +1715,8 @@ int wacom_equivalent_usage(int usage)
16601715
usage == WACOM_HID_WD_TOUCHSTRIP ||
16611716
usage == WACOM_HID_WD_TOUCHSTRIP2 ||
16621717
usage == WACOM_HID_WD_TOUCHRING ||
1663-
usage == WACOM_HID_WD_TOUCHRINGSTATUS) {
1718+
usage == WACOM_HID_WD_TOUCHRINGSTATUS ||
1719+
usage == WACOM_HID_WD_REPORT_VALID) {
16641720
return usage;
16651721
}
16661722

@@ -2017,15 +2073,15 @@ static void wacom_wac_pad_pre_report(struct hid_device *hdev,
20172073
}
20182074

20192075
static void wacom_wac_pad_report(struct hid_device *hdev,
2020-
struct hid_report *report)
2076+
struct hid_report *report, struct hid_field *field)
20212077
{
20222078
struct wacom *wacom = hid_get_drvdata(hdev);
20232079
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
20242080
struct input_dev *input = wacom_wac->pad_input;
20252081
bool active = wacom_wac->hid_data.inrange_state != 0;
20262082

20272083
/* report prox for expresskey events */
2028-
if ((wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY) &&
2084+
if ((wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) &&
20292085
wacom_wac->hid_data.pad_input_event_flag) {
20302086
input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0);
20312087
input_sync(input);
@@ -2144,6 +2200,9 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
21442200
struct input_dev *input = wacom_wac->pen_input;
21452201
unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
21462202

2203+
if (wacom_wac->is_invalid_bt_frame)
2204+
return;
2205+
21472206
switch (equivalent_usage) {
21482207
case HID_GD_Z:
21492208
/*
@@ -2240,6 +2299,9 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
22402299
features->offset_bottom);
22412300
features->offset_bottom = value;
22422301
return;
2302+
case WACOM_HID_WD_REPORT_VALID:
2303+
wacom_wac->is_invalid_bt_frame = !value;
2304+
return;
22432305
}
22442306

22452307
/* send pen events only when touch is up or forced out
@@ -2258,6 +2320,10 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
22582320
static void wacom_wac_pen_pre_report(struct hid_device *hdev,
22592321
struct hid_report *report)
22602322
{
2323+
struct wacom *wacom = hid_get_drvdata(hdev);
2324+
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
2325+
2326+
wacom_wac->is_invalid_bt_frame = false;
22612327
return;
22622328
}
22632329

@@ -2270,6 +2336,9 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
22702336
bool range = wacom_wac->hid_data.inrange_state;
22712337
bool sense = wacom_wac->hid_data.sense_state;
22722338

2339+
if (wacom_wac->is_invalid_bt_frame)
2340+
return;
2341+
22732342
if (!wacom_wac->tool[0] && range) { /* first in range */
22742343
/* Going into range select tool */
22752344
if (wacom_wac->hid_data.invert_state)
@@ -2572,11 +2641,13 @@ void wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
25722641
wacom_wac_finger_event(hdev, field, usage, value);
25732642
}
25742643

2575-
static void wacom_report_events(struct hid_device *hdev, struct hid_report *report)
2644+
static void wacom_report_events(struct hid_device *hdev,
2645+
struct hid_report *report, int collection_index,
2646+
int field_index)
25762647
{
25772648
int r;
25782649

2579-
for (r = 0; r < report->maxfield; r++) {
2650+
for (r = field_index; r < report->maxfield; r++) {
25802651
struct hid_field *field;
25812652
unsigned count, n;
25822653

@@ -2586,30 +2657,23 @@ static void wacom_report_events(struct hid_device *hdev, struct hid_report *repo
25862657
if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
25872658
continue;
25882659

2589-
for (n = 0; n < count; n++)
2590-
wacom_wac_event(hdev, field, &field->usage[n], field->value[n]);
2660+
for (n = 0 ; n < count; n++) {
2661+
if (field->usage[n].collection_index == collection_index)
2662+
wacom_wac_event(hdev, field, &field->usage[n],
2663+
field->value[n]);
2664+
else
2665+
return;
2666+
}
25912667
}
25922668
}
25932669

2594-
void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
2670+
static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *report,
2671+
int collection_index, struct hid_field *field,
2672+
int field_index)
25952673
{
25962674
struct wacom *wacom = hid_get_drvdata(hdev);
2597-
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
2598-
struct hid_field *field = report->field[0];
25992675

2600-
if (wacom_wac->features.type != HID_GENERIC)
2601-
return;
2602-
2603-
wacom_wac_battery_pre_report(hdev, report);
2604-
2605-
if (WACOM_PAD_FIELD(field) && wacom->wacom_wac.pad_input)
2606-
wacom_wac_pad_pre_report(hdev, report);
2607-
else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
2608-
wacom_wac_pen_pre_report(hdev, report);
2609-
else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input)
2610-
wacom_wac_finger_pre_report(hdev, report);
2611-
2612-
wacom_report_events(hdev, report);
2676+
wacom_report_events(hdev, report, collection_index, field_index);
26132677

26142678
/*
26152679
* Non-input reports may be sent prior to the device being
@@ -2619,16 +2683,63 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
26192683
* processing functions.
26202684
*/
26212685
if (report->type != HID_INPUT_REPORT)
2622-
return;
2623-
2624-
wacom_wac_battery_report(hdev, report);
2686+
return -1;
26252687

26262688
if (WACOM_PAD_FIELD(field) && wacom->wacom_wac.pad_input)
2627-
wacom_wac_pad_report(hdev, report);
2689+
wacom_wac_pad_report(hdev, report, field);
26282690
else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
26292691
wacom_wac_pen_report(hdev, report);
26302692
else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input)
26312693
wacom_wac_finger_report(hdev, report);
2694+
2695+
return 0;
2696+
}
2697+
2698+
void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
2699+
{
2700+
struct wacom *wacom = hid_get_drvdata(hdev);
2701+
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
2702+
struct hid_field *field;
2703+
bool pad_in_hid_field = false, pen_in_hid_field = false,
2704+
finger_in_hid_field = false;
2705+
int r;
2706+
int prev_collection = -1;
2707+
2708+
if (wacom_wac->features.type != HID_GENERIC)
2709+
return;
2710+
2711+
for (r = 0; r < report->maxfield; r++) {
2712+
field = report->field[r];
2713+
2714+
if (WACOM_PAD_FIELD(field))
2715+
pad_in_hid_field = true;
2716+
if (WACOM_PEN_FIELD(field))
2717+
pen_in_hid_field = true;
2718+
if (WACOM_FINGER_FIELD(field))
2719+
finger_in_hid_field = true;
2720+
}
2721+
2722+
wacom_wac_battery_pre_report(hdev, report);
2723+
2724+
if (pad_in_hid_field && wacom->wacom_wac.pad_input)
2725+
wacom_wac_pad_pre_report(hdev, report);
2726+
if (pen_in_hid_field && wacom->wacom_wac.pen_input)
2727+
wacom_wac_pen_pre_report(hdev, report);
2728+
if (finger_in_hid_field && wacom->wacom_wac.touch_input)
2729+
wacom_wac_finger_pre_report(hdev, report);
2730+
2731+
for (r = 0; r < report->maxfield; r++) {
2732+
field = report->field[r];
2733+
2734+
if (field->usage[0].collection_index != prev_collection) {
2735+
if (wacom_wac_collection(hdev, report,
2736+
field->usage[0].collection_index, field, r) < 0)
2737+
return;
2738+
prev_collection = field->usage[0].collection_index;
2739+
}
2740+
}
2741+
2742+
wacom_wac_battery_report(hdev, report);
26322743
}
26332744

26342745
static int wacom_bpt_touch(struct wacom_wac *wacom)
@@ -3093,6 +3204,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
30933204
break;
30943205

30953206
case INTUOSP2_BT:
3207+
case INTUOSHT3_BT:
30963208
sync = wacom_intuos_pro2_bt_irq(wacom_wac, len);
30973209
break;
30983210

@@ -3272,6 +3384,12 @@ void wacom_setup_device_quirks(struct wacom *wacom)
32723384
features->quirks |= WACOM_QUIRK_BATTERY;
32733385
}
32743386

3387+
if (features->type == INTUOSHT3_BT) {
3388+
features->device_type |= WACOM_DEVICETYPE_PEN |
3389+
WACOM_DEVICETYPE_PAD;
3390+
features->quirks |= WACOM_QUIRK_BATTERY;
3391+
}
3392+
32753393
switch (features->type) {
32763394
case PL:
32773395
case DTU:
@@ -3466,7 +3584,9 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
34663584
case BAMBOO_PT:
34673585
case BAMBOO_PEN:
34683586
case INTUOSHT2:
3469-
if (features->type == INTUOSHT2) {
3587+
case INTUOSHT3_BT:
3588+
if (features->type == INTUOSHT2 ||
3589+
features->type == INTUOSHT3_BT) {
34703590
wacom_setup_basic_pro_pen(wacom_wac);
34713591
} else {
34723592
__clear_bit(ABS_MISC, input_dev->absbit);
@@ -3887,6 +4007,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
38874007
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
38884008
break;
38894009

4010+
case INTUOSHT3_BT:
38904011
case HID_GENERIC:
38914012
break;
38924013

@@ -4415,6 +4536,12 @@ static const struct wacom_features wacom_features_0x360 =
44154536
static const struct wacom_features wacom_features_0x361 =
44164537
{ "Wacom Intuos Pro L", 62200, 43200, 8191, 63,
44174538
INTUOSP2_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 10 };
4539+
static const struct wacom_features wacom_features_0x377 =
4540+
{ "Wacom Intuos BT S", 15200, 9500, 4095, 63,
4541+
INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
4542+
static const struct wacom_features wacom_features_0x379 =
4543+
{ "Wacom Intuos BT M", 21600, 13500, 4095, 63,
4544+
INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
44184545
static const struct wacom_features wacom_features_0x37A =
44194546
{ "Wacom One by Wacom S", 15200, 9500, 2047, 63,
44204547
BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -4589,6 +4716,8 @@ const struct hid_device_id wacom_ids[] = {
45894716
{ USB_DEVICE_WACOM(0x343) },
45904717
{ BT_DEVICE_WACOM(0x360) },
45914718
{ BT_DEVICE_WACOM(0x361) },
4719+
{ BT_DEVICE_WACOM(0x377) },
4720+
{ BT_DEVICE_WACOM(0x379) },
45924721
{ USB_DEVICE_WACOM(0x37A) },
45934722
{ USB_DEVICE_WACOM(0x37B) },
45944723
{ USB_DEVICE_WACOM(0x4001) },

0 commit comments

Comments
 (0)