22/*
33 * HID driver for Nintendo Switch Joy-Cons and Pro Controllers
44 *
5- * Copyright (c) 2019-2020 Daniel J. Ogorchock <djogorchock@gmail.com>
5+ * Copyright (c) 2019-2021 Daniel J. Ogorchock <djogorchock@gmail.com>
66 *
77 * The following resources/projects were referenced for this driver:
88 * https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering
@@ -431,6 +431,7 @@ struct joycon_ctlr {
431431 u8 usb_ack_match ;
432432 u8 subcmd_ack_match ;
433433 bool received_input_report ;
434+ unsigned int last_subcmd_sent_msecs ;
434435
435436 /* factory calibration data */
436437 struct joycon_stick_cal left_stick_cal_x ;
@@ -510,6 +511,50 @@ static int __joycon_hid_send(struct hid_device *hdev, u8 *data, size_t len)
510511 return ret ;
511512}
512513
514+ static void joycon_wait_for_input_report (struct joycon_ctlr * ctlr )
515+ {
516+ int ret ;
517+
518+ /*
519+ * If we are in the proper reporting mode, wait for an input
520+ * report prior to sending the subcommand. This improves
521+ * reliability considerably.
522+ */
523+ if (ctlr -> ctlr_state == JOYCON_CTLR_STATE_READ ) {
524+ unsigned long flags ;
525+
526+ spin_lock_irqsave (& ctlr -> lock , flags );
527+ ctlr -> received_input_report = false;
528+ spin_unlock_irqrestore (& ctlr -> lock , flags );
529+ ret = wait_event_timeout (ctlr -> wait ,
530+ ctlr -> received_input_report ,
531+ HZ / 4 );
532+ /* We will still proceed, even with a timeout here */
533+ if (!ret )
534+ hid_warn (ctlr -> hdev ,
535+ "timeout waiting for input report\n" );
536+ }
537+ }
538+
539+ /*
540+ * Sending subcommands and/or rumble data at too high a rate can cause bluetooth
541+ * controller disconnections.
542+ */
543+ static void joycon_enforce_subcmd_rate (struct joycon_ctlr * ctlr )
544+ {
545+ static const unsigned int max_subcmd_rate_ms = 25 ;
546+ unsigned int current_ms = jiffies_to_msecs (jiffies );
547+ unsigned int delta_ms = current_ms - ctlr -> last_subcmd_sent_msecs ;
548+
549+ while (delta_ms < max_subcmd_rate_ms &&
550+ ctlr -> ctlr_state == JOYCON_CTLR_STATE_READ ) {
551+ joycon_wait_for_input_report (ctlr );
552+ current_ms = jiffies_to_msecs (jiffies );
553+ delta_ms = current_ms - ctlr -> last_subcmd_sent_msecs ;
554+ }
555+ ctlr -> last_subcmd_sent_msecs = current_ms ;
556+ }
557+
513558static int joycon_hid_send_sync (struct joycon_ctlr * ctlr , u8 * data , size_t len ,
514559 u32 timeout )
515560{
@@ -521,25 +566,7 @@ static int joycon_hid_send_sync(struct joycon_ctlr *ctlr, u8 *data, size_t len,
521566 * doing one retry after a timeout appears to always work.
522567 */
523568 while (tries -- ) {
524- /*
525- * If we are in the proper reporting mode, wait for an input
526- * report prior to sending the subcommand. This improves
527- * reliability considerably.
528- */
529- if (ctlr -> ctlr_state == JOYCON_CTLR_STATE_READ ) {
530- unsigned long flags ;
531-
532- spin_lock_irqsave (& ctlr -> lock , flags );
533- ctlr -> received_input_report = false;
534- spin_unlock_irqrestore (& ctlr -> lock , flags );
535- ret = wait_event_timeout (ctlr -> wait ,
536- ctlr -> received_input_report ,
537- HZ / 4 );
538- /* We will still proceed, even with a timeout here */
539- if (!ret )
540- hid_warn (ctlr -> hdev ,
541- "timeout waiting for input report\n" );
542- }
569+ joycon_enforce_subcmd_rate (ctlr );
543570
544571 ret = __joycon_hid_send (ctlr -> hdev , data , len );
545572 if (ret < 0 ) {
@@ -1359,6 +1386,8 @@ static int joycon_send_rumble_data(struct joycon_ctlr *ctlr)
13591386 if (++ ctlr -> subcmd_num > 0xF )
13601387 ctlr -> subcmd_num = 0 ;
13611388
1389+ joycon_enforce_subcmd_rate (ctlr );
1390+
13621391 ret = __joycon_hid_send (ctlr -> hdev , (u8 * )& rumble_output ,
13631392 sizeof (rumble_output ));
13641393 return ret ;
0 commit comments