aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoderick Colenbrander <roderick.colenbrander@sony.com>2017-03-24 18:17:49 -0400
committerJiri Kosina <jkosina@suse.cz>2017-04-06 08:41:17 -0400
commit77b499e739ed5561e5026fa7140ae53f6c4d1d8e (patch)
tree7ed7d966a6ae043dfdf7338feb525f70d9437eac
parent5caceb0695d0498b8c931cbc3cdafd99bd37b8ae (diff)
HID: sony: Make DS4 bt poll interval adjustable
By default when using bluetooth the DS4 reports data at about 1kHz, which is quite fast especially on weak devices. We now make the device use the USB poll interval, which is a fixed 4ms. In addition we make the value adjustable through sysfs. The error handling in sony_input_configured is a little tricky. It is not easy to add other goto's as not all codepaths have logic for adding this attribute. Luckily we are setting the value for the attribute to a default value, so we can use that to detect if we need to remove the file. Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-sony.c79
1 files changed, 69 insertions, 10 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 107aae9627bc..444a3f04f047 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -493,6 +493,9 @@ struct motion_output_report_02 {
493#define SENSOR_SUFFIX " Motion Sensors" 493#define SENSOR_SUFFIX " Motion Sensors"
494#define DS4_TOUCHPAD_SUFFIX " Touchpad" 494#define DS4_TOUCHPAD_SUFFIX " Touchpad"
495 495
496/* Default to 4ms poll interval, which is same as USB (not adjustable). */
497#define DS4_BT_DEFAULT_POLL_INTERVAL_MS 4
498#define DS4_BT_MAX_POLL_INTERVAL_MS 62
496#define DS4_GYRO_RES_PER_DEG_S 1024 499#define DS4_GYRO_RES_PER_DEG_S 1024
497#define DS4_ACC_RES_PER_G 8192 500#define DS4_ACC_RES_PER_G 8192
498 501
@@ -564,6 +567,7 @@ struct sony_sc {
564 u16 prev_timestamp; 567 u16 prev_timestamp;
565 unsigned int timestamp_us; 568 unsigned int timestamp_us;
566 569
570 u8 ds4_bt_poll_interval;
567 enum ds4_dongle_state ds4_dongle_state; 571 enum ds4_dongle_state ds4_dongle_state;
568 /* DS4 calibration data */ 572 /* DS4 calibration data */
569 struct ds4_calibration_data ds4_calib_data[6]; 573 struct ds4_calibration_data ds4_calib_data[6];
@@ -586,6 +590,44 @@ static inline void sony_schedule_work(struct sony_sc *sc,
586 } 590 }
587} 591}
588 592
593static ssize_t ds4_show_poll_interval(struct device *dev,
594 struct device_attribute
595 *attr, char *buf)
596{
597 struct hid_device *hdev = to_hid_device(dev);
598 struct sony_sc *sc = hid_get_drvdata(hdev);
599
600 return snprintf(buf, PAGE_SIZE, "%i\n", sc->ds4_bt_poll_interval);
601}
602
603static ssize_t ds4_store_poll_interval(struct device *dev,
604 struct device_attribute *attr,
605 const char *buf, size_t count)
606{
607 struct hid_device *hdev = to_hid_device(dev);
608 struct sony_sc *sc = hid_get_drvdata(hdev);
609 unsigned long flags;
610 u8 interval;
611
612 if (kstrtou8(buf, 0, &interval))
613 return -EINVAL;
614
615 if (interval > DS4_BT_MAX_POLL_INTERVAL_MS)
616 return -EINVAL;
617
618 spin_lock_irqsave(&sc->lock, flags);
619 sc->ds4_bt_poll_interval = interval;
620 spin_unlock_irqrestore(&sc->lock, flags);
621
622 sony_schedule_work(sc, SONY_WORKER_STATE);
623
624 return count;
625}
626
627static DEVICE_ATTR(bt_poll_interval, 0644, ds4_show_poll_interval,
628 ds4_store_poll_interval);
629
630
589static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc, 631static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
590 unsigned int *rsize) 632 unsigned int *rsize)
591{ 633{
@@ -1985,15 +2027,13 @@ static void dualshock4_send_output_report(struct sony_sc *sc)
1985 int offset; 2027 int offset;
1986 2028
1987 /* 2029 /*
1988 * NOTE: The buf[1] field of the Bluetooth report controls 2030 * NOTE: The lower 6 bits of buf[1] field of the Bluetooth report
1989 * the Dualshock 4 reporting rate. 2031 * control the interval at which Dualshock 4 reports data:
1990 * 2032 * 0x00 - 1ms
1991 * Known values include: 2033 * 0x01 - 1ms
1992 * 2034 * 0x02 - 2ms
1993 * 0x80 - 1000hz (full speed) 2035 * 0x3E - 62ms
1994 * 0xA0 - 31hz 2036 * 0x3F - disabled
1995 * 0xB0 - 20hz
1996 * 0xD0 - 66hz
1997 */ 2037 */
1998 if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) { 2038 if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) {
1999 memset(buf, 0, DS4_OUTPUT_REPORT_0x05_SIZE); 2039 memset(buf, 0, DS4_OUTPUT_REPORT_0x05_SIZE);
@@ -2003,7 +2043,7 @@ static void dualshock4_send_output_report(struct sony_sc *sc)
2003 } else { 2043 } else {
2004 memset(buf, 0, DS4_OUTPUT_REPORT_0x11_SIZE); 2044 memset(buf, 0, DS4_OUTPUT_REPORT_0x11_SIZE);
2005 buf[0] = 0x11; 2045 buf[0] = 0x11;
2006 buf[1] = 0xC0; /* HID + CRC */ 2046 buf[1] = 0xC0 /* HID + CRC */ | sc->ds4_bt_poll_interval;
2007 buf[3] = 0x07; /* blink + LEDs + motor */ 2047 buf[3] = 0x07; /* blink + LEDs + motor */
2008 offset = 6; 2048 offset = 6;
2009 } 2049 }
@@ -2454,6 +2494,7 @@ static inline void sony_cancel_work_sync(struct sony_sc *sc)
2454 cancel_work_sync(&sc->state_worker); 2494 cancel_work_sync(&sc->state_worker);
2455} 2495}
2456 2496
2497
2457static int sony_input_configured(struct hid_device *hdev, 2498static int sony_input_configured(struct hid_device *hdev,
2458 struct hid_input *hidinput) 2499 struct hid_input *hidinput)
2459{ 2500{
@@ -2591,6 +2632,15 @@ static int sony_input_configured(struct hid_device *hdev,
2591 goto err_stop; 2632 goto err_stop;
2592 } 2633 }
2593 2634
2635 if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
2636 sc->ds4_bt_poll_interval = DS4_BT_DEFAULT_POLL_INTERVAL_MS;
2637 ret = device_create_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
2638 if (ret)
2639 hid_warn(sc->hdev,
2640 "can't create sysfs bt_poll_interval attribute err: %d\n",
2641 ret);
2642 }
2643
2594 if (sc->quirks & DUALSHOCK4_DONGLE) { 2644 if (sc->quirks & DUALSHOCK4_DONGLE) {
2595 INIT_WORK(&sc->hotplug_worker, dualshock4_calibration_work); 2645 INIT_WORK(&sc->hotplug_worker, dualshock4_calibration_work);
2596 sc->hotplug_worker_initialized = 1; 2646 sc->hotplug_worker_initialized = 1;
@@ -2636,6 +2686,12 @@ static int sony_input_configured(struct hid_device *hdev,
2636err_close: 2686err_close:
2637 hid_hw_close(hdev); 2687 hid_hw_close(hdev);
2638err_stop: 2688err_stop:
2689 /* Piggy back on the default ds4_bt_ poll_interval to determine
2690 * if we need to remove the file as we don't know for sure if we
2691 * executed that logic.
2692 */
2693 if (sc->ds4_bt_poll_interval)
2694 device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
2639 if (sc->quirks & SONY_LED_SUPPORT) 2695 if (sc->quirks & SONY_LED_SUPPORT)
2640 sony_leds_remove(sc); 2696 sony_leds_remove(sc);
2641 if (sc->quirks & SONY_BATTERY_SUPPORT) 2697 if (sc->quirks & SONY_BATTERY_SUPPORT)
@@ -2733,6 +2789,9 @@ static void sony_remove(struct hid_device *hdev)
2733 if (sc->sensor_dev) 2789 if (sc->sensor_dev)
2734 sony_unregister_sensors(sc); 2790 sony_unregister_sensors(sc);
2735 2791
2792 if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
2793 device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
2794
2736 sony_cancel_work_sync(sc); 2795 sony_cancel_work_sync(sc);
2737 2796
2738 kfree(sc->output_report_dmabuf); 2797 kfree(sc->output_report_dmabuf);