aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoderick Colenbrander <roderick.colenbrander@sony.com>2016-11-23 17:07:07 -0500
committerJiri Kosina <jkosina@suse.cz>2016-11-28 08:54:57 -0500
commitac797b95f53276c132c51d53437e38dd912413d7 (patch)
tree7c5b65fdbdc613770a5d45446a729a5919c33f56
parent4f967f6d73746f66514528cc1191025f0b5d69b3 (diff)
HID: sony: Make the DS4 touchpad a separate device
The dualshock 4 supports both analog sticks of which one uses ABS_X/_Y and a touchpad. In a recent discussion with Dmitry about some input-mt changes we proposed for disabling pointer emulation from input_mt_sync_frame, Dmitry mentioned ABS_X/_Y should report the same data as ABS_MT_POSITION_X/_Y. The current driver is mixing axes for different subdevices. It was suggested to make the touchpad its own sub-device. This patch turns the touchpad into its own device. In addition this patch also moves the button underneath the touchpad into the new device. It felt like this button should be part of the device. No known user space application (not even SDL2) seems to be using it. Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-sony.c105
1 files changed, 84 insertions, 21 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 3385006accc0..995b5cf1afc9 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -376,7 +376,7 @@ static u8 dualshock4_usb_rdesc[] = {
376 0x65, 0x00, /* Unit, */ 376 0x65, 0x00, /* Unit, */
377 0x05, 0x09, /* Usage Page (Button), */ 377 0x05, 0x09, /* Usage Page (Button), */
378 0x19, 0x01, /* Usage Minimum (01h), */ 378 0x19, 0x01, /* Usage Minimum (01h), */
379 0x29, 0x0E, /* Usage Maximum (0Eh), */ 379 0x29, 0x0D, /* Usage Maximum (0Dh), */
380 0x15, 0x00, /* Logical Minimum (0), */ 380 0x15, 0x00, /* Logical Minimum (0), */
381 0x25, 0x01, /* Logical Maximum (1), */ 381 0x25, 0x01, /* Logical Maximum (1), */
382 0x75, 0x01, /* Report Size (1), */ 382 0x75, 0x01, /* Report Size (1), */
@@ -689,7 +689,7 @@ static u8 dualshock4_bt_rdesc[] = {
689 0x81, 0x42, /* Input (Variable, Null State), */ 689 0x81, 0x42, /* Input (Variable, Null State), */
690 0x05, 0x09, /* Usage Page (Button), */ 690 0x05, 0x09, /* Usage Page (Button), */
691 0x19, 0x01, /* Usage Minimum (01h), */ 691 0x19, 0x01, /* Usage Minimum (01h), */
692 0x29, 0x0E, /* Usage Maximum (0Eh), */ 692 0x29, 0x0D, /* Usage Maximum (0Dh), */
693 0x15, 0x00, /* Logical Minimum (0), */ 693 0x15, 0x00, /* Logical Minimum (0), */
694 0x25, 0x01, /* Logical Maximum (1), */ 694 0x25, 0x01, /* Logical Maximum (1), */
695 0x75, 0x01, /* Report Size (1), */ 695 0x75, 0x01, /* Report Size (1), */
@@ -1033,9 +1033,12 @@ struct motion_output_report_02 {
1033/* Offsets relative to USB input report (0x1). Bluetooth (0x11) requires an 1033/* Offsets relative to USB input report (0x1). Bluetooth (0x11) requires an
1034 * additional +2. 1034 * additional +2.
1035 */ 1035 */
1036#define DS4_INPUT_REPORT_BUTTON_OFFSET 5
1036#define DS4_INPUT_REPORT_BATTERY_OFFSET 30 1037#define DS4_INPUT_REPORT_BATTERY_OFFSET 30
1037#define DS4_INPUT_REPORT_TOUCHPAD_OFFSET 33 1038#define DS4_INPUT_REPORT_TOUCHPAD_OFFSET 33
1038 1039
1040#define DS4_TOUCHPAD_SUFFIX " Touchpad"
1041
1039static DEFINE_SPINLOCK(sony_dev_list_lock); 1042static DEFINE_SPINLOCK(sony_dev_list_lock);
1040static LIST_HEAD(sony_device_list); 1043static LIST_HEAD(sony_device_list);
1041static DEFINE_IDA(sony_device_id_allocator); 1044static DEFINE_IDA(sony_device_id_allocator);
@@ -1044,6 +1047,7 @@ struct sony_sc {
1044 spinlock_t lock; 1047 spinlock_t lock;
1045 struct list_head list_node; 1048 struct list_head list_node;
1046 struct hid_device *hdev; 1049 struct hid_device *hdev;
1050 struct input_dev *touchpad;
1047 struct led_classdev *leds[MAX_LEDS]; 1051 struct led_classdev *leds[MAX_LEDS];
1048 unsigned long quirks; 1052 unsigned long quirks;
1049 struct work_struct state_worker; 1053 struct work_struct state_worker;
@@ -1228,9 +1232,6 @@ static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size)
1228 1232
1229static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) 1233static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size)
1230{ 1234{
1231 struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
1232 struct hid_input, list);
1233 struct input_dev *input_dev = hidinput->input;
1234 unsigned long flags; 1235 unsigned long flags;
1235 int n, m, offset, num_touch_data, max_touch_data; 1236 int n, m, offset, num_touch_data, max_touch_data;
1236 u8 cable_state, battery_capacity, battery_charging; 1237 u8 cable_state, battery_capacity, battery_charging;
@@ -1238,6 +1239,10 @@ static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size)
1238 /* When using Bluetooth the header is 2 bytes longer, so skip these. */ 1239 /* When using Bluetooth the header is 2 bytes longer, so skip these. */
1239 int data_offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 0 : 2; 1240 int data_offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 0 : 2;
1240 1241
1242 /* Second bit of third button byte is for the touchpad button. */
1243 offset = data_offset + DS4_INPUT_REPORT_BUTTON_OFFSET;
1244 input_report_key(sc->touchpad, BTN_LEFT, rd[offset+2] & 0x2);
1245
1241 /* 1246 /*
1242 * The lower 4 bits of byte 30 (or 32 for BT) contain the battery level 1247 * The lower 4 bits of byte 30 (or 32 for BT) contain the battery level
1243 * and the 5th bit contains the USB cable state. 1248 * and the 5th bit contains the USB cable state.
@@ -1303,18 +1308,18 @@ static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size)
1303 y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4); 1308 y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4);
1304 1309
1305 active = !(rd[offset] >> 7); 1310 active = !(rd[offset] >> 7);
1306 input_mt_slot(input_dev, n); 1311 input_mt_slot(sc->touchpad, n);
1307 input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, active); 1312 input_mt_report_slot_state(sc->touchpad, MT_TOOL_FINGER, active);
1308 1313
1309 if (active) { 1314 if (active) {
1310 input_report_abs(input_dev, ABS_MT_POSITION_X, x); 1315 input_report_abs(sc->touchpad, ABS_MT_POSITION_X, x);
1311 input_report_abs(input_dev, ABS_MT_POSITION_Y, y); 1316 input_report_abs(sc->touchpad, ABS_MT_POSITION_Y, y);
1312 } 1317 }
1313 1318
1314 offset += 4; 1319 offset += 4;
1315 } 1320 }
1316 input_mt_sync_frame(input_dev); 1321 input_mt_sync_frame(sc->touchpad);
1317 input_sync(input_dev); 1322 input_sync(sc->touchpad);
1318 } 1323 }
1319} 1324}
1320 1325
@@ -1415,22 +1420,77 @@ static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
1415 return 0; 1420 return 0;
1416} 1421}
1417 1422
1418static int sony_register_touchpad(struct hid_input *hi, int touch_count, 1423static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
1419 int w, int h) 1424 int w, int h)
1420{ 1425{
1421 struct input_dev *input_dev = hi->input; 1426 size_t name_sz;
1427 char *name;
1422 int ret; 1428 int ret;
1423 1429
1424 ret = input_mt_init_slots(input_dev, touch_count, 0); 1430 sc->touchpad = input_allocate_device();
1431 if (!sc->touchpad)
1432 return -ENOMEM;
1433
1434 input_set_drvdata(sc->touchpad, sc);
1435 sc->touchpad->dev.parent = &sc->hdev->dev;
1436 sc->touchpad->phys = sc->hdev->phys;
1437 sc->touchpad->uniq = sc->hdev->uniq;
1438 sc->touchpad->id.bustype = sc->hdev->bus;
1439 sc->touchpad->id.vendor = sc->hdev->vendor;
1440 sc->touchpad->id.product = sc->hdev->product;
1441 sc->touchpad->id.version = sc->hdev->version;
1442
1443 /* Append a suffix to the controller name as there are various
1444 * DS4 compatible non-Sony devices with different names.
1445 */
1446 name_sz = strlen(sc->hdev->name) + sizeof(DS4_TOUCHPAD_SUFFIX);
1447 name = kzalloc(name_sz, GFP_KERNEL);
1448 if (!name) {
1449 ret = -ENOMEM;
1450 goto err;
1451 }
1452 snprintf(name, name_sz, "%s" DS4_TOUCHPAD_SUFFIX, sc->hdev->name);
1453 sc->touchpad->name = name;
1454
1455 ret = input_mt_init_slots(sc->touchpad, touch_count, 0);
1425 if (ret < 0) 1456 if (ret < 0)
1426 return ret; 1457 goto err;
1458
1459 /* We map the button underneath the touchpad to BTN_LEFT. */
1460 __set_bit(EV_KEY, sc->touchpad->evbit);
1461 __set_bit(BTN_LEFT, sc->touchpad->keybit);
1462 __set_bit(INPUT_PROP_BUTTONPAD, sc->touchpad->propbit);
1427 1463
1428 input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0); 1464 input_set_abs_params(sc->touchpad, ABS_MT_POSITION_X, 0, w, 0, 0);
1429 input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0); 1465 input_set_abs_params(sc->touchpad, ABS_MT_POSITION_Y, 0, h, 0, 0);
1466
1467 ret = input_register_device(sc->touchpad);
1468 if (ret < 0)
1469 goto err;
1430 1470
1431 return 0; 1471 return 0;
1472
1473err:
1474 kfree(sc->touchpad->name);
1475 sc->touchpad->name = NULL;
1476
1477 input_free_device(sc->touchpad);
1478 sc->touchpad = NULL;
1479
1480 return ret;
1432} 1481}
1433 1482
1483static void sony_unregister_touchpad(struct sony_sc *sc)
1484{
1485 if (!sc->touchpad)
1486 return;
1487
1488 kfree(sc->touchpad->name);
1489 sc->touchpad->name = NULL;
1490
1491 input_unregister_device(sc->touchpad);
1492 sc->touchpad = NULL;
1493}
1434 1494
1435/* 1495/*
1436 * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller 1496 * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
@@ -2422,7 +2482,7 @@ static int sony_input_configured(struct hid_device *hdev,
2422 * The Dualshock 4 touchpad supports 2 touches and has a 2482 * The Dualshock 4 touchpad supports 2 touches and has a
2423 * resolution of 1920x942 (44.86 dots/mm). 2483 * resolution of 1920x942 (44.86 dots/mm).
2424 */ 2484 */
2425 ret = sony_register_touchpad(hidinput, 2, 1920, 942); 2485 ret = sony_register_touchpad(sc, 2, 1920, 942);
2426 if (ret) { 2486 if (ret) {
2427 hid_err(sc->hdev, 2487 hid_err(sc->hdev,
2428 "Unable to initialize multi-touch slots: %d\n", 2488 "Unable to initialize multi-touch slots: %d\n",
@@ -2544,13 +2604,16 @@ static void sony_remove(struct hid_device *hdev)
2544{ 2604{
2545 struct sony_sc *sc = hid_get_drvdata(hdev); 2605 struct sony_sc *sc = hid_get_drvdata(hdev);
2546 2606
2607 hid_hw_close(hdev);
2608
2547 if (sc->quirks & SONY_LED_SUPPORT) 2609 if (sc->quirks & SONY_LED_SUPPORT)
2548 sony_leds_remove(sc); 2610 sony_leds_remove(sc);
2549 2611
2550 if (sc->quirks & SONY_BATTERY_SUPPORT) { 2612 if (sc->quirks & SONY_BATTERY_SUPPORT)
2551 hid_hw_close(hdev);
2552 sony_battery_remove(sc); 2613 sony_battery_remove(sc);
2553 } 2614
2615 if (sc->touchpad)
2616 sony_unregister_touchpad(sc);
2554 2617
2555 sony_cancel_work_sync(sc); 2618 sony_cancel_work_sync(sc);
2556 2619