@@ -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)
546556static 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
561598static 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
0 commit comments