Skip to contentSkip to conversation

Add ir-rcmm-driver

PATCH Superseded [email protected] 4 participants 18 messages Dec 4, 2018 – Jan 17, 2019 1 message not in the archive

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

PATCH 1/1 Add ir-rcmm-driver

From: Patrick LERDA <[email protected]>

---
 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
drivers/media/rc/Kconfig +10 -0
index 1021c08a9ba4..b7e08324b874 100644
@@ -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
drivers/media/rc/Makefile +1 -0
index e0340d043fe8..fc4058013234 100644
@@ -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
drivers/media/rc/ir-rcmm-decoder.c new file +185 -0

185 lines not on this page · raw message

drivers/media/rc/rc-core-priv.h +5 -0
index c2cbe7f6266c..c63d4ad007cc 100644
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
 		unsigned int bits;
 		bool stick_keyboard;
 	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned count;
+		u64 bits;
+	} rcmm;
 };
 
 /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +3 -0
index 552bbe82a160..ad1dee921f5b 100644
@@ -70,6 +70,8 @@ static const struct {
 	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
 	[RC_PROTO_IMON] = { .name = "imon",
 		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM] = { .name = "rcmm",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },
 };
 
 /* Used to keep track of known keymaps */
@@ -1004,6 +1006,7 @@ static const struct {
 	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
 	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
 	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM,	"rcmm",		"ir-rcmm-decoder"	},
 };
 
 /**
include/media/rc-map.h +4 -2
index bfa3017cecba..28e8e7692b38 100644
@@ -37,6 +37,7 @@
 #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
 #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
 #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM		BIT_ULL(RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL \
 			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +52,7 @@
 			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
 			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM)
 /* All rc protocols for which we have decoders */
 #define RC_PROTO_BIT_ALL_IR_DECODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +65,8 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL_IR_ENCODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
include/uapi/linux/lirc.h +1 -0
index 6b319581882f..2bc7915ff33a 100644
@@ -218,6 +218,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
tools/include/uapi/linux/lirc.h +1 -0
index f189931042a7..c03e9562e349 100644
@@ -212,6 +212,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
Signature · 1 line
2.19.2
maintainer
#1 lore raw
Quoted 13 lines · On Tue, Dec 04, 2018 at 09:20:25PM +0100, [email protected] wrote:

From: Patrick LERDA <[email protected]>

---
 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

We have a rc-mm decoder written in BPF, see:

https://git.linuxtv.org/v4l-utils.git/tree/utils/keytable/bpf_protocols/rc_mm.c

This is in v4l-utils 1.16 and higher.

Any reason to have it in the kernel rather than in BPF?

Sean

Quoted 319 lines
drivers/media/rc/Kconfig +10 -0
index 1021c08a9ba4..b7e08324b874 100644
@@ -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
drivers/media/rc/Makefile +1 -0
index e0340d043fe8..fc4058013234 100644
@@ -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
drivers/media/rc/ir-rcmm-decoder.c new file +185 -0
new file mode 100644
index 000000000000..b05063f0a552
@@ -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 <linux/module.h>
+#include <linux/version.h>
+
+
+#define RCMM_UNIT		166667	/* nanosecs */
+#define RCMM_0_NBITS		64
+#define RCMM_PREFIX_PULSE	416666  /* 166666.666666666*2.5 */
+#define RCMM_PULSE_0            277777  /* 166666.666666666*(1+2/3) */
+#define RCMM_PULSE_1            444444  /* 166666.666666666*(2+2/3) */
+#define RCMM_PULSE_2            611111  /* 166666.666666666*(3+2/3) */
+#define RCMM_PULSE_3            777778  /* 166666.666666666*(4+2/3) */
+#define RCMM_MODE_MASK          0x0000
+
+enum rcmm_state {
+	STATE_INACTIVE,
+	STATE_LOW,
+	STATE_BUMP,
+	STATE_VALUE,
+	STATE_FINISHED,
+};
+
+static bool rcmm_mode(struct rcmm_dec *data)
+{
+        return !((0x000c0000 & data->bits) == 0x000c0000);
+}
+
+/**
+ * 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 = &dev->raw->rcmm;
+	u32 scancode;
+	u8 toggle;
+
+	if (!(dev->enabled_protocols & RC_PROTO_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 takes some time to
+		   adjust to the signal */
+		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))
+			break;
+
+		data->state = STATE_VALUE;
+		return 0;
+
+	case STATE_VALUE:
+		if (ev.pulse)
+			break;
+	        {
+			int value;
+
+			if (eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2)) {
+				value = 0;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_1, RCMM_UNIT / 2))	{
+				value = 1;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_2, RCMM_UNIT / 2))	{
+				value = 2;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_3, RCMM_UNIT / 2))	{
+				value = 3;
+			} else
+				break;
+
+			data->bits <<= 2;
+			data->bits |= value;
+		}
+
+		data->count+=2;
+
+		if (data->count < 32) {
+			data->state = STATE_BUMP;
+		} else {
+			data->state = STATE_FINISHED;
+		}
+
+		return 0;
+
+	case STATE_FINISHED:
+	        if (!ev.pulse) break;
+
+		if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
+			break;
+
+		if (rcmm_mode(data)) {
+			toggle = !!(0x8000 & data->bits);
+			scancode = data->bits & ~0x8000;
+		} else {
+			toggle = 0;
+			scancode = data->bits;
+		}
+
+		rc_keydown(dev, RC_PROTO_RCMM, scancode, toggle);
+		data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+out:
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler rcmm_handler = {
+	.protocols	= RC_PROTO_RCMM,
+	.decode		= ir_rcmm_decode,
+};
+
+static int __init ir_rcmm_decode_init(void)
+{
+	ir_raw_handler_register(&rcmm_handler);
+
+	printk(KERN_INFO "IR RCMM protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_rcmm_decode_exit(void)
+{
+	ir_raw_handler_unregister(&rcmm_handler);
+}
+
+module_init(ir_rcmm_decode_init);
+module_exit(ir_rcmm_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick LERDA");
+MODULE_DESCRIPTION("RCMM IR protocol decoder");
drivers/media/rc/rc-core-priv.h +5 -0
index c2cbe7f6266c..c63d4ad007cc 100644
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
 		unsigned int bits;
 		bool stick_keyboard;
 	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned count;
+		u64 bits;
+	} rcmm;
 };
 
 /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +3 -0
index 552bbe82a160..ad1dee921f5b 100644
@@ -70,6 +70,8 @@ static const struct {
 	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
 	[RC_PROTO_IMON] = { .name = "imon",
 		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM] = { .name = "rcmm",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },
 };
 
 /* Used to keep track of known keymaps */
@@ -1004,6 +1006,7 @@ static const struct {
 	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
 	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
 	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM,	"rcmm",		"ir-rcmm-decoder"	},
 };
 
 /**
include/media/rc-map.h +4 -2
index bfa3017cecba..28e8e7692b38 100644
@@ -37,6 +37,7 @@
 #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
 #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
 #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM		BIT_ULL(RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL \
 			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +52,7 @@
 			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
 			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM)
 /* All rc protocols for which we have decoders */
 #define RC_PROTO_BIT_ALL_IR_DECODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +65,8 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL_IR_ENCODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
include/uapi/linux/lirc.h +1 -0
index 6b319581882f..2bc7915ff33a 100644
@@ -218,6 +218,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
tools/include/uapi/linux/lirc.h +1 -0
index f189931042a7..c03e9562e349 100644
@@ -212,6 +212,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
Signature · 1 line
2.19.2
author maintainer
#2 lore raw

We have so many decoders at the linux kernel level now. I'm not sure of the best option.

Patrick.

Quoted 354 lines · Sean Young
Quoted 14 lines · On Tue, Dec 04, 2018 at 09:20:25PM +0100, [email protected] wrote:

From: Patrick LERDA <[email protected]>

---
 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

We have a rc-mm decoder written in BPF, see:

https://git.linuxtv.org/v4l-utils.git/tree/utils/keytable/bpf_protocols/rc_mm.c

This is in v4l-utils 1.16 and higher.

Any reason to have it in the kernel rather than in BPF?

Sean

Quoted 326 lines
drivers/media/rc/Kconfig +10 -0
index 1021c08a9ba4..b7e08324b874 100644
@@ -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
drivers/media/rc/Makefile +1 -0
index e0340d043fe8..fc4058013234 100644
@@ -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
drivers/media/rc/ir-rcmm-decoder.c new file +5 -0
new file mode 100644
index 000000000000..b05063f0a552
@@ -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.
+ */

drivers/media/rc/ir-rcmm-decoder.c new file +10 -0
+
+#include "rc-core-priv.h"
+#include <linux/module.h>
+#include <linux/version.h>
+
+
+#define RCMM_UNIT		166667	/* nanosecs */
+#define RCMM_0_NBITS		64
+#define RCMM_PREFIX_PULSE	416666  /* 166666.666666666*2.5 */
+#define RCMM_PULSE_0            277777  /* 166666.666666666*(1+2/3) 

*/
+#define RCMM_PULSE_1 444444 /* 166666.666666666*(2+2/3)
*/
+#define RCMM_PULSE_2 611111 /* 166666.666666666*(3+2/3)
*/
+#define RCMM_PULSE_3 777778 /* 166666.666666666*(4+2/3)
*/

drivers/media/rc/ir-rcmm-decoder.c new file +21 -0
+#define RCMM_MODE_MASK          0x0000
+
+enum rcmm_state {
+	STATE_INACTIVE,
+	STATE_LOW,
+	STATE_BUMP,
+	STATE_VALUE,
+	STATE_FINISHED,
+};
+
+static bool rcmm_mode(struct rcmm_dec *data)
+{
+        return !((0x000c0000 & data->bits) == 0x000c0000);
+}
+
+/**
+ * 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
+ */

drivers/media/rc/ir-rcmm-decoder.c new file +137 -0
+static int ir_rcmm_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+	struct rcmm_dec *data = &dev->raw->rcmm;
+	u32 scancode;
+	u8 toggle;
+
+	if (!(dev->enabled_protocols & RC_PROTO_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 takes some time to
+		   adjust to the signal */
+		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))
+			break;
+
+		data->state = STATE_VALUE;
+		return 0;
+
+	case STATE_VALUE:
+		if (ev.pulse)
+			break;
+	        {
+			int value;
+
+			if (eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2)) {
+				value = 0;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_1, RCMM_UNIT / 2))	{
+				value = 1;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_2, RCMM_UNIT / 2))	{
+				value = 2;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_3, RCMM_UNIT / 2))	{
+				value = 3;
+			} else
+				break;
+
+			data->bits <<= 2;
+			data->bits |= value;
+		}
+
+		data->count+=2;
+
+		if (data->count < 32) {
+			data->state = STATE_BUMP;
+		} else {
+			data->state = STATE_FINISHED;
+		}
+
+		return 0;
+
+	case STATE_FINISHED:
+	        if (!ev.pulse) break;
+
+		if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
+			break;
+
+		if (rcmm_mode(data)) {
+			toggle = !!(0x8000 & data->bits);
+			scancode = data->bits & ~0x8000;
+		} else {
+			toggle = 0;
+			scancode = data->bits;
+		}
+
+		rc_keydown(dev, RC_PROTO_RCMM, scancode, toggle);
+		data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+out:
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler rcmm_handler = {
+	.protocols	= RC_PROTO_RCMM,
+	.decode		= ir_rcmm_decode,
+};
+
+static int __init ir_rcmm_decode_init(void)
+{
+	ir_raw_handler_register(&rcmm_handler);
+
+	printk(KERN_INFO "IR RCMM protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_rcmm_decode_exit(void)
+{
+	ir_raw_handler_unregister(&rcmm_handler);
+}
+
+module_init(ir_rcmm_decode_init);
+module_exit(ir_rcmm_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick LERDA");
+MODULE_DESCRIPTION("RCMM IR protocol decoder");
drivers/media/rc/rc-core-priv.h +5 -0
index c2cbe7f6266c..c63d4ad007cc 100644
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
 		unsigned int bits;
 		bool stick_keyboard;
 	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned count;
+		u64 bits;
+	} rcmm;
 };
 
 /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +3 -0
index 552bbe82a160..ad1dee921f5b 100644
@@ -70,6 +70,8 @@ static const struct {
 	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
 	[RC_PROTO_IMON] = { .name = "imon",
 		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM] = { .name = "rcmm",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },
 };
 
 /* Used to keep track of known keymaps */
@@ -1004,6 +1006,7 @@ static const struct {
 	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
 	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
 	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM,	"rcmm",		"ir-rcmm-decoder"	},
 };
 
 /**
include/media/rc-map.h +4 -2
index bfa3017cecba..28e8e7692b38 100644
@@ -37,6 +37,7 @@
 #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
 #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
 #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM		BIT_ULL(RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL \
 			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +52,7 @@
 			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
 			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM)
 /* All rc protocols for which we have decoders */
 #define RC_PROTO_BIT_ALL_IR_DECODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +65,8 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL_IR_ENCODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
include/uapi/linux/lirc.h +1 -0
index 6b319581882f..2bc7915ff33a 100644
@@ -218,6 +218,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
tools/include/uapi/linux/lirc.h +1 -1
index f189931042a7..c03e9562e349 100644
@@ -212,6 +212,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
--

2.19.2

author maintainer
#3 lore raw

The toggle flag is well handled with this code and at the kernel level; This adds reliability.

Patrick.

Quoted 362 lines · On 04/12/2018 22:06, [email protected] wrote:

We have so many decoders at the linux kernel level now. I'm not sure of the best option.

Patrick.

Quoted 356 lines · Sean Young
Quoted 14 lines · On Tue, Dec 04, 2018 at 09:20:25PM +0100, [email protected] wrote:

From: Patrick LERDA <[email protected]>

---
 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

We have a rc-mm decoder written in BPF, see:

https://git.linuxtv.org/v4l-utils.git/tree/utils/keytable/bpf_protocols/rc_mm.c

This is in v4l-utils 1.16 and higher.

Any reason to have it in the kernel rather than in BPF?

Sean

Quoted 328 lines
drivers/media/rc/Kconfig +10 -0
index 1021c08a9ba4..b7e08324b874 100644
@@ -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
drivers/media/rc/Makefile +0 -0
index e0340d043fe8..fc4058013234 100644
@@ -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

drivers/media/rc/Makefile +1 -0
+obj-$(CONFIG_IR_RCMM_DECODER) += ir-rcmm-decoder.o
 
 # stand-alone IR receivers/transmitters
 obj-$(CONFIG_RC_ATI_REMOTE) += ati_remote.o
drivers/media/rc/ir-rcmm-decoder.c new file +5 -0
new file mode 100644
index 000000000000..b05063f0a552
@@ -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.
+ */

drivers/media/rc/ir-rcmm-decoder.c new file +10 -0
+
+#include "rc-core-priv.h"
+#include <linux/module.h>
+#include <linux/version.h>
+
+
+#define RCMM_UNIT		166667	/* nanosecs */
+#define RCMM_0_NBITS		64
+#define RCMM_PREFIX_PULSE	416666  /* 166666.666666666*2.5 */
+#define RCMM_PULSE_0            277777  /* 166666.666666666*(1+2/3) 

*/
+#define RCMM_PULSE_1 444444 /* 166666.666666666*(2+2/3)
*/
+#define RCMM_PULSE_2 611111 /* 166666.666666666*(3+2/3)
*/
+#define RCMM_PULSE_3 777778 /* 166666.666666666*(4+2/3)
*/

drivers/media/rc/ir-rcmm-decoder.c new file +21 -0
+#define RCMM_MODE_MASK          0x0000
+
+enum rcmm_state {
+	STATE_INACTIVE,
+	STATE_LOW,
+	STATE_BUMP,
+	STATE_VALUE,
+	STATE_FINISHED,
+};
+
+static bool rcmm_mode(struct rcmm_dec *data)
+{
+        return !((0x000c0000 & data->bits) == 0x000c0000);
+}
+
+/**
+ * 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)

drivers/media/rc/ir-rcmm-decoder.c new file +136 -0
+{
+	struct rcmm_dec *data = &dev->raw->rcmm;
+	u32 scancode;
+	u8 toggle;
+
+	if (!(dev->enabled_protocols & RC_PROTO_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 takes some time to
+		   adjust to the signal */
+		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))
+			break;
+
+		data->state = STATE_VALUE;
+		return 0;
+
+	case STATE_VALUE:
+		if (ev.pulse)
+			break;
+	        {
+			int value;
+
+			if (eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2)) {
+				value = 0;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_1, RCMM_UNIT / 2))	{
+				value = 1;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_2, RCMM_UNIT / 2))	{
+				value = 2;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_3, RCMM_UNIT / 2))	{
+				value = 3;
+			} else
+				break;
+
+			data->bits <<= 2;
+			data->bits |= value;
+		}
+
+		data->count+=2;
+
+		if (data->count < 32) {
+			data->state = STATE_BUMP;
+		} else {
+			data->state = STATE_FINISHED;
+		}
+
+		return 0;
+
+	case STATE_FINISHED:
+	        if (!ev.pulse) break;
+
+		if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
+			break;
+
+		if (rcmm_mode(data)) {
+			toggle = !!(0x8000 & data->bits);
+			scancode = data->bits & ~0x8000;
+		} else {
+			toggle = 0;
+			scancode = data->bits;
+		}
+
+		rc_keydown(dev, RC_PROTO_RCMM, scancode, toggle);
+		data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+out:
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler rcmm_handler = {
+	.protocols	= RC_PROTO_RCMM,
+	.decode		= ir_rcmm_decode,
+};
+
+static int __init ir_rcmm_decode_init(void)
+{
+	ir_raw_handler_register(&rcmm_handler);
+
+	printk(KERN_INFO "IR RCMM protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_rcmm_decode_exit(void)
+{
+	ir_raw_handler_unregister(&rcmm_handler);
+}
+
+module_init(ir_rcmm_decode_init);
+module_exit(ir_rcmm_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick LERDA");
+MODULE_DESCRIPTION("RCMM IR protocol decoder");
drivers/media/rc/rc-core-priv.h +5 -0
index c2cbe7f6266c..c63d4ad007cc 100644
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
 		unsigned int bits;
 		bool stick_keyboard;
 	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned count;
+		u64 bits;
+	} rcmm;
 };
 
 /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +3 -0
index 552bbe82a160..ad1dee921f5b 100644
@@ -70,6 +70,8 @@ static const struct {
 	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
 	[RC_PROTO_IMON] = { .name = "imon",
 		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM] = { .name = "rcmm",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },
 };
 
 /* Used to keep track of known keymaps */
@@ -1004,6 +1006,7 @@ static const struct {
 	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
 	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
 	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM,	"rcmm",		"ir-rcmm-decoder"	},
 };
 
 /**
include/media/rc-map.h +4 -2
index bfa3017cecba..28e8e7692b38 100644
@@ -37,6 +37,7 @@
 #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
 #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
 #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM		BIT_ULL(RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL \
 			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +52,7 @@
 			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
 			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM)
 /* All rc protocols for which we have decoders */
 #define RC_PROTO_BIT_ALL_IR_DECODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +65,8 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL_IR_ENCODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
include/uapi/linux/lirc.h +1 -0
index 6b319581882f..2bc7915ff33a 100644
@@ -218,6 +218,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
tools/include/uapi/linux/lirc.h +1 -1
index f189931042a7..c03e9562e349 100644
@@ -212,6 +212,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
--

2.19.2

author maintainer
#5 lore raw

PATCH v2 1/1 Add ir-rcmm-driver

From: Patrick LERDA <[email protected]>

---
 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
drivers/media/rc/Kconfig +10 -0
index 1021c08a9ba4..b7e08324b874 100644
@@ -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
drivers/media/rc/Makefile +1 -0
index e0340d043fe8..fc4058013234 100644
@@ -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
drivers/media/rc/ir-rcmm-decoder.c new file +185 -0

185 lines not on this page · raw message

drivers/media/rc/rc-core-priv.h +5 -0
index c2cbe7f6266c..c63d4ad007cc 100644
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
 		unsigned int bits;
 		bool stick_keyboard;
 	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned count;
+		u64 bits;
+	} rcmm;
 };
 
 /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +3 -0
index 552bbe82a160..ad1dee921f5b 100644
@@ -70,6 +70,8 @@ static const struct {
 	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
 	[RC_PROTO_IMON] = { .name = "imon",
 		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM] = { .name = "rcmm",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },
 };
 
 /* Used to keep track of known keymaps */
@@ -1004,6 +1006,7 @@ static const struct {
 	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
 	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
 	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM,	"rcmm",		"ir-rcmm-decoder"	},
 };
 
 /**
include/media/rc-map.h +4 -2
index bfa3017cecba..f06200362a3c 100644
@@ -37,6 +37,7 @@
 #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
 #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
 #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM		BIT_ULL(RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL \
 			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +52,7 @@
 			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
 			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM)
 /* All rc protocols for which we have decoders */
 #define RC_PROTO_BIT_ALL_IR_DECODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +65,8 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_BIT_RCMM)
 
 #define RC_PROTO_BIT_ALL_IR_ENCODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
include/uapi/linux/lirc.h +1 -0
index 6b319581882f..2bc7915ff33a 100644
@@ -218,6 +218,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
tools/include/uapi/linux/lirc.h +1 -0
index f189931042a7..c03e9562e349 100644
@@ -212,6 +212,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
Signature · 1 line
2.19.2
maintainer
#6 lore raw
Quoted 2 lines · On Wed, Dec 05, 2018 at 01:29:33AM +0100, [email protected] wrote:

From: Patrick LERDA <[email protected]>

We need a Signed-off-by: here.

https://www.kernel.org/doc/html/v4.12/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin

Quoted 17 lines
---
 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
drivers/media/rc/Kconfig +0 -0
index 1021c08a9ba4..b7e08324b874 100644

drivers/media/rc/Kconfig config IR_IMON_DECODER · line 139

Quoted 7 lines
drivers/media/rc/Kconfig +4 -0
@@ -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

You're not using bitreverse, so don't depend on it.

Quoted 29 lines
drivers/media/rc/Kconfig +6 -0
+	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
drivers/media/rc/Makefile +1 -0
index e0340d043fe8..fc4058013234 100644
@@ -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
drivers/media/rc/ir-rcmm-decoder.c new file +2 -0
new file mode 100644
index 000000000000..94d5b70f7a0f
@@ -0,0 +1,185 @@
+/* ir-rcmm-decoder.c - A decoder for the RCMM IR protocol
+ *

drivers/media/rc/ir-rcmm-decoder.c line 12

Quoted 10 lines
drivers/media/rc/ir-rcmm-decoder.c new file +10 -0
+ * 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.

Replace this with the SPDX-License-Identifier.

drivers/media/rc/ir-rcmm-decoder.c line 21

Quoted 9 lines
drivers/media/rc/ir-rcmm-decoder.c new file +9 -0
+ */
+
+#include "rc-core-priv.h"
+#include <linux/module.h>
+#include <linux/version.h>
+
+
+#define RCMM_UNIT		166667	/* nanosecs */
+#define RCMM_0_NBITS		64

Not used.

drivers/media/rc/ir-rcmm-decoder.c line 27

Quoted 6 lines
drivers/media/rc/ir-rcmm-decoder.c new file +6 -0
+#define RCMM_PREFIX_PULSE	416666  /* 166666.666666666*2.5 */
+#define RCMM_PULSE_0            277777  /* 166666.666666666*(1+2/3) */
+#define RCMM_PULSE_1            444444  /* 166666.666666666*(2+2/3) */
+#define RCMM_PULSE_2            611111  /* 166666.666666666*(3+2/3) */
+#define RCMM_PULSE_3            777778  /* 166666.666666666*(4+2/3) */
+#define RCMM_MODE_MASK          0x0000

Not used.

Quoted 38 lines
drivers/media/rc/ir-rcmm-decoder.c new file +38 -0
+
+enum rcmm_state {
+	STATE_INACTIVE,
+	STATE_LOW,
+	STATE_BUMP,
+	STATE_VALUE,
+	STATE_FINISHED,
+};
+
+static bool rcmm_mode(struct rcmm_dec *data)
+{
+        return !((0x000c0000 & data->bits) == 0x000c0000);
+}
+
+/**
+ * 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 = &dev->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;

drivers/media/rc/ir-rcmm-decoder.c line 75

Quoted 10 lines
drivers/media/rc/ir-rcmm-decoder.c new file +10 -0
+
+	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 */

Use:
/*
* Note:
*/
Type multiline comments please.

Quoted 5 lines
drivers/media/rc/ir-rcmm-decoder.c new file +5 -0
+		if (!eq_margin(ev.duration, RCMM_PREFIX_PULSE, RCMM_UNIT/2))
+			break;
+
+		data->state = STATE_LOW;
+		data->count = 0;

drivers/media/rc/ir-rcmm-decoder.c line 90

Quoted 10 lines
drivers/media/rc/ir-rcmm-decoder.c new file +10 -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 takes some time to
+		   adjust to the signal */

Same here

Quoted 11 lines
drivers/media/rc/ir-rcmm-decoder.c new file +11 -0
+		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))

drivers/media/rc/ir-rcmm-decoder.c line 111

Quoted 10 lines
drivers/media/rc/ir-rcmm-decoder.c new file +10 -0
+			break;
+
+		data->state = STATE_VALUE;
+		return 0;
+
+	case STATE_VALUE:
+		if (ev.pulse)
+			break;
+	        {
+			int value;

Please declare value at the top so you don't need a new block.

drivers/media/rc/ir-rcmm-decoder.c line 113

Quoted 2 lines
drivers/media/rc/ir-rcmm-decoder.c new file +2 -0
+
+			if (eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2)) {

No { and } needed for oneline statements after if / else if.

Quoted 11 lines
drivers/media/rc/ir-rcmm-decoder.c new file +11 -0
+				value = 0;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_1, RCMM_UNIT / 2))	{
+				value = 1;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_2, RCMM_UNIT / 2))	{
+				value = 2;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_3, RCMM_UNIT / 2))	{
+				value = 3;
+			} else
+				break;
+
+			data->bits <<= 2;

drivers/media/rc/ir-rcmm-decoder.c line 134

Quoted 10 lines
drivers/media/rc/ir-rcmm-decoder.c new file +10 -0
+			data->bits |= value;
+		}
+
+		data->count+=2;
+
+		if (data->count < 32) {
+			data->state = STATE_BUMP;
+		} else {
+			data->state = STATE_FINISHED;
+		}

No braces for single line statements.

Quoted 20 lines
drivers/media/rc/ir-rcmm-decoder.c new file +20 -0
+
+		return 0;
+
+	case STATE_FINISHED:
+	        if (!ev.pulse) break;
+
+		if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
+			break;
+
+		if (rcmm_mode(data)) {
+			toggle = !!(0x8000 & data->bits);
+			scancode = data->bits & ~0x8000;
+		} else {
+			toggle = 0;
+			scancode = data->bits;
+		}
+
+		rc_keydown(dev, RC_PROTO_RCMM, scancode, toggle);
+		data->state = STATE_INACTIVE;
+		return 0;

drivers/media/rc/ir-rcmm-decoder.c line 164

Quoted 10 lines
drivers/media/rc/ir-rcmm-decoder.c new file +10 -0
+	}
+
+out:
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler rcmm_handler = {
+	.protocols	= RC_PROTO_BIT_RCMM,
+	.decode		= ir_rcmm_decode,

It would be nice to have an rcmm encoder as well.

drivers/media/rc/ir-rcmm-decoder.c line 171

Quoted 7 lines
drivers/media/rc/ir-rcmm-decoder.c new file +7 -0
+};
+
+static int __init ir_rcmm_decode_init(void)
+{
+	ir_raw_handler_register(&rcmm_handler);
+
+	printk(KERN_INFO "IR RCMM protocol handler initialized\n");

Use:

	pr_info()
Quoted 99 lines
drivers/media/rc/ir-rcmm-decoder.c new file +14 -0
+	return 0;
+}
+
+static void __exit ir_rcmm_decode_exit(void)
+{
+	ir_raw_handler_unregister(&rcmm_handler);
+}
+
+module_init(ir_rcmm_decode_init);
+module_exit(ir_rcmm_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick LERDA");
+MODULE_DESCRIPTION("RCMM IR protocol decoder");
drivers/media/rc/rc-core-priv.h +5 -0
index c2cbe7f6266c..c63d4ad007cc 100644
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
 		unsigned int bits;
 		bool stick_keyboard;
 	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned count;
+		u64 bits;
+	} rcmm;
 };
 
 /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +3 -0
index 552bbe82a160..ad1dee921f5b 100644
@@ -70,6 +70,8 @@ static const struct {
 	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
 	[RC_PROTO_IMON] = { .name = "imon",
 		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM] = { .name = "rcmm",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },
 };
 
 /* Used to keep track of known keymaps */
@@ -1004,6 +1006,7 @@ static const struct {
 	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
 	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
 	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM,	"rcmm",		"ir-rcmm-decoder"	},
 };
 
 /**
include/media/rc-map.h +4 -2
index bfa3017cecba..f06200362a3c 100644
@@ -37,6 +37,7 @@
 #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
 #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
 #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM		BIT_ULL(RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL \
 			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +52,7 @@
 			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
 			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM)
 /* All rc protocols for which we have decoders */
 #define RC_PROTO_BIT_ALL_IR_DECODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +65,8 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_BIT_RCMM)
 
 #define RC_PROTO_BIT_ALL_IR_ENCODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
include/uapi/linux/lirc.h +1 -0
index 6b319581882f..2bc7915ff33a 100644
@@ -218,6 +218,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
tools/include/uapi/linux/lirc.h +0 -0
index f189931042a7..c03e9562e349 100644

tools/include/uapi/linux/lirc.h enum rc_proto { · line 217

Quoted 6 lines
tools/include/uapi/linux/lirc.h +1 -0
@@ -212,6 +212,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 

An entry in MAINTAINERS would be good, and please run ./script/checkpatch.pl --strict on your patch and fix any issues you find.

Thanks,

Sean

Quoted 3 lines
tools/include/uapi/linux/lirc.h +0 -0
 #endif
Signature · 1 line
2.19.2
author maintainer
#7 lore raw

PATCH v3 1/1 Add ir-rcmm-driver

In reply to [email protected]

Add support for RCMM infrared remote controls.

---
 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
drivers/media/rc/Kconfig +10 -0
index 1021c08a9ba4..b7e08324b874 100644
@@ -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
drivers/media/rc/Makefile +1 -0
index e0340d043fe8..fc4058013234 100644
@@ -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
drivers/media/rc/ir-rcmm-decoder.c new file +185 -0

185 lines not on this page · raw message

drivers/media/rc/rc-core-priv.h +5 -0
index c2cbe7f6266c..c63d4ad007cc 100644
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
 		unsigned int bits;
 		bool stick_keyboard;
 	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned count;
+		u64 bits;
+	} rcmm;
 };
 
 /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +3 -0
index 552bbe82a160..ad1dee921f5b 100644
@@ -70,6 +70,8 @@ static const struct {
 	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
 	[RC_PROTO_IMON] = { .name = "imon",
 		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM] = { .name = "rcmm",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },
 };
 
 /* Used to keep track of known keymaps */
@@ -1004,6 +1006,7 @@ static const struct {
 	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
 	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
 	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM,	"rcmm",		"ir-rcmm-decoder"	},
 };
 
 /**
include/media/rc-map.h +4 -2
index bfa3017cecba..f06200362a3c 100644
@@ -37,6 +37,7 @@
 #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
 #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
 #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM		BIT_ULL(RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL \
 			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +52,7 @@
 			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
 			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM)
 /* All rc protocols for which we have decoders */
 #define RC_PROTO_BIT_ALL_IR_DECODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +65,8 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_BIT_RCMM)
 
 #define RC_PROTO_BIT_ALL_IR_ENCODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
include/uapi/linux/lirc.h +1 -0
index 6b319581882f..2bc7915ff33a 100644
@@ -218,6 +218,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
tools/include/uapi/linux/lirc.h +1 -0
index f189931042a7..c03e9562e349 100644
@@ -212,6 +212,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
Signature · 1 line
2.19.2
maintainer
#8 lore raw

Hi Patrick,

Quoted 3 lines · Patrick LERDA

Add support for RCMM infrared remote controls.

Other than the Signed-off-by this looks exactly like the v2 version; did you see my other comments on the v2 patch?

Thanks

Sean

Quoted 330 lines
---
 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
drivers/media/rc/Kconfig +10 -0
index 1021c08a9ba4..b7e08324b874 100644
@@ -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
drivers/media/rc/Makefile +1 -0
index e0340d043fe8..fc4058013234 100644
@@ -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
drivers/media/rc/ir-rcmm-decoder.c new file +185 -0
new file mode 100644
index 000000000000..94d5b70f7a0f
@@ -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 <linux/module.h>
+#include <linux/version.h>
+
+
+#define RCMM_UNIT		166667	/* nanosecs */
+#define RCMM_0_NBITS		64
+#define RCMM_PREFIX_PULSE	416666  /* 166666.666666666*2.5 */
+#define RCMM_PULSE_0            277777  /* 166666.666666666*(1+2/3) */
+#define RCMM_PULSE_1            444444  /* 166666.666666666*(2+2/3) */
+#define RCMM_PULSE_2            611111  /* 166666.666666666*(3+2/3) */
+#define RCMM_PULSE_3            777778  /* 166666.666666666*(4+2/3) */
+#define RCMM_MODE_MASK          0x0000
+
+enum rcmm_state {
+	STATE_INACTIVE,
+	STATE_LOW,
+	STATE_BUMP,
+	STATE_VALUE,
+	STATE_FINISHED,
+};
+
+static bool rcmm_mode(struct rcmm_dec *data)
+{
+        return !((0x000c0000 & data->bits) == 0x000c0000);
+}
+
+/**
+ * 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 = &dev->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 takes some time to
+		   adjust to the signal */
+		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))
+			break;
+
+		data->state = STATE_VALUE;
+		return 0;
+
+	case STATE_VALUE:
+		if (ev.pulse)
+			break;
+	        {
+			int value;
+
+			if (eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2)) {
+				value = 0;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_1, RCMM_UNIT / 2))	{
+				value = 1;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_2, RCMM_UNIT / 2))	{
+				value = 2;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_3, RCMM_UNIT / 2))	{
+				value = 3;
+			} else
+				break;
+
+			data->bits <<= 2;
+			data->bits |= value;
+		}
+
+		data->count+=2;
+
+		if (data->count < 32) {
+			data->state = STATE_BUMP;
+		} else {
+			data->state = STATE_FINISHED;
+		}
+
+		return 0;
+
+	case STATE_FINISHED:
+	        if (!ev.pulse) break;
+
+		if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
+			break;
+
+		if (rcmm_mode(data)) {
+			toggle = !!(0x8000 & data->bits);
+			scancode = data->bits & ~0x8000;
+		} else {
+			toggle = 0;
+			scancode = data->bits;
+		}
+
+		rc_keydown(dev, RC_PROTO_RCMM, scancode, toggle);
+		data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+out:
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler rcmm_handler = {
+	.protocols	= RC_PROTO_BIT_RCMM,
+	.decode		= ir_rcmm_decode,
+};
+
+static int __init ir_rcmm_decode_init(void)
+{
+	ir_raw_handler_register(&rcmm_handler);
+
+	printk(KERN_INFO "IR RCMM protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_rcmm_decode_exit(void)
+{
+	ir_raw_handler_unregister(&rcmm_handler);
+}
+
+module_init(ir_rcmm_decode_init);
+module_exit(ir_rcmm_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick LERDA");
+MODULE_DESCRIPTION("RCMM IR protocol decoder");
drivers/media/rc/rc-core-priv.h +5 -0
index c2cbe7f6266c..c63d4ad007cc 100644
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
 		unsigned int bits;
 		bool stick_keyboard;
 	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned count;
+		u64 bits;
+	} rcmm;
 };
 
 /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +3 -0
index 552bbe82a160..ad1dee921f5b 100644
@@ -70,6 +70,8 @@ static const struct {
 	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
 	[RC_PROTO_IMON] = { .name = "imon",
 		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM] = { .name = "rcmm",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },
 };
 
 /* Used to keep track of known keymaps */
@@ -1004,6 +1006,7 @@ static const struct {
 	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
 	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
 	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM,	"rcmm",		"ir-rcmm-decoder"	},
 };
 
 /**
include/media/rc-map.h +4 -2
index bfa3017cecba..f06200362a3c 100644
@@ -37,6 +37,7 @@
 #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
 #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
 #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM		BIT_ULL(RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL \
 			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +52,7 @@
 			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
 			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM)
 /* All rc protocols for which we have decoders */
 #define RC_PROTO_BIT_ALL_IR_DECODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +65,8 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_BIT_RCMM)
 
 #define RC_PROTO_BIT_ALL_IR_ENCODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
include/uapi/linux/lirc.h +1 -0
index 6b319581882f..2bc7915ff33a 100644
@@ -218,6 +218,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
tools/include/uapi/linux/lirc.h +1 -0
index f189931042a7..c03e9562e349 100644
@@ -212,6 +212,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
Signature · 1 line
2.19.2
author maintainer
#9 lore raw

Hi Sean,

Sorry, I just checked the first paragraph.

I will send you a new release.

Thanks,

Patrick.

Quoted 352 lines · Sean Young

Hi Patrick,

Quoted 3 lines · Patrick LERDA

Add support for RCMM infrared remote controls.

Other than the Signed-off-by this looks exactly like the v2 version; did you see my other comments on the v2 patch?

Thanks

Sean

Quoted 338 lines
---
 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
drivers/media/rc/Kconfig +10 -0
index 1021c08a9ba4..b7e08324b874 100644
@@ -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
drivers/media/rc/Makefile +1 -0
index e0340d043fe8..fc4058013234 100644
@@ -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
drivers/media/rc/ir-rcmm-decoder.c new file +5 -0
new file mode 100644
index 000000000000..94d5b70f7a0f
@@ -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.
+ */

drivers/media/rc/ir-rcmm-decoder.c new file +10 -0
+
+#include "rc-core-priv.h"
+#include <linux/module.h>
+#include <linux/version.h>
+
+
+#define RCMM_UNIT		166667	/* nanosecs */
+#define RCMM_0_NBITS		64
+#define RCMM_PREFIX_PULSE	416666  /* 166666.666666666*2.5 */
+#define RCMM_PULSE_0            277777  /* 166666.666666666*(1+2/3) 

*/
+#define RCMM_PULSE_1 444444 /* 166666.666666666*(2+2/3)
*/
+#define RCMM_PULSE_2 611111 /* 166666.666666666*(3+2/3)
*/
+#define RCMM_PULSE_3 777778 /* 166666.666666666*(4+2/3)
*/

drivers/media/rc/ir-rcmm-decoder.c new file +21 -0
+#define RCMM_MODE_MASK          0x0000
+
+enum rcmm_state {
+	STATE_INACTIVE,
+	STATE_LOW,
+	STATE_BUMP,
+	STATE_VALUE,
+	STATE_FINISHED,
+};
+
+static bool rcmm_mode(struct rcmm_dec *data)
+{
+        return !((0x000c0000 & data->bits) == 0x000c0000);
+}
+
+/**
+ * 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
+ */

drivers/media/rc/ir-rcmm-decoder.c new file +137 -0
+static int ir_rcmm_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+	struct rcmm_dec *data = &dev->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 takes some time to
+		   adjust to the signal */
+		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))
+			break;
+
+		data->state = STATE_VALUE;
+		return 0;
+
+	case STATE_VALUE:
+		if (ev.pulse)
+			break;
+	        {
+			int value;
+
+			if (eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2)) {
+				value = 0;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_1, RCMM_UNIT / 2))	{
+				value = 1;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_2, RCMM_UNIT / 2))	{
+				value = 2;
+			} else if (eq_margin(ev.duration, RCMM_PULSE_3, RCMM_UNIT / 2))	{
+				value = 3;
+			} else
+				break;
+
+			data->bits <<= 2;
+			data->bits |= value;
+		}
+
+		data->count+=2;
+
+		if (data->count < 32) {
+			data->state = STATE_BUMP;
+		} else {
+			data->state = STATE_FINISHED;
+		}
+
+		return 0;
+
+	case STATE_FINISHED:
+	        if (!ev.pulse) break;
+
+		if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
+			break;
+
+		if (rcmm_mode(data)) {
+			toggle = !!(0x8000 & data->bits);
+			scancode = data->bits & ~0x8000;
+		} else {
+			toggle = 0;
+			scancode = data->bits;
+		}
+
+		rc_keydown(dev, RC_PROTO_RCMM, scancode, toggle);
+		data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+out:
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler rcmm_handler = {
+	.protocols	= RC_PROTO_BIT_RCMM,
+	.decode		= ir_rcmm_decode,
+};
+
+static int __init ir_rcmm_decode_init(void)
+{
+	ir_raw_handler_register(&rcmm_handler);
+
+	printk(KERN_INFO "IR RCMM protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_rcmm_decode_exit(void)
+{
+	ir_raw_handler_unregister(&rcmm_handler);
+}
+
+module_init(ir_rcmm_decode_init);
+module_exit(ir_rcmm_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick LERDA");
+MODULE_DESCRIPTION("RCMM IR protocol decoder");
drivers/media/rc/rc-core-priv.h +5 -0
index c2cbe7f6266c..c63d4ad007cc 100644
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
 		unsigned int bits;
 		bool stick_keyboard;
 	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned count;
+		u64 bits;
+	} rcmm;
 };
 
 /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +3 -0
index 552bbe82a160..ad1dee921f5b 100644
@@ -70,6 +70,8 @@ static const struct {
 	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
 	[RC_PROTO_IMON] = { .name = "imon",
 		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM] = { .name = "rcmm",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },
 };
 
 /* Used to keep track of known keymaps */
@@ -1004,6 +1006,7 @@ static const struct {
 	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
 	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
 	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM,	"rcmm",		"ir-rcmm-decoder"	},
 };
 
 /**
include/media/rc-map.h +4 -2
index bfa3017cecba..f06200362a3c 100644
@@ -37,6 +37,7 @@
 #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
 #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
 #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM		BIT_ULL(RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL \
 			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +52,7 @@
 			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
 			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM)
 /* All rc protocols for which we have decoders */
 #define RC_PROTO_BIT_ALL_IR_DECODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +65,8 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_BIT_RCMM)
 
 #define RC_PROTO_BIT_ALL_IR_ENCODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
include/uapi/linux/lirc.h +1 -0
index 6b319581882f..2bc7915ff33a 100644
@@ -218,6 +218,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
tools/include/uapi/linux/lirc.h +1 -1
index f189931042a7..c03e9562e349 100644
@@ -212,6 +212,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
--

2.19.2

#10 lore raw
In reply to Patrick LERDA
Thank you for the patch! Perhaps something to improve:

Hi Patrick,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on v4.20-rc5 next-20181207]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Patrick-LERDA/Add-ir-rcmm-driver/20181208-025555
base:   git://linuxtv.org/media_tree.git master
reproduce: make htmldocs

All warnings (new ones prefixed by >>):

include/net/mac80211.h:477: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params ' include/net/mac80211.h:477: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params ' include/net/mac80211.h:477: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params ' include/net/mac80211.h:477: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params ' include/net/mac80211.h:477: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params ' include/net/mac80211.h:477: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params ' include/net/mac80211.h:477: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params ' include/net/mac80211.h:477: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params ' include/net/mac80211.h:477: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params ' net/mac80211/sta_info.h:588: warning: Function parameter or member 'rx_stats_avg' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'rx_stats_avg.signal' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'rx_stats_avg.chain_signal' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'status_stats.filtered' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'status_stats.retry_failed' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'status_stats.retry_count' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'status_stats.lost_packets' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'status_stats.last_tdls_pkt_time' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'status_stats.msdu_retries' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'status_stats.msdu_failed' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'status_stats.last_ack' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'status_stats.last_ack_signal' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'status_stats.ack_signal_filled' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'status_stats.avg_ack_signal' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'tx_stats.packets' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'tx_stats.bytes' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'tx_stats.last_rate' not described in 'sta_info' net/mac80211/sta_info.h:588: warning: Function parameter or member 'tx_stats.msdu' not described in 'sta_info' kernel/rcu/tree.c:685: warning: Excess function parameter 'irq' description in 'rcu_nmi_exit'
include/linux/dma-buf.h:304: warning: Function parameter or member 'cb_excl.cb' not described in 'dma_buf' include/linux/dma-buf.h:304: warning: Function parameter or member 'cb_excl.poll' not described in 'dma_buf' include/linux/dma-buf.h:304: warning: Function parameter or member 'cb_excl.active' not described in 'dma_buf' include/linux/dma-buf.h:304: warning: Function parameter or member 'cb_shared.cb' not described in 'dma_buf' include/linux/dma-buf.h:304: warning: Function parameter or member 'cb_shared.poll' not described in 'dma_buf' include/linux/dma-buf.h:304: warning: Function parameter or member 'cb_shared.active' not described in 'dma_buf' include/linux/dma-fence-array.h:54: warning: Function parameter or member 'work' not described in 'dma_fence_array' include/linux/gpio/driver.h:375: warning: Function parameter or member 'init_valid_mask' not described in 'gpio_chip' include/linux/iio/hw-consumer.h:1: warning: no structured comments found
include/linux/input/sparse-keymap.h:46: warning: Function parameter or member 'sw' not described in 'key_entry' include/linux/regulator/driver.h:227: warning: Function parameter or member 'resume' not described in 'regulator_ops' arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.esw0' not described in 'irb' arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.esw1' not described in 'irb' arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.esw2' not described in 'irb' arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.esw3' not described in 'irb' arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.eadm' not described in 'irb' drivers/slimbus/stream.c:1: warning: no structured comments found
include/linux/spi/spi.h:177: warning: Function parameter or member 'driver_override' not described in 'spi_device' drivers/target/target_core_device.c:1: warning: no structured comments found
drivers/usb/typec/bus.c:1: warning: no structured comments found
drivers/usb/typec/class.c:1: warning: no structured comments found
include/linux/w1.h:281: warning: Function parameter or member 'of_match_table' not described in 'w1_family' fs/direct-io.c:257: warning: Excess function parameter 'offset' description in 'dio_complete'
fs/file_table.c:1: warning: no structured comments found
fs/libfs.c:477: warning: Excess function parameter 'available' description in 'simple_write_end'
fs/posix_acl.c:646: warning: Function parameter or member 'inode' not described in 'posix_acl_update_mode' fs/posix_acl.c:646: warning: Function parameter or member 'mode_p' not described in 'posix_acl_update_mode' fs/posix_acl.c:646: warning: Function parameter or member 'acl' not described in 'posix_acl_update_mode' drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c:183: warning: Function parameter or member 'blockable' not described in 'amdgpu_mn_read_lock' drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c:254: warning: Function parameter or member 'blockable' not described in 'amdgpu_mn_invalidate_range_start_gfx' drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c:302: warning: Function parameter or member 'blockable' not described in 'amdgpu_mn_invalidate_range_start_hsa' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:382: warning: cannot understand function prototype: 'struct amdgpu_vm_pt_cursor ' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:383: warning: cannot understand function prototype: 'struct amdgpu_vm_pt_cursor ' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:555: warning: Function parameter or member 'adev' not described in 'for_each_amdgpu_vm_pt_leaf' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:555: warning: Function parameter or member 'vm' not described in 'for_each_amdgpu_vm_pt_leaf' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:555: warning: Function parameter or member 'start' not described in 'for_each_amdgpu_vm_pt_leaf' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:555: warning: Function parameter or member 'end' not described in 'for_each_amdgpu_vm_pt_leaf' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:555: warning: Function parameter or member 'cursor' not described in 'for_each_amdgpu_vm_pt_leaf' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:603: warning: Function parameter or member 'adev' not described in 'for_each_amdgpu_vm_pt_dfs_safe' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:603: warning: Function parameter or member 'vm' not described in 'for_each_amdgpu_vm_pt_dfs_safe' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:603: warning: Function parameter or member 'cursor' not described in 'for_each_amdgpu_vm_pt_dfs_safe' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:603: warning: Function parameter or member 'entry' not described in 'for_each_amdgpu_vm_pt_dfs_safe' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:848: warning: Function parameter or member 'level' not described in 'amdgpu_vm_bo_param' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1356: warning: Function parameter or member 'params' not described in 'amdgpu_vm_update_func' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1356: warning: Function parameter or member 'bo' not described in 'amdgpu_vm_update_func' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1356: warning: Function parameter or member 'pe' not described in 'amdgpu_vm_update_func' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1356: warning: Function parameter or member 'addr' not described in 'amdgpu_vm_update_func' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1356: warning: Function parameter or member 'count' not described in 'amdgpu_vm_update_func' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1356: warning: Function parameter or member 'incr' not described in 'amdgpu_vm_update_func' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1356: warning: Function parameter or member 'flags' not described in 'amdgpu_vm_update_func' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1523: warning: Function parameter or member 'params' not described in 'amdgpu_vm_update_huge' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1523: warning: Function parameter or member 'bo' not described in 'amdgpu_vm_update_huge' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1523: warning: Function parameter or member 'level' not described in 'amdgpu_vm_update_huge' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1523: warning: Function parameter or member 'pe' not described in 'amdgpu_vm_update_huge' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1523: warning: Function parameter or member 'addr' not described in 'amdgpu_vm_update_huge' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1523: warning: Function parameter or member 'count' not described in 'amdgpu_vm_update_huge' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1523: warning: Function parameter or member 'incr' not described in 'amdgpu_vm_update_huge' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1523: warning: Function parameter or member 'flags' not described in 'amdgpu_vm_update_huge' drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:3100: warning: Function parameter or member 'pasid' not described in 'amdgpu_vm_make_compute' include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_pin' not described in 'drm_driver' include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_unpin' not described in 'drm_driver' include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_res_obj' not described in 'drm_driver' include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_get_sg_table' not described in 'drm_driver' include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_import_sg_table' not described in 'drm_driver' include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_vmap' not described in 'drm_driver' include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_vunmap' not described in 'drm_driver' include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_mmap' not described in 'drm_driver' include/drm/drm_mode_config.h:869: warning: Function parameter or member 'quirk_addfb_prefer_xbgr_30bpp' not described in 'drm_mode_config' drivers/gpu/drm/i915/i915_vma.h:49: warning: cannot understand function prototype: 'struct i915_vma ' drivers/gpu/drm/i915/i915_vma.h:1: warning: no structured comments found
drivers/gpu/drm/i915/intel_guc_fwif.h:554: warning: cannot understand function prototype: 'struct guc_log_buffer_state ' drivers/gpu/drm/i915/i915_trace.h:1: warning: no structured comments found

>> include/uapi/linux/lirc.h:222: warning: Enum value 'RC_PROTO_RCMM' not described in enum 'rc_proto'

include/linux/skbuff.h:862: warning: Function parameter or member 'dev_scratch' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'list' not described in 'sk_buff'
include/linux/skbuff.h:862: warning: Function parameter or member 'ip_defrag_offset' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'skb_mstamp_ns' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member '__cloned_offset' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'head_frag' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member '__pkt_type_offset' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'encapsulation' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'encap_hdr_csum' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'csum_valid' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'csum_complete_sw' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'csum_level' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'inner_protocol_type' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'remcsum_offload' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'offload_fwd_mark' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'offload_mr_fwd_mark' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'sender_cpu' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'reserved_tailroom' not described in 'sk_buff' include/linux/skbuff.h:862: warning: Function parameter or member 'inner_ipproto' not described in 'sk_buff' include/net/sock.h:238: warning: Function parameter or member 'skc_addrpair' not described in 'sock_common' include/net/sock.h:238: warning: Function parameter or member 'skc_portpair' not described in 'sock_common' include/net/sock.h:238: warning: Function parameter or member 'skc_ipv6only' not described in 'sock_common' include/net/sock.h:238: warning: Function parameter or member 'skc_net_refcnt' not described in 'sock_common' include/net/sock.h:238: warning: Function parameter or member 'skc_v6_daddr' not described in 'sock_common' include/net/sock.h:238: warning: Function parameter or member 'skc_v6_rcv_saddr' not described in 'sock_common' include/net/sock.h:238: warning: Function parameter or member 'skc_cookie' not described in 'sock_common' include/net/sock.h:238: warning: Function parameter or member 'skc_listener' not described in 'sock_common' include/net/sock.h:238: warning: Function parameter or member 'skc_tw_dr' not described in 'sock_common' include/net/sock.h:238: warning: Function parameter or member 'skc_rcv_wnd' not described in 'sock_common' include/net/sock.h:238: warning: Function parameter or member 'skc_tw_rcv_nxt' not described in 'sock_common' include/net/sock.h:509: warning: Function parameter or member 'sk_backlog.rmem_alloc' not described in 'sock' include/net/sock.h:509: warning: Function parameter or member 'sk_backlog.len' not described in 'sock'
include/net/sock.h:509: warning: Function parameter or member 'sk_backlog.head' not described in 'sock'
include/net/sock.h:509: warning: Function parameter or member 'sk_backlog.tail' not described in 'sock'
include/net/sock.h:509: warning: Function parameter or member 'sk_wq_raw' not described in 'sock'
include/net/sock.h:509: warning: Function parameter or member 'tcp_rtx_queue' not described in 'sock'
include/net/sock.h:509: warning: Function parameter or member 'sk_route_forced_caps' not described in 'sock' include/net/sock.h:509: warning: Function parameter or member 'sk_txtime_report_errors' not described in 'sock' include/net/sock.h:509: warning: Function parameter or member 'sk_validate_xmit_skb' not described in 'sock' include/linux/netdevice.h:2052: warning: Function parameter or member 'adj_list.upper' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'adj_list.lower' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'gso_partial_features' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'switchdev_ops' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'l3mdev_ops' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'xfrmdev_ops' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'tlsdev_ops' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'name_assign_type' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'ieee802154_ptr' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'mpls_ptr' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'xdp_prog' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'gro_flush_timeout' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'nf_hooks_ingress' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member '____cacheline_aligned_in_smp' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'qdisc_hash' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'xps_cpus_map' not described in 'net_device' include/linux/netdevice.h:2052: warning: Function parameter or member 'xps_rxqs_map' not described in 'net_device' include/linux/phylink.h:56: warning: Function parameter or member '__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising' not described in 'phylink_link_state' include/linux/phylink.h:56: warning: Function parameter or member '__ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising' not described in 'phylink_link_state' Documentation/admin-guide/cgroup-v2.rst:1507: WARNING: Block quote ends without a blank line; unexpected unindent. Documentation/admin-guide/cgroup-v2.rst:1509: WARNING: Block quote ends without a blank line; unexpected unindent. Documentation/admin-guide/cgroup-v2.rst:1510: WARNING: Block quote ends without a blank line; unexpected unindent. include/net/mac80211.h:1211: ERROR: Unexpected indentation.
include/net/mac80211.h:1218: WARNING: Block quote ends without a blank line; unexpected unindent.
include/linux/wait.h:110: WARNING: Block quote ends without a blank line; unexpected unindent.
include/linux/wait.h:113: ERROR: Unexpected indentation.
include/linux/wait.h:115: WARNING: Block quote ends without a blank line; unexpected unindent.
kernel/time/hrtimer.c:1129: WARNING: Block quote ends without a blank line; unexpected unindent.
kernel/signal.c:344: WARNING: Inline literal start-string without end-string.
include/linux/kernel.h:137: WARNING: Inline interpreted text or phrase reference start-string without end-string. include/uapi/linux/firewire-cdev.h:312: WARNING: Inline literal start-string without end-string. Documentation/driver-api/gpio/board.rst:209: ERROR: Unexpected indentation.
drivers/ata/libata-core.c:5958: ERROR: Unknown target name: "hw".
drivers/message/fusion/mptbase.c:5057: WARNING: Definition list ends without a blank line; unexpected unindent. drivers/tty/serial/serial_core.c:1938: WARNING: Definition list ends without a blank line; unexpected unindent. include/linux/mtd/rawnand.h:1189: WARNING: Inline strong start-string without end-string.
include/linux/mtd/rawnand.h:1191: WARNING: Inline strong start-string without end-string.
include/linux/regulator/driver.h:286: ERROR: Unknown target name: "regulator_regmap_x_voltage". Documentation/driver-api/soundwire/locking.rst:50: ERROR: Inconsistent literal block quoting. Documentation/driver-api/soundwire/locking.rst:51: WARNING: Line block ends without a blank line. Documentation/driver-api/soundwire/locking.rst:55: WARNING: Inline substitution_reference start-string without end-string. Documentation/driver-api/soundwire/locking.rst:56: WARNING: Line block ends without a blank line.
include/linux/spi/spi.h:365: ERROR: Unexpected indentation.
Documentation/driver-api/usb/typec_bus.rst:76: WARNING: Definition list ends without a blank line; unexpected unindent. block/bio.c:883: WARNING: Inline emphasis start-string without end-string.
fs/posix_acl.c:635: WARNING: Inline emphasis start-string without end-string.
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c:1573: WARNING: Inline emphasis start-string without end-string. drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c:1575: WARNING: Inline emphasis start-string without end-string. include/drm/drm_drv.h:656: ERROR: Unknown target name: "driver".
Documentation/laptops/lg-laptop.rst:2: WARNING: Explicit markup ends without a blank line; unexpected unindent. Documentation/laptops/lg-laptop.rst:16: ERROR: Unexpected indentation.
Documentation/laptops/lg-laptop.rst:17: WARNING: Block quote ends without a blank line; unexpected unindent. Documentation/misc-devices/ibmvmc.rst:2: WARNING: Explicit markup ends without a blank line; unexpected unindent. Documentation/networking/dpaa2/dpio-driver.rst:30: ERROR: Unexpected indentation. Documentation/networking/dpaa2/dpio-driver.rst:42: WARNING: Definition list ends without a blank line; unexpected unindent. Documentation/networking/dpaa2/dpio-driver.rst:62: ERROR: Unexpected indentation. Documentation/networking/dpaa2/dpio-driver.rst:143: ERROR: Unexpected indentation.
include/linux/netdevice.h:3452: WARNING: Inline emphasis start-string without end-string.
include/linux/netdevice.h:3452: WARNING: Inline emphasis start-string without end-string.
net/core/dev.c:4949: ERROR: Unknown target name: "page_is".
Documentation/security/keys/core.rst:1597: WARNING: Inline literal start-string without end-string.

vim +222 include/uapi/linux/lirc.h

9b6192589 Sean Young    2017-02-25  167  
9b6192589 Sean Young    2017-02-25  168  /**
9b6192589 Sean Young    2017-02-25  169   * enum rc_proto - the Remote Controller protocol
9b6192589 Sean Young    2017-02-25  170   *
9b6192589 Sean Young    2017-02-25  171   * @RC_PROTO_UNKNOWN: Protocol not known
9b6192589 Sean Young    2017-02-25  172   * @RC_PROTO_OTHER: Protocol known but proprietary
9b6192589 Sean Young    2017-02-25  173   * @RC_PROTO_RC5: Philips RC5 protocol
9b6192589 Sean Young    2017-02-25  174   * @RC_PROTO_RC5X_20: Philips RC5x 20 bit protocol
9b6192589 Sean Young    2017-02-25  175   * @RC_PROTO_RC5_SZ: StreamZap variant of RC5
9b6192589 Sean Young    2017-02-25  176   * @RC_PROTO_JVC: JVC protocol
9b6192589 Sean Young    2017-02-25  177   * @RC_PROTO_SONY12: Sony 12 bit protocol
9b6192589 Sean Young    2017-02-25  178   * @RC_PROTO_SONY15: Sony 15 bit protocol
9b6192589 Sean Young    2017-02-25  179   * @RC_PROTO_SONY20: Sony 20 bit protocol
9b6192589 Sean Young    2017-02-25  180   * @RC_PROTO_NEC: NEC protocol
9b6192589 Sean Young    2017-02-25  181   * @RC_PROTO_NECX: Extended NEC protocol
9b6192589 Sean Young    2017-02-25  182   * @RC_PROTO_NEC32: NEC 32 bit protocol
9b6192589 Sean Young    2017-02-25  183   * @RC_PROTO_SANYO: Sanyo protocol
9b6192589 Sean Young    2017-02-25  184   * @RC_PROTO_MCIR2_KBD: RC6-ish MCE keyboard
9b6192589 Sean Young    2017-02-25  185   * @RC_PROTO_MCIR2_MSE: RC6-ish MCE mouse
9b6192589 Sean Young    2017-02-25  186   * @RC_PROTO_RC6_0: Philips RC6-0-16 protocol
9b6192589 Sean Young    2017-02-25  187   * @RC_PROTO_RC6_6A_20: Philips RC6-6A-20 protocol
9b6192589 Sean Young    2017-02-25  188   * @RC_PROTO_RC6_6A_24: Philips RC6-6A-24 protocol
9b6192589 Sean Young    2017-02-25  189   * @RC_PROTO_RC6_6A_32: Philips RC6-6A-32 protocol
9b6192589 Sean Young    2017-02-25  190   * @RC_PROTO_RC6_MCE: MCE (Philips RC6-6A-32 subtype) protocol
9b6192589 Sean Young    2017-02-25  191   * @RC_PROTO_SHARP: Sharp protocol
9b6192589 Sean Young    2017-02-25  192   * @RC_PROTO_XMP: XMP protocol
9b6192589 Sean Young    2017-02-25  193   * @RC_PROTO_CEC: CEC protocol
447dcc0cf Sean Young    2017-12-03  194   * @RC_PROTO_IMON: iMon Pad protocol
9b6192589 Sean Young    2017-02-25  195   */
9b6192589 Sean Young    2017-02-25  196  enum rc_proto {
9b6192589 Sean Young    2017-02-25  197  	RC_PROTO_UNKNOWN	= 0,
9b6192589 Sean Young    2017-02-25  198  	RC_PROTO_OTHER		= 1,
9b6192589 Sean Young    2017-02-25  199  	RC_PROTO_RC5		= 2,
9b6192589 Sean Young    2017-02-25  200  	RC_PROTO_RC5X_20	= 3,
9b6192589 Sean Young    2017-02-25  201  	RC_PROTO_RC5_SZ		= 4,
9b6192589 Sean Young    2017-02-25  202  	RC_PROTO_JVC		= 5,
9b6192589 Sean Young    2017-02-25  203  	RC_PROTO_SONY12		= 6,
9b6192589 Sean Young    2017-02-25  204  	RC_PROTO_SONY15		= 7,
9b6192589 Sean Young    2017-02-25  205  	RC_PROTO_SONY20		= 8,
9b6192589 Sean Young    2017-02-25  206  	RC_PROTO_NEC		= 9,
9b6192589 Sean Young    2017-02-25  207  	RC_PROTO_NECX		= 10,
9b6192589 Sean Young    2017-02-25  208  	RC_PROTO_NEC32		= 11,
9b6192589 Sean Young    2017-02-25  209  	RC_PROTO_SANYO		= 12,
9b6192589 Sean Young    2017-02-25  210  	RC_PROTO_MCIR2_KBD	= 13,
9b6192589 Sean Young    2017-02-25  211  	RC_PROTO_MCIR2_MSE	= 14,
9b6192589 Sean Young    2017-02-25  212  	RC_PROTO_RC6_0		= 15,
9b6192589 Sean Young    2017-02-25  213  	RC_PROTO_RC6_6A_20	= 16,
9b6192589 Sean Young    2017-02-25  214  	RC_PROTO_RC6_6A_24	= 17,
9b6192589 Sean Young    2017-02-25  215  	RC_PROTO_RC6_6A_32	= 18,
9b6192589 Sean Young    2017-02-25  216  	RC_PROTO_RC6_MCE	= 19,
9b6192589 Sean Young    2017-02-25  217  	RC_PROTO_SHARP		= 20,
9b6192589 Sean Young    2017-02-25  218  	RC_PROTO_XMP		= 21,
9b6192589 Sean Young    2017-02-25  219  	RC_PROTO_CEC		= 22,
447dcc0cf Sean Young    2017-12-03  220  	RC_PROTO_IMON		= 23,
d66d06430 Patrick LERDA 2018-12-07  221  	RC_PROTO_RCMM		= 24,

9b6192589 Sean Young 2017-02-25 @222 };
9b6192589 Sean Young 2017-02-25 223

:::::: The code at line 222 was first introduced by commit
:::::: 9b6192589be788dec73a0e99fe49b8f8ddaf825e media: lirc: implement scancode sending

:::::: TO: Sean Young <[email protected]>
:::::: CC: Mauro Carvalho Chehab <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

A message that is not in the archive (sent off-list or not yet received): [email protected]

author maintainer
#12 lore raw

PATCH v5 1/1 media: rc: rcmm decoder

media: add support for RCMM infrared remote controls.

---
 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
MAINTAINERS +5 -0
index 3e9f1710ed13..80426d1faaba 100644
@@ -16277,6 +16277,11 @@ M:	David Härdeman <[email protected]>
 S:	Maintained
 F:	drivers/media/rc/winbond-cir.c
 
+RCMM REMOTE CONTROLS DECODER
+M:	Patrick Lerda <[email protected]>
+S:	Maintained
+F:	drivers/media/rc/ir-rcmm-decoder.c
+
 WINSYSTEMS EBC-C384 WATCHDOG DRIVER
 M:	William Breathitt Gray <[email protected]>
 L:	[email protected]
drivers/media/rc/Kconfig +7 -0
index 8a216068a35a..43775ac74268 100644
@@ -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
drivers/media/rc/Makefile +1 -0
index 92c163816849..48d23433b3c0 100644
@@ -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
drivers/media/rc/ir-rcmm-decoder.c new file +164 -0

164 lines not on this page · raw message

drivers/media/rc/rc-core-priv.h +5 -0
index c2cbe7f6266c..2266f61f887f 100644
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
 		unsigned int bits;
 		bool stick_keyboard;
 	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned int count;
+		u64 bits;
+	} rcmm;
 };
 
 /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +3 -0
index 66a174979b3c..7df40578dac0 100644
@@ -70,6 +70,8 @@ static const struct {
 	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
 	[RC_PROTO_IMON] = { .name = "imon",
 		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM] = { .name = "rcmm",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },
 };
 
 /* Used to keep track of known keymaps */
@@ -1006,6 +1008,7 @@ static const struct {
 	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
 	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
 	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM,	"rcmm",		"ir-rcmm-decoder"	},
 };
 
 /**
include/media/rc-map.h +4 -2
index d621acadfbf3..ff5e3b002f91 100644
@@ -37,6 +37,7 @@
 #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
 #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
 #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM		BIT_ULL(RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL \
 			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +52,7 @@
 			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
 			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM)
 /* All rc protocols for which we have decoders */
 #define RC_PROTO_BIT_ALL_IR_DECODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +65,8 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_BIT_RCMM)
 
 #define RC_PROTO_BIT_ALL_IR_ENCODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
include/uapi/linux/lirc.h +2 -0
index 6b319581882f..56106ccea2cb 100644
@@ -192,6 +192,7 @@ struct lirc_scancode {
  * @RC_PROTO_XMP: XMP protocol
  * @RC_PROTO_CEC: CEC protocol
  * @RC_PROTO_IMON: iMon Pad protocol
+ * @RC_PROTO_RCMM: RC-MM protocol
  */
 enum rc_proto {
 	RC_PROTO_UNKNOWN	= 0,
@@ -218,6 +219,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
tools/include/uapi/linux/lirc.h +2 -0
index f189931042a7..c1e5850c56e1 100644
@@ -186,6 +186,7 @@ struct lirc_scancode {
  * @RC_PROTO_XMP: XMP protocol
  * @RC_PROTO_CEC: CEC protocol
  * @RC_PROTO_IMON: iMon Pad protocol
+ * @RC_PROTO_RCMM: RC-MM protocol
  */
 enum rc_proto {
 	RC_PROTO_UNKNOWN	= 0,
@@ -212,6 +213,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
Signature · 1 line
2.19.2
author maintainer
#13 lore raw

Re: [PATCH v5 1/1] media: rc: rcmm decoder

Hi Sean,

   Is the v5 OK?

   Thanks,

Patrick.

Quoted 340 lines · Patrick Lerda

media: add support for RCMM infrared remote controls.

---
  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

MAINTAINERS +5 -0
index 3e9f1710ed13..80426d1faaba 100644
@@ -16277,6 +16277,11 @@ M:	David Härdeman <[email protected]>
  S:	Maintained
  F:	drivers/media/rc/winbond-cir.c
 
+RCMM REMOTE CONTROLS DECODER
+M:	Patrick Lerda <[email protected]>
+S:	Maintained
+F:	drivers/media/rc/ir-rcmm-decoder.c
+
  WINSYSTEMS EBC-C384 WATCHDOG DRIVER
  M:	William Breathitt Gray <[email protected]>
  L:	[email protected]
drivers/media/rc/Kconfig +7 -0
index 8a216068a35a..43775ac74268 100644
@@ -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
drivers/media/rc/Makefile +1 -0
index 92c163816849..48d23433b3c0 100644
@@ -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
drivers/media/rc/ir-rcmm-decoder.c new file +164 -0
new file mode 100644
index 000000000000..a3c09885da5f
@@ -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 <[email protected]>
+
+#include "rc-core-priv.h"
+#include <linux/module.h>
+#include <linux/version.h>
+
+#define RCMM_UNIT		166667	/* nanosecs */
+#define RCMM_PREFIX_PULSE	416666  /* 166666.666666666*2.5 */
+#define RCMM_PULSE_0            277777  /* 166666.666666666*(1+2/3) */
+#define RCMM_PULSE_1            444444  /* 166666.666666666*(2+2/3) */
+#define RCMM_PULSE_2            611111  /* 166666.666666666*(3+2/3) */
+#define RCMM_PULSE_3            777778  /* 166666.666666666*(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 !((0x000c0000 & data->bits) == 0x000c0000);
+}
+
+/**
+ * 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 = &dev->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))
+			break;
+
+		data->state = STATE_VALUE;
+		return 0;
+
+	case STATE_VALUE:
+		if (ev.pulse)
+			break;
+
+		if (eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2))
+			value = 0;
+		else if (eq_margin(ev.duration, RCMM_PULSE_1, RCMM_UNIT / 2))
+			value = 1;
+		else if (eq_margin(ev.duration, RCMM_PULSE_2, RCMM_UNIT / 2))
+			value = 2;
+		else if (eq_margin(ev.duration, RCMM_PULSE_3, RCMM_UNIT / 2))
+			value = 3;
+		else
+			break;
+
+		data->bits <<= 2;
+		data->bits |= value;
+
+		data->count += 2;
+
+		if (data->count < 32)
+			data->state = STATE_BUMP;
+		else
+			data->state = STATE_FINISHED;
+
+		return 0;
+
+	case STATE_FINISHED:
+		if (!ev.pulse)
+			break;
+
+		if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
+			break;
+
+		if (rcmm_mode(data)) {
+			toggle = !!(0x8000 & data->bits);
+			scancode = data->bits & ~0x8000;
+		} else {
+			toggle = 0;
+			scancode = data->bits;
+		}
+
+		rc_keydown(dev, RC_PROTO_RCMM, scancode, toggle);
+		data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+out:
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler rcmm_handler = {
+	.protocols	= RC_PROTO_BIT_RCMM,
+	.decode		= ir_rcmm_decode,
+};
+
+static int __init ir_rcmm_decode_init(void)
+{
+	ir_raw_handler_register(&rcmm_handler);
+
+	pr_info("IR RCMM protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_rcmm_decode_exit(void)
+{
+	ir_raw_handler_unregister(&rcmm_handler);
+}
+
+module_init(ir_rcmm_decode_init);
+module_exit(ir_rcmm_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick Lerda");
+MODULE_DESCRIPTION("RCMM IR protocol decoder");
drivers/media/rc/rc-core-priv.h +5 -0
index c2cbe7f6266c..2266f61f887f 100644
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
  		unsigned int bits;
  		bool stick_keyboard;
  	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned int count;
+		u64 bits;
+	} rcmm;
  };
 
  /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +3 -0
index 66a174979b3c..7df40578dac0 100644
@@ -70,6 +70,8 @@ static const struct {
  	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
  	[RC_PROTO_IMON] = { .name = "imon",
  		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM] = { .name = "rcmm",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },
  };
 
  /* Used to keep track of known keymaps */
@@ -1006,6 +1008,7 @@ static const struct {
  	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
  	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
  	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM,	"rcmm",		"ir-rcmm-decoder"	},
  };
 
  /**
include/media/rc-map.h +4 -2
index d621acadfbf3..ff5e3b002f91 100644
@@ -37,6 +37,7 @@
  #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
  #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
  #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM		BIT_ULL(RC_PROTO_RCMM)
 
  #define RC_PROTO_BIT_ALL \
  			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +52,7 @@
  			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
  			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
  			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM)
  /* All rc protocols for which we have decoders */
  #define RC_PROTO_BIT_ALL_IR_DECODER \
  			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +65,8 @@
  			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
  			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
  			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_BIT_RCMM)
 
  #define RC_PROTO_BIT_ALL_IR_ENCODER \
  			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
include/uapi/linux/lirc.h +2 -0
index 6b319581882f..56106ccea2cb 100644
@@ -192,6 +192,7 @@ struct lirc_scancode {
   * @RC_PROTO_XMP: XMP protocol
   * @RC_PROTO_CEC: CEC protocol
   * @RC_PROTO_IMON: iMon Pad protocol
+ * @RC_PROTO_RCMM: RC-MM protocol
   */
  enum rc_proto {
  	RC_PROTO_UNKNOWN	= 0,
@@ -218,6 +219,7 @@ enum rc_proto {
  	RC_PROTO_XMP		= 21,
  	RC_PROTO_CEC		= 22,
  	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
  };
 
  #endif
tools/include/uapi/linux/lirc.h +2 -0
index f189931042a7..c1e5850c56e1 100644
@@ -186,6 +186,7 @@ struct lirc_scancode {
   * @RC_PROTO_XMP: XMP protocol
   * @RC_PROTO_CEC: CEC protocol
   * @RC_PROTO_IMON: iMon Pad protocol
+ * @RC_PROTO_RCMM: RC-MM protocol
   */
  enum rc_proto {
  	RC_PROTO_UNKNOWN	= 0,
@@ -212,6 +213,7 @@ enum rc_proto {
  	RC_PROTO_XMP		= 21,
  	RC_PROTO_CEC		= 22,
  	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
  };
 
  #endif
maintainer
#14 lore raw

Re: [PATCH v5 1/1] media: rc: rcmm decoder

Hi Patrick,

Quoted 3 lines · Patrick Lerda

Hi Sean,

   Is the v5 OK?

Sorry I'm currently at the Linux Foundation Hyperledger event in Basel, I'll be back next week and then I'll do a proper review. Looks good at first glance.

Thanks

Sean

maintainer
#15 lore raw

Re: [PATCH v5 1/1] media: rc: rcmm decoder

In reply to Patrick Lerda

Hi Patrick,

Quoted 3 lines · Patrick Lerda

media: add support for RCMM infrared remote controls.

Sorry about the delay in getting this reviewed. December was a very busy month for me.

Quoted 34 lines
---
 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
MAINTAINERS +5 -0
index 3e9f1710ed13..80426d1faaba 100644
@@ -16277,6 +16277,11 @@ M:	David Härdeman <[email protected]>
 S:	Maintained
 F:	drivers/media/rc/winbond-cir.c
 
+RCMM REMOTE CONTROLS DECODER
+M:	Patrick Lerda <[email protected]>
+S:	Maintained
+F:	drivers/media/rc/ir-rcmm-decoder.c
+
 WINSYSTEMS EBC-C384 WATCHDOG DRIVER
 M:	William Breathitt Gray <[email protected]>
 L:	[email protected]
drivers/media/rc/Kconfig +0 -0
index 8a216068a35a..43775ac74268 100644

drivers/media/rc/Kconfig config IR_IMON_DECODER · line 141

Quoted 9 lines
drivers/media/rc/Kconfig +6 -0
@@ -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

checkpatch.pl --strict complains it wants a longer explanation here.

Quoted 124 lines
drivers/media/rc/Kconfig +1 -0
+
 endif #RC_DECODERS
 
 menuconfig RC_DEVICES
drivers/media/rc/Makefile +1 -0
index 92c163816849..48d23433b3c0 100644
@@ -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
drivers/media/rc/ir-rcmm-decoder.c new file +102 -0
new file mode 100644
index 000000000000..a3c09885da5f
@@ -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 <[email protected]>
+
+#include "rc-core-priv.h"
+#include <linux/module.h>
+#include <linux/version.h>
+
+#define RCMM_UNIT		166667	/* nanosecs */
+#define RCMM_PREFIX_PULSE	416666  /* 166666.666666666*2.5 */
+#define RCMM_PULSE_0            277777  /* 166666.666666666*(1+2/3) */
+#define RCMM_PULSE_1            444444  /* 166666.666666666*(2+2/3) */
+#define RCMM_PULSE_2            611111  /* 166666.666666666*(3+2/3) */
+#define RCMM_PULSE_3            777778  /* 166666.666666666*(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 !((0x000c0000 & data->bits) == 0x000c0000);
+}
+
+/**
+ * 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 = &dev->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))
+			break;
+
+		data->state = STATE_VALUE;
+		return 0;
+
+	case STATE_VALUE:
+		if (ev.pulse)
+			break;
+
+		if (eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2))
+			value = 0;
+		else if (eq_margin(ev.duration, RCMM_PULSE_1, RCMM_UNIT / 2))
+			value = 1;
+		else if (eq_margin(ev.duration, RCMM_PULSE_2, RCMM_UNIT / 2))
+			value = 2;
+		else if (eq_margin(ev.duration, RCMM_PULSE_3, RCMM_UNIT / 2))
+			value = 3;
+		else
+			break;

drivers/media/rc/ir-rcmm-decoder.c line 112

Quoted 10 lines
drivers/media/rc/ir-rcmm-decoder.c new file +10 -0
+
+		data->bits <<= 2;
+		data->bits |= value;
+
+		data->count += 2;
+
+		if (data->count < 32)
+			data->state = STATE_BUMP;
+		else
+			data->state = STATE_FINISHED;

Your rcmm implementation only supports the 32 bits variant. There are other bit lengths; lirc supports 12 bits for example:

http://lirc.sourceforge.net/remotes/philips/KW-1009-01

24 bits also possible according to:

https://www.sbprojects.net/knowledge/ir/rcmm.php

Now there is nothing wrong with just supporting 32 bits, but I think the name should make that clear, so that if we ever need to add order bit length variants, we can do so without it ending up messy.

So we should call it rcmm-32, I think.

Quoted 21 lines
drivers/media/rc/ir-rcmm-decoder.c new file +21 -0
+
+		return 0;
+
+	case STATE_FINISHED:
+		if (!ev.pulse)
+			break;
+
+		if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
+			break;
+
+		if (rcmm_mode(data)) {
+			toggle = !!(0x8000 & data->bits);
+			scancode = data->bits & ~0x8000;
+		} else {
+			toggle = 0;
+			scancode = data->bits;
+		}
+
+		rc_keydown(dev, RC_PROTO_RCMM, scancode, toggle);
+		data->state = STATE_INACTIVE;
+		return 0;

drivers/media/rc/ir-rcmm-decoder.c line 143

Quoted 10 lines
drivers/media/rc/ir-rcmm-decoder.c new file +10 -0
+	}
+
+out:
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler rcmm_handler = {
+	.protocols	= RC_PROTO_BIT_RCMM,
+	.decode		= ir_rcmm_decode,

Again an encoder would be great. This is not only useful for transmission but also for self-testing. We now have a self-test in the kernel tree for this. Just nice to have of course.

Quoted 26 lines
drivers/media/rc/ir-rcmm-decoder.c new file +21 -0
+};
+
+static int __init ir_rcmm_decode_init(void)
+{
+	ir_raw_handler_register(&rcmm_handler);
+
+	pr_info("IR RCMM protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_rcmm_decode_exit(void)
+{
+	ir_raw_handler_unregister(&rcmm_handler);
+}
+
+module_init(ir_rcmm_decode_init);
+module_exit(ir_rcmm_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick Lerda");
+MODULE_DESCRIPTION("RCMM IR protocol decoder");
drivers/media/rc/rc-core-priv.h +0 -0
index c2cbe7f6266c..2266f61f887f 100644

drivers/media/rc/rc-core-priv.h struct ir_raw_event_ctrl { · line 137

Quoted 7 lines
drivers/media/rc/rc-core-priv.h +4 -0
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
 		unsigned int bits;
 		bool stick_keyboard;
 	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned int count;
+		u64 bits;

bits can be u32.

Quoted 9 lines
drivers/media/rc/rc-core-priv.h +1 -0
+	} rcmm;
 };
 
 /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +0 -0
index 66a174979b3c..7df40578dac0 100644

drivers/media/rc/rc-main.c static const struct { · line 74

Quoted 5 lines
drivers/media/rc/rc-main.c +2 -0
@@ -70,6 +70,8 @@ static const struct {
 	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
 	[RC_PROTO_IMON] = { .name = "imon",
 		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM] = { .name = "rcmm",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },

So I think this should be:

	[RC_PROTO_RCMM_32] = { .name = "rcmm-32",

drivers/media/rc/rc-main.c static const struct { · line 1011

Quoted 8 lines
drivers/media/rc/rc-main.c +1 -0
 };
 
 /* Used to keep track of known keymaps */
@@ -1006,6 +1008,7 @@ static const struct {
 	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
 	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
 	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM,	"rcmm",		"ir-rcmm-decoder"	},

Same here.

Quoted 76 lines
drivers/media/rc/rc-main.c +0 -0
 };
 
 /**
include/media/rc-map.h +4 -2
index d621acadfbf3..ff5e3b002f91 100644
@@ -37,6 +37,7 @@
 #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
 #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
 #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM		BIT_ULL(RC_PROTO_RCMM)
 
 #define RC_PROTO_BIT_ALL \
 			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +52,7 @@
 			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
 			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM)
 /* All rc protocols for which we have decoders */
 #define RC_PROTO_BIT_ALL_IR_DECODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +65,8 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_BIT_RCMM)
 
 #define RC_PROTO_BIT_ALL_IR_ENCODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
include/uapi/linux/lirc.h +2 -0
index 6b319581882f..56106ccea2cb 100644
@@ -192,6 +192,7 @@ struct lirc_scancode {
  * @RC_PROTO_XMP: XMP protocol
  * @RC_PROTO_CEC: CEC protocol
  * @RC_PROTO_IMON: iMon Pad protocol
+ * @RC_PROTO_RCMM: RC-MM protocol
  */
 enum rc_proto {
 	RC_PROTO_UNKNOWN	= 0,
@@ -218,6 +219,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
tools/include/uapi/linux/lirc.h +2 -0
index f189931042a7..c1e5850c56e1 100644
@@ -186,6 +186,7 @@ struct lirc_scancode {
  * @RC_PROTO_XMP: XMP protocol
  * @RC_PROTO_CEC: CEC protocol
  * @RC_PROTO_IMON: iMon Pad protocol
+ * @RC_PROTO_RCMM: RC-MM protocol
  */
 enum rc_proto {
 	RC_PROTO_UNKNOWN	= 0,
@@ -212,6 +213,7 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
 };
 
 #endif
Signature · 1 line
2.19.2

Again sorry for getting a timely review done. Unfortunately we had already missed the 4.21/5.0 deadline so was not going to make it to that release.

Thanks,

Sean

author maintainer
#16 lore raw

Re: [PATCH v5 1/1] media: rc: rcmm decoder

Hi Sean,

    I have a new release adding all the features, but not really tested. I will update the mailing list soon. Finding some time is not so easy.

Best Regards,
Patrick Lerda.

Quoted 385 lines · Sean Young

Hi Patrick,

Quoted 3 lines · Patrick Lerda

media: add support for RCMM infrared remote controls.

Sorry about the delay in getting this reviewed. December was a very busy month for me.

Quoted 34 lines
---
  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

MAINTAINERS +5 -0
index 3e9f1710ed13..80426d1faaba 100644
@@ -16277,6 +16277,11 @@ M:	David Härdeman <[email protected]>
  S:	Maintained
  F:	drivers/media/rc/winbond-cir.c
 
+RCMM REMOTE CONTROLS DECODER
+M:	Patrick Lerda <[email protected]>
+S:	Maintained
+F:	drivers/media/rc/ir-rcmm-decoder.c
+
  WINSYSTEMS EBC-C384 WATCHDOG DRIVER
  M:	William Breathitt Gray <[email protected]>
  L:	[email protected]
drivers/media/rc/Kconfig +0 -0
index 8a216068a35a..43775ac74268 100644

drivers/media/rc/Kconfig config IR_IMON_DECODER · line 141

Quoted 9 lines
drivers/media/rc/Kconfig +6 -0
@@ -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

checkpatch.pl --strict complains it wants a longer explanation here.

Quoted 124 lines
drivers/media/rc/Kconfig +1 -0
+
  endif #RC_DECODERS
 
  menuconfig RC_DEVICES
drivers/media/rc/Makefile +1 -0
index 92c163816849..48d23433b3c0 100644
@@ -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
drivers/media/rc/ir-rcmm-decoder.c new file +102 -0
new file mode 100644
index 000000000000..a3c09885da5f
@@ -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 <[email protected]>
+
+#include "rc-core-priv.h"
+#include <linux/module.h>
+#include <linux/version.h>
+
+#define RCMM_UNIT		166667	/* nanosecs */
+#define RCMM_PREFIX_PULSE	416666  /* 166666.666666666*2.5 */
+#define RCMM_PULSE_0            277777  /* 166666.666666666*(1+2/3) */
+#define RCMM_PULSE_1            444444  /* 166666.666666666*(2+2/3) */
+#define RCMM_PULSE_2            611111  /* 166666.666666666*(3+2/3) */
+#define RCMM_PULSE_3            777778  /* 166666.666666666*(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 !((0x000c0000 & data->bits) == 0x000c0000);
+}
+
+/**
+ * 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 = &dev->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))
+			break;
+
+		data->state = STATE_VALUE;
+		return 0;
+
+	case STATE_VALUE:
+		if (ev.pulse)
+			break;
+
+		if (eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2))
+			value = 0;
+		else if (eq_margin(ev.duration, RCMM_PULSE_1, RCMM_UNIT / 2))
+			value = 1;
+		else if (eq_margin(ev.duration, RCMM_PULSE_2, RCMM_UNIT / 2))
+			value = 2;
+		else if (eq_margin(ev.duration, RCMM_PULSE_3, RCMM_UNIT / 2))
+			value = 3;
+		else
+			break;

drivers/media/rc/ir-rcmm-decoder.c line 112

Quoted 10 lines
drivers/media/rc/ir-rcmm-decoder.c new file +10 -0
+
+		data->bits <<= 2;
+		data->bits |= value;
+
+		data->count += 2;
+
+		if (data->count < 32)
+			data->state = STATE_BUMP;
+		else
+			data->state = STATE_FINISHED;

Your rcmm implementation only supports the 32 bits variant. There are other bit lengths; lirc supports 12 bits for example:

http://lirc.sourceforge.net/remotes/philips/KW-1009-01

24 bits also possible according to:

https://www.sbprojects.net/knowledge/ir/rcmm.php

Now there is nothing wrong with just supporting 32 bits, but I think the name should make that clear, so that if we ever need to add order bit length variants, we can do so without it ending up messy.

So we should call it rcmm-32, I think.

Quoted 21 lines
drivers/media/rc/ir-rcmm-decoder.c new file +21 -0
+
+		return 0;
+
+	case STATE_FINISHED:
+		if (!ev.pulse)
+			break;
+
+		if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
+			break;
+
+		if (rcmm_mode(data)) {
+			toggle = !!(0x8000 & data->bits);
+			scancode = data->bits & ~0x8000;
+		} else {
+			toggle = 0;
+			scancode = data->bits;
+		}
+
+		rc_keydown(dev, RC_PROTO_RCMM, scancode, toggle);
+		data->state = STATE_INACTIVE;
+		return 0;

drivers/media/rc/ir-rcmm-decoder.c line 143

Quoted 10 lines
drivers/media/rc/ir-rcmm-decoder.c new file +10 -0
+	}
+
+out:
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler rcmm_handler = {
+	.protocols	= RC_PROTO_BIT_RCMM,
+	.decode		= ir_rcmm_decode,

Again an encoder would be great. This is not only useful for transmission but also for self-testing. We now have a self-test in the kernel tree for this. Just nice to have of course.

Quoted 26 lines
drivers/media/rc/ir-rcmm-decoder.c new file +21 -0
+};
+
+static int __init ir_rcmm_decode_init(void)
+{
+	ir_raw_handler_register(&rcmm_handler);
+
+	pr_info("IR RCMM protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_rcmm_decode_exit(void)
+{
+	ir_raw_handler_unregister(&rcmm_handler);
+}
+
+module_init(ir_rcmm_decode_init);
+module_exit(ir_rcmm_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick Lerda");
+MODULE_DESCRIPTION("RCMM IR protocol decoder");
drivers/media/rc/rc-core-priv.h +0 -0
index c2cbe7f6266c..2266f61f887f 100644

drivers/media/rc/rc-core-priv.h struct ir_raw_event_ctrl { · line 137

Quoted 7 lines
drivers/media/rc/rc-core-priv.h +4 -0
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
  		unsigned int bits;
  		bool stick_keyboard;
  	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned int count;
+		u64 bits;

bits can be u32.

Quoted 9 lines
drivers/media/rc/rc-core-priv.h +1 -0
+	} rcmm;
  };
 
  /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +0 -0
index 66a174979b3c..7df40578dac0 100644

drivers/media/rc/rc-main.c static const struct { · line 74

Quoted 5 lines
drivers/media/rc/rc-main.c +2 -0
@@ -70,6 +70,8 @@ static const struct {
  	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
  	[RC_PROTO_IMON] = { .name = "imon",
  		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM] = { .name = "rcmm",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },

So I think this should be:

	[RC_PROTO_RCMM_32] = { .name = "rcmm-32",

drivers/media/rc/rc-main.c static const struct { · line 1011

Quoted 8 lines
drivers/media/rc/rc-main.c +1 -0
  };
 
  /* Used to keep track of known keymaps */
@@ -1006,6 +1008,7 @@ static const struct {
  	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
  	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
  	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM,	"rcmm",		"ir-rcmm-decoder"	},

Same here.

Quoted 76 lines
drivers/media/rc/rc-main.c +0 -0
  };
 
  /**
include/media/rc-map.h +4 -2
index d621acadfbf3..ff5e3b002f91 100644
@@ -37,6 +37,7 @@
  #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
  #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
  #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM		BIT_ULL(RC_PROTO_RCMM)
 
  #define RC_PROTO_BIT_ALL \
  			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +52,7 @@
  			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
  			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
  			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM)
  /* All rc protocols for which we have decoders */
  #define RC_PROTO_BIT_ALL_IR_DECODER \
  			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +65,8 @@
  			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
  			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
  			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_BIT_RCMM)
 
  #define RC_PROTO_BIT_ALL_IR_ENCODER \
  			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
include/uapi/linux/lirc.h +2 -0
index 6b319581882f..56106ccea2cb 100644
@@ -192,6 +192,7 @@ struct lirc_scancode {
   * @RC_PROTO_XMP: XMP protocol
   * @RC_PROTO_CEC: CEC protocol
   * @RC_PROTO_IMON: iMon Pad protocol
+ * @RC_PROTO_RCMM: RC-MM protocol
   */
  enum rc_proto {
  	RC_PROTO_UNKNOWN	= 0,
@@ -218,6 +219,7 @@ enum rc_proto {
  	RC_PROTO_XMP		= 21,
  	RC_PROTO_CEC		= 22,
  	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
  };
 
  #endif
tools/include/uapi/linux/lirc.h +2 -0
index f189931042a7..c1e5850c56e1 100644
@@ -186,6 +186,7 @@ struct lirc_scancode {
   * @RC_PROTO_XMP: XMP protocol
   * @RC_PROTO_CEC: CEC protocol
   * @RC_PROTO_IMON: iMon Pad protocol
+ * @RC_PROTO_RCMM: RC-MM protocol
   */
  enum rc_proto {
  	RC_PROTO_UNKNOWN	= 0,
@@ -212,6 +213,7 @@ enum rc_proto {
  	RC_PROTO_XMP		= 21,
  	RC_PROTO_CEC		= 22,
  	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM		= 24,
  };
 
  #endif
Signature · 1 line
2.19.2

Again sorry for getting a timely review done. Unfortunately we had already missed the 4.21/5.0 deadline so was not going to make it to that release.

Thanks,

Sean

#17 lore raw

PATCH v6 1/1 media: rc: rcmm decoder

In reply to Sean Young

From: Patrick Lerda <[email protected]>

media: add support for RCMM infrared remote controls.

---
 MAINTAINERS                        |   5 +
 drivers/media/rc/Kconfig           |  13 ++
 drivers/media/rc/Makefile          |   1 +
 drivers/media/rc/ir-rcmm-decoder.c | 257 +++++++++++++++++++++++++++++
 drivers/media/rc/rc-core-priv.h    |   5 +
 drivers/media/rc/rc-main.c         |   9 +
 include/media/rc-map.h             |  14 +-
 include/uapi/linux/lirc.h          |   6 +
 tools/include/uapi/linux/lirc.h    |   6 +
 9 files changed, 313 insertions(+), 3 deletions(-)
 create mode 100644 drivers/media/rc/ir-rcmm-decoder.c
MAINTAINERS +5 -0
index 17ad1d7b5510..65a08454e99c 100644
@@ -16496,6 +16496,11 @@ M:	David Härdeman <[email protected]>
 S:	Maintained
 F:	drivers/media/rc/winbond-cir.c
 
+RCMM REMOTE CONTROLS DECODER
+M:	Patrick Lerda <[email protected]>
+S:	Maintained
+F:	drivers/media/rc/ir-rcmm-decoder.c
+
 WINSYSTEMS EBC-C384 WATCHDOG DRIVER
 M:	William Breathitt Gray <[email protected]>
 L:	[email protected]
drivers/media/rc/Kconfig +13 -0
index 8a216068a35a..2c468fa0299f 100644
@@ -133,6 +133,19 @@ 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 when you have IR with RC-MM protocol, and
+	   you need the software decoder. The driver supports 32,
+	   24 and 12 bits RC-MM variants. You can enable or disable the
+	   different modes using the following RC protocol keywords:
+	   'rcmm-32', 'rcmm-24' and 'rcmm-12'.
+
+	   To compile this driver as a module, choose M here: the module
+	   will be called ir-rcmm-decoder.
+
 endif #RC_DECODERS
 
 menuconfig RC_DEVICES
drivers/media/rc/Makefile +1 -0
index 92c163816849..48d23433b3c0 100644
@@ -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
drivers/media/rc/ir-rcmm-decoder.c new file +257 -0

257 lines not on this page · raw message

drivers/media/rc/rc-core-priv.h +5 -0
index c2cbe7f6266c..9f21b3e8b377 100644
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
 		unsigned int bits;
 		bool stick_keyboard;
 	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned int count;
+		u32 bits;
+	} rcmm;
 };
 
 /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +9 -0
index 66a174979b3c..971c041120e2 100644
@@ -70,6 +70,12 @@ static const struct {
 	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
 	[RC_PROTO_IMON] = { .name = "imon",
 		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM32] = { .name = "rcmm-32",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM24] = { .name = "rcmm-24",
+		.scancode_bits = 0x00ffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM12] = { .name = "rcmm-12",
+		.scancode_bits = 0x00000fff, .repeat_period = 114 },
 };
 
 /* Used to keep track of known keymaps */
@@ -1006,6 +1012,9 @@ static const struct {
 	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
 	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
 	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM32,	"rcmm-32",	"ir-rcmm-decoder"	},
+	{ RC_PROTO_BIT_RCMM24,	"rcmm-24",	"ir-rcmm-decoder"	},
+	{ RC_PROTO_BIT_RCMM12,	"rcmm-12",	"ir-rcmm-decoder"	},
 };
 
 /**
include/media/rc-map.h +11 -3
index d621acadfbf3..27631659b8ac 100644
@@ -37,6 +37,9 @@
 #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
 #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
 #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM32		BIT_ULL(RC_PROTO_RCMM32)
+#define RC_PROTO_BIT_RCMM24		BIT_ULL(RC_PROTO_RCMM24)
+#define RC_PROTO_BIT_RCMM12		BIT_ULL(RC_PROTO_RCMM12)
 
 #define RC_PROTO_BIT_ALL \
 			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +54,8 @@
 			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
 			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM32 | \
+			 RC_PROTO_BIT_RCMM24 | RC_PROTO_BIT_RCMM12)
 /* All rc protocols for which we have decoders */
 #define RC_PROTO_BIT_ALL_IR_DECODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +68,9 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_BIT_RCMM32 | RC_PROTO_BIT_RCMM24 | \
+			 RC_PROTO_BIT_RCMM12)
 
 #define RC_PROTO_BIT_ALL_IR_ENCODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -77,7 +83,9 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 | \
 			 RC_PROTO_BIT_RC6_6A_32 | RC_PROTO_BIT_RC6_MCE | \
-			 RC_PROTO_BIT_SHARP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_SHARP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_BIT_RCMM32 | RC_PROTO_BIT_RCMM24 | \
+			 RC_PROTO_BIT_RCMM12)
 
 #define RC_SCANCODE_UNKNOWN(x)			(x)
 #define RC_SCANCODE_OTHER(x)			(x)
include/uapi/linux/lirc.h +6 -0
index 6b319581882f..bd0d54880e6b 100644
@@ -192,6 +192,9 @@ struct lirc_scancode {
  * @RC_PROTO_XMP: XMP protocol
  * @RC_PROTO_CEC: CEC protocol
  * @RC_PROTO_IMON: iMon Pad protocol
+ * @RC_PROTO_RCMM32: RC-MM protocol 32 bits
+ * @RC_PROTO_RCMM24: RC-MM protocol 24 bits
+ * @RC_PROTO_RCMM12: RC-MM protocol 12 bits
  */
 enum rc_proto {
 	RC_PROTO_UNKNOWN	= 0,
@@ -218,6 +221,9 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM32		= 24,
+	RC_PROTO_RCMM24		= 25,
+	RC_PROTO_RCMM12		= 26,
 };
 
 #endif
tools/include/uapi/linux/lirc.h +6 -0
index f189931042a7..e6ac4f4d66c1 100644
@@ -186,6 +186,9 @@ struct lirc_scancode {
  * @RC_PROTO_XMP: XMP protocol
  * @RC_PROTO_CEC: CEC protocol
  * @RC_PROTO_IMON: iMon Pad protocol
+ * @RC_PROTO_RCMM32: RC-MM protocol 32 bits
+ * @RC_PROTO_RCMM24: RC-MM protocol 24 bits
+ * @RC_PROTO_RCMM12: RC-MM protocol 12 bits
  */
 enum rc_proto {
 	RC_PROTO_UNKNOWN	= 0,
@@ -212,6 +215,9 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM32		= 24,
+	RC_PROTO_RCMM24		= 25,
+	RC_PROTO_RCMM12		= 26,
 };
 
 #endif
Signature · 1 line
2.20.1
author maintainer
#18 lore raw

PATCH v7 1/1 media: rc: rcmm decoder

In reply to Sean Young

media: add support for RCMM infrared remote controls.

---
 MAINTAINERS                        |   5 +
 drivers/media/rc/Kconfig           |  13 ++
 drivers/media/rc/Makefile          |   1 +
 drivers/media/rc/ir-rcmm-decoder.c | 257 +++++++++++++++++++++++++++++
 drivers/media/rc/rc-core-priv.h    |   5 +
 drivers/media/rc/rc-main.c         |   9 +
 include/media/rc-map.h             |  14 +-
 include/uapi/linux/lirc.h          |   6 +
 tools/include/uapi/linux/lirc.h    |   6 +
 9 files changed, 313 insertions(+), 3 deletions(-)
 create mode 100644 drivers/media/rc/ir-rcmm-decoder.c
MAINTAINERS +5 -0
index 17ad1d7b5510..65a08454e99c 100644
@@ -16496,6 +16496,11 @@ M:	David Härdeman <[email protected]>
 S:	Maintained
 F:	drivers/media/rc/winbond-cir.c
 
+RCMM REMOTE CONTROLS DECODER
+M:	Patrick Lerda <[email protected]>
+S:	Maintained
+F:	drivers/media/rc/ir-rcmm-decoder.c
+
 WINSYSTEMS EBC-C384 WATCHDOG DRIVER
 M:	William Breathitt Gray <[email protected]>
 L:	[email protected]
drivers/media/rc/Kconfig +13 -0
index 8a216068a35a..2c468fa0299f 100644
@@ -133,6 +133,19 @@ 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 when you have IR with RC-MM protocol, and
+	   you need the software decoder. The driver supports 32,
+	   24 and 12 bits RC-MM variants. You can enable or disable the
+	   different modes using the following RC protocol keywords:
+	   'rcmm-32', 'rcmm-24' and 'rcmm-12'.
+
+	   To compile this driver as a module, choose M here: the module
+	   will be called ir-rcmm-decoder.
+
 endif #RC_DECODERS
 
 menuconfig RC_DEVICES
drivers/media/rc/Makefile +1 -0
index 92c163816849..48d23433b3c0 100644
@@ -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
drivers/media/rc/ir-rcmm-decoder.c new file +257 -0

257 lines not on this page · raw message

drivers/media/rc/rc-core-priv.h +5 -0
index c2cbe7f6266c..9f21b3e8b377 100644
@@ -131,6 +131,11 @@ struct ir_raw_event_ctrl {
 		unsigned int bits;
 		bool stick_keyboard;
 	} imon;
+	struct rcmm_dec {
+		int state;
+		unsigned int count;
+		u32 bits;
+	} rcmm;
 };
 
 /* Mutex for locking raw IR processing and handler change */
drivers/media/rc/rc-main.c +9 -0
index 66a174979b3c..971c041120e2 100644
@@ -70,6 +70,12 @@ static const struct {
 	[RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
 	[RC_PROTO_IMON] = { .name = "imon",
 		.scancode_bits = 0x7fffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM32] = { .name = "rcmm-32",
+		.scancode_bits = 0xffffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM24] = { .name = "rcmm-24",
+		.scancode_bits = 0x00ffffff, .repeat_period = 114 },
+	[RC_PROTO_RCMM12] = { .name = "rcmm-12",
+		.scancode_bits = 0x00000fff, .repeat_period = 114 },
 };
 
 /* Used to keep track of known keymaps */
@@ -1006,6 +1012,9 @@ static const struct {
 	{ RC_PROTO_BIT_XMP,	"xmp",		"ir-xmp-decoder"	},
 	{ RC_PROTO_BIT_CEC,	"cec",		NULL			},
 	{ RC_PROTO_BIT_IMON,	"imon",		"ir-imon-decoder"	},
+	{ RC_PROTO_BIT_RCMM32,	"rcmm-32",	"ir-rcmm-decoder"	},
+	{ RC_PROTO_BIT_RCMM24,	"rcmm-24",	"ir-rcmm-decoder"	},
+	{ RC_PROTO_BIT_RCMM12,	"rcmm-12",	"ir-rcmm-decoder"	},
 };
 
 /**
include/media/rc-map.h +11 -3
index d621acadfbf3..27631659b8ac 100644
@@ -37,6 +37,9 @@
 #define RC_PROTO_BIT_XMP		BIT_ULL(RC_PROTO_XMP)
 #define RC_PROTO_BIT_CEC		BIT_ULL(RC_PROTO_CEC)
 #define RC_PROTO_BIT_IMON		BIT_ULL(RC_PROTO_IMON)
+#define RC_PROTO_BIT_RCMM32		BIT_ULL(RC_PROTO_RCMM32)
+#define RC_PROTO_BIT_RCMM24		BIT_ULL(RC_PROTO_RCMM24)
+#define RC_PROTO_BIT_RCMM12		BIT_ULL(RC_PROTO_RCMM12)
 
 #define RC_PROTO_BIT_ALL \
 			(RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \
@@ -51,7 +54,8 @@
 			 RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
 			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \
-			 RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM32 | \
+			 RC_PROTO_BIT_RCMM24 | RC_PROTO_BIT_RCMM12)
 /* All rc protocols for which we have decoders */
 #define RC_PROTO_BIT_ALL_IR_DECODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -64,7 +68,9 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 |  RC_PROTO_BIT_RC6_6A_32 | \
 			 RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \
-			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_BIT_RCMM32 | RC_PROTO_BIT_RCMM24 | \
+			 RC_PROTO_BIT_RCMM12)
 
 #define RC_PROTO_BIT_ALL_IR_ENCODER \
 			(RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \
@@ -77,7 +83,9 @@
 			 RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \
 			 RC_PROTO_BIT_RC6_6A_24 | \
 			 RC_PROTO_BIT_RC6_6A_32 | RC_PROTO_BIT_RC6_MCE | \
-			 RC_PROTO_BIT_SHARP | RC_PROTO_BIT_IMON)
+			 RC_PROTO_BIT_SHARP | RC_PROTO_BIT_IMON | \
+			 RC_PROTO_BIT_RCMM32 | RC_PROTO_BIT_RCMM24 | \
+			 RC_PROTO_BIT_RCMM12)
 
 #define RC_SCANCODE_UNKNOWN(x)			(x)
 #define RC_SCANCODE_OTHER(x)			(x)
include/uapi/linux/lirc.h +6 -0
index 6b319581882f..bd0d54880e6b 100644
@@ -192,6 +192,9 @@ struct lirc_scancode {
  * @RC_PROTO_XMP: XMP protocol
  * @RC_PROTO_CEC: CEC protocol
  * @RC_PROTO_IMON: iMon Pad protocol
+ * @RC_PROTO_RCMM32: RC-MM protocol 32 bits
+ * @RC_PROTO_RCMM24: RC-MM protocol 24 bits
+ * @RC_PROTO_RCMM12: RC-MM protocol 12 bits
  */
 enum rc_proto {
 	RC_PROTO_UNKNOWN	= 0,
@@ -218,6 +221,9 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM32		= 24,
+	RC_PROTO_RCMM24		= 25,
+	RC_PROTO_RCMM12		= 26,
 };
 
 #endif
tools/include/uapi/linux/lirc.h +6 -0
index f189931042a7..e6ac4f4d66c1 100644
@@ -186,6 +186,9 @@ struct lirc_scancode {
  * @RC_PROTO_XMP: XMP protocol
  * @RC_PROTO_CEC: CEC protocol
  * @RC_PROTO_IMON: iMon Pad protocol
+ * @RC_PROTO_RCMM32: RC-MM protocol 32 bits
+ * @RC_PROTO_RCMM24: RC-MM protocol 24 bits
+ * @RC_PROTO_RCMM12: RC-MM protocol 12 bits
  */
 enum rc_proto {
 	RC_PROTO_UNKNOWN	= 0,
@@ -212,6 +215,9 @@ enum rc_proto {
 	RC_PROTO_XMP		= 21,
 	RC_PROTO_CEC		= 22,
 	RC_PROTO_IMON		= 23,
+	RC_PROTO_RCMM32		= 24,
+	RC_PROTO_RCMM24		= 25,
+	RC_PROTO_RCMM12		= 26,
 };
 
 #endif
Signature · 1 line
2.20.1