Commit 98c32bcd authored by Jarod Wilson's avatar Jarod Wilson Committed by Mauro Carvalho Chehab

[media] rc: call input_sync after scancode reports

Due to commit cdda911c, evdev only
becomes readable when the buffer contains an EV_SYN/SYN_REPORT event. If
we get a repeat or a scancode we don't have a mapping for, we never call
input_sync, and thus those events don't get reported in a timely
fashion.

For example, take an mceusb transceiver with a default rc6 keymap. Press
buttons on an rc5 remote while monitoring with ir-keytable, and you'll
see nothing. Now press a button on the rc6 remote matching the keymap.
You'll suddenly get the rc5 key scancodes, the rc6 scancode and the rc6
key spit out all at the same time.

Pressing and holding a button on a remote we do have a keymap for also
works rather unreliably right now, due to repeat events also happening
without a call to input_sync (we bail from ir_do_keydown before getting
to the point where it calls input_sync).

Easy fix though, just add two strategically placed input_sync calls
right after our input_event calls for EV_MSC, and all is well again.
Technically, we probably should have been doing this all along, its just
that it never caused any functional difference until the referenced
change went into the input layer.

input_sync once per IR signal. There was another hidden bug in the code
where we were calling input_report_key using last_keycode instead of our
just discovered keycode, which manifested with the reordering of calling
input_report_key and setting last_keycode.
Reported-by: default avatarStephan Raue <sraue@openelec.tv>
CC: Stephan Raue <sraue@openelec.tv>
CC: Mauro Carvalho Chehab <mchehab@redhat.com>
CC: Jeff Brown <jeffbrown@android.com>
Acked-by: default avatarDmitry Torokhov <dtor@mail.ru>
Signed-off-by: default avatarJarod Wilson <jarod@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 372b4249
...@@ -522,18 +522,20 @@ EXPORT_SYMBOL_GPL(rc_g_keycode_from_table); ...@@ -522,18 +522,20 @@ EXPORT_SYMBOL_GPL(rc_g_keycode_from_table);
/** /**
* ir_do_keyup() - internal function to signal the release of a keypress * ir_do_keyup() - internal function to signal the release of a keypress
* @dev: the struct rc_dev descriptor of the device * @dev: the struct rc_dev descriptor of the device
* @sync: whether or not to call input_sync
* *
* This function is used internally to release a keypress, it must be * This function is used internally to release a keypress, it must be
* called with keylock held. * called with keylock held.
*/ */
static void ir_do_keyup(struct rc_dev *dev) static void ir_do_keyup(struct rc_dev *dev, bool sync)
{ {
if (!dev->keypressed) if (!dev->keypressed)
return; return;
IR_dprintk(1, "keyup key 0x%04x\n", dev->last_keycode); IR_dprintk(1, "keyup key 0x%04x\n", dev->last_keycode);
input_report_key(dev->input_dev, dev->last_keycode, 0); input_report_key(dev->input_dev, dev->last_keycode, 0);
input_sync(dev->input_dev); if (sync)
input_sync(dev->input_dev);
dev->keypressed = false; dev->keypressed = false;
} }
...@@ -549,7 +551,7 @@ void rc_keyup(struct rc_dev *dev) ...@@ -549,7 +551,7 @@ void rc_keyup(struct rc_dev *dev)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&dev->keylock, flags); spin_lock_irqsave(&dev->keylock, flags);
ir_do_keyup(dev); ir_do_keyup(dev, true);
spin_unlock_irqrestore(&dev->keylock, flags); spin_unlock_irqrestore(&dev->keylock, flags);
} }
EXPORT_SYMBOL_GPL(rc_keyup); EXPORT_SYMBOL_GPL(rc_keyup);
...@@ -578,7 +580,7 @@ static void ir_timer_keyup(unsigned long cookie) ...@@ -578,7 +580,7 @@ static void ir_timer_keyup(unsigned long cookie)
*/ */
spin_lock_irqsave(&dev->keylock, flags); spin_lock_irqsave(&dev->keylock, flags);
if (time_is_before_eq_jiffies(dev->keyup_jiffies)) if (time_is_before_eq_jiffies(dev->keyup_jiffies))
ir_do_keyup(dev); ir_do_keyup(dev, true);
spin_unlock_irqrestore(&dev->keylock, flags); spin_unlock_irqrestore(&dev->keylock, flags);
} }
...@@ -597,6 +599,7 @@ void rc_repeat(struct rc_dev *dev) ...@@ -597,6 +599,7 @@ void rc_repeat(struct rc_dev *dev)
spin_lock_irqsave(&dev->keylock, flags); spin_lock_irqsave(&dev->keylock, flags);
input_event(dev->input_dev, EV_MSC, MSC_SCAN, dev->last_scancode); input_event(dev->input_dev, EV_MSC, MSC_SCAN, dev->last_scancode);
input_sync(dev->input_dev);
if (!dev->keypressed) if (!dev->keypressed)
goto out; goto out;
...@@ -622,29 +625,28 @@ EXPORT_SYMBOL_GPL(rc_repeat); ...@@ -622,29 +625,28 @@ EXPORT_SYMBOL_GPL(rc_repeat);
static void ir_do_keydown(struct rc_dev *dev, int scancode, static void ir_do_keydown(struct rc_dev *dev, int scancode,
u32 keycode, u8 toggle) u32 keycode, u8 toggle)
{ {
input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode); bool new_event = !dev->keypressed ||
dev->last_scancode != scancode ||
/* Repeat event? */ dev->last_toggle != toggle;
if (dev->keypressed &&
dev->last_scancode == scancode &&
dev->last_toggle == toggle)
return;
/* Release old keypress */ if (new_event && dev->keypressed)
ir_do_keyup(dev); ir_do_keyup(dev, false);
dev->last_scancode = scancode; input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode);
dev->last_toggle = toggle;
dev->last_keycode = keycode;
if (keycode == KEY_RESERVED) if (new_event && keycode != KEY_RESERVED) {
return; /* Register a keypress */
dev->keypressed = true;
dev->last_scancode = scancode;
dev->last_toggle = toggle;
dev->last_keycode = keycode;
IR_dprintk(1, "%s: key down event, "
"key 0x%04x, scancode 0x%04x\n",
dev->input_name, keycode, scancode);
input_report_key(dev->input_dev, keycode, 1);
}
/* Register a keypress */
dev->keypressed = true;
IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n",
dev->input_name, keycode, scancode);
input_report_key(dev->input_dev, dev->last_keycode, 1);
input_sync(dev->input_dev); input_sync(dev->input_dev);
} }
......
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