aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorRoderick Colenbrander <roderick.colenbrander@sony.com>2017-03-07 18:45:10 -0500
committerJiri Kosina <jkosina@suse.cz>2017-03-21 10:12:07 -0400
commit510c8b7c168bcad75e2864f73e5125d7218ee3cf (patch)
tree37a6858d485438a40eb86806fafec3ccdcebba16 /drivers/hid
parent80ecc48c0ade5e99cc9d84febd17c44a4f011c13 (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.c130
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
556static DEFINE_SPINLOCK(sony_dev_list_lock); 559static DEFINE_SPINLOCK(sony_dev_list_lock);
557static LIST_HEAD(sony_device_list); 560static LIST_HEAD(sony_device_list);
558static DEFINE_IDA(sony_device_id_allocator); 561static 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
846static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) 866static 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);