]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
media: cec: move cec autorepeat handling to rc-core
authorSean Young <sean@mess.org>
Thu, 23 Nov 2017 22:37:10 +0000 (17:37 -0500)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Thu, 14 Dec 2017 15:35:30 +0000 (10:35 -0500)
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 <hans.verkuil@cisco.com>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
drivers/media/cec/cec-adap.c
drivers/media/cec/cec-core.c
drivers/media/rc/rc-main.c
include/media/cec.h
include/media/rc-core.h

index 2a097e016414e6c5470e32b047b5a02ca6d44ac5..2b1e540587d6a79f394817abe24174a0b1922130 100644 (file)
@@ -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;
 
index b5845b47fe6c2c1ecf13145b151f5b2bfb1e98a0..a9f9525db9ae88b07d84c19f699e63744a7e05fb 100644 (file)
@@ -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
 
index 5830cb2c59436d01013254cafd230aad4573d04f..1870b799906281ca40eea4559e99aa3f18c2f284 100644 (file)
@@ -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,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);
index 1c6a797cb6d4a116c34c9772607e268039287711..7cdf71d7125a3e6bd1bd627b2aca8ba4dbd91c7f 100644 (file)
@@ -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
index 3a47a25a65930995ecc5191a0d199514ef584e47..0a4026cf64f33291a34cbdb3a42ec689679cec1e 100644 (file)
@@ -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;