aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorJason Gerecke <killertofu@gmail.com>2014-12-10 19:26:04 -0500
committerJiri Kosina <jkosina@suse.cz>2014-12-11 17:01:56 -0500
commit601a22f3791473baa2923e4a3125e840279f8bba (patch)
tree18d6f81096220c62f249345ac1eefe96ba8bb6e2 /drivers/hid
parentb58ba1ba1af9cfbad6f3af4c4fc3575d9aeae542 (diff)
HID: wacom: Report input events for each finger on generic devices
The existing generic touch code only reports events after reading an entire HID report, which practically means that only data about the last contact in a report will ever be provided to userspace. This patch uses a trick from hid-multitouch.c to discover what type of field is at the end of each contact; when such a field is encountered all the stored contact data will be reported. Signed-off-by: Jason Gerecke <killertofu@gmail.com> Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/wacom_wac.c86
-rw-r--r--drivers/hid/wacom_wac.h1
2 files changed, 59 insertions, 28 deletions
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 064fd6cf36c6..26f27bd6b95c 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1381,10 +1381,12 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
1381{ 1381{
1382 struct wacom *wacom = hid_get_drvdata(hdev); 1382 struct wacom *wacom = hid_get_drvdata(hdev);
1383 struct wacom_wac *wacom_wac = &wacom->wacom_wac; 1383 struct wacom_wac *wacom_wac = &wacom->wacom_wac;
1384 struct wacom_features *features = &wacom_wac->features;
1384 unsigned touch_max = wacom_wac->features.touch_max; 1385 unsigned touch_max = wacom_wac->features.touch_max;
1385 1386
1386 switch (usage->hid) { 1387 switch (usage->hid) {
1387 case HID_GD_X: 1388 case HID_GD_X:
1389 features->last_slot_field = usage->hid;
1388 if (touch_max == 1) 1390 if (touch_max == 1)
1389 wacom_map_usage(wacom, usage, field, EV_ABS, ABS_X, 4); 1391 wacom_map_usage(wacom, usage, field, EV_ABS, ABS_X, 4);
1390 else 1392 else
@@ -1392,6 +1394,7 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
1392 ABS_MT_POSITION_X, 4); 1394 ABS_MT_POSITION_X, 4);
1393 break; 1395 break;
1394 case HID_GD_Y: 1396 case HID_GD_Y:
1397 features->last_slot_field = usage->hid;
1395 if (touch_max == 1) 1398 if (touch_max == 1)
1396 wacom_map_usage(wacom, usage, field, EV_ABS, ABS_Y, 4); 1399 wacom_map_usage(wacom, usage, field, EV_ABS, ABS_Y, 4);
1397 else 1400 else
@@ -1399,17 +1402,48 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
1399 ABS_MT_POSITION_Y, 4); 1402 ABS_MT_POSITION_Y, 4);
1400 break; 1403 break;
1401 case HID_DG_CONTACTID: 1404 case HID_DG_CONTACTID:
1405 features->last_slot_field = usage->hid;
1402 break; 1406 break;
1403 case HID_DG_INRANGE: 1407 case HID_DG_INRANGE:
1408 features->last_slot_field = usage->hid;
1404 break; 1409 break;
1405 case HID_DG_INVERT: 1410 case HID_DG_INVERT:
1411 features->last_slot_field = usage->hid;
1406 break; 1412 break;
1407 case HID_DG_TIPSWITCH: 1413 case HID_DG_TIPSWITCH:
1414 features->last_slot_field = usage->hid;
1408 wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOUCH, 0); 1415 wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOUCH, 0);
1409 break; 1416 break;
1410 } 1417 }
1411} 1418}
1412 1419
1420static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac,
1421 struct input_dev *input)
1422{
1423 struct hid_data *hid_data = &wacom_wac->hid_data;
1424 bool mt = wacom_wac->features.touch_max > 1;
1425 bool prox = hid_data->tipswitch &&
1426 !wacom_wac->shared->stylus_in_proximity;
1427
1428 if (mt) {
1429 int slot;
1430
1431 slot = input_mt_get_slot_by_key(input, hid_data->id);
1432 input_mt_slot(input, slot);
1433 input_mt_report_slot_state(input, MT_TOOL_FINGER, prox);
1434 }
1435 else {
1436 input_report_key(input, BTN_TOUCH, prox);
1437 }
1438
1439 if (prox) {
1440 input_report_abs(input, mt ? ABS_MT_POSITION_X : ABS_X,
1441 hid_data->x);
1442 input_report_abs(input, mt ? ABS_MT_POSITION_Y : ABS_Y,
1443 hid_data->y);
1444 }
1445}
1446
1413static int wacom_wac_finger_event(struct hid_device *hdev, 1447static int wacom_wac_finger_event(struct hid_device *hdev,
1414 struct hid_field *field, struct hid_usage *usage, __s32 value) 1448 struct hid_field *field, struct hid_usage *usage, __s32 value)
1415{ 1449{
@@ -1432,36 +1466,35 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
1432 } 1466 }
1433 1467
1434 1468
1469 if (usage->usage_index + 1 == field->report_count) {
1470 if (usage->hid == wacom_wac->features.last_slot_field)
1471 wacom_wac_finger_slot(wacom_wac, wacom_wac->input);
1472 }
1473
1435 return 0; 1474 return 0;
1436} 1475}
1437 1476
1438static void wacom_wac_finger_mt_report(struct wacom_wac *wacom_wac, 1477static int wacom_wac_finger_count_touches(struct hid_device *hdev)
1439 struct input_dev *input, bool touch)
1440{ 1478{
1441 int slot; 1479 struct wacom *wacom = hid_get_drvdata(hdev);
1442 struct hid_data *hid_data = &wacom_wac->hid_data; 1480 struct wacom_wac *wacom_wac = &wacom->wacom_wac;
1481 struct input_dev *input = wacom_wac->input;
1482 unsigned touch_max = wacom_wac->features.touch_max;
1483 int count = 0;
1484 int i;
1443 1485
1444 slot = input_mt_get_slot_by_key(input, hid_data->id); 1486 if (touch_max == 1)
1487 return wacom_wac->hid_data.tipswitch &&
1488 !wacom_wac->shared->stylus_in_proximity;
1445 1489
1446 input_mt_slot(input, slot); 1490 for (i = 0; i < input->mt->num_slots; i++) {
1447 input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); 1491 struct input_mt_slot *ps = &input->mt->slots[i];
1448 if (touch) { 1492 int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
1449 input_report_abs(input, ABS_MT_POSITION_X, hid_data->x); 1493 if (id >= 0)
1450 input_report_abs(input, ABS_MT_POSITION_Y, hid_data->y); 1494 count++;
1451 } 1495 }
1452 input_mt_sync_frame(input);
1453}
1454
1455static void wacom_wac_finger_single_touch_report(struct wacom_wac *wacom_wac,
1456 struct input_dev *input, bool touch)
1457{
1458 struct hid_data *hid_data = &wacom_wac->hid_data;
1459 1496
1460 if (touch) { 1497 return count;
1461 input_report_abs(input, ABS_X, hid_data->x);
1462 input_report_abs(input, ABS_Y, hid_data->y);
1463 }
1464 input_report_key(input, BTN_TOUCH, touch);
1465} 1498}
1466 1499
1467static void wacom_wac_finger_report(struct hid_device *hdev, 1500static void wacom_wac_finger_report(struct hid_device *hdev,
@@ -1470,18 +1503,15 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
1470 struct wacom *wacom = hid_get_drvdata(hdev); 1503 struct wacom *wacom = hid_get_drvdata(hdev);
1471 struct wacom_wac *wacom_wac = &wacom->wacom_wac; 1504 struct wacom_wac *wacom_wac = &wacom->wacom_wac;
1472 struct input_dev *input = wacom_wac->input; 1505 struct input_dev *input = wacom_wac->input;
1473 bool touch = wacom_wac->hid_data.tipswitch &&
1474 !wacom_wac->shared->stylus_in_proximity;
1475 unsigned touch_max = wacom_wac->features.touch_max; 1506 unsigned touch_max = wacom_wac->features.touch_max;
1476 1507
1477 if (touch_max > 1) 1508 if (touch_max > 1)
1478 wacom_wac_finger_mt_report(wacom_wac, input, touch); 1509 input_mt_sync_frame(input);
1479 else 1510
1480 wacom_wac_finger_single_touch_report(wacom_wac, input, touch);
1481 input_sync(input); 1511 input_sync(input);
1482 1512
1483 /* keep touch state for pen event */ 1513 /* keep touch state for pen event */
1484 wacom_wac->shared->touch_down = touch; 1514 wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(hdev);
1485} 1515}
1486 1516
1487#define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ 1517#define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 5384043778fc..bfad815cda8a 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -145,6 +145,7 @@ struct wacom_features {
145 int pktlen; 145 int pktlen;
146 bool check_for_hid_type; 146 bool check_for_hid_type;
147 int hid_type; 147 int hid_type;
148 int last_slot_field;
148}; 149};
149 150
150struct wacom_shared { 151struct wacom_shared {