Skip to content

Commit c36ef91

Browse files
committed
xpadneo, rumble: Do not send rumble commands unless ready
We shouldn't allow games to run rumble commands until we are actually fully initialized. This allows us to announce rumble support early now which may fix some rare racing with SDL rumble support. We can now run rumble tests while a concurrent application already queries rumble or sends rumble commands, and only then enable the worker and hardware access. Fixes: #387 Fixes: #444 Signed-off-by: Kai Krakow <kai@kaishome.de>
1 parent c28b4e1 commit c36ef91

2 files changed

Lines changed: 30 additions & 6 deletions

File tree

hid-xpadneo/src/xpadneo/rumble.c

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <linux/delay.h>
1111
#include <linux/module.h>
12+
#include <linux/smp.h>
1213

1314
#include "xpadneo.h"
1415
#include "helpers.h"
@@ -87,6 +88,10 @@ static void rumble_worker(struct work_struct *work)
8788
/* let our scheduler know we've been called */
8889
xdata->rumble.scheduled = false;
8990

91+
/* only proceed once initialization data is globally visible */
92+
if (unlikely(!smp_load_acquire(&xdata->rumble.enabled)))
93+
return;
94+
9095
if (unlikely(xdata->quirks & XPADNEO_QUIRK_NO_TRIGGER_RUMBLE)) {
9196
/* do not send these bits if not supported */
9297
r->data.enable &= ~XBOX_RUMBLE_TRIGGERS;
@@ -161,7 +166,11 @@ static int rumble_play(struct input_dev *dev, void *data, struct ff_effect *effe
161166
struct hid_device *hdev = input_get_drvdata(dev);
162167
struct xpadneo_devdata *xdata = hid_get_drvdata(hdev);
163168

164-
if (effect->type != FF_RUMBLE)
169+
/* do not let FF clients run before rumble state is ready */
170+
if (unlikely(!smp_load_acquire(&xdata->rumble.enabled)))
171+
return 0;
172+
173+
if (unlikely(effect->type != FF_RUMBLE))
165174
return 0;
166175

167176
/* copy data from effect structure at the very beginning */
@@ -343,6 +352,10 @@ int xpadneo_rumble_init(struct hid_device *hdev)
343352
{
344353
struct xpadneo_devdata *xdata = hid_get_drvdata(hdev);
345354
struct input_dev *gamepad = xdata->gamepad.idev;
355+
int ret;
356+
357+
/* publish that rumble is not ready until init finishes */
358+
smp_store_release(&xdata->rumble.enabled, false);
346359

347360
spin_lock_init(&xdata->rumble.lock);
348361
INIT_DELAYED_WORK(&xdata->rumble.worker, rumble_worker);
@@ -355,14 +368,22 @@ int xpadneo_rumble_init(struct hid_device *hdev)
355368
if (param_trigger_rumble_mode == PARAM_TRIGGER_RUMBLE_DISABLE)
356369
xdata->quirks |= XPADNEO_QUIRK_NO_TRIGGER_RUMBLE;
357370

358-
if (param_ff_connect_notify)
359-
xpadneo_benchmark(rumble_welcome, hdev);
360-
361371
/* initialize our rumble command throttle */
362372
xdata->rumble.throttle_until = RUMBLE_THROTTLE_JIFFIES;
363373

374+
/* set capabilities */
364375
input_set_capability(gamepad, EV_FF, FF_RUMBLE);
365-
return input_ff_create_memless(gamepad, NULL, rumble_play);
376+
ret = input_ff_create_memless(gamepad, NULL, rumble_play);
377+
if (ret)
378+
return ret;
379+
380+
if (param_ff_connect_notify)
381+
xpadneo_benchmark(rumble_welcome, hdev);
382+
383+
/* publish readiness once all rumble state is initialized */
384+
smp_store_release(&xdata->rumble.enabled, true);
385+
386+
return 0;
366387
}
367388

368389
int xpadneo_rumble_init_workqueue(void)
@@ -385,5 +406,8 @@ void xpadneo_rumble_destroy_workqueue(void)
385406

386407
void xpadneo_rumble_remove(struct xpadneo_devdata *xdata)
387408
{
409+
/* disable rumble before removable to prevent queueing new data */
410+
smp_store_release(&xdata->rumble.enabled, false);
411+
388412
cancel_delayed_work_sync(&xdata->rumble.worker);
389413
}

hid-xpadneo/src/xpadneo/xpadneo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ struct xpadneo_devdata {
173173
spinlock_t lock;
174174
struct delayed_work worker;
175175
unsigned long throttle_until;
176-
bool scheduled;
176+
bool scheduled, enabled;
177177
struct xpadneo_rumble_data data;
178178
struct xpadneo_rumble_data shadow;
179179
void *output_report_dmabuf;

0 commit comments

Comments
 (0)