Skip to content

Commit bcba9f3

Browse files
DanielOgorchockJiri Kosina
authored andcommitted
HID: nintendo: prevent rumble queue overruns
Make sure that we never throw out the most recent rumble setting, opting to overwrite the prior queue head instead. This prevents instances where we could get rumble stuck on if there were an overrun at the wrong time. Signed-off-by: Daniel J. Ogorchock <[email protected]> Reviewed-by: Silvan Jegen <[email protected] Signed-off-by: Jiri Kosina <[email protected]>
1 parent 2653e3f commit bcba9f3

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

drivers/hid/hid-nintendo.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,6 +1527,7 @@ static int joycon_set_rumble(struct joycon_ctlr *ctlr, u16 amp_r, u16 amp_l,
15271527
u16 freq_l_low;
15281528
u16 freq_l_high;
15291529
unsigned long flags;
1530+
int next_rq_head;
15301531

15311532
spin_lock_irqsave(&ctlr->lock, flags);
15321533
freq_r_low = ctlr->rumble_rl_freq;
@@ -1547,8 +1548,21 @@ static int joycon_set_rumble(struct joycon_ctlr *ctlr, u16 amp_r, u16 amp_l,
15471548
joycon_encode_rumble(data, freq_l_low, freq_l_high, amp);
15481549

15491550
spin_lock_irqsave(&ctlr->lock, flags);
1550-
if (++ctlr->rumble_queue_head >= JC_RUMBLE_QUEUE_SIZE)
1551-
ctlr->rumble_queue_head = 0;
1551+
1552+
next_rq_head = ctlr->rumble_queue_head + 1;
1553+
if (next_rq_head >= JC_RUMBLE_QUEUE_SIZE)
1554+
next_rq_head = 0;
1555+
1556+
/* Did we overrun the circular buffer?
1557+
* If so, be sure we keep the latest intended rumble state.
1558+
*/
1559+
if (next_rq_head == ctlr->rumble_queue_tail) {
1560+
hid_dbg(ctlr->hdev, "rumble queue is full");
1561+
/* overwrite the prior value at the end of the circular buf */
1562+
next_rq_head = ctlr->rumble_queue_head;
1563+
}
1564+
1565+
ctlr->rumble_queue_head = next_rq_head;
15521566
memcpy(ctlr->rumble_data[ctlr->rumble_queue_head], data,
15531567
JC_RUMBLE_DATA_SIZE);
15541568

@@ -2128,7 +2142,7 @@ static int nintendo_hid_probe(struct hid_device *hdev,
21282142

21292143
ctlr->hdev = hdev;
21302144
ctlr->ctlr_state = JOYCON_CTLR_STATE_INIT;
2131-
ctlr->rumble_queue_head = JC_RUMBLE_QUEUE_SIZE - 1;
2145+
ctlr->rumble_queue_head = 0;
21322146
ctlr->rumble_queue_tail = 0;
21332147
hid_set_drvdata(hdev, ctlr);
21342148
mutex_init(&ctlr->output_mutex);

0 commit comments

Comments
 (0)