summaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-playstation.c
diff options
context:
space:
mode:
authorRoderick Colenbrander <roderick@gaikai.com>2022-10-29 11:48:50 -0700
committerJiri Kosina <jkosina@suse.cz>2022-11-11 11:07:09 +0100
commit58feecb4172b49ad1459e57556667a59df5bdda2 (patch)
tree4876a343cbe39dea75ab9ad71bbcfa4fa8b36e16 /drivers/hid/hid-playstation.c
parent2d77474a239294786feb4fe9864c845fe92db239 (diff)
downloadlinux-stable-58feecb4172b49ad1459e57556667a59df5bdda2.tar.gz
linux-stable-58feecb4172b49ad1459e57556667a59df5bdda2.tar.bz2
linux-stable-58feecb4172b49ad1459e57556667a59df5bdda2.zip
HID: playstation: set default DualShock4 BT poll interval to 4ms.
The poll interval for DualShock4 in Bluetooth mode is adjustable through the main output report. Configure it to 4ms, which is similar to USB. Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-playstation.c')
-rw-r--r--drivers/hid/hid-playstation.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c
index a2f1bd1400a2..05553d07cb1b 100644
--- a/drivers/hid/hid-playstation.c
+++ b/drivers/hid/hid-playstation.c
@@ -316,6 +316,17 @@ struct dualsense_output_report {
/* Battery status within batery_status field. */
#define DS4_BATTERY_STATUS_FULL 11
+/* The lower 6 bits of hw_control of the Bluetooth main output report
+ * control the interval at which Dualshock 4 reports data:
+ * 0x00 - 1ms
+ * 0x01 - 1ms
+ * 0x02 - 2ms
+ * 0x3E - 62ms
+ * 0x3F - disabled
+ */
+#define DS4_OUTPUT_HWCTL_BT_POLL_MASK 0x3F
+/* Default to 4ms poll interval, which is same as USB (not adjustable). */
+#define DS4_BT_DEFAULT_POLL_INTERVAL_MS 4
#define DS4_OUTPUT_HWCTL_CRC32 0x40
#define DS4_OUTPUT_HWCTL_HID 0x80
@@ -348,6 +359,10 @@ struct dualshock4 {
uint32_t prev_sensor_timestamp;
uint32_t sensor_timestamp_us;
+ /* Bluetooth poll interval */
+ bool update_bt_poll_interval;
+ uint8_t bt_poll_interval;
+
bool update_rumble;
uint8_t motor_left;
uint8_t motor_right;
@@ -2010,6 +2025,11 @@ static void dualshock4_output_worker(struct work_struct *work)
*/
report.bt->hw_control = DS4_OUTPUT_HWCTL_HID | DS4_OUTPUT_HWCTL_CRC32;
+ if (ds4->update_bt_poll_interval) {
+ report.bt->hw_control |= ds4->bt_poll_interval;
+ ds4->update_bt_poll_interval = false;
+ }
+
crc = crc32_le(0xFFFFFFFF, &seed, 1);
crc = ~crc32_le(crc, report.data, report.len - 4);
@@ -2241,6 +2261,13 @@ static inline void dualshock4_schedule_work(struct dualshock4 *ds4)
spin_unlock_irqrestore(&ds4->base.lock, flags);
}
+static void dualshock4_set_bt_poll_interval(struct dualshock4 *ds4, uint8_t interval)
+{
+ ds4->bt_poll_interval = interval;
+ ds4->update_bt_poll_interval = true;
+ dualshock4_schedule_work(ds4);
+}
+
/* Set default lightbar color based on player. */
static void dualshock4_set_default_lightbar_colors(struct dualshock4 *ds4)
{
@@ -2372,6 +2399,8 @@ static struct ps_device *dualshock4_create(struct hid_device *hdev)
goto err;
}
+ dualshock4_set_bt_poll_interval(ds4, DS4_BT_DEFAULT_POLL_INTERVAL_MS);
+
ret = ps_device_set_player_id(ps_dev);
if (ret) {
hid_err(hdev, "Failed to assign player id for DualShock4: %d\n", ret);