Skip to content

Commit 5ae6e89

Browse files
bentissJiri Kosina
authored andcommitted
HID: wacom: implement the finger part of the HID generic handling
Signed-off-by: Benjamin Tissoires <[email protected]> Acked-by: Jason Gerecke <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 7704ac9 commit 5ae6e89

File tree

3 files changed

+164
-3
lines changed

3 files changed

+164
-3
lines changed

drivers/hid/wacom_sys.c

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
109109
{
110110
struct wacom *wacom = hid_get_drvdata(hdev);
111111
struct wacom_features *features = &wacom->wacom_wac.features;
112+
struct hid_data *hid_data = &wacom->wacom_wac.hid_data;
112113
u8 *data;
113114
int ret;
114115

@@ -128,6 +129,16 @@ static void wacom_feature_mapping(struct hid_device *hdev,
128129
kfree(data);
129130
}
130131
break;
132+
case HID_DG_INPUTMODE:
133+
/* Ignore if value index is out of bounds. */
134+
if (usage->usage_index >= field->report_count) {
135+
dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n");
136+
break;
137+
}
138+
139+
hid_data->inputmode = field->report->id;
140+
hid_data->inputmode_index = usage->usage_index;
141+
break;
131142
}
132143
}
133144

@@ -255,6 +266,25 @@ static void wacom_parse_hid(struct hid_device *hdev,
255266
}
256267
}
257268

269+
static int wacom_hid_set_device_mode(struct hid_device *hdev)
270+
{
271+
struct wacom *wacom = hid_get_drvdata(hdev);
272+
struct hid_data *hid_data = &wacom->wacom_wac.hid_data;
273+
struct hid_report *r;
274+
struct hid_report_enum *re;
275+
276+
if (hid_data->inputmode < 0)
277+
return 0;
278+
279+
re = &(hdev->report_enum[HID_FEATURE_REPORT]);
280+
r = re->report_id_hash[hid_data->inputmode];
281+
if (r) {
282+
r->field[0]->value[hid_data->inputmode_index] = 2;
283+
hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
284+
}
285+
return 0;
286+
}
287+
258288
static int wacom_set_device_mode(struct hid_device *hdev, int report_id,
259289
int length, int mode)
260290
{
@@ -347,6 +377,9 @@ static int wacom_query_tablet_data(struct hid_device *hdev,
347377
if (hdev->bus == BUS_BLUETOOTH)
348378
return wacom_bt_query_tablet_data(hdev, 1, features);
349379

380+
if (features->type == HID_GENERIC)
381+
return wacom_hid_set_device_mode(hdev);
382+
350383
if (features->device_type == BTN_TOOL_FINGER) {
351384
if (features->type > TABLETPC) {
352385
/* MT Tablet PC touch */
@@ -1451,9 +1484,6 @@ static int wacom_probe(struct hid_device *hdev,
14511484
error);
14521485
}
14531486

1454-
/* Note that if query fails it is not a hard failure */
1455-
wacom_query_tablet_data(hdev, features);
1456-
14571487
if (features->type == HID_GENERIC)
14581488
connect_mask |= HID_CONNECT_DRIVER;
14591489

@@ -1464,6 +1494,9 @@ static int wacom_probe(struct hid_device *hdev,
14641494
goto fail_hw_start;
14651495
}
14661496

1497+
/* Note that if query fails it is not a hard failure */
1498+
wacom_query_tablet_data(hdev, features);
1499+
14671500
if (features->quirks & WACOM_QUIRK_MONITOR)
14681501
error = hid_hw_open(hdev);
14691502

drivers/hid/wacom_wac.c

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,117 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
13721372
}
13731373
}
13741374

1375+
static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
1376+
struct hid_field *field, struct hid_usage *usage)
1377+
{
1378+
struct wacom *wacom = hid_get_drvdata(hdev);
1379+
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
1380+
struct input_dev *input = wacom_wac->input;
1381+
unsigned touch_max = wacom_wac->features.touch_max;
1382+
1383+
switch (usage->hid) {
1384+
case HID_GD_X:
1385+
if (touch_max == 1)
1386+
wacom_map_usage(wacom, usage, field, EV_ABS, ABS_X, 4);
1387+
else
1388+
wacom_map_usage(wacom, usage, field, EV_ABS,
1389+
ABS_MT_POSITION_X, 4);
1390+
break;
1391+
case HID_GD_Y:
1392+
if (touch_max == 1)
1393+
wacom_map_usage(wacom, usage, field, EV_ABS, ABS_Y, 4);
1394+
else
1395+
wacom_map_usage(wacom, usage, field, EV_ABS,
1396+
ABS_MT_POSITION_Y, 4);
1397+
break;
1398+
case HID_DG_CONTACTID:
1399+
input_mt_init_slots(input, wacom_wac->features.touch_max,
1400+
INPUT_MT_DIRECT);
1401+
break;
1402+
case HID_DG_INRANGE:
1403+
break;
1404+
case HID_DG_INVERT:
1405+
break;
1406+
case HID_DG_TIPSWITCH:
1407+
wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOUCH, 0);
1408+
break;
1409+
}
1410+
}
1411+
1412+
static int wacom_wac_finger_event(struct hid_device *hdev,
1413+
struct hid_field *field, struct hid_usage *usage, __s32 value)
1414+
{
1415+
struct wacom *wacom = hid_get_drvdata(hdev);
1416+
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
1417+
1418+
switch (usage->hid) {
1419+
case HID_GD_X:
1420+
wacom_wac->hid_data.x = value;
1421+
break;
1422+
case HID_GD_Y:
1423+
wacom_wac->hid_data.y = value;
1424+
break;
1425+
case HID_DG_CONTACTID:
1426+
wacom_wac->hid_data.id = value;
1427+
break;
1428+
case HID_DG_TIPSWITCH:
1429+
wacom_wac->hid_data.tipswitch = value;
1430+
break;
1431+
}
1432+
1433+
1434+
return 0;
1435+
}
1436+
1437+
static void wacom_wac_finger_mt_report(struct wacom_wac *wacom_wac,
1438+
struct input_dev *input, bool touch)
1439+
{
1440+
int slot;
1441+
struct hid_data *hid_data = &wacom_wac->hid_data;
1442+
1443+
slot = input_mt_get_slot_by_key(input, hid_data->id);
1444+
1445+
input_mt_slot(input, slot);
1446+
input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
1447+
if (touch) {
1448+
input_report_abs(input, ABS_MT_POSITION_X, hid_data->x);
1449+
input_report_abs(input, ABS_MT_POSITION_Y, hid_data->y);
1450+
}
1451+
input_mt_sync_frame(input);
1452+
}
1453+
1454+
static void wacom_wac_finger_single_touch_report(struct wacom_wac *wacom_wac,
1455+
struct input_dev *input, bool touch)
1456+
{
1457+
struct hid_data *hid_data = &wacom_wac->hid_data;
1458+
1459+
if (touch) {
1460+
input_report_abs(input, ABS_X, hid_data->x);
1461+
input_report_abs(input, ABS_Y, hid_data->y);
1462+
}
1463+
input_report_key(input, BTN_TOUCH, touch);
1464+
}
1465+
1466+
static void wacom_wac_finger_report(struct hid_device *hdev,
1467+
struct hid_report *report)
1468+
{
1469+
struct wacom *wacom = hid_get_drvdata(hdev);
1470+
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
1471+
struct input_dev *input = wacom_wac->input;
1472+
bool touch = wacom_wac->hid_data.tipswitch &&
1473+
!wacom_wac->shared->stylus_in_proximity;
1474+
unsigned touch_max = wacom_wac->features.touch_max;
1475+
1476+
if (touch_max > 1)
1477+
wacom_wac_finger_mt_report(wacom_wac, input, touch);
1478+
else
1479+
wacom_wac_finger_single_touch_report(wacom_wac, input, touch);
1480+
input_sync(input);
1481+
1482+
/* keep touch state for pen event */
1483+
wacom_wac->shared->touch_down = touch;
1484+
}
1485+
13751486
#define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \
13761487
((f)->physical == HID_DG_STYLUS))
13771488
#define WACOM_FINGER_FIELD(f) (((f)->logical == HID_DG_FINGER) || \
@@ -1389,6 +1500,9 @@ void wacom_wac_usage_mapping(struct hid_device *hdev,
13891500

13901501
if (WACOM_PEN_FIELD(field))
13911502
return wacom_wac_pen_usage_mapping(hdev, field, usage);
1503+
1504+
if (WACOM_FINGER_FIELD(field))
1505+
return wacom_wac_finger_usage_mapping(hdev, field, usage);
13921506
}
13931507

13941508
int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
@@ -1402,6 +1516,9 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
14021516
if (WACOM_PEN_FIELD(field))
14031517
return wacom_wac_pen_event(hdev, field, usage, value);
14041518

1519+
if (WACOM_FINGER_FIELD(field))
1520+
return wacom_wac_finger_event(hdev, field, usage, value);
1521+
14051522
return 0;
14061523
}
14071524

@@ -1416,6 +1533,9 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
14161533

14171534
if (WACOM_PEN_FIELD(field))
14181535
return wacom_wac_pen_report(hdev, report);
1536+
1537+
if (WACOM_FINGER_FIELD(field))
1538+
return wacom_wac_finger_report(hdev, report);
14191539
}
14201540

14211541
static int wacom_bpt_touch(struct wacom_wac *wacom)

drivers/hid/wacom_wac.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,17 @@ struct wacom_shared {
156156
};
157157

158158
struct hid_data {
159+
__s16 inputmode; /* InputMode HID feature, -1 if non-existent */
160+
__s16 inputmode_index; /* InputMode HID feature index in the report */
159161
bool inrange_state;
160162
bool invert_state;
161163
bool tipswitch;
164+
int x;
165+
int y;
166+
int pressure;
167+
int width;
168+
int height;
169+
int id;
162170
};
163171

164172
struct wacom_wac {

0 commit comments

Comments
 (0)