[PATCH v5 1/1] media: rc: rcmm decoder
media: add support for RCMM infrared remote controls. Signed-off-by: Patrick Lerda --- MAINTAINERS| 5 + drivers/media/rc/Kconfig | 7 ++ drivers/media/rc/Makefile | 1 + drivers/media/rc/ir-rcmm-decoder.c | 164 + drivers/media/rc/rc-core-priv.h| 5 + drivers/media/rc/rc-main.c | 3 + include/media/rc-map.h | 6 +- include/uapi/linux/lirc.h | 2 + tools/include/uapi/linux/lirc.h| 2 + 9 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 drivers/media/rc/ir-rcmm-decoder.c diff --git a/MAINTAINERS b/MAINTAINERS index 3e9f1710ed13..80426d1faaba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16277,6 +16277,11 @@ M: David Härdeman S: Maintained F: drivers/media/rc/winbond-cir.c +RCMM REMOTE CONTROLS DECODER +M: Patrick Lerda +S: Maintained +F: drivers/media/rc/ir-rcmm-decoder.c + WINSYSTEMS EBC-C384 WATCHDOG DRIVER M: William Breathitt Gray L: linux-watch...@vger.kernel.org diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 8a216068a35a..43775ac74268 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -133,6 +133,13 @@ config IR_IMON_DECODER remote control and you would like to use it with a raw IR receiver, or if you wish to use an encoder to transmit this IR. +config IR_RCMM_DECODER + tristate "Enable IR raw decoder for the RC-MM protocol" + depends on RC_CORE + help + Enable this option if you have IR with RC-MM protocol, and + if the IR is decoded in software + endif #RC_DECODERS menuconfig RC_DEVICES diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 92c163816849..48d23433b3c0 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-decoder.o obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o obj-$(CONFIG_IR_XMP_DECODER) += ir-xmp-decoder.o obj-$(CONFIG_IR_IMON_DECODER) += ir-imon-decoder.o +obj-$(CONFIG_IR_RCMM_DECODER) += ir-rcmm-decoder.o # stand-alone IR receivers/transmitters obj-$(CONFIG_RC_ATI_REMOTE) += ati_remote.o diff --git a/drivers/media/rc/ir-rcmm-decoder.c b/drivers/media/rc/ir-rcmm-decoder.c new file mode 100644 index ..a3c09885da5f --- /dev/null +++ b/drivers/media/rc/ir-rcmm-decoder.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0+ +// ir-rcmm-decoder.c - A decoder for the RCMM IR protocol +// +// Copyright (C) 2018 by Patrick Lerda + +#include "rc-core-priv.h" +#include +#include + +#define RCMM_UNIT 17 /* nanosecs */ +#define RCMM_PREFIX_PULSE 41 /* 16.6*2.5 */ +#define RCMM_PULSE_027 /* 16.6*(1+2/3) */ +#define RCMM_PULSE_144 /* 16.6*(2+2/3) */ +#define RCMM_PULSE_261 /* 16.6*(3+2/3) */ +#define RCMM_PULSE_378 /* 16.6*(4+2/3) */ + +enum rcmm_state { + STATE_INACTIVE, + STATE_LOW, + STATE_BUMP, + STATE_VALUE, + STATE_FINISHED, +}; + +static bool rcmm_mode(struct rcmm_dec *data) +{ + return !((0x000c & data->bits) == 0x000c); +} + +/** + * ir_rcmm_decode() - Decode one RCMM pulse or space + * @dev: the struct rc_dev descriptor of the device + * @ev:the struct ir_raw_event descriptor of the pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int ir_rcmm_decode(struct rc_dev *dev, struct ir_raw_event ev) +{ + struct rcmm_dec *data = >raw->rcmm; + u32 scancode; + u8 toggle; + int value; + + if (!(dev->enabled_protocols & RC_PROTO_BIT_RCMM)) + return 0; + + if (!is_timing_event(ev)) { + if (ev.reset) + data->state = STATE_INACTIVE; + return 0; + } + + if (ev.duration > RCMM_PULSE_3 + RCMM_UNIT) + goto out; + + switch (data->state) { + case STATE_INACTIVE: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, RCMM_PREFIX_PULSE, RCMM_UNIT / 2)) + break; + + data->state = STATE_LOW; + data->count = 0; + data->bits = 0; + return 0; + + case STATE_LOW: + if (ev.pulse) + break; + + if (!eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2)) + break; + + data->state = STATE_BUMP; + return 0; + + case STATE_BUMP: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2)) +
[PATCHv3 1/1] Add ir-rcmm-driver
Add support for RCMM infrared remote controls. Signed-off-by: Patrick Lerda --- drivers/media/rc/Kconfig | 10 ++ drivers/media/rc/Makefile | 1 + drivers/media/rc/ir-rcmm-decoder.c | 185 + drivers/media/rc/rc-core-priv.h| 5 + drivers/media/rc/rc-main.c | 3 + include/media/rc-map.h | 6 +- include/uapi/linux/lirc.h | 1 + tools/include/uapi/linux/lirc.h| 1 + 8 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 drivers/media/rc/ir-rcmm-decoder.c diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 1021c08a9ba4..b7e08324b874 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -133,6 +133,16 @@ config IR_IMON_DECODER remote control and you would like to use it with a raw IR receiver, or if you wish to use an encoder to transmit this IR. +config IR_RCMM_DECODER + tristate "Enable IR raw decoder for the RC-MM protocol" + depends on RC_CORE + select BITREVERSE + default y + + ---help--- + Enable this option if you have IR with RC-MM protocol, and + if the IR is decoded in software + endif #RC_DECODERS menuconfig RC_DEVICES diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index e0340d043fe8..fc4058013234 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-decoder.o obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o obj-$(CONFIG_IR_XMP_DECODER) += ir-xmp-decoder.o obj-$(CONFIG_IR_IMON_DECODER) += ir-imon-decoder.o +obj-$(CONFIG_IR_RCMM_DECODER) += ir-rcmm-decoder.o # stand-alone IR receivers/transmitters obj-$(CONFIG_RC_ATI_REMOTE) += ati_remote.o diff --git a/drivers/media/rc/ir-rcmm-decoder.c b/drivers/media/rc/ir-rcmm-decoder.c new file mode 100644 index ..94d5b70f7a0f --- /dev/null +++ b/drivers/media/rc/ir-rcmm-decoder.c @@ -0,0 +1,185 @@ +/* ir-rcmm-decoder.c - A decoder for the RCMM IR protocol + * + * Copyright (C) 2016 by Patrick Lerda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "rc-core-priv.h" +#include +#include + + +#define RCMM_UNIT 17 /* nanosecs */ +#define RCMM_0_NBITS 64 +#define RCMM_PREFIX_PULSE 41 /* 16.6*2.5 */ +#define RCMM_PULSE_027 /* 16.6*(1+2/3) */ +#define RCMM_PULSE_144 /* 16.6*(2+2/3) */ +#define RCMM_PULSE_261 /* 16.6*(3+2/3) */ +#define RCMM_PULSE_378 /* 16.6*(4+2/3) */ +#define RCMM_MODE_MASK 0x + +enum rcmm_state { + STATE_INACTIVE, + STATE_LOW, + STATE_BUMP, + STATE_VALUE, + STATE_FINISHED, +}; + +static bool rcmm_mode(struct rcmm_dec *data) +{ +return !((0x000c & data->bits) == 0x000c); +} + +/** + * ir_rcmm_decode() - Decode one RCMM pulse or space + * @dev: the struct rc_dev descriptor of the device + * @ev:the struct ir_raw_event descriptor of the pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int ir_rcmm_decode(struct rc_dev *dev, struct ir_raw_event ev) +{ + struct rcmm_dec *data = >raw->rcmm; + u32 scancode; + u8 toggle; + + if (!(dev->enabled_protocols & RC_PROTO_BIT_RCMM)) + return 0; + + if (!is_timing_event(ev)) { + if (ev.reset) + data->state = STATE_INACTIVE; + return 0; + } + + if (ev.duration > RCMM_PULSE_3 + RCMM_UNIT) + goto out; + + switch (data->state) { + + case STATE_INACTIVE: + if (!ev.pulse) + break; + + /* Note: larger margin on first pulse since each RCMM_UNIT + is quite short and some hardware takes some time to + adjust to the signal */ + if (!eq_margin(ev.duration, RCMM_PREFIX_PULSE, RCMM_UNIT/2)) + break; + + data->state = STATE_LOW; + data->count = 0; + data->bits = 0; + return 0; + + case STATE_LOW: + if (ev.pulse) + break; + + /* Note: larger margin on first pulse since each RCMM_UNIT + is quite short and some hardware