diff options
author | Roderick Colenbrander <roderick.colenbrander@sony.com> | 2017-03-07 18:45:10 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2017-03-21 10:12:07 -0400 |
commit | 510c8b7c168bcad75e2864f73e5125d7218ee3cf (patch) | |
tree | 37a6858d485438a40eb86806fafec3ccdcebba16 /drivers/hid | |
parent | 80ecc48c0ade5e99cc9d84febd17c44a4f011c13 (diff) |
HID: sony: Expose DS3 motion sensors through separate device
This patch adds a separate evdev node for the DS3 its motion
sensors. We only expose the accelerometers as the gyroscope
is extremely difficult to manage and behavior varies a lot
between hardware revisions.
Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/hid-sony.c | 130 |
1 files changed, 105 insertions, 25 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index fa2ea085fec8..d8a13081701f 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
@@ -547,12 +547,15 @@ struct motion_output_report_02 { | |||
547 | #define DS4_INPUT_REPORT_BATTERY_OFFSET 30 | 547 | #define DS4_INPUT_REPORT_BATTERY_OFFSET 30 |
548 | #define DS4_INPUT_REPORT_TOUCHPAD_OFFSET 33 | 548 | #define DS4_INPUT_REPORT_TOUCHPAD_OFFSET 33 |
549 | 549 | ||
550 | #define DS4_SENSOR_SUFFIX " Motion Sensors" | 550 | #define SENSOR_SUFFIX " Motion Sensors" |
551 | #define DS4_TOUCHPAD_SUFFIX " Touchpad" | 551 | #define DS4_TOUCHPAD_SUFFIX " Touchpad" |
552 | 552 | ||
553 | #define DS4_GYRO_RES_PER_DEG_S 1024 | 553 | #define DS4_GYRO_RES_PER_DEG_S 1024 |
554 | #define DS4_ACC_RES_PER_G 8192 | 554 | #define DS4_ACC_RES_PER_G 8192 |
555 | 555 | ||
556 | #define SIXAXIS_INPUT_REPORT_ACC_X_OFFSET 41 | ||
557 | #define SIXAXIS_ACC_RES_PER_G 113 | ||
558 | |||
556 | static DEFINE_SPINLOCK(sony_dev_list_lock); | 559 | static DEFINE_SPINLOCK(sony_dev_list_lock); |
557 | static LIST_HEAD(sony_device_list); | 560 | static LIST_HEAD(sony_device_list); |
558 | static DEFINE_IDA(sony_device_id_allocator); | 561 | static DEFINE_IDA(sony_device_id_allocator); |
@@ -841,6 +844,23 @@ static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size) | |||
841 | sc->battery_capacity = battery_capacity; | 844 | sc->battery_capacity = battery_capacity; |
842 | sc->battery_charging = battery_charging; | 845 | sc->battery_charging = battery_charging; |
843 | spin_unlock_irqrestore(&sc->lock, flags); | 846 | spin_unlock_irqrestore(&sc->lock, flags); |
847 | |||
848 | if (sc->quirks & SIXAXIS_CONTROLLER) { | ||
849 | int val; | ||
850 | |||
851 | offset = SIXAXIS_INPUT_REPORT_ACC_X_OFFSET; | ||
852 | val = ((rd[offset+1] << 8) | rd[offset]) - 511; | ||
853 | input_report_abs(sc->sensor_dev, ABS_X, val); | ||
854 | |||
855 | /* Y and Z are swapped and inversed */ | ||
856 | val = 511 - ((rd[offset+5] << 8) | rd[offset+4]); | ||
857 | input_report_abs(sc->sensor_dev, ABS_Y, val); | ||
858 | |||
859 | val = 511 - ((rd[offset+3] << 8) | rd[offset+2]); | ||
860 | input_report_abs(sc->sensor_dev, ABS_Z, val); | ||
861 | |||
862 | input_sync(sc->sensor_dev); | ||
863 | } | ||
844 | } | 864 | } |
845 | 865 | ||
846 | static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) | 866 | static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) |
@@ -1285,33 +1305,49 @@ static int sony_register_sensors(struct sony_sc *sc) | |||
1285 | /* Append a suffix to the controller name as there are various | 1305 | /* Append a suffix to the controller name as there are various |
1286 | * DS4 compatible non-Sony devices with different names. | 1306 | * DS4 compatible non-Sony devices with different names. |
1287 | */ | 1307 | */ |
1288 | name_sz = strlen(sc->hdev->name) + sizeof(DS4_SENSOR_SUFFIX); | 1308 | name_sz = strlen(sc->hdev->name) + sizeof(SENSOR_SUFFIX); |
1289 | name = kzalloc(name_sz, GFP_KERNEL); | 1309 | name = kzalloc(name_sz, GFP_KERNEL); |
1290 | if (!name) { | 1310 | if (!name) { |
1291 | ret = -ENOMEM; | 1311 | ret = -ENOMEM; |
1292 | goto err; | 1312 | goto err; |
1293 | } | 1313 | } |
1294 | snprintf(name, name_sz, "%s" DS4_SENSOR_SUFFIX, sc->hdev->name); | 1314 | snprintf(name, name_sz, "%s" SENSOR_SUFFIX, sc->hdev->name); |
1295 | sc->sensor_dev->name = name; | 1315 | sc->sensor_dev->name = name; |
1296 | 1316 | ||
1297 | range = DS4_ACC_RES_PER_G*4; | 1317 | if (sc->quirks & SIXAXIS_CONTROLLER) { |
1298 | input_set_abs_params(sc->sensor_dev, ABS_X, -range, range, 16, 0); | 1318 | /* For the DS3 we only support the accelerometer, which works |
1299 | input_set_abs_params(sc->sensor_dev, ABS_Y, -range, range, 16, 0); | 1319 | * quite well even without calibration. The device also has |
1300 | input_set_abs_params(sc->sensor_dev, ABS_Z, -range, range, 16, 0); | 1320 | * a 1-axis gyro, but it is very difficult to manage from within |
1301 | input_abs_set_res(sc->sensor_dev, ABS_X, DS4_ACC_RES_PER_G); | 1321 | * the driver even to get data, the sensor is inaccurate and |
1302 | input_abs_set_res(sc->sensor_dev, ABS_Y, DS4_ACC_RES_PER_G); | 1322 | * the behavior is very different between hardware revisions. |
1303 | input_abs_set_res(sc->sensor_dev, ABS_Z, DS4_ACC_RES_PER_G); | 1323 | */ |
1304 | 1324 | input_set_abs_params(sc->sensor_dev, ABS_X, -512, 511, 4, 0); | |
1305 | range = DS4_GYRO_RES_PER_DEG_S*2048; | 1325 | input_set_abs_params(sc->sensor_dev, ABS_Y, -512, 511, 4, 0); |
1306 | input_set_abs_params(sc->sensor_dev, ABS_RX, -range, range, 16, 0); | 1326 | input_set_abs_params(sc->sensor_dev, ABS_Z, -512, 511, 4, 0); |
1307 | input_set_abs_params(sc->sensor_dev, ABS_RY, -range, range, 16, 0); | 1327 | input_abs_set_res(sc->sensor_dev, ABS_X, SIXAXIS_ACC_RES_PER_G); |
1308 | input_set_abs_params(sc->sensor_dev, ABS_RZ, -range, range, 16, 0); | 1328 | input_abs_set_res(sc->sensor_dev, ABS_Y, SIXAXIS_ACC_RES_PER_G); |
1309 | input_abs_set_res(sc->sensor_dev, ABS_RX, DS4_GYRO_RES_PER_DEG_S); | 1329 | input_abs_set_res(sc->sensor_dev, ABS_Z, SIXAXIS_ACC_RES_PER_G); |
1310 | input_abs_set_res(sc->sensor_dev, ABS_RY, DS4_GYRO_RES_PER_DEG_S); | 1330 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { |
1311 | input_abs_set_res(sc->sensor_dev, ABS_RZ, DS4_GYRO_RES_PER_DEG_S); | 1331 | range = DS4_ACC_RES_PER_G*4; |
1312 | 1332 | input_set_abs_params(sc->sensor_dev, ABS_X, -range, range, 16, 0); | |
1313 | __set_bit(EV_MSC, sc->sensor_dev->evbit); | 1333 | input_set_abs_params(sc->sensor_dev, ABS_Y, -range, range, 16, 0); |
1314 | __set_bit(MSC_TIMESTAMP, sc->sensor_dev->mscbit); | 1334 | input_set_abs_params(sc->sensor_dev, ABS_Z, -range, range, 16, 0); |
1335 | input_abs_set_res(sc->sensor_dev, ABS_X, DS4_ACC_RES_PER_G); | ||
1336 | input_abs_set_res(sc->sensor_dev, ABS_Y, DS4_ACC_RES_PER_G); | ||
1337 | input_abs_set_res(sc->sensor_dev, ABS_Z, DS4_ACC_RES_PER_G); | ||
1338 | |||
1339 | range = DS4_GYRO_RES_PER_DEG_S*2048; | ||
1340 | input_set_abs_params(sc->sensor_dev, ABS_RX, -range, range, 16, 0); | ||
1341 | input_set_abs_params(sc->sensor_dev, ABS_RY, -range, range, 16, 0); | ||
1342 | input_set_abs_params(sc->sensor_dev, ABS_RZ, -range, range, 16, 0); | ||
1343 | input_abs_set_res(sc->sensor_dev, ABS_RX, DS4_GYRO_RES_PER_DEG_S); | ||
1344 | input_abs_set_res(sc->sensor_dev, ABS_RY, DS4_GYRO_RES_PER_DEG_S); | ||
1345 | input_abs_set_res(sc->sensor_dev, ABS_RZ, DS4_GYRO_RES_PER_DEG_S); | ||
1346 | |||
1347 | __set_bit(EV_MSC, sc->sensor_dev->evbit); | ||
1348 | __set_bit(MSC_TIMESTAMP, sc->sensor_dev->mscbit); | ||
1349 | } | ||
1350 | |||
1315 | __set_bit(INPUT_PROP_ACCELEROMETER, sc->sensor_dev->propbit); | 1351 | __set_bit(INPUT_PROP_ACCELEROMETER, sc->sensor_dev->propbit); |
1316 | 1352 | ||
1317 | ret = input_register_device(sc->sensor_dev); | 1353 | ret = input_register_device(sc->sensor_dev); |
@@ -2447,8 +2483,7 @@ static int sony_input_configured(struct hid_device *hdev, | |||
2447 | goto err_stop; | 2483 | goto err_stop; |
2448 | } | 2484 | } |
2449 | 2485 | ||
2450 | if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || | 2486 | if (sc->quirks & NAVIGATION_CONTROLLER_USB) { |
2451 | (sc->quirks & NAVIGATION_CONTROLLER_USB)) { | ||
2452 | /* | 2487 | /* |
2453 | * The Sony Sixaxis does not handle HID Output Reports on the | 2488 | * The Sony Sixaxis does not handle HID Output Reports on the |
2454 | * Interrupt EP like it could, so we need to force HID Output | 2489 | * Interrupt EP like it could, so we need to force HID Output |
@@ -2476,8 +2511,46 @@ static int sony_input_configured(struct hid_device *hdev, | |||
2476 | } | 2511 | } |
2477 | 2512 | ||
2478 | sony_init_output_report(sc, sixaxis_send_output_report); | 2513 | sony_init_output_report(sc, sixaxis_send_output_report); |
2479 | } else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) || | 2514 | } else if (sc->quirks & NAVIGATION_CONTROLLER_BT) { |
2480 | (sc->quirks & NAVIGATION_CONTROLLER_BT)) { | 2515 | /* |
2516 | * The Navigation controller wants output reports sent on the ctrl | ||
2517 | * endpoint when connected via Bluetooth. | ||
2518 | */ | ||
2519 | hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; | ||
2520 | |||
2521 | ret = sixaxis_set_operational_bt(hdev); | ||
2522 | if (ret < 0) { | ||
2523 | hid_err(hdev, "Failed to set controller into operational mode\n"); | ||
2524 | goto err_stop; | ||
2525 | } | ||
2526 | |||
2527 | sony_init_output_report(sc, sixaxis_send_output_report); | ||
2528 | } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) { | ||
2529 | /* | ||
2530 | * The Sony Sixaxis does not handle HID Output Reports on the | ||
2531 | * Interrupt EP and the device only becomes active when the | ||
2532 | * PS button is pressed. See comment for Navigation controller | ||
2533 | * above for more details. | ||
2534 | */ | ||
2535 | hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; | ||
2536 | hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; | ||
2537 | sc->defer_initialization = 1; | ||
2538 | |||
2539 | ret = sixaxis_set_operational_usb(hdev); | ||
2540 | if (ret < 0) { | ||
2541 | hid_err(hdev, "Failed to set controller into operational mode\n"); | ||
2542 | goto err_stop; | ||
2543 | } | ||
2544 | |||
2545 | ret = sony_register_sensors(sc); | ||
2546 | if (ret) { | ||
2547 | hid_err(sc->hdev, | ||
2548 | "Unable to initialize motion sensors: %d\n", ret); | ||
2549 | goto err_stop; | ||
2550 | } | ||
2551 | |||
2552 | sony_init_output_report(sc, sixaxis_send_output_report); | ||
2553 | } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) { | ||
2481 | /* | 2554 | /* |
2482 | * The Sixaxis wants output reports sent on the ctrl endpoint | 2555 | * The Sixaxis wants output reports sent on the ctrl endpoint |
2483 | * when connected via Bluetooth. | 2556 | * when connected via Bluetooth. |
@@ -2490,6 +2563,13 @@ static int sony_input_configured(struct hid_device *hdev, | |||
2490 | goto err_stop; | 2563 | goto err_stop; |
2491 | } | 2564 | } |
2492 | 2565 | ||
2566 | ret = sony_register_sensors(sc); | ||
2567 | if (ret) { | ||
2568 | hid_err(sc->hdev, | ||
2569 | "Unable to initialize motion sensors: %d\n", ret); | ||
2570 | goto err_stop; | ||
2571 | } | ||
2572 | |||
2493 | sony_init_output_report(sc, sixaxis_send_output_report); | 2573 | sony_init_output_report(sc, sixaxis_send_output_report); |
2494 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { | 2574 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { |
2495 | ret = dualshock4_get_calibration_data(sc); | 2575 | ret = dualshock4_get_calibration_data(sc); |