diff options
Diffstat (limited to 'drivers/media/rc')
26 files changed, 821 insertions, 192 deletions
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index eb2c3b6eca7f..1021c08a9ba4 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -25,6 +25,19 @@ config LIRC passes raw IR to and from userspace, which is needed for IR transmitting (aka "blasting") and for the lirc daemon. +config BPF_LIRC_MODE2 + bool "Support for eBPF programs attached to lirc devices" + depends on BPF_SYSCALL + depends on RC_CORE=y + depends on LIRC + help + Allow attaching eBPF programs to a lirc device using the bpf(2) + syscall command BPF_PROG_ATTACH. This is supported for raw IR + receivers. + + These eBPF programs can be used to decode IR into scancodes, for + IR protocols not supported by the kernel decoders. + menuconfig RC_DECODERS bool "Remote controller decoders" depends on RC_CORE @@ -149,7 +162,7 @@ config RC_ATI_REMOTE config IR_ENE tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)" - depends on PNP + depends on PNP || COMPILE_TEST depends on RC_CORE ---help--- Say Y here to enable support for integrated infrared receiver @@ -210,7 +223,7 @@ config IR_MCEUSB config IR_ITE_CIR tristate "ITE Tech Inc. IT8712/IT8512 Consumer Infrared Transceiver" - depends on PNP + depends on PNP || COMPILE_TEST depends on RC_CORE ---help--- Say Y here to enable support for integrated infrared receivers @@ -223,7 +236,7 @@ config IR_ITE_CIR config IR_FINTEK tristate "Fintek Consumer Infrared Transceiver" - depends on PNP + depends on PNP || COMPILE_TEST depends on RC_CORE ---help--- Say Y here to enable support for integrated infrared receiver @@ -257,7 +270,7 @@ config IR_MTK config IR_NUVOTON tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" - depends on PNP + depends on PNP || COMPILE_TEST depends on RC_CORE ---help--- Say Y here to enable support for integrated infrared receiver @@ -305,7 +318,7 @@ config IR_STREAMZAP config IR_WINBOND_CIR tristate "Winbond IR remote control" - depends on X86 && PNP + depends on (X86 && PNP) || COMPILE_TEST depends on RC_CORE select NEW_LEDS select LEDS_CLASS diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 2e1c87066f6c..e0340d043fe8 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -5,6 +5,7 @@ obj-y += keymaps/ obj-$(CONFIG_RC_CORE) += rc-core.o rc-core-y := rc-main.o rc-ir-raw.o rc-core-$(CONFIG_LIRC) += lirc_dev.o +rc-core-$(CONFIG_BPF_LIRC_MODE2) += bpf-lirc.o obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o diff --git a/drivers/media/rc/bpf-lirc.c b/drivers/media/rc/bpf-lirc.c new file mode 100644 index 000000000000..40826bba06b6 --- /dev/null +++ b/drivers/media/rc/bpf-lirc.c @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: GPL-2.0 +// bpf-lirc.c - handles bpf +// +// Copyright (C) 2018 Sean Young <sean@mess.org> + +#include <linux/bpf.h> +#include <linux/filter.h> +#include <linux/bpf_lirc.h> +#include "rc-core-priv.h" + +/* + * BPF interface for raw IR + */ +const struct bpf_prog_ops lirc_mode2_prog_ops = { +}; + +BPF_CALL_1(bpf_rc_repeat, u32*, sample) +{ + struct ir_raw_event_ctrl *ctrl; + + ctrl = container_of(sample, struct ir_raw_event_ctrl, bpf_sample); + + rc_repeat(ctrl->dev); + + return 0; +} + +static const struct bpf_func_proto rc_repeat_proto = { + .func = bpf_rc_repeat, + .gpl_only = true, /* rc_repeat is EXPORT_SYMBOL_GPL */ + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, +}; + +/* + * Currently rc-core does not support 64-bit scancodes, but there are many + * known protocols with more than 32 bits. So, define the interface as u64 + * as a future-proof. + */ +BPF_CALL_4(bpf_rc_keydown, u32*, sample, u32, protocol, u64, scancode, + u32, toggle) +{ + struct ir_raw_event_ctrl *ctrl; + + ctrl = container_of(sample, struct ir_raw_event_ctrl, bpf_sample); + + rc_keydown(ctrl->dev, protocol, scancode, toggle != 0); + + return 0; +} + +static const struct bpf_func_proto rc_keydown_proto = { + .func = bpf_rc_keydown, + .gpl_only = true, /* rc_keydown is EXPORT_SYMBOL_GPL */ + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_ANYTHING, + .arg4_type = ARG_ANYTHING, +}; + +static const struct bpf_func_proto * +lirc_mode2_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) +{ + switch (func_id) { + case BPF_FUNC_rc_repeat: + return &rc_repeat_proto; + case BPF_FUNC_rc_keydown: + return &rc_keydown_proto; + case BPF_FUNC_map_lookup_elem: + return &bpf_map_lookup_elem_proto; + case BPF_FUNC_map_update_elem: + return &bpf_map_update_elem_proto; + case BPF_FUNC_map_delete_elem: + return &bpf_map_delete_elem_proto; + case BPF_FUNC_ktime_get_ns: + return &bpf_ktime_get_ns_proto; + case BPF_FUNC_tail_call: + return &bpf_tail_call_proto; + case BPF_FUNC_get_prandom_u32: + return &bpf_get_prandom_u32_proto; + case BPF_FUNC_trace_printk: + if (capable(CAP_SYS_ADMIN)) + return bpf_get_trace_printk_proto(); + /* fall through */ + default: + return NULL; + } +} + +static bool lirc_mode2_is_valid_access(int off, int size, + enum bpf_access_type type, + const struct bpf_prog *prog, + struct bpf_insn_access_aux *info) +{ + /* We have one field of u32 */ + return type == BPF_READ && off == 0 && size == sizeof(u32); +} + +const struct bpf_verifier_ops lirc_mode2_verifier_ops = { + .get_func_proto = lirc_mode2_func_proto, + .is_valid_access = lirc_mode2_is_valid_access +}; + +#define BPF_MAX_PROGS 64 + +static int lirc_bpf_attach(struct rc_dev *rcdev, struct bpf_prog *prog) +{ + struct bpf_prog_array __rcu *old_array; + struct bpf_prog_array *new_array; + struct ir_raw_event_ctrl *raw; + int ret; + + if (rcdev->driver_type != RC_DRIVER_IR_RAW) + return -EINVAL; + + ret = mutex_lock_interruptible(&ir_raw_handler_lock); + if (ret) + return ret; + + raw = rcdev->raw; + if (!raw) { + ret = -ENODEV; + goto unlock; + } + + if (raw->progs && bpf_prog_array_length(raw->progs) >= BPF_MAX_PROGS) { + ret = -E2BIG; + goto unlock; + } + + old_array = raw->progs; + ret = bpf_prog_array_copy(old_array, NULL, prog, &new_array); + if (ret < 0) + goto unlock; + + rcu_assign_pointer(raw->progs, new_array); + bpf_prog_array_free(old_array); + +unlock: + mutex_unlock(&ir_raw_handler_lock); + return ret; +} + +static int lirc_bpf_detach(struct rc_dev *rcdev, struct bpf_prog *prog) +{ + struct bpf_prog_array __rcu *old_array; + struct bpf_prog_array *new_array; + struct ir_raw_event_ctrl *raw; + int ret; + + if (rcdev->driver_type != RC_DRIVER_IR_RAW) + return -EINVAL; + + ret = mutex_lock_interruptible(&ir_raw_handler_lock); + if (ret) + return ret; + + raw = rcdev->raw; + if (!raw) { + ret = -ENODEV; + goto unlock; + } + + old_array = raw->progs; + ret = bpf_prog_array_copy(old_array, prog, NULL, &new_array); + /* + * Do not use bpf_prog_array_delete_safe() as we would end up + * with a dummy entry in the array, and the we would free the + * dummy in lirc_bpf_free() + */ + if (ret) + goto unlock; + + rcu_assign_pointer(raw->progs, new_array); + bpf_prog_array_free(old_array); +unlock: + mutex_unlock(&ir_raw_handler_lock); + return ret; +} + +void lirc_bpf_run(struct rc_dev *rcdev, u32 sample) +{ + struct ir_raw_event_ctrl *raw = rcdev->raw; + + raw->bpf_sample = sample; + + if (raw->progs) + BPF_PROG_RUN_ARRAY(raw->progs, &raw->bpf_sample, BPF_PROG_RUN); +} + +/* + * This should be called once the rc thread has been stopped, so there can be + * no concurrent bpf execution. + */ +void lirc_bpf_free(struct rc_dev *rcdev) +{ + struct bpf_prog **progs; + + if (!rcdev->raw->progs) + return; + + progs = rcu_dereference(rcdev->raw->progs)->progs; + while (*progs) + bpf_prog_put(*progs++); + + bpf_prog_array_free(rcdev->raw->progs); +} + +int lirc_prog_attach(const union bpf_attr *attr) +{ + struct bpf_prog *prog; + struct rc_dev *rcdev; + int ret; + + if (attr->attach_flags) + return -EINVAL; + + prog = bpf_prog_get_type(attr->attach_bpf_fd, + BPF_PROG_TYPE_LIRC_MODE2); + if (IS_ERR(prog)) + return PTR_ERR(prog); + + rcdev = rc_dev_get_from_fd(attr->target_fd); + if (IS_ERR(rcdev)) { + bpf_prog_put(prog); + return PTR_ERR(rcdev); + } + + ret = lirc_bpf_attach(rcdev, prog); + if (ret) + bpf_prog_put(prog); + + put_device(&rcdev->dev); + + return ret; +} + +int lirc_prog_detach(const union bpf_attr *attr) +{ + struct bpf_prog *prog; + struct rc_dev *rcdev; + int ret; + + if (attr->attach_flags) + return -EINVAL; + + prog = bpf_prog_get_type(attr->attach_bpf_fd, + BPF_PROG_TYPE_LIRC_MODE2); + if (IS_ERR(prog)) + return PTR_ERR(prog); + + rcdev = rc_dev_get_from_fd(attr->target_fd); + if (IS_ERR(rcdev)) { + bpf_prog_put(prog); + return PTR_ERR(rcdev); + } + + ret = lirc_bpf_detach(rcdev, prog); + + bpf_prog_put(prog); + put_device(&rcdev->dev); + + return ret; +} + +int lirc_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr) +{ + __u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids); + struct bpf_prog_array __rcu *progs; + struct rc_dev *rcdev; + u32 cnt, flags = 0; + int ret; + + if (attr->query.query_flags) + return -EINVAL; + + rcdev = rc_dev_get_from_fd(attr->query.target_fd); + if (IS_ERR(rcdev)) + return PTR_ERR(rcdev); + + if (rcdev->driver_type != RC_DRIVER_IR_RAW) { + ret = -EINVAL; + goto put; + } + + ret = mutex_lock_interruptible(&ir_raw_handler_lock); + if (ret) + goto put; + + progs = rcdev->raw->progs; + cnt = progs ? bpf_prog_array_length(progs) : 0; + + if (copy_to_user(&uattr->query.prog_cnt, &cnt, sizeof(cnt))) { + ret = -EFAULT; + goto unlock; + } + + if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags))) { + ret = -EFAULT; + goto unlock; + } + + if (attr->query.prog_cnt != 0 && prog_ids && cnt) + ret = bpf_prog_array_copy_to_user(progs, prog_ids, cnt); + +unlock: + mutex_unlock(&ir_raw_handler_lock); +put: + put_device(&rcdev->dev); + + return ret; +} diff --git a/drivers/media/rc/ir-imon-decoder.c b/drivers/media/rc/ir-imon-decoder.c index a1ff06a26542..67c1b0c15aae 100644 --- a/drivers/media/rc/ir-imon-decoder.c +++ b/drivers/media/rc/ir-imon-decoder.c @@ -31,9 +31,69 @@ enum imon_state { STATE_INACTIVE, STATE_BIT_CHK, STATE_BIT_START, - STATE_FINISHED + STATE_FINISHED, + STATE_ERROR, }; +static void ir_imon_decode_scancode(struct rc_dev *dev) +{ + struct imon_dec *imon = &dev->raw->imon; + + /* Keyboard/Mouse toggle */ + if (imon->bits == 0x299115b7) + imon->stick_keyboard = !imon->stick_keyboard; + + if ((imon->bits & 0xfc0000ff) == 0x680000b7) { + int rel_x, rel_y; + u8 buf; + + buf = imon->bits >> 16; + rel_x = (buf & 0x08) | (buf & 0x10) >> 2 | + (buf & 0x20) >> 4 | (buf & 0x40) >> 6; + if (imon->bits & 0x02000000) + rel_x |= ~0x0f; + buf = imon->bits >> 8; + rel_y = (buf & 0x08) | (buf & 0x10) >> 2 | + (buf & 0x20) >> 4 | (buf & 0x40) >> 6; + if (imon->bits & 0x01000000) + rel_y |= ~0x0f; + + if (rel_x && rel_y && imon->stick_keyboard) { + if (abs(rel_y) > abs(rel_x)) + imon->bits = rel_y > 0 ? + 0x289515b7 : /* KEY_DOWN */ + 0x2aa515b7; /* KEY_UP */ + else + imon->bits = rel_x > 0 ? + 0x2ba515b7 : /* KEY_RIGHT */ + 0x29a515b7; /* KEY_LEFT */ + } + + if (!imon->stick_keyboard) { + struct lirc_scancode lsc = { + .scancode = imon->bits, + .rc_proto = RC_PROTO_IMON, + }; + + ir_lirc_scancode_event(dev, &lsc); + + input_event(imon->idev, EV_MSC, MSC_SCAN, imon->bits); + + input_report_rel(imon->idev, REL_X, rel_x); + input_report_rel(imon->idev, REL_Y, rel_y); + + input_report_key(imon->idev, BTN_LEFT, + (imon->bits & 0x00010000) != 0); + input_report_key(imon->idev, BTN_RIGHT, + (imon->bits & 0x00040000) != 0); + input_sync(imon->idev); + return; + } + } + + rc_keydown(dev, RC_PROTO_IMON, imon->bits, 0); +} + /** * ir_imon_decode() - Decode one iMON pulse or space * @dev: the struct rc_dev descriptor of the device @@ -56,6 +116,22 @@ static int ir_imon_decode(struct rc_dev *dev, struct ir_raw_event ev) data->state, data->count, TO_US(ev.duration), TO_STR(ev.pulse)); + /* + * Since iMON protocol is a series of bits, if at any point + * we encounter an error, make sure that any remaining bits + * aren't parsed as a scancode made up of less bits. + * + * Note that if the stick is held, then the remote repeats + * the scancode with about 12ms between them. So, make sure + * we have at least 10ms of space after an error. That way, + * we're at a new scancode. + */ + if (data->state == STATE_ERROR) { + if (!ev.pulse && ev.duration > MS_TO_NS(10)) + data->state = STATE_INACTIVE; + return 0; + } + for (;;) { if (!geq_margin(ev.duration, IMON_UNIT, IMON_UNIT / 2)) return 0; @@ -95,7 +171,7 @@ static int ir_imon_decode(struct rc_dev *dev, struct ir_raw_event ev) case STATE_FINISHED: if (ev.pulse) goto err_out; - rc_keydown(dev, RC_PROTO_IMON, data->bits, 0); + ir_imon_decode_scancode(dev); data->state = STATE_INACTIVE; break; } @@ -107,7 +183,7 @@ err_out: data->state, data->count, TO_US(ev.duration), TO_STR(ev.pulse)); - data->state = STATE_INACTIVE; + data->state = STATE_ERROR; return -EINVAL; } @@ -165,11 +241,65 @@ static int ir_imon_encode(enum rc_proto protocol, u32 scancode, return e - events; } +static int ir_imon_register(struct rc_dev *dev) +{ + struct input_dev *idev; + struct imon_dec *imon = &dev->raw->imon; + int ret; + + idev = input_allocate_device(); + if (!idev) + return -ENOMEM; + + snprintf(imon->name, sizeof(imon->name), + "iMON PAD Stick (%s)", dev->device_name); + idev->name = imon->name; + idev->phys = dev->input_phys; + + /* Mouse bits */ + set_bit(EV_REL, idev->evbit); + set_bit(EV_KEY, idev->evbit); + set_bit(REL_X, idev->relbit); + set_bit(REL_Y, idev->relbit); + set_bit(BTN_LEFT, idev->keybit); + set_bit(BTN_RIGHT, idev->keybit); + + /* Report scancodes too */ + set_bit(EV_MSC, idev->evbit); + set_bit(MSC_SCAN, idev->mscbit); + + input_set_drvdata(idev, imon); + + ret = input_register_device(idev); + if (ret < 0) { + input_free_device(idev); + return -EIO; + } + + imon->idev = idev; + imon->stick_keyboard = false; + + return 0; +} + +static int ir_imon_unregister(struct rc_dev *dev) +{ + struct imon_dec *imon = &dev->raw->imon; + + input_unregister_device(imon->idev); + imon->idev = NULL; + + return 0; +} + static struct ir_raw_handler imon_handler = { .protocols = RC_PROTO_BIT_IMON, .decode = ir_imon_decode, .encode = ir_imon_encode, .carrier = 38000, + .raw_register = ir_imon_register, + .raw_unregister = ir_imon_unregister, + .min_timeout = IMON_UNIT * IMON_BITS * 2, }; static int __init ir_imon_decode_init(void) diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c index 8cb68ae43282..5706cfe60027 100644 --- a/drivers/media/rc/ir-jvc-decoder.c +++ b/drivers/media/rc/ir-jvc-decoder.c @@ -213,6 +213,7 @@ static struct ir_raw_handler jvc_handler = { .decode = ir_jvc_decode, .encode = ir_jvc_encode, .carrier = 38000, + .min_timeout = 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 c110984ca671..64ea42927669 100644 --- a/drivers/media/rc/ir-mce_kbd-decoder.c +++ b/drivers/media/rc/ir-mce_kbd-decoder.c @@ -119,17 +119,25 @@ static void mce_kbd_rx_timeout(struct timer_list *t) { struct ir_raw_event_ctrl *raw = from_timer(raw, t, mce_kbd.rx_timeout); unsigned char maskcode; + unsigned long flags; int i; dev_dbg(&raw->dev->dev, "timer callback clearing all keys\n"); - for (i = 0; i < 7; i++) { - maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i]; - input_report_key(raw->mce_kbd.idev, maskcode, 0); - } + spin_lock_irqsave(&raw->mce_kbd.keylock, flags); + + if (time_is_before_eq_jiffies(raw->mce_kbd.rx_timeout.expires)) { + for (i = 0; i < 7; i++) { + maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i]; + input_report_key(raw->mce_kbd.idev, maskcode, 0); + } + + for (i = 0; i < MCIR2_MASK_KEYS_START; i++) + input_report_key(raw->mce_kbd.idev, kbd_keycodes[i], 0); - for (i = 0; i < MCIR2_MASK_KEYS_START; i++) - input_report_key(raw->mce_kbd.idev, kbd_keycodes[i], 0); + input_sync(raw->mce_kbd.idev); + } + spin_unlock_irqrestore(&raw->mce_kbd.keylock, flags); } static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data) @@ -147,13 +155,14 @@ static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data) static void ir_mce_kbd_process_keyboard_data(struct rc_dev *dev, u32 scancode) { struct mce_kbd_dec *data = &dev->raw->mce_kbd; - 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; - dev_dbg(&dev->dev, "keyboard: keydata = 0x%02x, shiftmask = 0x%02x\n", - keydata, shiftmask); + dev_dbg(&dev->dev, "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 +173,12 @@ static void ir_mce_kbd_process_keyboard_data(struct rc_dev *dev, u32 scancode) input_report_key(data->idev, maskcode, keystate); } - if (keydata) { - keycode = kbd_keycodes[keydata]; - input_report_key(data->idev, keycode, 1); - } else { + if (keydata1) + input_report_key(data->idev, kbd_keycodes[keydata1], 1); + if (keydata2) + input_report_key(data->idev, kbd_keycodes[keydata2], 1); + + if (!keydata1 && !keydata2) { for (i = 0; i < MCIR2_MASK_KEYS_START; i++) input_report_key(data->idev, kbd_keycodes[i], 0); } @@ -263,9 +274,6 @@ again: return 0; case STATE_HEADER_BIT_END: - if (!is_transition(&ev, &dev->raw->prev_ev)) - break; - decrease_duration(&ev, MCIR2_BIT_END); if (data->count != MCIR2_HEADER_NBITS) { @@ -302,9 +310,6 @@ again: return 0; case STATE_BODY_BIT_END: - if (!is_transition(&ev, &dev->raw->prev_ev)) - break; - if (data->count == data->wanted_bits) data->state = STATE_FINISHED; else @@ -319,16 +324,20 @@ again: switch (data->wanted_bits) { case MCIR2_KEYBOARD_NBITS: - scancode = data->body & 0xffff; + scancode = data->body & 0xffffff; dev_dbg(&dev->dev, "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); + spin_lock(&data->keylock); + 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(dev, scancode); + spin_unlock(&data->keylock); lsc.rc_proto = RC_PROTO_MCIR2_KBD; break; case MCIR2_MOUSE_NBITS: @@ -355,7 +364,6 @@ out: dev_dbg(&dev->dev, "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; } @@ -394,6 +402,7 @@ static int ir_mce_kbd_register(struct rc_dev *dev) set_bit(MSC_SCAN, idev->mscbit); timer_setup(&mce_kbd->rx_timeout, mce_kbd_rx_timeout, 0); + spin_lock_init(&mce_kbd->keylock); input_set_drvdata(idev, mce_kbd); @@ -475,6 +484,7 @@ static struct ir_raw_handler mce_kbd_handler = { .raw_register = ir_mce_kbd_register, .raw_unregister = ir_mce_kbd_unregister, .carrier = 36000, + .min_timeout = MCIR2_MAX_LEN + MCIR2_UNIT / 2, }; 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 21647b809e6f..6a8973ae3684 100644 --- a/drivers/media/rc/ir-nec-decoder.c +++ b/drivers/media/rc/ir-nec-decoder.c @@ -253,6 +253,7 @@ static struct ir_raw_handler nec_handler = { .decode = ir_nec_decode, .encode = ir_nec_encode, .carrier = 38000, + .min_timeout = 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 74d3b859c3a2..63624654a71e 100644 --- a/drivers/media/rc/ir-rc5-decoder.c +++ b/drivers/media/rc/ir-rc5-decoder.c @@ -88,9 +88,6 @@ again: return 0; case STATE_BIT_END: - if (!is_transition(&ev, &dev->raw->prev_ev)) - break; - if (data->count == CHECK_RC5X_NBITS) data->state = STATE_CHECK_RC5X; else @@ -274,6 +271,7 @@ static struct ir_raw_handler rc5_handler = { .decode = ir_rc5_decode, .encode = ir_rc5_encode, .carrier = 36000, + .min_timeout = 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 8314da32453f..68487ce9f79b 100644 --- a/drivers/media/rc/ir-rc6-decoder.c +++ b/drivers/media/rc/ir-rc6-decoder.c @@ -145,9 +145,6 @@ again: return 0; case STATE_HEADER_BIT_END: - if (!is_transition(&ev, &dev->raw->prev_ev)) - break; - if (data->count == RC6_HEADER_NBITS) data->state = STATE_TOGGLE_START; else @@ -165,10 +162,6 @@ again: return 0; case STATE_TOGGLE_END: - if (!is_transition(&ev, &dev->raw->prev_ev) || - !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2)) - break; - if (!(data->header & RC6_STARTBIT_MASK)) { dev_dbg(&dev->dev, "RC6 invalid start bit\n"); break; @@ -210,9 +203,6 @@ again: break; case STATE_BODY_BIT_END: - if (!is_transition(&ev, &dev->raw->prev_ev)) - break; - if (data->count == data->wanted_bits) data->state = STATE_FINISHED; else @@ -394,6 +384,7 @@ static struct ir_raw_handler rc6_handler = { .decode = ir_rc6_decode, .encode = ir_rc6_encode, .carrier = 36000, + .min_timeout = RC6_SUFFIX_SPACE, }; static int __init ir_rc6_decode_init(void) diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c index 49265f02e772..8a93f7468622 100644 --- a/drivers/media/rc/ir-rx51.c +++ b/drivers/media/rc/ir-rx51.c @@ -22,7 +22,6 @@ #include <linux/hrtimer.h> #include <media/rc-core.h> -#include <linux/platform_data/media/ir-rx51.h> #define WBUF_LEN 256 @@ -31,7 +30,6 @@ struct ir_rx51 { struct pwm_device *pwm; struct hrtimer timer; struct device *dev; - struct ir_rx51_platform_data *pdata; wait_queue_head_t wqueue; unsigned int freq; /* carrier frequency */ @@ -130,10 +128,9 @@ static int ir_rx51_tx(struct rc_dev *dev, unsigned int *buffer, ir_rx51->wbuf[count] = -1; /* Insert termination mark */ /* - * Adjust latency requirements so the device doesn't go in too - * deep sleep states + * REVISIT: Adjust latency requirements so the device doesn't go in too + * deep sleep states with pm_qos_add_request(). */ - ir_rx51->pdata->set_max_mpu_wakeup_lat(ir_rx51->dev, 50); ir_rx51_on(ir_rx51); ir_rx51->wbuf_index = 1; @@ -146,8 +143,7 @@ static int ir_rx51_tx(struct rc_dev *dev, unsigned int *buffer, */ wait_event_interruptible(ir_rx51->wqueue, ir_rx51->wbuf_index < 0); - /* We can sleep again */ - ir_rx51->pdata->set_max_mpu_wakeup_lat(ir_rx51->dev, -1); + /* REVISIT: Remove pm_qos constraint, we can sleep again */ return count; } @@ -244,13 +240,6 @@ static int ir_rx51_probe(struct platform_device *dev) struct pwm_device *pwm; struct rc_dev *rcdev; - ir_rx51.pdata = dev->dev.platform_data; - - if (!ir_rx51.pdata) { - dev_err(&dev->dev, "Platform Data is missing\n"); - return -ENXIO; - } - pwm = pwm_get(&dev->dev, NULL); if (IS_ERR(pwm)) { int err = PTR_ERR(pwm); diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c index 4efe6db5376a..dd6ee1e339d6 100644 --- a/drivers/media/rc/ir-sanyo-decoder.c +++ b/drivers/media/rc/ir-sanyo-decoder.c @@ -210,6 +210,7 @@ static struct ir_raw_handler sanyo_handler = { .decode = ir_sanyo_decode, .encode = ir_sanyo_encode, .carrier = 38000, + .min_timeout = 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 6a38c50566a4..f96e0c992eed 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 = { .decode = ir_sharp_decode, .encode = ir_sharp_encode, .carrier = 38000, + .min_timeout = SHARP_ECHO_SPACE + SHARP_ECHO_SPACE / 4, }; 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 6764ec9de646..5065c081238d 100644 --- a/drivers/media/rc/ir-sony-decoder.c +++ b/drivers/media/rc/ir-sony-decoder.c @@ -224,6 +224,7 @@ static struct ir_raw_handler sony_handler = { .decode = ir_sony_decode, .encode = ir_sony_encode, .carrier = 40000, + .min_timeout = SONY_TRAILER_SPACE, }; static int __init ir_sony_decode_init(void) diff --git a/drivers/media/rc/ir-spi.c b/drivers/media/rc/ir-spi.c index 7163d5ce2e64..66334e8d63ba 100644 --- a/drivers/media/rc/ir-spi.c +++ b/drivers/media/rc/ir-spi.c @@ -2,7 +2,7 @@ // SPI driven IR LED device driver // // Copyright (c) 2016 Samsung Electronics Co., Ltd. -// Copyright (c) Andi Shyti <andi.shyti@samsung.com> +// Copyright (c) Andi Shyti <andi@etezian.org> #include <linux/delay.h> #include <linux/fs.h> @@ -173,6 +173,6 @@ static struct spi_driver ir_spi_driver = { module_spi_driver(ir_spi_driver); -MODULE_AUTHOR("Andi Shyti <andi.shyti@samsung.com>"); +MODULE_AUTHOR("Andi Shyti <andi@etezian.org>"); MODULE_DESCRIPTION("SPI IR LED"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/rc/ir-xmp-decoder.c b/drivers/media/rc/ir-xmp-decoder.c index 58b47af1a763..c965f51df1c1 100644 --- a/drivers/media/rc/ir-xmp-decoder.c +++ b/drivers/media/rc/ir-xmp-decoder.c @@ -199,6 +199,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, + .min_timeout = XMP_TRAILER_SPACE, }; static int __init ir_xmp_decode_init(void) diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index 65e104c7ddfc..de77d22c30a7 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c @@ -1561,9 +1561,11 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id rdev->close = ite_close; rdev->s_idle = ite_s_idle; rdev->s_rx_carrier_range = ite_set_rx_carrier_range; - rdev->min_timeout = ITE_MIN_IDLE_TIMEOUT; - rdev->max_timeout = ITE_MAX_IDLE_TIMEOUT; - rdev->timeout = ITE_IDLE_TIMEOUT; + /* FIFO threshold is 17 bytes, so 17 * 8 samples minimum */ + rdev->min_timeout = 17 * 8 * ITE_BAUDRATE_DIVISOR * + itdev->params.sample_period; + rdev->timeout = IR_DEFAULT_TIMEOUT; + rdev->max_timeout = 10 * IR_DEFAULT_TIMEOUT; rdev->rx_resolution = ITE_BAUDRATE_DIVISOR * itdev->params.sample_period; rdev->tx_resolution = ITE_BAUDRATE_DIVISOR * diff --git a/drivers/media/rc/ite-cir.h b/drivers/media/rc/ite-cir.h index 0e8ebc880d1f..9cb24ac01350 100644 --- a/drivers/media/rc/ite-cir.h +++ b/drivers/media/rc/ite-cir.h @@ -154,13 +154,6 @@ struct ite_dev { /* default carrier freq for when demodulator is off (Hz) */ #define ITE_DEFAULT_CARRIER_FREQ 38000 -/* default idling timeout in ns (0.2 seconds) */ -#define ITE_IDLE_TIMEOUT 200000000UL - -/* limit timeout values */ -#define ITE_MIN_IDLE_TIMEOUT 100000000UL -#define ITE_MAX_IDLE_TIMEOUT 1000000000UL - /* convert bits to us */ #define ITE_BITS_TO_NS(bits, sample_period) \ ((u32) ((bits) * ITE_BAUDRATE_DIVISOR * sample_period)) diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 24e9fbb80e81..f862f1b7f996 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -20,6 +20,7 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/device.h> +#include <linux/file.h> #include <linux/idr.h> #include <linux/poll.h> #include <linux/sched.h> @@ -104,6 +105,12 @@ void ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev) TO_US(ev.duration), TO_STR(ev.pulse)); } + /* + * bpf does not care about the gap generated above; that exists + * for backwards compatibility + */ + lirc_bpf_run(dev, sample); + spin_lock_irqsave(&dev->lirc_fh_lock, flags); list_for_each_entry(fh, &dev->lirc_fh, list) { if (LIRC_IS_TIMEOUT(sample) && !fh->send_timeout_reports) @@ -575,10 +582,17 @@ static long ir_lirc_ioctl(struct file *file, unsigned int cmd, } break; - case LIRC_SET_REC_TIMEOUT_REPORTS: + case LIRC_GET_REC_TIMEOUT: if (!dev->timeout) ret = -ENOTTY; else + val = DIV_ROUND_UP(dev->timeout, 1000); + break; + + case LIRC_SET_REC_TIMEOUT_REPORTS: + if (dev->driver_type != RC_DRIVER_IR_RAW) + ret = -ENOTTY; + else fh->send_timeout_reports = !!val; break; @@ -735,6 +749,7 @@ static void lirc_release_device(struct device *ld) int ir_lirc_register(struct rc_dev *dev) { + const char *rx_type, *tx_type; int err, minor; minor = ida_simple_get(&lirc_ida, 0, RC_DEV_MAX, GFP_KERNEL); @@ -759,8 +774,25 @@ int ir_lirc_register(struct rc_dev *dev) get_device(&dev->dev); - dev_info(&dev->dev, "lirc_dev: driver %s registered at minor = %d", - dev->driver_name, minor); + switch (dev->driver_type) { + case RC_DRIVER_SCANCODE: + rx_type = "scancode"; + break; + case RC_DRIVER_IR_RAW: + rx_type = "raw IR"; + break; + default: + rx_type = "no"; + break; + } + + if (dev->tx_ir) + tx_type = "raw IR"; + else + tx_type = "no"; + + dev_info(&dev->dev, "lirc_dev: driver %s registered at minor = %d, %s receiver, %s transmitter", + dev->driver_name, minor, rx_type, tx_type); return 0; @@ -816,4 +848,27 @@ void __exit lirc_dev_exit(void) unregister_chrdev_region(lirc_base_dev, RC_DEV_MAX); } +struct rc_dev *rc_dev_get_from_fd(int fd) +{ + struct fd f = fdget(fd); + struct lirc_fh *fh; + struct rc_dev *dev; + + if (!f.file) + return ERR_PTR(-EBADF); + + if (f.file->f_op != &lirc_fops) { + fdput(f); + return ERR_PTR(-EINVAL); + } + + fh = f.file->private_data; + dev = fh->rc; + + get_device(&dev->dev); + fdput(f); + + return dev; +} + MODULE_ALIAS("lirc_dev"); diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 69ba57372c05..4c0c8008872a 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -181,6 +181,7 @@ enum mceusb_model_type { MCE_GEN2 = 0, /* Most boards */ MCE_GEN1, MCE_GEN3, + MCE_GEN3_BROKEN_IRTIMEOUT, MCE_GEN2_TX_INV, MCE_GEN2_TX_INV_RX_GOOD, POLARIS_EVK, @@ -199,6 +200,7 @@ struct mceusb_model { u32 mce_gen3:1; u32 tx_mask_normal:1; u32 no_tx:1; + u32 broken_irtimeout:1; /* * 2nd IR receiver (short-range, wideband) for learning mode: * 0, absent 2nd receiver (rx2) @@ -242,6 +244,12 @@ static const struct mceusb_model mceusb_model[] = { .tx_mask_normal = 1, .rx2 = 2, }, + [MCE_GEN3_BROKEN_IRTIMEOUT] = { + .mce_gen3 = 1, + .tx_mask_normal = 1, + .rx2 = 2, + .broken_irtimeout = 1 + }, [POLARIS_EVK] = { /* * In fact, the EVK is shipped without @@ -352,7 +360,7 @@ static const struct usb_device_id mceusb_dev_table[] = { .driver_info = MCE_GEN2_TX_INV }, /* Topseed eHome Infrared Transceiver */ { USB_DEVICE(VENDOR_TOPSEED, 0x0011), - .driver_info = MCE_GEN3 }, + .driver_info = MCE_GEN3_BROKEN_IRTIMEOUT }, /* Ricavision internal Infrared Transceiver */ { USB_DEVICE(VENDOR_RICAVISION, 0x0010) }, /* Itron ione Libra Q-11 */ @@ -564,6 +572,7 @@ static int mceusb_cmd_datasize(u8 cmd, u8 subcmd) datasize = 1; break; } + break; case MCE_CMD_PORT_IR: switch (subcmd) { case MCE_CMD_UNKNOWN: @@ -982,6 +991,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; +} + /* * Select or deselect the 2nd receiver port. * Second receiver is learning mode, wide-band, short-range receiver. @@ -1150,6 +1178,11 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) init_ir_raw_event(&rawir); rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0); rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK); + if (unlikely(!rawir.duration)) { + dev_warn(ir->dev, "nonsensical irdata %02x with duration 0", + ir->buf_in[i]); + break; + } if (rawir.pulse) { ir->pulse_tunit += rawir.duration; ir->pulse_count++; @@ -1182,7 +1215,12 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) if (ir->rem) { ir->parser_state = PARSE_IRDATA; } else { - ir_raw_event_reset(ir->rc); + 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; ir->pulse_tunit = 0; ir->pulse_count = 0; } @@ -1415,7 +1453,18 @@ 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); + if (!mceusb_model[ir->model].broken_irtimeout) { + rc->s_timeout = mceusb_set_timeout; + rc->max_timeout = 10 * IR_DEFAULT_TIMEOUT; + } else { + /* + * If we can't set the timeout using CMD_SETIRTIMEOUT, we can + * rely on software timeouts for timeouts < 100ms. + */ + rc->max_timeout = rc->timeout; + } if (!ir->flags.no_tx) { rc->s_tx_mask = mceusb_set_tx_mask; rc->s_tx_carrier = mceusb_set_tx_carrier; diff --git a/drivers/media/rc/mtk-cir.c b/drivers/media/rc/mtk-cir.c index e88eb64e8e69..e42efd9d382e 100644 --- a/drivers/media/rc/mtk-cir.c +++ b/drivers/media/rc/mtk-cir.c @@ -299,8 +299,6 @@ static int mtk_ir_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *dn = dev->of_node; - const struct of_device_id *of_id = - of_match_device(mtk_ir_match, &pdev->dev); struct resource *res; struct mtk_ir *ir; u32 val; @@ -312,7 +310,7 @@ static int mtk_ir_probe(struct platform_device *pdev) return -ENOMEM; ir->dev = dev; - ir->data = of_id->data; + ir->data = of_device_get_match_data(dev); ir->clk = devm_clk_get(dev, "clk"); if (IS_ERR(ir->clk)) { diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 5e1d866a61a5..b8299c9a9744 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -535,6 +535,8 @@ static void nvt_set_cir_iren(struct nvt_dev *nvt) static void nvt_cir_regs_init(struct nvt_dev *nvt) { + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); + /* set sample limit count (PE interrupt raised when reached) */ nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_SLCH); nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_SLCL); @@ -543,31 +545,17 @@ static void nvt_cir_regs_init(struct nvt_dev *nvt) nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV | CIR_FIFOCON_RX_TRIGGER_LEV, CIR_FIFOCON); - /* - * Enable TX and RX, specify carrier on = low, off = high, and set - * sample period (currently 50us) - */ - nvt_cir_reg_write(nvt, - CIR_IRCON_TXEN | CIR_IRCON_RXEN | - CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, - CIR_IRCON); - /* clear hardware rx and tx fifos */ nvt_clear_cir_fifo(nvt); nvt_clear_tx_fifo(nvt); - /* clear any and all stray interrupts */ - nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); - - /* and finally, enable interrupts */ - nvt_set_cir_iren(nvt); - - /* enable the CIR logical device */ - nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); + nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); } static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) { + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); + /* * Disable RX, set specific carrier on = low, off = high, * and sample period (currently 50us) @@ -579,9 +567,6 @@ static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) /* clear any and all stray interrupts */ nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); - - /* enable the CIR WAKE logical device */ - nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); } static void nvt_enable_wake(struct nvt_dev *nvt) @@ -892,6 +877,32 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) return IRQ_HANDLED; } +static void nvt_enable_cir(struct nvt_dev *nvt) +{ + unsigned long flags; + + /* enable the CIR logical device */ + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); + + spin_lock_irqsave(&nvt->lock, flags); + + /* + * Enable TX and RX, specify carrier on = low, off = high, and set + * sample period (currently 50us) + */ + nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | + CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, + CIR_IRCON); + + /* clear all pending interrupts */ + nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); + + /* enable interrupts */ + nvt_set_cir_iren(nvt); + + spin_unlock_irqrestore(&nvt->lock, flags); +} + static void nvt_disable_cir(struct nvt_dev *nvt) { unsigned long flags; @@ -920,25 +931,8 @@ static void nvt_disable_cir(struct nvt_dev *nvt) static int nvt_open(struct rc_dev *dev) { struct nvt_dev *nvt = dev->priv; - unsigned long flags; - - spin_lock_irqsave(&nvt->lock, flags); - - /* set function enable flags */ - nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | - CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, - CIR_IRCON); - - /* clear all pending interrupts */ - nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); - - /* enable interrupts */ - nvt_set_cir_iren(nvt); - spin_unlock_irqrestore(&nvt->lock, flags); - - /* enable the CIR logical device */ - nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); + nvt_enable_cir(nvt); return 0; } @@ -1093,19 +1087,13 @@ static void nvt_remove(struct pnp_dev *pdev) static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) { struct nvt_dev *nvt = pnp_get_drvdata(pdev); - unsigned long flags; nvt_dbg("%s called", __func__); - spin_lock_irqsave(&nvt->lock, flags); - - /* disable all CIR interrupts */ - nvt_cir_reg_write(nvt, 0, CIR_IREN); - - spin_unlock_irqrestore(&nvt->lock, flags); - - /* disable cir logical dev */ - nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); + mutex_lock(&nvt->rdev->lock); + if (nvt->rdev->users) + nvt_disable_cir(nvt); + mutex_unlock(&nvt->rdev->lock); /* make sure wake is enabled */ nvt_enable_wake(nvt); @@ -1122,6 +1110,11 @@ static int nvt_resume(struct pnp_dev *pdev) nvt_cir_regs_init(nvt); nvt_cir_wake_regs_init(nvt); + mutex_lock(&nvt->rdev->lock); + if (nvt->rdev->users) + nvt_enable_cir(nvt); + mutex_unlock(&nvt->rdev->lock); + return 0; } diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index e0e6a17460f6..e847bdad5c51 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -13,6 +13,7 @@ #define MAX_IR_EVENT_SIZE 512 #include <linux/slab.h> +#include <uapi/linux/bpf.h> #include <media/rc-core.h> /** @@ -37,6 +38,7 @@ struct ir_raw_handler { int (*encode)(enum rc_proto protocol, u32 scancode, struct ir_raw_event *events, unsigned int max); u32 carrier; + u32 min_timeout; /* These two should only be used by the mce kbd decoder */ int (*raw_register)(struct rc_dev *dev); @@ -57,6 +59,11 @@ struct ir_raw_event_ctrl { /* raw decoder state follows */ struct ir_raw_event prev_ev; struct ir_raw_event this_ev; + +#ifdef CONFIG_BPF_LIRC_MODE2 + u32 bpf_sample; + struct bpf_prog_array __rcu *progs; +#endif struct nec_dec { int state; unsigned count; @@ -104,6 +111,8 @@ struct ir_raw_event_ctrl { } sharp; struct mce_kbd_dec { struct input_dev *idev; + /* locks key up timer */ + spinlock_t keylock; struct timer_list rx_timeout; char name[64]; char phys[64]; @@ -123,9 +132,15 @@ struct ir_raw_event_ctrl { int count; int last_chk; unsigned int bits; + bool stick_keyboard; + struct input_dev *idev; + char name[64]; } imon; }; +/* Mutex for locking raw IR processing and handler change */ +extern struct mutex ir_raw_handler_lock; + /* macros for IR decoders */ static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin) { @@ -288,6 +303,7 @@ void ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev); void ir_lirc_scancode_event(struct rc_dev *dev, struct lirc_scancode *lsc); int ir_lirc_register(struct rc_dev *dev); void ir_lirc_unregister(struct rc_dev *dev); +struct rc_dev *rc_dev_get_from_fd(int fd); #else static inline int lirc_dev_init(void) { return 0; } static inline void lirc_dev_exit(void) {} @@ -299,4 +315,15 @@ static inline int ir_lirc_register(struct rc_dev *dev) { return 0; } static inline void ir_lirc_unregister(struct rc_dev *dev) { } #endif +/* + * bpf interface + */ +#ifdef CONFIG_BPF_LIRC_MODE2 +void lirc_bpf_free(struct rc_dev *dev); +void lirc_bpf_run(struct rc_dev *dev, u32 sample); +#else +static inline void lirc_bpf_free(struct rc_dev *dev) { } +static inline void lirc_bpf_run(struct rc_dev *dev, u32 sample) { } +#endif + #endif /* _RC_CORE_PRIV */ diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c index 374f83105a23..2e0066b1a31c 100644 --- a/drivers/media/rc/rc-ir-raw.c +++ b/drivers/media/rc/rc-ir-raw.c @@ -14,7 +14,7 @@ static LIST_HEAD(ir_raw_client_list); /* Used to handle IR raw handler extensions */ -static DEFINE_MUTEX(ir_raw_handler_lock); +DEFINE_MUTEX(ir_raw_handler_lock); static LIST_HEAD(ir_raw_handler_list); static atomic64_t available_protocols = ATOMIC64_INIT(0); @@ -22,16 +22,27 @@ static int ir_raw_event_thread(void *data) { struct ir_raw_event ev; struct ir_raw_handler *handler; - struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; + struct ir_raw_event_ctrl *raw = data; + struct rc_dev *dev = raw->dev; while (1) { mutex_lock(&ir_raw_handler_lock); while (kfifo_out(&raw->kfifo, &ev, 1)) { + if (is_timing_event(ev)) { + if (ev.duration == 0) + dev_err(&dev->dev, "nonsensical timing event of duration 0"); + if (is_timing_event(raw->prev_ev) && + !is_transition(&ev, &raw->prev_ev)) + dev_err(&dev->dev, "two consecutive events of type %s", + TO_STR(ev.pulse)); + if (raw->prev_ev.reset && ev.pulse == 0) + dev_err(&dev->dev, "timing event after reset should be pulse"); + } list_for_each_entry(handler, &ir_raw_handler_list, list) - if (raw->dev->enabled_protocols & + if (dev->enabled_protocols & handler->protocols || !handler->protocols) - handler->decode(raw->dev, ev); - ir_lirc_raw_event(raw->dev, ev); + handler->decode(dev, ev); + ir_lirc_raw_event(dev, ev); raw->prev_ev = ev; } mutex_unlock(&ir_raw_handler_lock); @@ -233,7 +244,49 @@ 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; + + mutex_lock(&ir_raw_handler_lock); + list_for_each_entry(handler, &ir_raw_handler_list, list) { + if (!(dev->enabled_protocols & handler->protocols) && + (*rc_proto & handler->protocols) && handler->raw_register) + handler->raw_register(dev); + + if ((dev->enabled_protocols & handler->protocols) && + !(*rc_proto & handler->protocols) && + handler->raw_unregister) + handler->raw_unregister(dev); + } + mutex_unlock(&ir_raw_handler_lock); + + 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->min_timeout) + timeout = handler->min_timeout; + } + } + mutex_unlock(&ir_raw_handler_lock); + + if (timeout == 0) + timeout = IR_DEFAULT_TIMEOUT; + else + timeout += MS_TO_NS(10); + + 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; } @@ -569,6 +622,7 @@ int ir_raw_event_prepare(struct rc_dev *dev) dev->raw->dev = dev; dev->change_protocol = change_protocol; + dev->idle = true; spin_lock_init(&dev->raw->edge_spinlock); timer_setup(&dev->raw->edge_handle, ir_raw_edge_handle, 0); INIT_KFIFO(dev->raw->kfifo); @@ -578,7 +632,6 @@ int ir_raw_event_prepare(struct rc_dev *dev) int ir_raw_event_register(struct rc_dev *dev) { - struct ir_raw_handler *handler; struct task_struct *thread; thread = kthread_run(ir_raw_event_thread, dev->raw, "rc%u", dev->minor); @@ -589,9 +642,6 @@ int ir_raw_event_register(struct rc_dev *dev) mutex_lock(&ir_raw_handler_lock); list_add_tail(&dev->raw->list, &ir_raw_client_list); - list_for_each_entry(handler, &ir_raw_handler_list, list) - if (handler->raw_register) - handler->raw_register(dev); mutex_unlock(&ir_raw_handler_lock); return 0; @@ -619,11 +669,20 @@ void ir_raw_event_unregister(struct rc_dev *dev) mutex_lock(&ir_raw_handler_lock); list_del(&dev->raw->list); list_for_each_entry(handler, &ir_raw_handler_list, list) - if (handler->raw_unregister) + if (handler->raw_unregister && + (handler->protocols & dev->enabled_protocols)) handler->raw_unregister(dev); - mutex_unlock(&ir_raw_handler_lock); + + lirc_bpf_free(dev); ir_raw_event_free(dev); + + /* + * A user can be calling bpf(BPF_PROG_{QUERY|ATTACH|DETACH}), so + * ensure that the raw member is null on unlock; this is how + * "device gone" is checked. + */ + mutex_unlock(&ir_raw_handler_lock); } /* @@ -632,13 +691,8 @@ void ir_raw_event_unregister(struct rc_dev *dev) int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) { - struct ir_raw_event_ctrl *raw; - mutex_lock(&ir_raw_handler_lock); list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); - if (ir_raw_handler->raw_register) - list_for_each_entry(raw, &ir_raw_client_list, list) - ir_raw_handler->raw_register(raw->dev); atomic64_or(ir_raw_handler->protocols, &available_protocols); mutex_unlock(&ir_raw_handler_lock); @@ -654,9 +708,10 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) mutex_lock(&ir_raw_handler_lock); list_del(&ir_raw_handler->list); list_for_each_entry(raw, &ir_raw_client_list, list) { - ir_raw_disable_protocols(raw->dev, protocols); - if (ir_raw_handler->raw_unregister) + if (ir_raw_handler->raw_unregister && + (raw->dev->enabled_protocols & protocols)) ir_raw_handler->raw_unregister(raw->dev); + ir_raw_disable_protocols(raw->dev, protocols); } atomic64_andnot(protocols, &available_protocols); mutex_unlock(&ir_raw_handler_lock); diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index b67be33bd62f..2e222d9ee01f 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -26,50 +26,50 @@ 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 = 0xffffff, .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 }, [RC_PROTO_IMON] = { .name = "imon", - .scancode_bits = 0x7fffffff, .repeat_period = 250 }, + .scancode_bits = 0x7fffffff, .repeat_period = 114 }, }; /* Used to keep track of known keymaps */ @@ -690,7 +690,8 @@ static void ir_timer_repeat(struct timer_list *t) 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); struct lirc_scancode sc = { .scancode = dev->last_scancode, .rc_proto = dev->last_protocol, .keycode = dev->keypressed ? dev->last_keycode : KEY_RESERVED, @@ -706,7 +707,7 @@ void rc_repeat(struct rc_dev *dev) input_sync(dev->input_dev); if (dev->keypressed) { - dev->keyup_jiffies = jiffies + msecs_to_jiffies(timeout); + dev->keyup_jiffies = jiffies + timeout; mod_timer(&dev->timer_keyup, dev->keyup_jiffies); } @@ -801,7 +802,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); } @@ -1241,6 +1242,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) { dev_dbg(&dev->dev, "Error setting protocols to 0x%llx\n", @@ -1248,9 +1252,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; dev_dbg(&dev->dev, "Protocols changed to 0x%llx\n", @@ -1647,6 +1648,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; timer_setup(&dev->timer_keyup, ir_timer_keyup, 0); timer_setup(&dev->timer_repeat, ir_timer_repeat, 0); @@ -1735,6 +1737,9 @@ static int rc_prepare_rx_device(struct rc_dev *dev) if (dev->driver_type == RC_DRIVER_SCANCODE && !dev->change_protocol) dev->enabled_protocols = dev->allowed_protocols; + 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) @@ -1742,9 +1747,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); @@ -1860,6 +1862,8 @@ int rc_register_device(struct rc_dev *dev) dev->device_name ?: "Unspecified device", path ?: "N/A"); kfree(path); + dev->registered = true; + if (dev->driver_type != RC_DRIVER_IR_RAW_TX) { rc = rc_setup_rx_device(dev); if (rc) @@ -1879,8 +1883,6 @@ int rc_register_device(struct rc_dev *dev) goto out_lirc; } - dev->registered = true; - dev_dbg(&dev->dev, "Registered rc%u (driver: %s)\n", dev->minor, dev->driver_name ? dev->driver_name : "unknown"); diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c index d2efd7b2c3bc..c855b177103c 100644 --- a/drivers/media/rc/st_rc.c +++ b/drivers/media/rc/st_rc.c @@ -96,19 +96,24 @@ static void st_rc_send_lirc_timeout(struct rc_dev *rdev) static irqreturn_t st_rc_rx_interrupt(int irq, void *data) { + unsigned long timeout; unsigned int symbol, mark = 0; struct st_rc_device *dev = data; int last_symbol = 0; - u32 status; + u32 status, int_status; DEFINE_IR_RAW_EVENT(ev); if (dev->irq_wake) pm_wakeup_event(dev->dev, 0); - status = readl(dev->rx_base + IRB_RX_STATUS); + /* FIXME: is 10ms good enough ? */ + timeout = jiffies + msecs_to_jiffies(10); + do { + status = readl(dev->rx_base + IRB_RX_STATUS); + if (!(status & (IRB_FIFO_NOT_EMPTY | IRB_OVERFLOW))) + break; - while (status & (IRB_FIFO_NOT_EMPTY | IRB_OVERFLOW)) { - u32 int_status = readl(dev->rx_base + IRB_RX_INT_STATUS); + int_status = readl(dev->rx_base + IRB_RX_INT_STATUS); if (unlikely(int_status & IRB_RX_OVERRUN_INT)) { /* discard the entire collection in case of errors! */ ir_raw_event_reset(dev->rdev); @@ -148,8 +153,7 @@ static irqreturn_t st_rc_rx_interrupt(int irq, void *data) } last_symbol = 0; - status = readl(dev->rx_base + IRB_RX_STATUS); - } + } while (time_is_after_jiffies(timeout)); writel(IRB_RX_INTS, dev->rx_base + IRB_RX_INT_CLEAR); diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c index 0adf0991f5ab..851acba9b436 100644 --- a/drivers/media/rc/winbond-cir.c +++ b/drivers/media/rc/winbond-cir.c @@ -989,8 +989,7 @@ wbcir_init_hw(struct wbcir_data *data) /* Clear RX state */ data->rxstate = WBCIR_RXSTATE_INACTIVE; - ir_raw_event_reset(data->dev); - ir_raw_event_set_idle(data->dev, true); + wbcir_idle_rx(data->dev, true); /* Clear TX state */ if (data->txstate == WBCIR_TXSTATE_ACTIVE) { @@ -1009,6 +1008,7 @@ wbcir_resume(struct pnp_dev *device) struct wbcir_data *data = pnp_get_drvdata(device); wbcir_init_hw(data); + ir_raw_event_reset(data->dev); enable_irq(data->irq); led_classdev_resume(&data->led); |