mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 13:14:02 +02:00
HID: steam: Coalesce rumble packets
The Steam Deck resets the haptic pattern every time it receives a rumble packet, leading to weird discontinuities or sometimes cutting out entirely. Instead of overloading the interface, Steam interally rate-limits sending these packets, so we should too. Signed-off-by: Vicki Pfau <vi@endrift.com> Signed-off-by: Jiri Kosina <jkosina@suse.com>
This commit is contained in:
parent
2eb7cf02b5
commit
1d4549fd11
|
|
@ -343,6 +343,7 @@ struct steam_device {
|
|||
bool did_mode_switch;
|
||||
bool gamepad_mode;
|
||||
struct work_struct rumble_work;
|
||||
struct delayed_work coalesce_rumble_work;
|
||||
u16 rumble_left;
|
||||
u16 rumble_right;
|
||||
unsigned int sensor_timestamp_us;
|
||||
|
|
@ -603,10 +604,24 @@ static void steam_haptic_rumble_cb(struct work_struct *work)
|
|||
{
|
||||
struct steam_device *steam = container_of(work, struct steam_device,
|
||||
rumble_work);
|
||||
|
||||
steam_haptic_rumble(steam, 0, steam->rumble_left,
|
||||
steam->rumble_right, 2, 0);
|
||||
}
|
||||
|
||||
static void steam_coalesce_rumble_cb(struct work_struct *work)
|
||||
{
|
||||
struct steam_device *steam = container_of(to_delayed_work(work),
|
||||
struct steam_device,
|
||||
coalesce_rumble_work);
|
||||
|
||||
steam_haptic_rumble(steam, 0, steam->rumble_left,
|
||||
steam->rumble_right, 2, 0);
|
||||
|
||||
if (steam->rumble_left || steam->rumble_right)
|
||||
schedule_delayed_work(&steam->coalesce_rumble_work, HZ / 20);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_STEAM_FF
|
||||
static int steam_play_effect(struct input_dev *dev, void *data,
|
||||
struct ff_effect *effect)
|
||||
|
|
@ -616,6 +631,14 @@ static int steam_play_effect(struct input_dev *dev, void *data,
|
|||
steam->rumble_left = effect->u.rumble.strong_magnitude;
|
||||
steam->rumble_right = effect->u.rumble.weak_magnitude;
|
||||
|
||||
/*
|
||||
* The interface gets somewhat overloaded when too many rumble
|
||||
* packets are sent in a row, so Steam throttles it to 20 Hz
|
||||
*/
|
||||
if (delayed_work_pending(&steam->coalesce_rumble_work))
|
||||
return 0;
|
||||
|
||||
schedule_delayed_work(&steam->coalesce_rumble_work, HZ / 20);
|
||||
return schedule_work(&steam->rumble_work);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1360,6 +1383,7 @@ static int steam_probe(struct hid_device *hdev,
|
|||
INIT_DELAYED_WORK(&steam->mode_switch, steam_mode_switch_cb);
|
||||
INIT_LIST_HEAD(&steam->list);
|
||||
INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb);
|
||||
INIT_DELAYED_WORK(&steam->coalesce_rumble_work, steam_coalesce_rumble_cb);
|
||||
steam->sensor_timestamp_us = 0;
|
||||
if (steam->quirks & STEAM_QUIRK_DECK)
|
||||
steam->sensor_update_rate_us = 4000;
|
||||
|
|
@ -1426,6 +1450,7 @@ static int steam_probe(struct hid_device *hdev,
|
|||
cancel_work_sync(&steam->work_connect);
|
||||
cancel_delayed_work_sync(&steam->mode_switch);
|
||||
cancel_work_sync(&steam->rumble_work);
|
||||
cancel_delayed_work_sync(&steam->coalesce_rumble_work);
|
||||
cancel_work_sync(&steam->unregister_work);
|
||||
|
||||
return ret;
|
||||
|
|
@ -1444,6 +1469,7 @@ static void steam_remove(struct hid_device *hdev)
|
|||
cancel_delayed_work_sync(&steam->mode_switch);
|
||||
cancel_work_sync(&steam->work_connect);
|
||||
cancel_work_sync(&steam->rumble_work);
|
||||
cancel_delayed_work_sync(&steam->coalesce_rumble_work);
|
||||
cancel_work_sync(&steam->unregister_work);
|
||||
steam->client_hdev = NULL;
|
||||
steam->client_opened = 0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user