mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 22:51:35 +00:00
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 a9a249a2c9
("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>
This commit is contained in:
parent
6d4a36d183
commit
57c642cb45
@ -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];
|
||||
rc_keydown(adap->rc, RC_PROTO_CEC, msg->msg[2], 0);
|
||||
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;
|
||||
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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user