Commit 57c642cb authored by Sean Young's avatar Sean Young Committed by Mauro Carvalho Chehab
Browse files

media: cec: move cec autorepeat handling to rc-core



CEC autorepeat is different than other protocols. Autorepeat is triggered
by the first repeated user control pressed CEC message, rather than a
fixed REP_DELAY.

This change also does away with the KEY_UP event directly after the first
KEY_DOWN event, which was used to stop autorepeat from starting.

See commit a9a249a2 ("media: cec: fix remote control passthrough")
for the original change.

Acked-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarSean Young <sean@mess.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 6d4a36d1
Loading
Loading
Loading
Loading
+5 −51
Original line number Diff line number Diff line
@@ -1788,9 +1788,6 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
	int la_idx = cec_log_addr2idx(adap, dest_laddr);
	bool from_unregistered = init_laddr == 0xf;
	struct cec_msg tx_cec_msg = { };
#ifdef CONFIG_MEDIA_CEC_RC
	int scancode;
#endif

	dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg);

@@ -1886,9 +1883,11 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
		 */
		case 0x60:
			if (msg->len == 2)
				scancode = msg->msg[2];
				rc_keydown(adap->rc, RC_PROTO_CEC,
					   msg->msg[2], 0);
			else
				scancode = msg->msg[2] << 8 | msg->msg[3];
				rc_keydown(adap->rc, RC_PROTO_CEC,
					   msg->msg[2] << 8 | msg->msg[3], 0);
			break;
		/*
		 * Other function messages that are not handled.
@@ -1901,54 +1900,11 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
		 */
		case 0x56: case 0x57:
		case 0x67: case 0x68: case 0x69: case 0x6a:
			scancode = -1;
			break;
		default:
			scancode = msg->msg[2];
			break;
		}

		/* Was repeating, but keypress timed out */
		if (adap->rc_repeating && !adap->rc->keypressed) {
			adap->rc_repeating = false;
			adap->rc_last_scancode = -1;
		}
		/* Different keypress from last time, ends repeat mode */
		if (adap->rc_last_scancode != scancode) {
			rc_keyup(adap->rc);
			adap->rc_repeating = false;
		}
		/* We can't handle this scancode */
		if (scancode < 0) {
			adap->rc_last_scancode = scancode;
			rc_keydown(adap->rc, RC_PROTO_CEC, msg->msg[2], 0);
			break;
		}

		/* Send key press */
		rc_keydown(adap->rc, RC_PROTO_CEC, scancode, 0);

		/* When in repeating mode, we're done */
		if (adap->rc_repeating)
			break;

		/*
		 * We are not repeating, but the new scancode is
		 * the same as the last one, and this second key press is
		 * within 550 ms (the 'Follower Safety Timeout') from the
		 * previous key press, so we now enable the repeating mode.
		 */
		if (adap->rc_last_scancode == scancode &&
		    msg->rx_ts - adap->rc_last_keypress < 550 * NSEC_PER_MSEC) {
			adap->rc_repeating = true;
			break;
		}
		/*
		 * Not in repeating mode, so avoid triggering repeat mode
		 * by calling keyup.
		 */
		rc_keyup(adap->rc);
		adap->rc_last_scancode = scancode;
		adap->rc_last_keypress = msg->rx_ts;
#endif
		break;

@@ -1958,8 +1914,6 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
			break;
#ifdef CONFIG_MEDIA_CEC_RC
		rc_keyup(adap->rc);
		adap->rc_repeating = false;
		adap->rc_last_scancode = -1;
#endif
		break;

+0 −12
Original line number Diff line number Diff line
@@ -286,7 +286,6 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
	adap->rc->priv = adap;
	adap->rc->map_name = RC_MAP_CEC;
	adap->rc->timeout = MS_TO_NS(100);
	adap->rc_last_scancode = -1;
#endif
	return adap;
}
@@ -318,17 +317,6 @@ int cec_register_adapter(struct cec_adapter *adap,
			adap->rc = NULL;
			return res;
		}
		/*
		 * The REP_DELAY for CEC is really the time between the initial
		 * 'User Control Pressed' message and the second. The first
		 * keypress is always seen as non-repeating, the second
		 * (provided it has the same UI Command) will start the 'Press
		 * and Hold' (aka repeat) behavior. By setting REP_DELAY to the
		 * same value as REP_PERIOD the expected CEC behavior is
		 * reproduced.
		 */
		adap->rc->input_dev->rep[REP_DELAY] =
			adap->rc->input_dev->rep[REP_PERIOD];
	}
#endif

+48 −1
Original line number Diff line number Diff line
@@ -597,6 +597,7 @@ static void ir_do_keyup(struct rc_dev *dev, bool sync)
		return;

	IR_dprintk(1, "keyup key 0x%04x\n", dev->last_keycode);
	del_timer_sync(&dev->timer_repeat);
	input_report_key(dev->input_dev, dev->last_keycode, 0);
	led_trigger_event(led_feedback, LED_OFF);
	if (sync)
@@ -650,6 +651,31 @@ static void ir_timer_keyup(struct timer_list *t)
	spin_unlock_irqrestore(&dev->keylock, flags);
}

/**
 * ir_timer_repeat() - generates a repeat event after a timeout
 *
 * @t:		a pointer to the struct timer_list
 *
 * This routine will generate a soft repeat event every REP_PERIOD
 * milliseconds.
 */
static void ir_timer_repeat(struct timer_list *t)
{
	struct rc_dev *dev = from_timer(dev, t, timer_repeat);
	struct input_dev *input = dev->input_dev;
	unsigned long flags;

	spin_lock_irqsave(&dev->keylock, flags);
	if (dev->keypressed) {
		input_event(input, EV_KEY, dev->last_keycode, 2);
		input_sync(input);
		if (input->rep[REP_PERIOD])
			mod_timer(&dev->timer_repeat, jiffies +
				  msecs_to_jiffies(input->rep[REP_PERIOD]));
	}
	spin_unlock_irqrestore(&dev->keylock, flags);
}

/**
 * rc_repeat() - signals that a key is still pressed
 * @dev:	the struct rc_dev descriptor of the device
@@ -732,6 +758,22 @@ static void ir_do_keydown(struct rc_dev *dev, enum rc_proto protocol,
		led_trigger_event(led_feedback, LED_FULL);
	}

	/*
	 * For CEC, start sending repeat messages as soon as the first
	 * repeated message is sent, as long as REP_DELAY = 0 and REP_PERIOD
	 * is non-zero. Otherwise, the input layer will generate repeat
	 * messages.
	 */
	if (!new_event && keycode != KEY_RESERVED &&
	    dev->allowed_protocols == RC_PROTO_BIT_CEC &&
	    !timer_pending(&dev->timer_repeat) &&
	    dev->input_dev->rep[REP_PERIOD] &&
	    !dev->input_dev->rep[REP_DELAY]) {
		input_event(dev->input_dev, EV_KEY, keycode, 2);
		mod_timer(&dev->timer_repeat, jiffies +
			  msecs_to_jiffies(dev->input_dev->rep[REP_PERIOD]));
	}

	input_sync(dev->input_dev);
}

@@ -1599,6 +1641,7 @@ struct rc_dev *rc_allocate_device(enum rc_driver_type type)
		input_set_drvdata(dev->input_dev, dev);

		timer_setup(&dev->timer_keyup, ir_timer_keyup, 0);
		timer_setup(&dev->timer_repeat, ir_timer_repeat, 0);

		spin_lock_init(&dev->rc_map.lock);
		spin_lock_init(&dev->keylock);
@@ -1732,6 +1775,9 @@ static int rc_setup_rx_device(struct rc_dev *dev)
	 * to avoid wrong repetition of the keycodes. Note that this must be
	 * set after the call to input_register_device().
	 */
	if (dev->allowed_protocols == RC_PROTO_BIT_CEC)
		dev->input_dev->rep[REP_DELAY] = 0;
	else
		dev->input_dev->rep[REP_DELAY] = 500;

	/*
@@ -1884,6 +1930,7 @@ void rc_unregister_device(struct rc_dev *dev)
		return;

	del_timer_sync(&dev->timer_keyup);
	del_timer_sync(&dev->timer_repeat);

	if (dev->driver_type == RC_DRIVER_IR_RAW)
		ir_raw_event_unregister(dev);
+0 −5
Original line number Diff line number Diff line
@@ -192,11 +192,6 @@ struct cec_adapter {

	u32 tx_timeouts;

#ifdef CONFIG_MEDIA_CEC_RC
	bool rc_repeating;
	int rc_last_scancode;
	u64 rc_last_keypress;
#endif
#ifdef CONFIG_CEC_NOTIFIER
	struct cec_notifier *notifier;
#endif
+3 −0
Original line number Diff line number Diff line
@@ -134,6 +134,8 @@ struct lirc_fh {
 * @keypressed: whether a key is currently pressed
 * @keyup_jiffies: time (in jiffies) when the current keypress should be released
 * @timer_keyup: timer for releasing a keypress
 * @timer_repeat: timer for autorepeat events. This is needed for CEC, which
 *	has non-standard repeats.
 * @last_keycode: keycode of last keypress
 * @last_protocol: protocol of last keypress
 * @last_scancode: scancode of last keypress
@@ -202,6 +204,7 @@ struct rc_dev {
	bool				keypressed;
	unsigned long			keyup_jiffies;
	struct timer_list		timer_keyup;
	struct timer_list		timer_repeat;
	u32				last_keycode;
	enum rc_proto			last_protocol;
	u32				last_scancode;