Skip to content

Commit 67471b8

Browse files
author
Jiri Kosina
committed
Merge branch 'for-6.4/nintendo' into for-linus
- drastically reducing Bluetooth disconnects on hid-nintendo driven devices (Daniel J. Ogorchock) - proper rumble queue overrun handling (Daniel J. Ogorchock)
2 parents 5fce154 + d750d14 commit 67471b8

File tree

1 file changed

+86
-9
lines changed

1 file changed

+86
-9
lines changed

drivers/hid/hid-nintendo.c

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,9 @@ struct joycon_ctlr {
433433
u8 usb_ack_match;
434434
u8 subcmd_ack_match;
435435
bool received_input_report;
436+
unsigned int last_input_report_msecs;
436437
unsigned int last_subcmd_sent_msecs;
438+
unsigned int consecutive_valid_report_deltas;
437439

438440
/* factory calibration data */
439441
struct joycon_stick_cal left_stick_cal_x;
@@ -543,19 +545,54 @@ static void joycon_wait_for_input_report(struct joycon_ctlr *ctlr)
543545
* Sending subcommands and/or rumble data at too high a rate can cause bluetooth
544546
* controller disconnections.
545547
*/
548+
#define JC_INPUT_REPORT_MIN_DELTA 8
549+
#define JC_INPUT_REPORT_MAX_DELTA 17
550+
#define JC_SUBCMD_TX_OFFSET_MS 4
551+
#define JC_SUBCMD_VALID_DELTA_REQ 3
552+
#define JC_SUBCMD_RATE_MAX_ATTEMPTS 500
553+
#define JC_SUBCMD_RATE_LIMITER_USB_MS 20
554+
#define JC_SUBCMD_RATE_LIMITER_BT_MS 60
555+
#define JC_SUBCMD_RATE_LIMITER_MS(ctlr) ((ctlr)->hdev->bus == BUS_USB ? JC_SUBCMD_RATE_LIMITER_USB_MS : JC_SUBCMD_RATE_LIMITER_BT_MS)
546556
static void joycon_enforce_subcmd_rate(struct joycon_ctlr *ctlr)
547557
{
548-
static const unsigned int max_subcmd_rate_ms = 25;
549-
unsigned int current_ms = jiffies_to_msecs(jiffies);
550-
unsigned int delta_ms = current_ms - ctlr->last_subcmd_sent_msecs;
558+
unsigned int current_ms;
559+
unsigned long subcmd_delta;
560+
int consecutive_valid_deltas = 0;
561+
int attempts = 0;
562+
unsigned long flags;
563+
564+
if (unlikely(ctlr->ctlr_state != JOYCON_CTLR_STATE_READ))
565+
return;
551566

552-
while (delta_ms < max_subcmd_rate_ms &&
553-
ctlr->ctlr_state == JOYCON_CTLR_STATE_READ) {
567+
do {
554568
joycon_wait_for_input_report(ctlr);
555569
current_ms = jiffies_to_msecs(jiffies);
556-
delta_ms = current_ms - ctlr->last_subcmd_sent_msecs;
570+
subcmd_delta = current_ms - ctlr->last_subcmd_sent_msecs;
571+
572+
spin_lock_irqsave(&ctlr->lock, flags);
573+
consecutive_valid_deltas = ctlr->consecutive_valid_report_deltas;
574+
spin_unlock_irqrestore(&ctlr->lock, flags);
575+
576+
attempts++;
577+
} while ((consecutive_valid_deltas < JC_SUBCMD_VALID_DELTA_REQ ||
578+
subcmd_delta < JC_SUBCMD_RATE_LIMITER_MS(ctlr)) &&
579+
ctlr->ctlr_state == JOYCON_CTLR_STATE_READ &&
580+
attempts < JC_SUBCMD_RATE_MAX_ATTEMPTS);
581+
582+
if (attempts >= JC_SUBCMD_RATE_MAX_ATTEMPTS) {
583+
hid_warn(ctlr->hdev, "%s: exceeded max attempts", __func__);
584+
return;
557585
}
586+
558587
ctlr->last_subcmd_sent_msecs = current_ms;
588+
589+
/*
590+
* Wait a short time after receiving an input report before
591+
* transmitting. This should reduce odds of a TX coinciding with an RX.
592+
* Minimizing concurrent BT traffic with the controller seems to lower
593+
* the rate of disconnections.
594+
*/
595+
msleep(JC_SUBCMD_TX_OFFSET_MS);
559596
}
560597

561598
static int joycon_hid_send_sync(struct joycon_ctlr *ctlr, u8 *data, size_t len,
@@ -1223,6 +1260,7 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
12231260
u8 tmp;
12241261
u32 btns;
12251262
unsigned long msecs = jiffies_to_msecs(jiffies);
1263+
unsigned long report_delta_ms = msecs - ctlr->last_input_report_msecs;
12261264

12271265
spin_lock_irqsave(&ctlr->lock, flags);
12281266
if (IS_ENABLED(CONFIG_NINTENDO_FF) && rep->vibrator_report &&
@@ -1364,6 +1402,31 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
13641402

13651403
input_sync(dev);
13661404

1405+
spin_lock_irqsave(&ctlr->lock, flags);
1406+
ctlr->last_input_report_msecs = msecs;
1407+
/*
1408+
* Was this input report a reasonable time delta compared to the prior
1409+
* report? We use this information to decide when a safe time is to send
1410+
* rumble packets or subcommand packets.
1411+
*/
1412+
if (report_delta_ms >= JC_INPUT_REPORT_MIN_DELTA &&
1413+
report_delta_ms <= JC_INPUT_REPORT_MAX_DELTA) {
1414+
if (ctlr->consecutive_valid_report_deltas < JC_SUBCMD_VALID_DELTA_REQ)
1415+
ctlr->consecutive_valid_report_deltas++;
1416+
} else {
1417+
ctlr->consecutive_valid_report_deltas = 0;
1418+
}
1419+
/*
1420+
* Our consecutive valid report tracking is only relevant for
1421+
* bluetooth-connected controllers. For USB devices, we're beholden to
1422+
* USB's underlying polling rate anyway. Always set to the consecutive
1423+
* delta requirement.
1424+
*/
1425+
if (ctlr->hdev->bus == BUS_USB)
1426+
ctlr->consecutive_valid_report_deltas = JC_SUBCMD_VALID_DELTA_REQ;
1427+
1428+
spin_unlock_irqrestore(&ctlr->lock, flags);
1429+
13671430
/*
13681431
* Immediately after receiving a report is the most reliable time to
13691432
* send a subcommand to the controller. Wake any subcommand senders
@@ -1527,6 +1590,7 @@ static int joycon_set_rumble(struct joycon_ctlr *ctlr, u16 amp_r, u16 amp_l,
15271590
u16 freq_l_low;
15281591
u16 freq_l_high;
15291592
unsigned long flags;
1593+
int next_rq_head;
15301594

15311595
spin_lock_irqsave(&ctlr->lock, flags);
15321596
freq_r_low = ctlr->rumble_rl_freq;
@@ -1547,8 +1611,21 @@ static int joycon_set_rumble(struct joycon_ctlr *ctlr, u16 amp_r, u16 amp_l,
15471611
joycon_encode_rumble(data, freq_l_low, freq_l_high, amp);
15481612

15491613
spin_lock_irqsave(&ctlr->lock, flags);
1550-
if (++ctlr->rumble_queue_head >= JC_RUMBLE_QUEUE_SIZE)
1551-
ctlr->rumble_queue_head = 0;
1614+
1615+
next_rq_head = ctlr->rumble_queue_head + 1;
1616+
if (next_rq_head >= JC_RUMBLE_QUEUE_SIZE)
1617+
next_rq_head = 0;
1618+
1619+
/* Did we overrun the circular buffer?
1620+
* If so, be sure we keep the latest intended rumble state.
1621+
*/
1622+
if (next_rq_head == ctlr->rumble_queue_tail) {
1623+
hid_dbg(ctlr->hdev, "rumble queue is full");
1624+
/* overwrite the prior value at the end of the circular buf */
1625+
next_rq_head = ctlr->rumble_queue_head;
1626+
}
1627+
1628+
ctlr->rumble_queue_head = next_rq_head;
15521629
memcpy(ctlr->rumble_data[ctlr->rumble_queue_head], data,
15531630
JC_RUMBLE_DATA_SIZE);
15541631

@@ -2128,7 +2205,7 @@ static int nintendo_hid_probe(struct hid_device *hdev,
21282205

21292206
ctlr->hdev = hdev;
21302207
ctlr->ctlr_state = JOYCON_CTLR_STATE_INIT;
2131-
ctlr->rumble_queue_head = JC_RUMBLE_QUEUE_SIZE - 1;
2208+
ctlr->rumble_queue_head = 0;
21322209
ctlr->rumble_queue_tail = 0;
21332210
hid_set_drvdata(hdev, ctlr);
21342211
mutex_init(&ctlr->output_mutex);

0 commit comments

Comments
 (0)