diff --git a/packages/linux/patches/default/linux-999-improve-ir-timeout-handling.patch b/packages/linux/patches/default/linux-999-improve-ir-timeout-handling.patch new file mode 100644 index 0000000000..7941fbd121 --- /dev/null +++ b/packages/linux/patches/default/linux-999-improve-ir-timeout-handling.patch @@ -0,0 +1,810 @@ +From 057ccfd1d18842bd2fa39c4b996a9a952c5a821d Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +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 +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Sean Young +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Sean Young +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Matthias Reichl +--- + 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 + diff --git a/packages/linux/patches/raspberrypi/linux-999-improve-ir-timeout-handling.patch b/packages/linux/patches/raspberrypi/linux-999-improve-ir-timeout-handling.patch new file mode 100644 index 0000000000..7941fbd121 --- /dev/null +++ b/packages/linux/patches/raspberrypi/linux-999-improve-ir-timeout-handling.patch @@ -0,0 +1,810 @@ +From 057ccfd1d18842bd2fa39c4b996a9a952c5a821d Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +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 +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Sean Young +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Sean Young +Signed-off-by: Matthias Reichl +--- + 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 +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 +Signed-off-by: Matthias Reichl +--- + 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 +