From 57c642cb45d6f7d0d950c3bc67439989062ac743 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Thu, 23 Nov 2017 17:37:10 -0500 Subject: 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 a9a249a2c997 ("media: cec: fix remote control passthrough") for the original change. Acked-by: Hans Verkuil Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/cec-adap.c | 56 ++++---------------------------------------- drivers/media/cec/cec-core.c | 12 ---------- drivers/media/rc/rc-main.c | 49 +++++++++++++++++++++++++++++++++++++- include/media/cec.h | 5 ---- include/media/rc-core.h | 3 +++ 5 files changed, 56 insertions(+), 69 deletions(-) diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c index 2a097e0..2b1e540 100644 --- a/drivers/media/cec/cec-adap.c +++ b/drivers/media/cec/cec-adap.c @@ -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; - 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; + rc_keydown(adap->rc, RC_PROTO_CEC, msg->msg[2], 0); 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; diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c index b5845b4..a9f9525 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c @@ -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 diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 5830cb2..1870b79 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -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) @@ -651,6 +652,31 @@ static void ir_timer_keyup(struct timer_list *t) } /** + * 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,7 +1775,10 @@ 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(). */ - dev->input_dev->rep[REP_DELAY] = 500; + if (dev->allowed_protocols == RC_PROTO_BIT_CEC) + dev->input_dev->rep[REP_DELAY] = 0; + else + dev->input_dev->rep[REP_DELAY] = 500; /* * As a repeat event on protocols like RC-5 and NEC take as long as @@ -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); diff --git a/include/media/cec.h b/include/media/cec.h index 1c6a797..7cdf71d 100644 --- a/include/media/cec.h +++ b/include/media/cec.h @@ -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 diff --git a/include/media/rc-core.h b/include/media/rc-core.h index 3a47a25..0a4026c 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -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; -- cgit v1.1