@@ -2,7 +2,7 @@
/*
* HID driver for Nintendo Switch Joy-Cons and Pro Controllers
*
- * Copyright (c) 2019-2020 Daniel J. Ogorchock <djogorchock@gmail.com>
+ * Copyright (c) 2019-2021 Daniel J. Ogorchock <djogorchock@gmail.com>
*
* The following resources/projects were referenced for this driver:
* https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering
@@ -511,6 +511,31 @@ static int __joycon_hid_send(struct hid_device *hdev, u8 *data, size_t len)
return ret;
}
+static void joycon_wait_for_input_report(struct joycon_ctlr *ctlr)
+{
+ int ret;
+
+ /*
+ * If we are in the proper reporting mode, wait for an input
+ * report prior to sending the subcommand. This improves
+ * reliability considerably.
+ */
+ if (ctlr->ctlr_state == JOYCON_CTLR_STATE_READ) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&ctlr->lock, flags);
+ ctlr->received_input_report = false;
+ spin_unlock_irqrestore(&ctlr->lock, flags);
+ ret = wait_event_timeout(ctlr->wait,
+ ctlr->received_input_report,
+ HZ / 4);
+ /* We will still proceed, even with a timeout here */
+ if (!ret)
+ hid_warn(ctlr->hdev,
+ "timeout waiting for input report\n");
+ }
+}
+
static int joycon_hid_send_sync(struct joycon_ctlr *ctlr, u8 *data, size_t len,
u32 timeout)
{
@@ -522,25 +547,7 @@ static int joycon_hid_send_sync(struct joycon_ctlr *ctlr, u8 *data, size_t len,
* doing one retry after a timeout appears to always work.
*/
while (tries--) {
- /*
- * If we are in the proper reporting mode, wait for an input
- * report prior to sending the subcommand. This improves
- * reliability considerably.
- */
- if (ctlr->ctlr_state == JOYCON_CTLR_STATE_READ) {
- unsigned long flags;
-
- spin_lock_irqsave(&ctlr->lock, flags);
- ctlr->received_input_report = false;
- spin_unlock_irqrestore(&ctlr->lock, flags);
- ret = wait_event_timeout(ctlr->wait,
- ctlr->received_input_report,
- HZ / 4);
- /* We will still proceed, even with a timeout here */
- if (!ret)
- hid_warn(ctlr->hdev,
- "timeout waiting for input report\n");
- }
+ joycon_wait_for_input_report(ctlr);
ret = __joycon_hid_send(ctlr->hdev, data, len);
if (ret < 0) {
@@ -1379,6 +1386,8 @@ static int joycon_send_rumble_data(struct joycon_ctlr *ctlr)
if (++ctlr->subcmd_num > 0xF)
ctlr->subcmd_num = 0;
+ joycon_wait_for_input_report(ctlr);
+
ret = __joycon_hid_send(ctlr->hdev, (u8 *)&rumble_output,
sizeof(rumble_output));
return ret;
Similar to sending subcommands, it is more reliable to send the rumble data packets immediately after we've received an input report from the controller. This results in far fewer bluetooth disconnects for the controller. Signed-off-by: Daniel J. Ogorchock <djogorchock@gmail.com> --- drivers/hid/hid-nintendo.c | 49 ++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-)