Commit a9a249a2 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

media: cec: fix remote control passthrough

The 'Press and Hold' operation was not correctly implemented, in
particular the requirement that the repeat doesn't start until
the second identical keypress arrives. The REP_DELAY value also
had to be adjusted (see the comment in the code) to achieve the
desired behavior.

The 'enabled_protocols' field was also never set, fix that too. Since
CEC is a fixed protocol the driver has to set this field.
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Acked-by: default avatarSean Young <sean@mess.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent d57ea877
...@@ -1767,6 +1767,9 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, ...@@ -1767,6 +1767,9 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
int la_idx = cec_log_addr2idx(adap, dest_laddr); int la_idx = cec_log_addr2idx(adap, dest_laddr);
bool from_unregistered = init_laddr == 0xf; bool from_unregistered = init_laddr == 0xf;
struct cec_msg tx_cec_msg = { }; struct cec_msg tx_cec_msg = { };
#ifdef CONFIG_MEDIA_CEC_RC
int scancode;
#endif
dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg); dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg);
...@@ -1855,11 +1858,9 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, ...@@ -1855,11 +1858,9 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
*/ */
case 0x60: case 0x60:
if (msg->len == 2) if (msg->len == 2)
rc_keydown(adap->rc, RC_TYPE_CEC, scancode = msg->msg[2];
msg->msg[2], 0);
else else
rc_keydown(adap->rc, RC_TYPE_CEC, scancode = msg->msg[2] << 8 | msg->msg[3];
msg->msg[2] << 8 | msg->msg[3], 0);
break; break;
/* /*
* Other function messages that are not handled. * Other function messages that are not handled.
...@@ -1872,11 +1873,54 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, ...@@ -1872,11 +1873,54 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
*/ */
case 0x56: case 0x57: case 0x56: case 0x57:
case 0x67: case 0x68: case 0x69: case 0x6a: case 0x67: case 0x68: case 0x69: case 0x6a:
scancode = -1;
break; break;
default: default:
rc_keydown(adap->rc, RC_TYPE_CEC, msg->msg[2], 0); 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_TYPE_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; 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 #endif
break; break;
...@@ -1886,6 +1930,8 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, ...@@ -1886,6 +1930,8 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
break; break;
#ifdef CONFIG_MEDIA_CEC_RC #ifdef CONFIG_MEDIA_CEC_RC
rc_keyup(adap->rc); rc_keyup(adap->rc);
adap->rc_repeating = false;
adap->rc_last_scancode = -1;
#endif #endif
break; break;
......
...@@ -276,9 +276,11 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, ...@@ -276,9 +276,11 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
adap->rc->input_id.version = 1; adap->rc->input_id.version = 1;
adap->rc->driver_name = CEC_NAME; adap->rc->driver_name = CEC_NAME;
adap->rc->allowed_protocols = RC_BIT_CEC; adap->rc->allowed_protocols = RC_BIT_CEC;
adap->rc->enabled_protocols = RC_BIT_CEC;
adap->rc->priv = adap; adap->rc->priv = adap;
adap->rc->map_name = RC_MAP_CEC; adap->rc->map_name = RC_MAP_CEC;
adap->rc->timeout = MS_TO_NS(100); adap->rc->timeout = MS_TO_NS(100);
adap->rc_last_scancode = -1;
#endif #endif
return adap; return adap;
} }
...@@ -310,6 +312,17 @@ int cec_register_adapter(struct cec_adapter *adap, ...@@ -310,6 +312,17 @@ int cec_register_adapter(struct cec_adapter *adap,
adap->rc = NULL; adap->rc = NULL;
return res; 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 #endif
......
...@@ -190,6 +190,11 @@ struct cec_adapter { ...@@ -190,6 +190,11 @@ struct cec_adapter {
u32 tx_timeouts; u32 tx_timeouts;
#ifdef CONFIG_MEDIA_CEC_RC
bool rc_repeating;
int rc_last_scancode;
u64 rc_last_keypress;
#endif
#ifdef CONFIG_CEC_NOTIFIER #ifdef CONFIG_CEC_NOTIFIER
struct cec_notifier *notifier; struct cec_notifier *notifier;
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment