Inter-revision diff: patch 16

Comparing v14 (message) to v16 (message)

--- v14
+++ v16
@@ -1,94 +1,73 @@
-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.
+This patch adds a check for if the rumble queue ringbuffer is empty
+prior to queuing the rumble workqueue. If the current rumble setting is
+using a non-zero amplitude though, it will queue the worker anyway. This
+is because the controller will automatically disable the rumble effect
+if it isn't "refreshed".
+
+This change improves bluetooth communication reliability with the
+controller, since it reduces the amount of traffic.
+
+Note that we still send a few periodic zero packets to avoid scenarios
+where the controller fails to process the zero amplitude packet. Without
+sending a few to be sure, the rumble could get stuck on until the
+controller times out.
 
 Signed-off-by: Daniel J. Ogorchock <djogorchock@gmail.com>
 ---
- drivers/hid/hid-nintendo.c | 49 ++++++++++++++++++++++----------------
- 1 file changed, 29 insertions(+), 20 deletions(-)
+ drivers/hid/hid-nintendo.c | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
 
 diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c
-index 71aa676ba3907..d3ec45de9649f 100644
+index ae3cd8ca9fa78..c4270499fc6f3 100644
 --- a/drivers/hid/hid-nintendo.c
 +++ b/drivers/hid/hid-nintendo.c
-@@ -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;
- }
+@@ -400,6 +400,7 @@ struct joycon_input_report {
+ static const u16 JC_RUMBLE_DFLT_LOW_FREQ = 160;
+ static const u16 JC_RUMBLE_DFLT_HIGH_FREQ = 320;
+ static const u16 JC_RUMBLE_PERIOD_MS = 50;
++static const unsigned short JC_RUMBLE_ZERO_AMP_PKT_CNT = 5;
  
-+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 const char * const joycon_player_led_names[] = {
+ 	LED_FUNCTION_PLAYER1,
+@@ -464,6 +465,7 @@ struct joycon_ctlr {
+ 	u16 rumble_lh_freq;
+ 	u16 rumble_rl_freq;
+ 	u16 rumble_rh_freq;
++	unsigned short rumble_zero_countdown;
+ 
+ 	/* imu */
+ 	struct input_dev *imu_input;
+@@ -1218,8 +1220,19 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
+ 
+ 	spin_lock_irqsave(&ctlr->lock, flags);
+ 	if (IS_ENABLED(CONFIG_NINTENDO_FF) && rep->vibrator_report &&
+-	    (msecs - ctlr->rumble_msecs) >= JC_RUMBLE_PERIOD_MS)
++	    (msecs - ctlr->rumble_msecs) >= JC_RUMBLE_PERIOD_MS &&
++	    (ctlr->rumble_queue_head != ctlr->rumble_queue_tail ||
++	     ctlr->rumble_zero_countdown > 0)) {
++		/*
++		 * When this value reaches 0, we know we've sent multiple
++		 * packets to the controller instructing it to disable rumble.
++		 * We can safely stop sending periodic rumble packets until the
++		 * next ff effect.
++		 */
++		if (ctlr->rumble_zero_countdown > 0)
++			ctlr->rumble_zero_countdown--;
+ 		queue_work(ctlr->rumble_queue, &ctlr->rumble_worker);
 +	}
-+}
-+
- 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;
+ 	/* Parse the battery status */
+ 	tmp = rep->bat_con;
+@@ -1513,6 +1526,9 @@ static int joycon_set_rumble(struct joycon_ctlr *ctlr, u16 amp_r, u16 amp_l,
+ 	freq_r_high = ctlr->rumble_rh_freq;
+ 	freq_l_low = ctlr->rumble_ll_freq;
+ 	freq_l_high = ctlr->rumble_lh_freq;
++	/* limit number of silent rumble packets to reduce traffic */
++	if (amp_l != 0 || amp_r != 0)
++		ctlr->rumble_zero_countdown = JC_RUMBLE_ZERO_AMP_PKT_CNT;
+ 	spin_unlock_irqrestore(&ctlr->lock, flags);
  
-+	joycon_wait_for_input_report(ctlr);
-+
- 	ret = __joycon_hid_send(ctlr->hdev, (u8 *)&rumble_output,
- 				sizeof(rumble_output));
- 	return ret;
+ 	/* right joy-con */
 -- 
-2.32.0
+2.33.0
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help