RPi, Generic: backport IR latency patch and mce_kbd/mceusb fixes

See https://www.spinics.net/lists/linux-media/msg131804.html
https://patchwork.linuxtv.org/patch/48681/
https://patchwork.linuxtv.org/patch/48680/
https://patchwork.linuxtv.org/patch/48782/

The current IR decoding is much too slow. Many IR protocols rely on
a trailing space for decoding (e.g. rc-6 needs to know when the bits
end). The trailing space is generated by the IR timeout, and if this
is longer than required, buttons can feel slow to respond.

The other issue is the keyup timer. IR has no concept of a keyup message,
this is implied by the absence of IR. So, minimising the timeout for
this makes buttons less "sticky"; the are released much quicker.

With these patches in place, using IR with the builtin decoders is much
improved and feels very snappy.

Signed-off-by: Matthias Reichl <hias@horus.com>
This commit is contained in:
Matthias Reichl 2018-05-04 13:51:33 +02:00
parent f0b4786f1a
commit e131c14bb2
2 changed files with 1620 additions and 0 deletions

View File

@ -0,0 +1,810 @@
From 057ccfd1d18842bd2fa39c4b996a9a952c5a821d Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Tue, 27 Mar 2018 19:35:11 +0200
Subject: [PATCH 1/9] media: rc: set timeout to smallest value required by
enabled protocols
backport of https://patchwork.linuxtv.org/patch/48516/
The longer the IR timeout, the longer the rc device waits until delivering
the trailing space. So, by reducing this timeout, we reduce the delay for
the last scancode to be delivered.
Note that the lirc daemon disables all protocols, in which case we revert
back to the default value.
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/ir-jvc-decoder.c | 1 +
drivers/media/rc/ir-mce_kbd-decoder.c | 1 +
drivers/media/rc/ir-nec-decoder.c | 1 +
drivers/media/rc/ir-rc5-decoder.c | 1 +
drivers/media/rc/ir-rc6-decoder.c | 1 +
drivers/media/rc/ir-sanyo-decoder.c | 1 +
drivers/media/rc/ir-sharp-decoder.c | 1 +
drivers/media/rc/ir-sony-decoder.c | 1 +
drivers/media/rc/ir-xmp-decoder.c | 1 +
drivers/media/rc/rc-core-priv.h | 1 +
drivers/media/rc/rc-ir-raw.c | 31 ++++++++++++++++++++++++++++++-
drivers/media/rc/rc-main.c | 12 ++++++------
12 files changed, 46 insertions(+), 7 deletions(-)
diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c
index e2bd68c42edfa..fc931fe39bb75 100644
--- a/drivers/media/rc/ir-jvc-decoder.c
+++ b/drivers/media/rc/ir-jvc-decoder.c
@@ -212,6 +212,7 @@ static struct ir_raw_handler jvc_handler = {
.protocols = RC_PROTO_BIT_JVC,
.decode = ir_jvc_decode,
.encode = ir_jvc_encode,
+ .max_space = JVC_TRAILER_SPACE,
};
static int __init ir_jvc_decode_init(void)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 7c572a6436563..7afeab04dbbfd 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -474,6 +474,7 @@ static struct ir_raw_handler mce_kbd_handler = {
.encode = ir_mce_kbd_encode,
.raw_register = ir_mce_kbd_register,
.raw_unregister = ir_mce_kbd_unregister,
+ .max_space = MCIR2_MAX_LEN,
};
static int __init ir_mce_kbd_decode_init(void)
diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index a95d09acc22a5..3e12059add84d 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -264,6 +264,7 @@ static struct ir_raw_handler nec_handler = {
RC_PROTO_BIT_NEC32,
.decode = ir_nec_decode,
.encode = ir_nec_encode,
+ .max_space = NEC_TRAILER_SPACE,
};
static int __init ir_nec_decode_init(void)
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 1292f534de434..1eaca0528b691 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -282,6 +282,7 @@ static struct ir_raw_handler rc5_handler = {
RC_PROTO_BIT_RC5_SZ,
.decode = ir_rc5_decode,
.encode = ir_rc5_encode,
+ .max_space = RC5_TRAILER,
};
static int __init ir_rc5_decode_init(void)
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index 5d0d2fe3b7a7f..8c4c733a5f27b 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -408,6 +408,7 @@ static struct ir_raw_handler rc6_handler = {
RC_PROTO_BIT_RC6_MCE,
.decode = ir_rc6_decode,
.encode = ir_rc6_encode,
+ .max_space = RC6_SUFFIX_SPACE,
};
static int __init ir_rc6_decode_init(void)
diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
index 758c60956850f..935880d4889ec 100644
--- a/drivers/media/rc/ir-sanyo-decoder.c
+++ b/drivers/media/rc/ir-sanyo-decoder.c
@@ -218,6 +218,7 @@ static struct ir_raw_handler sanyo_handler = {
.protocols = RC_PROTO_BIT_SANYO,
.decode = ir_sanyo_decode,
.encode = ir_sanyo_encode,
+ .max_space = SANYO_TRAILER_SPACE,
};
static int __init ir_sanyo_decode_init(void)
diff --git a/drivers/media/rc/ir-sharp-decoder.c b/drivers/media/rc/ir-sharp-decoder.c
index 129b558acc921..96d818bd0cc98 100644
--- a/drivers/media/rc/ir-sharp-decoder.c
+++ b/drivers/media/rc/ir-sharp-decoder.c
@@ -226,6 +226,7 @@ static struct ir_raw_handler sharp_handler = {
.protocols = RC_PROTO_BIT_SHARP,
.decode = ir_sharp_decode,
.encode = ir_sharp_encode,
+ .max_space = SHARP_ECHO_SPACE,
};
static int __init ir_sharp_decode_init(void)
diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c
index a47ced763031d..d57d15b431f6d 100644
--- a/drivers/media/rc/ir-sony-decoder.c
+++ b/drivers/media/rc/ir-sony-decoder.c
@@ -221,6 +221,7 @@ static struct ir_raw_handler sony_handler = {
RC_PROTO_BIT_SONY20,
.decode = ir_sony_decode,
.encode = ir_sony_encode,
+ .max_space = SONY_TRAILER_SPACE,
};
static int __init ir_sony_decode_init(void)
diff --git a/drivers/media/rc/ir-xmp-decoder.c b/drivers/media/rc/ir-xmp-decoder.c
index 6f464be1c8d7a..1ac3a4cee69e3 100644
--- a/drivers/media/rc/ir-xmp-decoder.c
+++ b/drivers/media/rc/ir-xmp-decoder.c
@@ -198,6 +198,7 @@ static int ir_xmp_decode(struct rc_dev *dev, struct ir_raw_event ev)
static struct ir_raw_handler xmp_handler = {
.protocols = RC_PROTO_BIT_XMP,
.decode = ir_xmp_decode,
+ .max_space = XMP_TRAILER_SPACE,
};
static int __init ir_xmp_decode_init(void)
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 7da9c96cb0588..5fd3b5aed9ece 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -29,6 +29,7 @@ struct ir_raw_handler {
int (*decode)(struct rc_dev *dev, struct ir_raw_event event);
int (*encode)(enum rc_proto protocol, u32 scancode,
struct ir_raw_event *events, unsigned int max);
+ u32 max_space;
/* These two should only be used by the lirc decoder */
int (*raw_register)(struct rc_dev *dev);
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 503bc425a187c..7f0197bf5d32d 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -215,7 +215,36 @@ ir_raw_get_allowed_protocols(void)
static int change_protocol(struct rc_dev *dev, u64 *rc_proto)
{
- /* the caller will update dev->enabled_protocols */
+ struct ir_raw_handler *handler;
+ u32 timeout = 0;
+
+ if (!dev->max_timeout)
+ return 0;
+
+ mutex_lock(&ir_raw_handler_lock);
+ list_for_each_entry(handler, &ir_raw_handler_list, list) {
+ if (handler->protocols & *rc_proto) {
+ if (timeout < handler->max_space)
+ timeout = handler->max_space;
+ }
+ }
+ mutex_unlock(&ir_raw_handler_lock);
+
+ if (timeout == 0)
+ timeout = IR_DEFAULT_TIMEOUT;
+ else
+ timeout += MS_TO_NS(20);
+
+ if (timeout < dev->min_timeout)
+ timeout = dev->min_timeout;
+ else if (timeout > dev->max_timeout)
+ timeout = dev->max_timeout;
+
+ if (dev->s_timeout)
+ dev->s_timeout(dev, timeout);
+ else
+ dev->timeout = timeout;
+
return 0;
}
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 72f381522cb26..e7e20bcfe2729 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1161,6 +1161,9 @@ static ssize_t store_protocols(struct device *device,
if (rc < 0)
goto out;
+ if (dev->driver_type == RC_DRIVER_IR_RAW)
+ ir_raw_load_modules(&new_protocols);
+
rc = dev->change_protocol(dev, &new_protocols);
if (rc < 0) {
IR_dprintk(1, "Error setting protocols to 0x%llx\n",
@@ -1168,9 +1171,6 @@ static ssize_t store_protocols(struct device *device,
goto out;
}
- if (dev->driver_type == RC_DRIVER_IR_RAW)
- ir_raw_load_modules(&new_protocols);
-
if (new_protocols != old_protocols) {
*current_protocols = new_protocols;
IR_dprintk(1, "Protocols changed to 0x%llx\n",
@@ -1638,6 +1638,9 @@ static int rc_prepare_rx_device(struct rc_dev *dev)
rc_proto = BIT_ULL(rc_map->rc_proto);
+ if (dev->driver_type == RC_DRIVER_IR_RAW)
+ ir_raw_load_modules(&rc_proto);
+
if (dev->change_protocol) {
rc = dev->change_protocol(dev, &rc_proto);
if (rc < 0)
@@ -1645,9 +1648,6 @@ static int rc_prepare_rx_device(struct rc_dev *dev)
dev->enabled_protocols = rc_proto;
}
- if (dev->driver_type == RC_DRIVER_IR_RAW)
- ir_raw_load_modules(&rc_proto);
-
set_bit(EV_KEY, dev->input_dev->evbit);
set_bit(EV_REP, dev->input_dev->evbit);
set_bit(EV_MSC, dev->input_dev->evbit);
--
2.11.0
From 00f54931b0ff7202020567544605b7e3c4f1dee8 Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Tue, 27 Mar 2018 19:45:36 +0200
Subject: [PATCH 2/9] media: rc: per-protocol repeat period and minimum keyup
timer
backport of https://patchwork.linuxtv.org/patch/48520/
Each IR protocol has its own repeat period. We can minimise the keyup
timer to be the protocol period + IR timeout. This makes keys less
"sticky" and makes IR more reactive and nicer to use.
This feature was previously attempted in commit d57ea877af38 ("media: rc:
per-protocol repeat period"), but that did not take the IR timeout into
account, and had to be reverted.
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/cec/cec-core.c | 2 +-
drivers/media/rc/ir-lirc-codec.c | 2 +-
drivers/media/rc/rc-main.c | 54 +++++++++++++++++++++-------------------
3 files changed, 30 insertions(+), 28 deletions(-)
diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c
index 648136e552d5b..4cf35e4af7bd6 100644
--- a/drivers/media/cec/cec-core.c
+++ b/drivers/media/cec/cec-core.c
@@ -280,7 +280,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
adap->rc->enabled_protocols = RC_PROTO_BIT_CEC;
adap->rc->priv = adap;
adap->rc->map_name = RC_MAP_CEC;
- adap->rc->timeout = MS_TO_NS(100);
+ adap->rc->timeout = MS_TO_NS(550);
adap->rc_last_scancode = -1;
#endif
return adap;
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 4c8f456238bca..ef7e43038092f 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -314,7 +314,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
break;
case LIRC_SET_REC_TIMEOUT_REPORTS:
- if (!dev->timeout)
+ if (dev->driver_type != RC_DRIVER_IR_RAW)
return -ENOTTY;
lirc->send_timeout_reports = !!val;
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index e7e20bcfe2729..36f99a0919c30 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -35,48 +35,48 @@ static const struct {
unsigned int repeat_period;
unsigned int scancode_bits;
} protocols[] = {
- [RC_PROTO_UNKNOWN] = { .name = "unknown", .repeat_period = 250 },
- [RC_PROTO_OTHER] = { .name = "other", .repeat_period = 250 },
+ [RC_PROTO_UNKNOWN] = { .name = "unknown", .repeat_period = 125 },
+ [RC_PROTO_OTHER] = { .name = "other", .repeat_period = 125 },
[RC_PROTO_RC5] = { .name = "rc-5",
- .scancode_bits = 0x1f7f, .repeat_period = 250 },
+ .scancode_bits = 0x1f7f, .repeat_period = 114 },
[RC_PROTO_RC5X_20] = { .name = "rc-5x-20",
- .scancode_bits = 0x1f7f3f, .repeat_period = 250 },
+ .scancode_bits = 0x1f7f3f, .repeat_period = 114 },
[RC_PROTO_RC5_SZ] = { .name = "rc-5-sz",
- .scancode_bits = 0x2fff, .repeat_period = 250 },
+ .scancode_bits = 0x2fff, .repeat_period = 114 },
[RC_PROTO_JVC] = { .name = "jvc",
- .scancode_bits = 0xffff, .repeat_period = 250 },
+ .scancode_bits = 0xffff, .repeat_period = 125 },
[RC_PROTO_SONY12] = { .name = "sony-12",
- .scancode_bits = 0x1f007f, .repeat_period = 250 },
+ .scancode_bits = 0x1f007f, .repeat_period = 100 },
[RC_PROTO_SONY15] = { .name = "sony-15",
- .scancode_bits = 0xff007f, .repeat_period = 250 },
+ .scancode_bits = 0xff007f, .repeat_period = 100 },
[RC_PROTO_SONY20] = { .name = "sony-20",
- .scancode_bits = 0x1fff7f, .repeat_period = 250 },
+ .scancode_bits = 0x1fff7f, .repeat_period = 100 },
[RC_PROTO_NEC] = { .name = "nec",
- .scancode_bits = 0xffff, .repeat_period = 250 },
+ .scancode_bits = 0xffff, .repeat_period = 110 },
[RC_PROTO_NECX] = { .name = "nec-x",
- .scancode_bits = 0xffffff, .repeat_period = 250 },
+ .scancode_bits = 0xffffff, .repeat_period = 110 },
[RC_PROTO_NEC32] = { .name = "nec-32",
- .scancode_bits = 0xffffffff, .repeat_period = 250 },
+ .scancode_bits = 0xffffffff, .repeat_period = 110 },
[RC_PROTO_SANYO] = { .name = "sanyo",
- .scancode_bits = 0x1fffff, .repeat_period = 250 },
+ .scancode_bits = 0x1fffff, .repeat_period = 125 },
[RC_PROTO_MCIR2_KBD] = { .name = "mcir2-kbd",
- .scancode_bits = 0xffff, .repeat_period = 250 },
+ .scancode_bits = 0xffff, .repeat_period = 100 },
[RC_PROTO_MCIR2_MSE] = { .name = "mcir2-mse",
- .scancode_bits = 0x1fffff, .repeat_period = 250 },
+ .scancode_bits = 0x1fffff, .repeat_period = 100 },
[RC_PROTO_RC6_0] = { .name = "rc-6-0",
- .scancode_bits = 0xffff, .repeat_period = 250 },
+ .scancode_bits = 0xffff, .repeat_period = 114 },
[RC_PROTO_RC6_6A_20] = { .name = "rc-6-6a-20",
- .scancode_bits = 0xfffff, .repeat_period = 250 },
+ .scancode_bits = 0xfffff, .repeat_period = 114 },
[RC_PROTO_RC6_6A_24] = { .name = "rc-6-6a-24",
- .scancode_bits = 0xffffff, .repeat_period = 250 },
+ .scancode_bits = 0xffffff, .repeat_period = 114 },
[RC_PROTO_RC6_6A_32] = { .name = "rc-6-6a-32",
- .scancode_bits = 0xffffffff, .repeat_period = 250 },
+ .scancode_bits = 0xffffffff, .repeat_period = 114 },
[RC_PROTO_RC6_MCE] = { .name = "rc-6-mce",
- .scancode_bits = 0xffff7fff, .repeat_period = 250 },
+ .scancode_bits = 0xffff7fff, .repeat_period = 114 },
[RC_PROTO_SHARP] = { .name = "sharp",
- .scancode_bits = 0x1fff, .repeat_period = 250 },
- [RC_PROTO_XMP] = { .name = "xmp", .repeat_period = 250 },
- [RC_PROTO_CEC] = { .name = "cec", .repeat_period = 550 },
+ .scancode_bits = 0x1fff, .repeat_period = 125 },
+ [RC_PROTO_XMP] = { .name = "xmp", .repeat_period = 125 },
+ [RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
};
/* Used to keep track of known keymaps */
@@ -659,7 +659,8 @@ static void ir_timer_keyup(unsigned long cookie)
void rc_repeat(struct rc_dev *dev)
{
unsigned long flags;
- unsigned int timeout = protocols[dev->last_protocol].repeat_period;
+ unsigned int timeout = nsecs_to_jiffies(dev->timeout) +
+ msecs_to_jiffies(protocols[dev->last_protocol].repeat_period);
spin_lock_irqsave(&dev->keylock, flags);
@@ -669,7 +670,7 @@ void rc_repeat(struct rc_dev *dev)
input_event(dev->input_dev, EV_MSC, MSC_SCAN, dev->last_scancode);
input_sync(dev->input_dev);
- dev->keyup_jiffies = jiffies + msecs_to_jiffies(timeout);
+ dev->keyup_jiffies = jiffies + timeout;
mod_timer(&dev->timer_keyup, dev->keyup_jiffies);
out:
@@ -740,7 +741,7 @@ void rc_keydown(struct rc_dev *dev, enum rc_proto protocol, u32 scancode,
ir_do_keydown(dev, protocol, scancode, keycode, toggle);
if (dev->keypressed) {
- dev->keyup_jiffies = jiffies +
+ dev->keyup_jiffies = jiffies + nsecs_to_jiffies(dev->timeout) +
msecs_to_jiffies(protocols[protocol].repeat_period);
mod_timer(&dev->timer_keyup, dev->keyup_jiffies);
}
@@ -1553,6 +1554,7 @@ struct rc_dev *rc_allocate_device(enum rc_driver_type type)
dev->input_dev->setkeycode = ir_setkeycode;
input_set_drvdata(dev->input_dev, dev);
+ dev->timeout = IR_DEFAULT_TIMEOUT;
setup_timer(&dev->timer_keyup, ir_timer_keyup,
(unsigned long)dev);
--
2.11.0
From 6f3d979fa02a3847799d838a03ad9c5ad009a778 Mon Sep 17 00:00:00 2001
From: Sean Young <sean@mess.org>
Date: Sun, 8 Apr 2018 22:19:39 +0100
Subject: [PATCH 3/9] media: rc: mce_kbd decoder: low timeout values cause
double keydowns
backport of https://patchwork.linuxtv.org/patch/48522/
The mce keyboard repeats pressed keys every 100ms. If the IR timeout
is set to less than that, we send key up events before the repeat
arrives, so we have key up/key down for each IR repeat.
The keyboard ends any sequence with a 0 scancode, in which case all keys
are cleared so there is no need to run the timeout timer: it only exists
for the case that the final 0 was not received.
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/ir-mce_kbd-decoder.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 7afeab04dbbfd..a243d2d1ca935 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -319,11 +319,13 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
case MCIR2_KEYBOARD_NBITS:
scancode = data->body & 0xffff;
IR_dprintk(1, "keyboard data 0x%08x\n", data->body);
- if (dev->timeout)
- delay = usecs_to_jiffies(dev->timeout / 1000);
- else
- delay = msecs_to_jiffies(100);
- mod_timer(&data->rx_timeout, jiffies + delay);
+ if (scancode) {
+ delay = nsecs_to_jiffies(dev->timeout) +
+ msecs_to_jiffies(100);
+ mod_timer(&data->rx_timeout, jiffies + delay);
+ } else {
+ del_timer(&data->rx_timeout);
+ }
/* Pass data to keyboard buffer parser */
ir_mce_kbd_process_keyboard_data(data->idev, scancode);
break;
--
2.11.0
From f4d8df33339167784bb6a17e3ee2d20f9efe1b21 Mon Sep 17 00:00:00 2001
From: Sean Young <sean@mess.org>
Date: Sun, 8 Apr 2018 22:19:40 +0100
Subject: [PATCH 4/9] media: rc: mce_kbd protocol encodes two scancodes
backport of https://patchwork.linuxtv.org/patch/48518/
If two keys are pressed, then both keys are encoded in the scancode. This
makes the mce keyboard more responsive.
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/ir-mce_kbd-decoder.c | 21 ++++++++++++---------
drivers/media/rc/rc-main.c | 2 +-
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index a243d2d1ca935..2ea48a54f2b3e 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -147,13 +147,14 @@ static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data)
static void ir_mce_kbd_process_keyboard_data(struct input_dev *idev,
u32 scancode)
{
- u8 keydata = (scancode >> 8) & 0xff;
+ u8 keydata1 = (scancode >> 8) & 0xff;
+ u8 keydata2 = (scancode >> 16) & 0xff;
u8 shiftmask = scancode & 0xff;
- unsigned char keycode, maskcode;
+ unsigned char maskcode;
int i, keystate;
- IR_dprintk(1, "keyboard: keydata = 0x%02x, shiftmask = 0x%02x\n",
- keydata, shiftmask);
+ IR_dprintk(1, "keyboard: keydata2 = 0x%02x, keydata1 = 0x%02x, shiftmask = 0x%02x\n",
+ keydata2, keydata1, shiftmask);
for (i = 0; i < 7; i++) {
maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
@@ -164,10 +165,12 @@ static void ir_mce_kbd_process_keyboard_data(struct input_dev *idev,
input_report_key(idev, maskcode, keystate);
}
- if (keydata) {
- keycode = kbd_keycodes[keydata];
- input_report_key(idev, keycode, 1);
- } else {
+ if (keydata1)
+ input_report_key(idev, kbd_keycodes[keydata1], 1);
+ if (keydata2)
+ input_report_key(idev, kbd_keycodes[keydata2], 1);
+
+ if (!keydata1 && !keydata2) {
for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
input_report_key(idev, kbd_keycodes[i], 0);
}
@@ -317,7 +320,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
switch (data->wanted_bits) {
case MCIR2_KEYBOARD_NBITS:
- scancode = data->body & 0xffff;
+ scancode = data->body & 0xffffff;
IR_dprintk(1, "keyboard data 0x%08x\n", data->body);
if (scancode) {
delay = nsecs_to_jiffies(dev->timeout) +
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 36f99a0919c30..34cef7aa207c9 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -60,7 +60,7 @@ static const struct {
[RC_PROTO_SANYO] = { .name = "sanyo",
.scancode_bits = 0x1fffff, .repeat_period = 125 },
[RC_PROTO_MCIR2_KBD] = { .name = "mcir2-kbd",
- .scancode_bits = 0xffff, .repeat_period = 100 },
+ .scancode_bits = 0xffffff, .repeat_period = 100 },
[RC_PROTO_MCIR2_MSE] = { .name = "mcir2-mse",
.scancode_bits = 0x1fffff, .repeat_period = 100 },
[RC_PROTO_RC6_0] = { .name = "rc-6-0",
--
2.11.0
From 8b0ffc3eccf8737aa93c6b7bf9bc9d1e10d634bd Mon Sep 17 00:00:00 2001
From: Sean Young <sean@mess.org>
Date: Sun, 8 Apr 2018 22:19:41 +0100
Subject: [PATCH 5/9] media: rc: mce_kbd decoder: fix stuck keys
backport of https://patchwork.linuxtv.org/patch/48519/
The MCE Remote sends a 0 scancode when keys are released. If this is not
received or decoded, then keys can get "stuck"; the keyup event is not
sent since the input_sync() is missing from the timeout handler.
Cc: stable@vger.kernel.org
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/ir-mce_kbd-decoder.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 2ea48a54f2b3e..164302ec4fef0 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -130,6 +130,8 @@ static void mce_kbd_rx_timeout(unsigned long data)
for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
input_report_key(mce_kbd->idev, kbd_keycodes[i], 0);
+
+ input_sync(mce_kbd->idev);
}
static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data)
--
2.11.0
From b77de094b54449079890b8cc4fbc2f98573253b2 Mon Sep 17 00:00:00 2001
From: Sean Young <sean@mess.org>
Date: Sun, 8 Apr 2018 22:19:42 +0100
Subject: [PATCH 6/9] media: rc: mceusb: allow the timeout to be configurable
backport of https://patchwork.linuxtv.org/patch/48521/
mceusb devices have a default timeout of 100ms, but this can be changed.
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/mceusb.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index bf7aaff3aa375..160754a7a3822 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -937,6 +937,25 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier)
return 0;
}
+static int mceusb_set_timeout(struct rc_dev *dev, unsigned int timeout)
+{
+ u8 cmdbuf[4] = { MCE_CMD_PORT_IR, MCE_CMD_SETIRTIMEOUT, 0, 0 };
+ struct mceusb_dev *ir = dev->priv;
+ unsigned int units;
+
+ units = DIV_ROUND_CLOSEST(timeout, US_TO_NS(MCE_TIME_UNIT));
+
+ cmdbuf[2] = units >> 8;
+ cmdbuf[3] = units;
+
+ mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
+
+ /* get receiver timeout value */
+ mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT));
+
+ return 0;
+}
+
/*
* We don't do anything but print debug spew for many of the command bits
* we receive from the hardware, but some of them are useful information
@@ -1268,7 +1287,10 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
rc->dev.parent = dev;
rc->priv = ir;
rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
+ rc->min_timeout = US_TO_NS(MCE_TIME_UNIT);
rc->timeout = MS_TO_NS(100);
+ rc->max_timeout = 10 * IR_DEFAULT_TIMEOUT;
+ rc->s_timeout = mceusb_set_timeout;
if (!ir->flags.no_tx) {
rc->s_tx_mask = mceusb_set_tx_mask;
rc->s_tx_carrier = mceusb_set_tx_carrier;
--
2.11.0
From dccebb7231209acb8da7f9f1e8fd1e7c12c3e70f Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Sun, 15 Apr 2018 17:26:21 +0200
Subject: [PATCH 7/9] media: rc: mce_kbd decoder: remove superfluous call to
input_sync
backport of https://patchwork.linuxtv.org/patch/48681/
There is nothing to sync in this code path.
Reported-by: Matthias Reichl <hias@horus.com>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/ir-mce_kbd-decoder.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 164302ec4fef0..f057b57074c97 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -355,7 +355,6 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
IR_dprintk(1, "failed at state %i (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
- input_sync(data->idev);
return -EINVAL;
}
--
2.11.0
From 731b38824c8145bbc7d55a9c2af4e449ff5988fb Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Sun, 15 Apr 2018 17:38:49 +0200
Subject: [PATCH 8/9] media: rc: mce_kbd decoder: fix race condition
backport of https://patchwork.linuxtv.org/patch/48680/
The MCE keyboard sends both key down and key up events. We have a timeout
handler mce_kbd_rx_timeout() in case the keyup event is never received;
however, this may race with new key down events from occurring.
The race is that key down scancode arrives and key down events are
generated. The timeout handler races this and generates key up events
straight afterwards. Since the keyboard generates scancodes every 100ms,
most likely the keys will be repeated 100ms later, and now we have new
key down events and the user sees duplicate key presses.
Reported-by: Matthias Reichl <hias@horus.com>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/ir-mce_kbd-decoder.c | 23 ++++++++++++++++-------
drivers/media/rc/rc-core-priv.h | 1 +
2 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index f057b57074c97..67c37db76737f 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -120,18 +120,24 @@ static void mce_kbd_rx_timeout(unsigned long data)
struct mce_kbd_dec *mce_kbd = (struct mce_kbd_dec *)data;
int i;
unsigned char maskcode;
+ unsigned long flags;
IR_dprintk(2, "timer callback clearing all keys\n");
- for (i = 0; i < 7; i++) {
- maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
- input_report_key(mce_kbd->idev, maskcode, 0);
- }
+ spin_lock_irqsave(&mce_kbd->keylock, flags);
- for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
- input_report_key(mce_kbd->idev, kbd_keycodes[i], 0);
+ if (time_is_before_eq_jiffies(mce_kbd->rx_timeout.expires)) {
+ for (i = 0; i < 7; i++) {
+ maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
+ input_report_key(mce_kbd->idev, maskcode, 0);
+ }
- input_sync(mce_kbd->idev);
+ for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
+ input_report_key(mce_kbd->idev, kbd_keycodes[i], 0);
+
+ input_sync(mce_kbd->idev);
+ }
+ spin_unlock_irqrestore(&mce_kbd->keylock, flags);
}
static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data)
@@ -324,6 +330,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
case MCIR2_KEYBOARD_NBITS:
scancode = data->body & 0xffffff;
IR_dprintk(1, "keyboard data 0x%08x\n", data->body);
+ spin_lock(&data->keylock);
if (scancode) {
delay = nsecs_to_jiffies(dev->timeout) +
msecs_to_jiffies(100);
@@ -333,6 +340,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
}
/* Pass data to keyboard buffer parser */
ir_mce_kbd_process_keyboard_data(data->idev, scancode);
+ spin_unlock(&data->keylock);
break;
case MCIR2_MOUSE_NBITS:
scancode = data->body & 0x1fffff;
@@ -397,6 +405,7 @@ static int ir_mce_kbd_register(struct rc_dev *dev)
setup_timer(&mce_kbd->rx_timeout, mce_kbd_rx_timeout,
(unsigned long)mce_kbd);
+ spin_lock_init(&mce_kbd->keylock);
input_set_drvdata(idev, mce_kbd);
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 5fd3b5aed9ece..77928ae431041 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -97,6 +97,7 @@ struct ir_raw_event_ctrl {
struct mce_kbd_dec {
struct input_dev *idev;
struct timer_list rx_timeout;
+ spinlock_t keylock;
char name[64];
char phys[64];
int state;
--
2.11.0
From 4e363f78b2aae387980ac411e0f901caee5da9e1 Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Wed, 18 Apr 2018 13:50:52 +0200
Subject: [PATCH 9/9] media: rc: mceusb: IR of length 0 means IR timeout, not
reset
backport of https://patchwork.linuxtv.org/patch/48782/
The last usb packet with IR data will end with 0x80 (MCE_IRDATA_TRAILER).
If we reset the decoder state at this point, IR decoding can fail.
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/mceusb.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 160754a7a3822..dc7ebed00b3ac 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -1056,8 +1056,14 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
i, ir->rem + 1, false);
if (ir->rem)
ir->parser_state = PARSE_IRDATA;
- else
- ir_raw_event_reset(ir->rc);
+ else {
+ init_ir_raw_event(&rawir);
+ rawir.timeout = 1;
+ rawir.duration = ir->rc->timeout;
+ if (ir_raw_event_store_with_filter(ir->rc,
+ &rawir))
+ event = true;
+ }
break;
}
--
2.11.0

View File

@ -0,0 +1,810 @@
From 057ccfd1d18842bd2fa39c4b996a9a952c5a821d Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Tue, 27 Mar 2018 19:35:11 +0200
Subject: [PATCH 1/9] media: rc: set timeout to smallest value required by
enabled protocols
backport of https://patchwork.linuxtv.org/patch/48516/
The longer the IR timeout, the longer the rc device waits until delivering
the trailing space. So, by reducing this timeout, we reduce the delay for
the last scancode to be delivered.
Note that the lirc daemon disables all protocols, in which case we revert
back to the default value.
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/ir-jvc-decoder.c | 1 +
drivers/media/rc/ir-mce_kbd-decoder.c | 1 +
drivers/media/rc/ir-nec-decoder.c | 1 +
drivers/media/rc/ir-rc5-decoder.c | 1 +
drivers/media/rc/ir-rc6-decoder.c | 1 +
drivers/media/rc/ir-sanyo-decoder.c | 1 +
drivers/media/rc/ir-sharp-decoder.c | 1 +
drivers/media/rc/ir-sony-decoder.c | 1 +
drivers/media/rc/ir-xmp-decoder.c | 1 +
drivers/media/rc/rc-core-priv.h | 1 +
drivers/media/rc/rc-ir-raw.c | 31 ++++++++++++++++++++++++++++++-
drivers/media/rc/rc-main.c | 12 ++++++------
12 files changed, 46 insertions(+), 7 deletions(-)
diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c
index e2bd68c42edfa..fc931fe39bb75 100644
--- a/drivers/media/rc/ir-jvc-decoder.c
+++ b/drivers/media/rc/ir-jvc-decoder.c
@@ -212,6 +212,7 @@ static struct ir_raw_handler jvc_handler = {
.protocols = RC_PROTO_BIT_JVC,
.decode = ir_jvc_decode,
.encode = ir_jvc_encode,
+ .max_space = JVC_TRAILER_SPACE,
};
static int __init ir_jvc_decode_init(void)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 7c572a6436563..7afeab04dbbfd 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -474,6 +474,7 @@ static struct ir_raw_handler mce_kbd_handler = {
.encode = ir_mce_kbd_encode,
.raw_register = ir_mce_kbd_register,
.raw_unregister = ir_mce_kbd_unregister,
+ .max_space = MCIR2_MAX_LEN,
};
static int __init ir_mce_kbd_decode_init(void)
diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index a95d09acc22a5..3e12059add84d 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -264,6 +264,7 @@ static struct ir_raw_handler nec_handler = {
RC_PROTO_BIT_NEC32,
.decode = ir_nec_decode,
.encode = ir_nec_encode,
+ .max_space = NEC_TRAILER_SPACE,
};
static int __init ir_nec_decode_init(void)
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 1292f534de434..1eaca0528b691 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -282,6 +282,7 @@ static struct ir_raw_handler rc5_handler = {
RC_PROTO_BIT_RC5_SZ,
.decode = ir_rc5_decode,
.encode = ir_rc5_encode,
+ .max_space = RC5_TRAILER,
};
static int __init ir_rc5_decode_init(void)
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index 5d0d2fe3b7a7f..8c4c733a5f27b 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -408,6 +408,7 @@ static struct ir_raw_handler rc6_handler = {
RC_PROTO_BIT_RC6_MCE,
.decode = ir_rc6_decode,
.encode = ir_rc6_encode,
+ .max_space = RC6_SUFFIX_SPACE,
};
static int __init ir_rc6_decode_init(void)
diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
index 758c60956850f..935880d4889ec 100644
--- a/drivers/media/rc/ir-sanyo-decoder.c
+++ b/drivers/media/rc/ir-sanyo-decoder.c
@@ -218,6 +218,7 @@ static struct ir_raw_handler sanyo_handler = {
.protocols = RC_PROTO_BIT_SANYO,
.decode = ir_sanyo_decode,
.encode = ir_sanyo_encode,
+ .max_space = SANYO_TRAILER_SPACE,
};
static int __init ir_sanyo_decode_init(void)
diff --git a/drivers/media/rc/ir-sharp-decoder.c b/drivers/media/rc/ir-sharp-decoder.c
index 129b558acc921..96d818bd0cc98 100644
--- a/drivers/media/rc/ir-sharp-decoder.c
+++ b/drivers/media/rc/ir-sharp-decoder.c
@@ -226,6 +226,7 @@ static struct ir_raw_handler sharp_handler = {
.protocols = RC_PROTO_BIT_SHARP,
.decode = ir_sharp_decode,
.encode = ir_sharp_encode,
+ .max_space = SHARP_ECHO_SPACE,
};
static int __init ir_sharp_decode_init(void)
diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c
index a47ced763031d..d57d15b431f6d 100644
--- a/drivers/media/rc/ir-sony-decoder.c
+++ b/drivers/media/rc/ir-sony-decoder.c
@@ -221,6 +221,7 @@ static struct ir_raw_handler sony_handler = {
RC_PROTO_BIT_SONY20,
.decode = ir_sony_decode,
.encode = ir_sony_encode,
+ .max_space = SONY_TRAILER_SPACE,
};
static int __init ir_sony_decode_init(void)
diff --git a/drivers/media/rc/ir-xmp-decoder.c b/drivers/media/rc/ir-xmp-decoder.c
index 6f464be1c8d7a..1ac3a4cee69e3 100644
--- a/drivers/media/rc/ir-xmp-decoder.c
+++ b/drivers/media/rc/ir-xmp-decoder.c
@@ -198,6 +198,7 @@ static int ir_xmp_decode(struct rc_dev *dev, struct ir_raw_event ev)
static struct ir_raw_handler xmp_handler = {
.protocols = RC_PROTO_BIT_XMP,
.decode = ir_xmp_decode,
+ .max_space = XMP_TRAILER_SPACE,
};
static int __init ir_xmp_decode_init(void)
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 7da9c96cb0588..5fd3b5aed9ece 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -29,6 +29,7 @@ struct ir_raw_handler {
int (*decode)(struct rc_dev *dev, struct ir_raw_event event);
int (*encode)(enum rc_proto protocol, u32 scancode,
struct ir_raw_event *events, unsigned int max);
+ u32 max_space;
/* These two should only be used by the lirc decoder */
int (*raw_register)(struct rc_dev *dev);
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 503bc425a187c..7f0197bf5d32d 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -215,7 +215,36 @@ ir_raw_get_allowed_protocols(void)
static int change_protocol(struct rc_dev *dev, u64 *rc_proto)
{
- /* the caller will update dev->enabled_protocols */
+ struct ir_raw_handler *handler;
+ u32 timeout = 0;
+
+ if (!dev->max_timeout)
+ return 0;
+
+ mutex_lock(&ir_raw_handler_lock);
+ list_for_each_entry(handler, &ir_raw_handler_list, list) {
+ if (handler->protocols & *rc_proto) {
+ if (timeout < handler->max_space)
+ timeout = handler->max_space;
+ }
+ }
+ mutex_unlock(&ir_raw_handler_lock);
+
+ if (timeout == 0)
+ timeout = IR_DEFAULT_TIMEOUT;
+ else
+ timeout += MS_TO_NS(20);
+
+ if (timeout < dev->min_timeout)
+ timeout = dev->min_timeout;
+ else if (timeout > dev->max_timeout)
+ timeout = dev->max_timeout;
+
+ if (dev->s_timeout)
+ dev->s_timeout(dev, timeout);
+ else
+ dev->timeout = timeout;
+
return 0;
}
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 72f381522cb26..e7e20bcfe2729 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1161,6 +1161,9 @@ static ssize_t store_protocols(struct device *device,
if (rc < 0)
goto out;
+ if (dev->driver_type == RC_DRIVER_IR_RAW)
+ ir_raw_load_modules(&new_protocols);
+
rc = dev->change_protocol(dev, &new_protocols);
if (rc < 0) {
IR_dprintk(1, "Error setting protocols to 0x%llx\n",
@@ -1168,9 +1171,6 @@ static ssize_t store_protocols(struct device *device,
goto out;
}
- if (dev->driver_type == RC_DRIVER_IR_RAW)
- ir_raw_load_modules(&new_protocols);
-
if (new_protocols != old_protocols) {
*current_protocols = new_protocols;
IR_dprintk(1, "Protocols changed to 0x%llx\n",
@@ -1638,6 +1638,9 @@ static int rc_prepare_rx_device(struct rc_dev *dev)
rc_proto = BIT_ULL(rc_map->rc_proto);
+ if (dev->driver_type == RC_DRIVER_IR_RAW)
+ ir_raw_load_modules(&rc_proto);
+
if (dev->change_protocol) {
rc = dev->change_protocol(dev, &rc_proto);
if (rc < 0)
@@ -1645,9 +1648,6 @@ static int rc_prepare_rx_device(struct rc_dev *dev)
dev->enabled_protocols = rc_proto;
}
- if (dev->driver_type == RC_DRIVER_IR_RAW)
- ir_raw_load_modules(&rc_proto);
-
set_bit(EV_KEY, dev->input_dev->evbit);
set_bit(EV_REP, dev->input_dev->evbit);
set_bit(EV_MSC, dev->input_dev->evbit);
--
2.11.0
From 00f54931b0ff7202020567544605b7e3c4f1dee8 Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Tue, 27 Mar 2018 19:45:36 +0200
Subject: [PATCH 2/9] media: rc: per-protocol repeat period and minimum keyup
timer
backport of https://patchwork.linuxtv.org/patch/48520/
Each IR protocol has its own repeat period. We can minimise the keyup
timer to be the protocol period + IR timeout. This makes keys less
"sticky" and makes IR more reactive and nicer to use.
This feature was previously attempted in commit d57ea877af38 ("media: rc:
per-protocol repeat period"), but that did not take the IR timeout into
account, and had to be reverted.
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/cec/cec-core.c | 2 +-
drivers/media/rc/ir-lirc-codec.c | 2 +-
drivers/media/rc/rc-main.c | 54 +++++++++++++++++++++-------------------
3 files changed, 30 insertions(+), 28 deletions(-)
diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c
index 648136e552d5b..4cf35e4af7bd6 100644
--- a/drivers/media/cec/cec-core.c
+++ b/drivers/media/cec/cec-core.c
@@ -280,7 +280,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
adap->rc->enabled_protocols = RC_PROTO_BIT_CEC;
adap->rc->priv = adap;
adap->rc->map_name = RC_MAP_CEC;
- adap->rc->timeout = MS_TO_NS(100);
+ adap->rc->timeout = MS_TO_NS(550);
adap->rc_last_scancode = -1;
#endif
return adap;
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 4c8f456238bca..ef7e43038092f 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -314,7 +314,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
break;
case LIRC_SET_REC_TIMEOUT_REPORTS:
- if (!dev->timeout)
+ if (dev->driver_type != RC_DRIVER_IR_RAW)
return -ENOTTY;
lirc->send_timeout_reports = !!val;
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index e7e20bcfe2729..36f99a0919c30 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -35,48 +35,48 @@ static const struct {
unsigned int repeat_period;
unsigned int scancode_bits;
} protocols[] = {
- [RC_PROTO_UNKNOWN] = { .name = "unknown", .repeat_period = 250 },
- [RC_PROTO_OTHER] = { .name = "other", .repeat_period = 250 },
+ [RC_PROTO_UNKNOWN] = { .name = "unknown", .repeat_period = 125 },
+ [RC_PROTO_OTHER] = { .name = "other", .repeat_period = 125 },
[RC_PROTO_RC5] = { .name = "rc-5",
- .scancode_bits = 0x1f7f, .repeat_period = 250 },
+ .scancode_bits = 0x1f7f, .repeat_period = 114 },
[RC_PROTO_RC5X_20] = { .name = "rc-5x-20",
- .scancode_bits = 0x1f7f3f, .repeat_period = 250 },
+ .scancode_bits = 0x1f7f3f, .repeat_period = 114 },
[RC_PROTO_RC5_SZ] = { .name = "rc-5-sz",
- .scancode_bits = 0x2fff, .repeat_period = 250 },
+ .scancode_bits = 0x2fff, .repeat_period = 114 },
[RC_PROTO_JVC] = { .name = "jvc",
- .scancode_bits = 0xffff, .repeat_period = 250 },
+ .scancode_bits = 0xffff, .repeat_period = 125 },
[RC_PROTO_SONY12] = { .name = "sony-12",
- .scancode_bits = 0x1f007f, .repeat_period = 250 },
+ .scancode_bits = 0x1f007f, .repeat_period = 100 },
[RC_PROTO_SONY15] = { .name = "sony-15",
- .scancode_bits = 0xff007f, .repeat_period = 250 },
+ .scancode_bits = 0xff007f, .repeat_period = 100 },
[RC_PROTO_SONY20] = { .name = "sony-20",
- .scancode_bits = 0x1fff7f, .repeat_period = 250 },
+ .scancode_bits = 0x1fff7f, .repeat_period = 100 },
[RC_PROTO_NEC] = { .name = "nec",
- .scancode_bits = 0xffff, .repeat_period = 250 },
+ .scancode_bits = 0xffff, .repeat_period = 110 },
[RC_PROTO_NECX] = { .name = "nec-x",
- .scancode_bits = 0xffffff, .repeat_period = 250 },
+ .scancode_bits = 0xffffff, .repeat_period = 110 },
[RC_PROTO_NEC32] = { .name = "nec-32",
- .scancode_bits = 0xffffffff, .repeat_period = 250 },
+ .scancode_bits = 0xffffffff, .repeat_period = 110 },
[RC_PROTO_SANYO] = { .name = "sanyo",
- .scancode_bits = 0x1fffff, .repeat_period = 250 },
+ .scancode_bits = 0x1fffff, .repeat_period = 125 },
[RC_PROTO_MCIR2_KBD] = { .name = "mcir2-kbd",
- .scancode_bits = 0xffff, .repeat_period = 250 },
+ .scancode_bits = 0xffff, .repeat_period = 100 },
[RC_PROTO_MCIR2_MSE] = { .name = "mcir2-mse",
- .scancode_bits = 0x1fffff, .repeat_period = 250 },
+ .scancode_bits = 0x1fffff, .repeat_period = 100 },
[RC_PROTO_RC6_0] = { .name = "rc-6-0",
- .scancode_bits = 0xffff, .repeat_period = 250 },
+ .scancode_bits = 0xffff, .repeat_period = 114 },
[RC_PROTO_RC6_6A_20] = { .name = "rc-6-6a-20",
- .scancode_bits = 0xfffff, .repeat_period = 250 },
+ .scancode_bits = 0xfffff, .repeat_period = 114 },
[RC_PROTO_RC6_6A_24] = { .name = "rc-6-6a-24",
- .scancode_bits = 0xffffff, .repeat_period = 250 },
+ .scancode_bits = 0xffffff, .repeat_period = 114 },
[RC_PROTO_RC6_6A_32] = { .name = "rc-6-6a-32",
- .scancode_bits = 0xffffffff, .repeat_period = 250 },
+ .scancode_bits = 0xffffffff, .repeat_period = 114 },
[RC_PROTO_RC6_MCE] = { .name = "rc-6-mce",
- .scancode_bits = 0xffff7fff, .repeat_period = 250 },
+ .scancode_bits = 0xffff7fff, .repeat_period = 114 },
[RC_PROTO_SHARP] = { .name = "sharp",
- .scancode_bits = 0x1fff, .repeat_period = 250 },
- [RC_PROTO_XMP] = { .name = "xmp", .repeat_period = 250 },
- [RC_PROTO_CEC] = { .name = "cec", .repeat_period = 550 },
+ .scancode_bits = 0x1fff, .repeat_period = 125 },
+ [RC_PROTO_XMP] = { .name = "xmp", .repeat_period = 125 },
+ [RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
};
/* Used to keep track of known keymaps */
@@ -659,7 +659,8 @@ static void ir_timer_keyup(unsigned long cookie)
void rc_repeat(struct rc_dev *dev)
{
unsigned long flags;
- unsigned int timeout = protocols[dev->last_protocol].repeat_period;
+ unsigned int timeout = nsecs_to_jiffies(dev->timeout) +
+ msecs_to_jiffies(protocols[dev->last_protocol].repeat_period);
spin_lock_irqsave(&dev->keylock, flags);
@@ -669,7 +670,7 @@ void rc_repeat(struct rc_dev *dev)
input_event(dev->input_dev, EV_MSC, MSC_SCAN, dev->last_scancode);
input_sync(dev->input_dev);
- dev->keyup_jiffies = jiffies + msecs_to_jiffies(timeout);
+ dev->keyup_jiffies = jiffies + timeout;
mod_timer(&dev->timer_keyup, dev->keyup_jiffies);
out:
@@ -740,7 +741,7 @@ void rc_keydown(struct rc_dev *dev, enum rc_proto protocol, u32 scancode,
ir_do_keydown(dev, protocol, scancode, keycode, toggle);
if (dev->keypressed) {
- dev->keyup_jiffies = jiffies +
+ dev->keyup_jiffies = jiffies + nsecs_to_jiffies(dev->timeout) +
msecs_to_jiffies(protocols[protocol].repeat_period);
mod_timer(&dev->timer_keyup, dev->keyup_jiffies);
}
@@ -1553,6 +1554,7 @@ struct rc_dev *rc_allocate_device(enum rc_driver_type type)
dev->input_dev->setkeycode = ir_setkeycode;
input_set_drvdata(dev->input_dev, dev);
+ dev->timeout = IR_DEFAULT_TIMEOUT;
setup_timer(&dev->timer_keyup, ir_timer_keyup,
(unsigned long)dev);
--
2.11.0
From 6f3d979fa02a3847799d838a03ad9c5ad009a778 Mon Sep 17 00:00:00 2001
From: Sean Young <sean@mess.org>
Date: Sun, 8 Apr 2018 22:19:39 +0100
Subject: [PATCH 3/9] media: rc: mce_kbd decoder: low timeout values cause
double keydowns
backport of https://patchwork.linuxtv.org/patch/48522/
The mce keyboard repeats pressed keys every 100ms. If the IR timeout
is set to less than that, we send key up events before the repeat
arrives, so we have key up/key down for each IR repeat.
The keyboard ends any sequence with a 0 scancode, in which case all keys
are cleared so there is no need to run the timeout timer: it only exists
for the case that the final 0 was not received.
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/ir-mce_kbd-decoder.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 7afeab04dbbfd..a243d2d1ca935 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -319,11 +319,13 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
case MCIR2_KEYBOARD_NBITS:
scancode = data->body & 0xffff;
IR_dprintk(1, "keyboard data 0x%08x\n", data->body);
- if (dev->timeout)
- delay = usecs_to_jiffies(dev->timeout / 1000);
- else
- delay = msecs_to_jiffies(100);
- mod_timer(&data->rx_timeout, jiffies + delay);
+ if (scancode) {
+ delay = nsecs_to_jiffies(dev->timeout) +
+ msecs_to_jiffies(100);
+ mod_timer(&data->rx_timeout, jiffies + delay);
+ } else {
+ del_timer(&data->rx_timeout);
+ }
/* Pass data to keyboard buffer parser */
ir_mce_kbd_process_keyboard_data(data->idev, scancode);
break;
--
2.11.0
From f4d8df33339167784bb6a17e3ee2d20f9efe1b21 Mon Sep 17 00:00:00 2001
From: Sean Young <sean@mess.org>
Date: Sun, 8 Apr 2018 22:19:40 +0100
Subject: [PATCH 4/9] media: rc: mce_kbd protocol encodes two scancodes
backport of https://patchwork.linuxtv.org/patch/48518/
If two keys are pressed, then both keys are encoded in the scancode. This
makes the mce keyboard more responsive.
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/ir-mce_kbd-decoder.c | 21 ++++++++++++---------
drivers/media/rc/rc-main.c | 2 +-
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index a243d2d1ca935..2ea48a54f2b3e 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -147,13 +147,14 @@ static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data)
static void ir_mce_kbd_process_keyboard_data(struct input_dev *idev,
u32 scancode)
{
- u8 keydata = (scancode >> 8) & 0xff;
+ u8 keydata1 = (scancode >> 8) & 0xff;
+ u8 keydata2 = (scancode >> 16) & 0xff;
u8 shiftmask = scancode & 0xff;
- unsigned char keycode, maskcode;
+ unsigned char maskcode;
int i, keystate;
- IR_dprintk(1, "keyboard: keydata = 0x%02x, shiftmask = 0x%02x\n",
- keydata, shiftmask);
+ IR_dprintk(1, "keyboard: keydata2 = 0x%02x, keydata1 = 0x%02x, shiftmask = 0x%02x\n",
+ keydata2, keydata1, shiftmask);
for (i = 0; i < 7; i++) {
maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
@@ -164,10 +165,12 @@ static void ir_mce_kbd_process_keyboard_data(struct input_dev *idev,
input_report_key(idev, maskcode, keystate);
}
- if (keydata) {
- keycode = kbd_keycodes[keydata];
- input_report_key(idev, keycode, 1);
- } else {
+ if (keydata1)
+ input_report_key(idev, kbd_keycodes[keydata1], 1);
+ if (keydata2)
+ input_report_key(idev, kbd_keycodes[keydata2], 1);
+
+ if (!keydata1 && !keydata2) {
for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
input_report_key(idev, kbd_keycodes[i], 0);
}
@@ -317,7 +320,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
switch (data->wanted_bits) {
case MCIR2_KEYBOARD_NBITS:
- scancode = data->body & 0xffff;
+ scancode = data->body & 0xffffff;
IR_dprintk(1, "keyboard data 0x%08x\n", data->body);
if (scancode) {
delay = nsecs_to_jiffies(dev->timeout) +
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 36f99a0919c30..34cef7aa207c9 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -60,7 +60,7 @@ static const struct {
[RC_PROTO_SANYO] = { .name = "sanyo",
.scancode_bits = 0x1fffff, .repeat_period = 125 },
[RC_PROTO_MCIR2_KBD] = { .name = "mcir2-kbd",
- .scancode_bits = 0xffff, .repeat_period = 100 },
+ .scancode_bits = 0xffffff, .repeat_period = 100 },
[RC_PROTO_MCIR2_MSE] = { .name = "mcir2-mse",
.scancode_bits = 0x1fffff, .repeat_period = 100 },
[RC_PROTO_RC6_0] = { .name = "rc-6-0",
--
2.11.0
From 8b0ffc3eccf8737aa93c6b7bf9bc9d1e10d634bd Mon Sep 17 00:00:00 2001
From: Sean Young <sean@mess.org>
Date: Sun, 8 Apr 2018 22:19:41 +0100
Subject: [PATCH 5/9] media: rc: mce_kbd decoder: fix stuck keys
backport of https://patchwork.linuxtv.org/patch/48519/
The MCE Remote sends a 0 scancode when keys are released. If this is not
received or decoded, then keys can get "stuck"; the keyup event is not
sent since the input_sync() is missing from the timeout handler.
Cc: stable@vger.kernel.org
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/ir-mce_kbd-decoder.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 2ea48a54f2b3e..164302ec4fef0 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -130,6 +130,8 @@ static void mce_kbd_rx_timeout(unsigned long data)
for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
input_report_key(mce_kbd->idev, kbd_keycodes[i], 0);
+
+ input_sync(mce_kbd->idev);
}
static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data)
--
2.11.0
From b77de094b54449079890b8cc4fbc2f98573253b2 Mon Sep 17 00:00:00 2001
From: Sean Young <sean@mess.org>
Date: Sun, 8 Apr 2018 22:19:42 +0100
Subject: [PATCH 6/9] media: rc: mceusb: allow the timeout to be configurable
backport of https://patchwork.linuxtv.org/patch/48521/
mceusb devices have a default timeout of 100ms, but this can be changed.
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/mceusb.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index bf7aaff3aa375..160754a7a3822 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -937,6 +937,25 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier)
return 0;
}
+static int mceusb_set_timeout(struct rc_dev *dev, unsigned int timeout)
+{
+ u8 cmdbuf[4] = { MCE_CMD_PORT_IR, MCE_CMD_SETIRTIMEOUT, 0, 0 };
+ struct mceusb_dev *ir = dev->priv;
+ unsigned int units;
+
+ units = DIV_ROUND_CLOSEST(timeout, US_TO_NS(MCE_TIME_UNIT));
+
+ cmdbuf[2] = units >> 8;
+ cmdbuf[3] = units;
+
+ mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
+
+ /* get receiver timeout value */
+ mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT));
+
+ return 0;
+}
+
/*
* We don't do anything but print debug spew for many of the command bits
* we receive from the hardware, but some of them are useful information
@@ -1268,7 +1287,10 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
rc->dev.parent = dev;
rc->priv = ir;
rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
+ rc->min_timeout = US_TO_NS(MCE_TIME_UNIT);
rc->timeout = MS_TO_NS(100);
+ rc->max_timeout = 10 * IR_DEFAULT_TIMEOUT;
+ rc->s_timeout = mceusb_set_timeout;
if (!ir->flags.no_tx) {
rc->s_tx_mask = mceusb_set_tx_mask;
rc->s_tx_carrier = mceusb_set_tx_carrier;
--
2.11.0
From dccebb7231209acb8da7f9f1e8fd1e7c12c3e70f Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Sun, 15 Apr 2018 17:26:21 +0200
Subject: [PATCH 7/9] media: rc: mce_kbd decoder: remove superfluous call to
input_sync
backport of https://patchwork.linuxtv.org/patch/48681/
There is nothing to sync in this code path.
Reported-by: Matthias Reichl <hias@horus.com>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/ir-mce_kbd-decoder.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 164302ec4fef0..f057b57074c97 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -355,7 +355,6 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
IR_dprintk(1, "failed at state %i (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
- input_sync(data->idev);
return -EINVAL;
}
--
2.11.0
From 731b38824c8145bbc7d55a9c2af4e449ff5988fb Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Sun, 15 Apr 2018 17:38:49 +0200
Subject: [PATCH 8/9] media: rc: mce_kbd decoder: fix race condition
backport of https://patchwork.linuxtv.org/patch/48680/
The MCE keyboard sends both key down and key up events. We have a timeout
handler mce_kbd_rx_timeout() in case the keyup event is never received;
however, this may race with new key down events from occurring.
The race is that key down scancode arrives and key down events are
generated. The timeout handler races this and generates key up events
straight afterwards. Since the keyboard generates scancodes every 100ms,
most likely the keys will be repeated 100ms later, and now we have new
key down events and the user sees duplicate key presses.
Reported-by: Matthias Reichl <hias@horus.com>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/ir-mce_kbd-decoder.c | 23 ++++++++++++++++-------
drivers/media/rc/rc-core-priv.h | 1 +
2 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index f057b57074c97..67c37db76737f 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -120,18 +120,24 @@ static void mce_kbd_rx_timeout(unsigned long data)
struct mce_kbd_dec *mce_kbd = (struct mce_kbd_dec *)data;
int i;
unsigned char maskcode;
+ unsigned long flags;
IR_dprintk(2, "timer callback clearing all keys\n");
- for (i = 0; i < 7; i++) {
- maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
- input_report_key(mce_kbd->idev, maskcode, 0);
- }
+ spin_lock_irqsave(&mce_kbd->keylock, flags);
- for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
- input_report_key(mce_kbd->idev, kbd_keycodes[i], 0);
+ if (time_is_before_eq_jiffies(mce_kbd->rx_timeout.expires)) {
+ for (i = 0; i < 7; i++) {
+ maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
+ input_report_key(mce_kbd->idev, maskcode, 0);
+ }
- input_sync(mce_kbd->idev);
+ for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
+ input_report_key(mce_kbd->idev, kbd_keycodes[i], 0);
+
+ input_sync(mce_kbd->idev);
+ }
+ spin_unlock_irqrestore(&mce_kbd->keylock, flags);
}
static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data)
@@ -324,6 +330,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
case MCIR2_KEYBOARD_NBITS:
scancode = data->body & 0xffffff;
IR_dprintk(1, "keyboard data 0x%08x\n", data->body);
+ spin_lock(&data->keylock);
if (scancode) {
delay = nsecs_to_jiffies(dev->timeout) +
msecs_to_jiffies(100);
@@ -333,6 +340,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
}
/* Pass data to keyboard buffer parser */
ir_mce_kbd_process_keyboard_data(data->idev, scancode);
+ spin_unlock(&data->keylock);
break;
case MCIR2_MOUSE_NBITS:
scancode = data->body & 0x1fffff;
@@ -397,6 +405,7 @@ static int ir_mce_kbd_register(struct rc_dev *dev)
setup_timer(&mce_kbd->rx_timeout, mce_kbd_rx_timeout,
(unsigned long)mce_kbd);
+ spin_lock_init(&mce_kbd->keylock);
input_set_drvdata(idev, mce_kbd);
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 5fd3b5aed9ece..77928ae431041 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -97,6 +97,7 @@ struct ir_raw_event_ctrl {
struct mce_kbd_dec {
struct input_dev *idev;
struct timer_list rx_timeout;
+ spinlock_t keylock;
char name[64];
char phys[64];
int state;
--
2.11.0
From 4e363f78b2aae387980ac411e0f901caee5da9e1 Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Wed, 18 Apr 2018 13:50:52 +0200
Subject: [PATCH 9/9] media: rc: mceusb: IR of length 0 means IR timeout, not
reset
backport of https://patchwork.linuxtv.org/patch/48782/
The last usb packet with IR data will end with 0x80 (MCE_IRDATA_TRAILER).
If we reset the decoder state at this point, IR decoding can fail.
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Matthias Reichl <hias@horus.com>
---
drivers/media/rc/mceusb.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 160754a7a3822..dc7ebed00b3ac 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -1056,8 +1056,14 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
i, ir->rem + 1, false);
if (ir->rem)
ir->parser_state = PARSE_IRDATA;
- else
- ir_raw_event_reset(ir->rc);
+ else {
+ init_ir_raw_event(&rawir);
+ rawir.timeout = 1;
+ rawir.duration = ir->rc->timeout;
+ if (ir_raw_event_store_with_filter(ir->rc,
+ &rawir))
+ event = true;
+ }
break;
}
--
2.11.0