Commit 67471b89 authored by Jiri Kosina's avatar Jiri Kosina
Browse files

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)
parents 5fce154a d750d148
Loading
Loading
Loading
Loading
+86 −9
Original line number Diff line number Diff line
@@ -433,7 +433,9 @@ struct joycon_ctlr {
	u8 usb_ack_match;
	u8 subcmd_ack_match;
	bool received_input_report;
	unsigned int last_input_report_msecs;
	unsigned int last_subcmd_sent_msecs;
	unsigned int consecutive_valid_report_deltas;

	/* factory calibration data */
	struct joycon_stick_cal left_stick_cal_x;
@@ -543,19 +545,54 @@ static void joycon_wait_for_input_report(struct joycon_ctlr *ctlr)
 * Sending subcommands and/or rumble data at too high a rate can cause bluetooth
 * controller disconnections.
 */
#define JC_INPUT_REPORT_MIN_DELTA	8
#define JC_INPUT_REPORT_MAX_DELTA	17
#define JC_SUBCMD_TX_OFFSET_MS		4
#define JC_SUBCMD_VALID_DELTA_REQ	3
#define JC_SUBCMD_RATE_MAX_ATTEMPTS	500
#define JC_SUBCMD_RATE_LIMITER_USB_MS	20
#define JC_SUBCMD_RATE_LIMITER_BT_MS	60
#define JC_SUBCMD_RATE_LIMITER_MS(ctlr)	((ctlr)->hdev->bus == BUS_USB ? JC_SUBCMD_RATE_LIMITER_USB_MS : JC_SUBCMD_RATE_LIMITER_BT_MS)
static void joycon_enforce_subcmd_rate(struct joycon_ctlr *ctlr)
{
	static const unsigned int max_subcmd_rate_ms = 25;
	unsigned int current_ms = jiffies_to_msecs(jiffies);
	unsigned int delta_ms = current_ms - ctlr->last_subcmd_sent_msecs;
	unsigned int current_ms;
	unsigned long subcmd_delta;
	int consecutive_valid_deltas = 0;
	int attempts = 0;
	unsigned long flags;

	if (unlikely(ctlr->ctlr_state != JOYCON_CTLR_STATE_READ))
		return;

	while (delta_ms < max_subcmd_rate_ms &&
	       ctlr->ctlr_state == JOYCON_CTLR_STATE_READ) {
	do {
		joycon_wait_for_input_report(ctlr);
		current_ms = jiffies_to_msecs(jiffies);
		delta_ms = current_ms - ctlr->last_subcmd_sent_msecs;
		subcmd_delta = current_ms - ctlr->last_subcmd_sent_msecs;

		spin_lock_irqsave(&ctlr->lock, flags);
		consecutive_valid_deltas = ctlr->consecutive_valid_report_deltas;
		spin_unlock_irqrestore(&ctlr->lock, flags);

		attempts++;
	} while ((consecutive_valid_deltas < JC_SUBCMD_VALID_DELTA_REQ ||
		  subcmd_delta < JC_SUBCMD_RATE_LIMITER_MS(ctlr)) &&
		 ctlr->ctlr_state == JOYCON_CTLR_STATE_READ &&
		 attempts < JC_SUBCMD_RATE_MAX_ATTEMPTS);

	if (attempts >= JC_SUBCMD_RATE_MAX_ATTEMPTS) {
		hid_warn(ctlr->hdev, "%s: exceeded max attempts", __func__);
		return;
	}

	ctlr->last_subcmd_sent_msecs = current_ms;

	/*
	 * Wait a short time after receiving an input report before
	 * transmitting. This should reduce odds of a TX coinciding with an RX.
	 * Minimizing concurrent BT traffic with the controller seems to lower
	 * the rate of disconnections.
	 */
	msleep(JC_SUBCMD_TX_OFFSET_MS);
}

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,
	u8 tmp;
	u32 btns;
	unsigned long msecs = jiffies_to_msecs(jiffies);
	unsigned long report_delta_ms = msecs - ctlr->last_input_report_msecs;

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

	input_sync(dev);

	spin_lock_irqsave(&ctlr->lock, flags);
	ctlr->last_input_report_msecs = msecs;
	/*
	 * Was this input report a reasonable time delta compared to the prior
	 * report? We use this information to decide when a safe time is to send
	 * rumble packets or subcommand packets.
	 */
	if (report_delta_ms >= JC_INPUT_REPORT_MIN_DELTA &&
	    report_delta_ms <= JC_INPUT_REPORT_MAX_DELTA) {
		if (ctlr->consecutive_valid_report_deltas < JC_SUBCMD_VALID_DELTA_REQ)
			ctlr->consecutive_valid_report_deltas++;
	} else {
		ctlr->consecutive_valid_report_deltas = 0;
	}
	/*
	 * Our consecutive valid report tracking is only relevant for
	 * bluetooth-connected controllers. For USB devices, we're beholden to
	 * USB's underlying polling rate anyway. Always set to the consecutive
	 * delta requirement.
	 */
	if (ctlr->hdev->bus == BUS_USB)
		ctlr->consecutive_valid_report_deltas = JC_SUBCMD_VALID_DELTA_REQ;

	spin_unlock_irqrestore(&ctlr->lock, flags);

	/*
	 * Immediately after receiving a report is the most reliable time to
	 * 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,
	u16 freq_l_low;
	u16 freq_l_high;
	unsigned long flags;
	int next_rq_head;

	spin_lock_irqsave(&ctlr->lock, flags);
	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,
	joycon_encode_rumble(data, freq_l_low, freq_l_high, amp);

	spin_lock_irqsave(&ctlr->lock, flags);
	if (++ctlr->rumble_queue_head >= JC_RUMBLE_QUEUE_SIZE)
		ctlr->rumble_queue_head = 0;

	next_rq_head = ctlr->rumble_queue_head + 1;
	if (next_rq_head >= JC_RUMBLE_QUEUE_SIZE)
		next_rq_head = 0;

	/* Did we overrun the circular buffer?
	 * If so, be sure we keep the latest intended rumble state.
	 */
	if (next_rq_head == ctlr->rumble_queue_tail) {
		hid_dbg(ctlr->hdev, "rumble queue is full");
		/* overwrite the prior value at the end of the circular buf */
		next_rq_head = ctlr->rumble_queue_head;
	}

	ctlr->rumble_queue_head = next_rq_head;
	memcpy(ctlr->rumble_data[ctlr->rumble_queue_head], data,
	       JC_RUMBLE_DATA_SIZE);

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

	ctlr->hdev = hdev;
	ctlr->ctlr_state = JOYCON_CTLR_STATE_INIT;
	ctlr->rumble_queue_head = JC_RUMBLE_QUEUE_SIZE - 1;
	ctlr->rumble_queue_head = 0;
	ctlr->rumble_queue_tail = 0;
	hid_set_drvdata(hdev, ctlr);
	mutex_init(&ctlr->output_mutex);