mirror of
https://github.com/torvalds/linux.git
synced 2024-11-12 07:01:57 +00:00
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: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Sean Young <sean@mess.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
parent
d57ea877af
commit
a9a249a2c9
@ -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,
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
*/
|
*/
|
||||||
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;
|
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;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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 {
|
|||||||
|
|
||||||
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
|
||||||
|
Loading…
Reference in New Issue
Block a user