Skip to contentSkip to conversation

In-kernel IR remote control support

RFC PATCH In review Jon Smirl 3 participants 15 messages Nov 5, 2008

Subsystems (3)
lore
Share & tools
lore

Jon Smirl

author
#0 lore raw

v4 cover In-kernel IR remote control support

New release of in-kernel IR support implementing evdev support. The goal of in-kernel IR is to integrate IR events into the evdev input event queue and maintain ordering of events from all input devices. Still looking for help with this project.

Git tree: git://github.com/jonsmirl/digispeaker.git

ir-core is now a module. Minimal IR code is built into input, that code can't be separated from input. The rest of the core IR code is moved to a module. The IR code in input will be passive if IR-core isn't loaded.

Now uses configfs to build mappings from remote buttons to key strokes. When ir-core loads it creates /config/remotes. Make a directory for each remote you have; this will cause a new input devices to be created. Inside these directories make a directory for each key on the remote. In the key directory attributes fill in the protocol, device, command, keycode. Since this is configfs all of this can be easily scripted.

Now when a key is pressed on a remote, the configfs directories are searched for a match on protocol, device, command. If a matches is found, a key stroke corresponding to keycode is created and sent on the input device that was created when the directory for the remote was made.

The configfs directories are pretty flexible. You can use them to map multiple remotes to the same key stroke, or send a single button push to multiple apps.

Quoted 1 line

From last release...

Raw mode. There are three sysfs attributes - ir_raw, ir_carrier, ir_xmitter. Read from ir_raw to get the raw timing data from the IR device. Set carrier and active xmitters and then copy raw data to ir_raw to send. These attributes may be better on a debug switch. You would use raw mode when decoding a new protocol. After you figure out the new protocol, write an in-kernel encoder/decoder for it.

The in-kernel code is tiny, about 20K including a driver.

Quoted 1 line

From last post...

Note that user space IR device drivers can use the existing support in evdev to inject events into the input queue.

Send and receive are implemented. Received IR messages are decoded and sent to user space as input messages. Send is done via an IOCTL on the input device.

Two drivers are supplied. mceusb2 implements send and receive support for the Microsoft USB IR dongle.

The GPT driver implements receive only support for a GPT pin - GPT is a GPIO with a timer attached.

Code is only lightly tested. Encoders and decoders have not been written for all protocols. Repeat is not handled for any protocol. I'm looking for help. There are 15 more existing LIRC drivers.

---

Jon Smirl (6):
Microsoft mceusb2 driver for in-kernel IR subsystem Example of PowerPC device tree support for GPT based IR GPT driver for in-kernel IR support.
Configfs support for IR
Core IR module
Minimal changes to the core input system

 arch/powerpc/boot/dts/dspeak01.dts |   19 -
 drivers/input/Kconfig              |    2 
 drivers/input/Makefile             |    1 
 drivers/input/evdev.c              |   55 +++
 drivers/input/input.c              |   17 +
 drivers/input/ir/Kconfig           |   27 +
 drivers/input/ir/Makefile          |   12 +
 drivers/input/ir/ir-configfs.c     |  333 ++++++++++++++++
 drivers/input/ir/ir-core.c         |  678 +++++++++++++++++++++++++++++++++
 drivers/input/ir/ir-gpt.c          |  224 +++++++++++
 drivers/input/ir/ir-mceusb2.c      |  744 ++++++++++++++++++++++++++++++++++++
 drivers/input/ir/ir.h              |   48 ++
 include/linux/input.h              |   75 ++++
 include/linux/mod_devicetable.h    |    3 
 14 files changed, 2227 insertions(+), 11 deletions(-)
 create mode 100644 drivers/input/ir/Kconfig
 create mode 100644 drivers/input/ir/Makefile
 create mode 100644 drivers/input/ir/ir-configfs.c
 create mode 100644 drivers/input/ir/ir-core.c
 create mode 100644 drivers/input/ir/ir-gpt.c
 create mode 100644 drivers/input/ir/ir-mceusb2.c
 create mode 100644 drivers/input/ir/ir.h
Signature · 2 lines
Jon Smirl
[email protected]
author
#1 lore raw

RFC PATCH v4 1/6 Minimal changes to the core input system

Minimal changes to the core input system. The bulk of IR support loads as a module. These changes are passive if the rest of IR isn't loaded.

Jon Smirl
<[email protected]>

---
 drivers/input/evdev.c           |   55 +++++++++++++++++++++++++++++
 drivers/input/input.c           |   17 +++++++++
 include/linux/input.h           |   75 +++++++++++++++++++++++++++++++++++++++
 include/linux/mod_devicetable.h |    3 ++
 4 files changed, 150 insertions(+), 0 deletions(-)
drivers/input/evdev.c +55 -0
index 1070db3..33a01dc 100644
@@ -328,6 +328,14 @@ struct ff_effect_compat {
 	} u;
 };
 
+struct ir_command_compat {
+	__u32 protocol;
+	__u32 device;
+	__u32 command;
+	__u32 transmitters;
+};
+
+
 /* Note to the author of this code: did it ever occur to
    you why the ifdefs are needed? Think about it again. -AK */
 #ifdef CONFIG_X86_64
@@ -432,6 +440,32 @@ static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
 	return 0;
 }
 
+static int evdev_ir_send_from_user(const char __user *buffer, size_t size,
+				     struct ir_command *ir_command)
+{
+	if (COMPAT_TEST) {
+		struct ir_command_compat *compat_ir_command;
+
+		if (size != sizeof(struct ir_command_compat))
+			return -EINVAL;
+
+		compat_ir_command = (struct ir_command_compat *)ir_command;
+
+		if (copy_from_user(compat_ir_command, buffer,
+				   sizeof(struct ir_command_compat)))
+			return -EFAULT;
+
+	} else {
+		if (size != sizeof(struct ir_command))
+			return -EINVAL;
+
+		if (copy_from_user(ir_command, buffer, sizeof(struct ir_command)))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
 #else
 
 static inline size_t evdev_event_size(void)
@@ -469,6 +503,18 @@ static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
 	return 0;
 }
 
+static int evdev_ir_send_from_user(const char __user *buffer, size_t size,
+				     struct ir_command *ir_command)
+{
+	if (size != sizeof(struct ir_command))
+		return -EINVAL;
+
+	if (copy_from_user(ir_command, buffer, sizeof(struct ir_command)))
+		return -EFAULT;
+
+	return 0;
+}
+
 #endif /* CONFIG_COMPAT */
 
 static ssize_t evdev_write(struct file *file, const char __user *buffer,
@@ -695,6 +741,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 	struct input_dev *dev = evdev->handle.dev;
 	struct input_absinfo abs;
 	struct ff_effect effect;
+	struct ir_command ir_command;
 	int __user *ip = (int __user *)p;
 	int i, t, u, v;
 	int error;
@@ -859,6 +906,14 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 
 				return 0;
 			}
+
+			if (_IOC_NR(cmd) == _IOC_NR(EVIOIRSEND)) {
+
+				if (evdev_ir_send_from_user(p, _IOC_SIZE(cmd), &ir_command))
+					return -EFAULT;
+
+				return input_ir_send(dev, &ir_command, file);
+			}
 		}
 	}
 	return -EINVAL;
drivers/input/input.c +17 -0
index c13ced3..0a9b15a 100644
@@ -240,6 +240,10 @@ static void input_handle_event(struct input_dev *dev,
 	case EV_PWR:
 		disposition = INPUT_PASS_TO_ALL;
 		break;
+
+	case EV_IR:
+		disposition = INPUT_PASS_TO_ALL;
+		break;
 	}
 
 	if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
@@ -693,6 +697,7 @@ static const struct input_device_id *input_match_device(const struct input_devic
 		MATCH_BIT(sndbit, SND_MAX);
 		MATCH_BIT(ffbit,  FF_MAX);
 		MATCH_BIT(swbit,  SW_MAX);
+		MATCH_BIT(irbit,  IR_MAX);
 
 		return id;
 	}
@@ -815,6 +820,8 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
 		input_seq_print_bitmap(seq, "FF", dev->ffbit, FF_MAX);
 	if (test_bit(EV_SW, dev->evbit))
 		input_seq_print_bitmap(seq, "SW", dev->swbit, SW_MAX);
+	if (test_bit(EV_IR, dev->evbit))
+		input_seq_print_bitmap(seq, "IR", dev->irbit, IR_MAX);
 
 	seq_putc(seq, '\n');
 
@@ -992,6 +999,8 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
 				'f', id->ffbit, 0, FF_MAX);
 	len += input_print_modalias_bits(buf + len, size - len,
 				'w', id->swbit, 0, SW_MAX);
+	len += input_print_modalias_bits(buf + len, size - len,
+				'i', id->irbit, 0, IR_MAX);
 
 	if (add_cr)
 		len += snprintf(buf + len, max(size - len, 0), "\n");
@@ -1093,6 +1102,7 @@ INPUT_DEV_CAP_ATTR(LED, led);
 INPUT_DEV_CAP_ATTR(SND, snd);
 INPUT_DEV_CAP_ATTR(FF, ff);
 INPUT_DEV_CAP_ATTR(SW, sw);
+INPUT_DEV_CAP_ATTR(IR, ir);
 
 static struct attribute *input_dev_caps_attrs[] = {
 	&dev_attr_ev.attr,
@@ -1104,6 +1114,7 @@ static struct attribute *input_dev_caps_attrs[] = {
 	&dev_attr_snd.attr,
 	&dev_attr_ff.attr,
 	&dev_attr_sw.attr,
+	&dev_attr_ir.attr,
 	NULL
 };
 
@@ -1221,6 +1232,8 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
 		INPUT_ADD_HOTPLUG_BM_VAR("FF=", dev->ffbit, FF_MAX);
 	if (test_bit(EV_SW, dev->evbit))
 		INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
+	if (test_bit(EV_IR, dev->evbit))
+		INPUT_ADD_HOTPLUG_BM_VAR("IR=", dev->irbit, IR_MAX);
 
 	INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
 
@@ -1333,6 +1346,10 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
 		__set_bit(code, dev->ffbit);
 		break;
 
+	case EV_IR:
+		__set_bit(code, dev->irbit);
+		break;
+
 	case EV_PWR:
 		/* do nothing */
 		break;
include/linux/input.h +75 -0

122 lines not on this page · raw message

include/linux/mod_devicetable.h +3 -0
index 97b91d1..ea35367 100644
@@ -293,6 +293,7 @@ struct pcmcia_device_id {
 #define INPUT_DEVICE_ID_SND_MAX		0x07
 #define INPUT_DEVICE_ID_FF_MAX		0x7f
 #define INPUT_DEVICE_ID_SW_MAX		0x0f
+#define INPUT_DEVICE_ID_IR_MAX		0x0f
 
 #define INPUT_DEVICE_ID_MATCH_BUS	1
 #define INPUT_DEVICE_ID_MATCH_VENDOR	2
@@ -308,6 +309,7 @@ struct pcmcia_device_id {
 #define INPUT_DEVICE_ID_MATCH_SNDBIT	0x0400
 #define INPUT_DEVICE_ID_MATCH_FFBIT	0x0800
 #define INPUT_DEVICE_ID_MATCH_SWBIT	0x1000
+#define INPUT_DEVICE_ID_MATCH_IRBIT	0x2000
 
 struct input_device_id {
 
@@ -327,6 +329,7 @@ struct input_device_id {
 	kernel_ulong_t sndbit[INPUT_DEVICE_ID_SND_MAX / BITS_PER_LONG + 1];
 	kernel_ulong_t ffbit[INPUT_DEVICE_ID_FF_MAX / BITS_PER_LONG + 1];
 	kernel_ulong_t swbit[INPUT_DEVICE_ID_SW_MAX / BITS_PER_LONG + 1];
+	kernel_ulong_t irbit[INPUT_DEVICE_ID_IR_MAX / BITS_PER_LONG + 1];
 
 	kernel_ulong_t driver_info;
 };
#2 lore raw

Re: [RFC PATCH V4 1/6] Minimal changes to the core input system

Quoted 4 lines · Jon Smirl

Minimal changes to the core input system. The bulk of IR support loads as a module. These changes are passive if the rest of IR isn't loaded.

Jon Smirl
<[email protected]>

Apart from too long lines in changelog and missed Signed-off-by: it looks okay to me ;-).

Quoted 346 lines
---
 drivers/input/evdev.c           |   55 +++++++++++++++++++++++++++++
 drivers/input/input.c           |   17 +++++++++
 include/linux/input.h           |   75 +++++++++++++++++++++++++++++++++++++++
 include/linux/mod_devicetable.h |    3 ++
 4 files changed, 150 insertions(+), 0 deletions(-)
drivers/input/evdev.c +55 -0
index 1070db3..33a01dc 100644
@@ -328,6 +328,14 @@ struct ff_effect_compat {
 	} u;
 };
 
+struct ir_command_compat {
+	__u32 protocol;
+	__u32 device;
+	__u32 command;
+	__u32 transmitters;
+};
+
+
 /* Note to the author of this code: did it ever occur to
    you why the ifdefs are needed? Think about it again. -AK */
 #ifdef CONFIG_X86_64
@@ -432,6 +440,32 @@ static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
 	return 0;
 }
 
+static int evdev_ir_send_from_user(const char __user *buffer, size_t size,
+				     struct ir_command *ir_command)
+{
+	if (COMPAT_TEST) {
+		struct ir_command_compat *compat_ir_command;
+
+		if (size != sizeof(struct ir_command_compat))
+			return -EINVAL;
+
+		compat_ir_command = (struct ir_command_compat *)ir_command;
+
+		if (copy_from_user(compat_ir_command, buffer,
+				   sizeof(struct ir_command_compat)))
+			return -EFAULT;
+
+	} else {
+		if (size != sizeof(struct ir_command))
+			return -EINVAL;
+
+		if (copy_from_user(ir_command, buffer, sizeof(struct ir_command)))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
 #else
 
 static inline size_t evdev_event_size(void)
@@ -469,6 +503,18 @@ static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
 	return 0;
 }
 
+static int evdev_ir_send_from_user(const char __user *buffer, size_t size,
+				     struct ir_command *ir_command)
+{
+	if (size != sizeof(struct ir_command))
+		return -EINVAL;
+
+	if (copy_from_user(ir_command, buffer, sizeof(struct ir_command)))
+		return -EFAULT;
+
+	return 0;
+}
+
 #endif /* CONFIG_COMPAT */
 
 static ssize_t evdev_write(struct file *file, const char __user *buffer,
@@ -695,6 +741,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 	struct input_dev *dev = evdev->handle.dev;
 	struct input_absinfo abs;
 	struct ff_effect effect;
+	struct ir_command ir_command;
 	int __user *ip = (int __user *)p;
 	int i, t, u, v;
 	int error;
@@ -859,6 +906,14 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 
 				return 0;
 			}
+
+			if (_IOC_NR(cmd) == _IOC_NR(EVIOIRSEND)) {
+
+				if (evdev_ir_send_from_user(p, _IOC_SIZE(cmd), &ir_command))
+					return -EFAULT;
+
+				return input_ir_send(dev, &ir_command, file);
+			}
 		}
 	}
 	return -EINVAL;
drivers/input/input.c +17 -0
index c13ced3..0a9b15a 100644
@@ -240,6 +240,10 @@ static void input_handle_event(struct input_dev *dev,
 	case EV_PWR:
 		disposition = INPUT_PASS_TO_ALL;
 		break;
+
+	case EV_IR:
+		disposition = INPUT_PASS_TO_ALL;
+		break;
 	}
 
 	if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
@@ -693,6 +697,7 @@ static const struct input_device_id *input_match_device(const struct input_devic
 		MATCH_BIT(sndbit, SND_MAX);
 		MATCH_BIT(ffbit,  FF_MAX);
 		MATCH_BIT(swbit,  SW_MAX);
+		MATCH_BIT(irbit,  IR_MAX);
 
 		return id;
 	}
@@ -815,6 +820,8 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
 		input_seq_print_bitmap(seq, "FF", dev->ffbit, FF_MAX);
 	if (test_bit(EV_SW, dev->evbit))
 		input_seq_print_bitmap(seq, "SW", dev->swbit, SW_MAX);
+	if (test_bit(EV_IR, dev->evbit))
+		input_seq_print_bitmap(seq, "IR", dev->irbit, IR_MAX);
 
 	seq_putc(seq, '\n');
 
@@ -992,6 +999,8 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
 				'f', id->ffbit, 0, FF_MAX);
 	len += input_print_modalias_bits(buf + len, size - len,
 				'w', id->swbit, 0, SW_MAX);
+	len += input_print_modalias_bits(buf + len, size - len,
+				'i', id->irbit, 0, IR_MAX);
 
 	if (add_cr)
 		len += snprintf(buf + len, max(size - len, 0), "\n");
@@ -1093,6 +1102,7 @@ INPUT_DEV_CAP_ATTR(LED, led);
 INPUT_DEV_CAP_ATTR(SND, snd);
 INPUT_DEV_CAP_ATTR(FF, ff);
 INPUT_DEV_CAP_ATTR(SW, sw);
+INPUT_DEV_CAP_ATTR(IR, ir);
 
 static struct attribute *input_dev_caps_attrs[] = {
 	&dev_attr_ev.attr,
@@ -1104,6 +1114,7 @@ static struct attribute *input_dev_caps_attrs[] = {
 	&dev_attr_snd.attr,
 	&dev_attr_ff.attr,
 	&dev_attr_sw.attr,
+	&dev_attr_ir.attr,
 	NULL
 };
 
@@ -1221,6 +1232,8 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
 		INPUT_ADD_HOTPLUG_BM_VAR("FF=", dev->ffbit, FF_MAX);
 	if (test_bit(EV_SW, dev->evbit))
 		INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
+	if (test_bit(EV_IR, dev->evbit))
+		INPUT_ADD_HOTPLUG_BM_VAR("IR=", dev->irbit, IR_MAX);
 
 	INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
 
@@ -1333,6 +1346,10 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
 		__set_bit(code, dev->ffbit);
 		break;
 
+	case EV_IR:
+		__set_bit(code, dev->irbit);
+		break;
+
 	case EV_PWR:
 		/* do nothing */
 		break;
include/linux/input.h +75 -0
index b86fb55..95e385f 100644
@@ -79,6 +79,8 @@ struct input_absinfo {
 #define EVIOCRMFF		_IOW('E', 0x81, int)			/* Erase a force effect */
 #define EVIOCGEFFECTS		_IOR('E', 0x84, int)			/* Report number of effects playable at the same time */
 
+#define EVIOIRSEND		_IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ir_command))	/* send an IR command */
+
 #define EVIOCGRAB		_IOW('E', 0x90, int)			/* Grab/Release device */
 
 /*
@@ -97,6 +99,7 @@ struct input_absinfo {
 #define EV_FF			0x15
 #define EV_PWR			0x16
 #define EV_FF_STATUS		0x17
+#define EV_IR			0x18
 #define EV_MAX			0x1f
 #define EV_CNT			(EV_MAX+1)
 
@@ -959,6 +962,56 @@ struct ff_effect {
 #define FF_MAX		0x7f
 #define FF_CNT		(FF_MAX+1)
 
+/*
+ * IR Support
+ */
+
+#define IR_PROTOCOL_RESERVED 0
+#define IR_PROTOCOL_JVC 1
+#define IR_PROTOCOL_NEC 2
+#define IR_PROTOCOL_NOKIA 3
+#define IR_PROTOCOL_SHARP 4
+#define IR_PROTOCOL_SONY_12 5
+#define IR_PROTOCOL_SONY_15 6
+#define IR_PROTOCOL_SONY_20 7
+#define IR_PROTOCOL_PHILIPS_RC5 8
+#define IR_PROTOCOL_PHILIPS_RC6 9
+#define IR_PROTOCOL_PHILIPS_RCMM 10
+#define IR_PROTOCOL_PHILIPS_RECS80 11
+#define IR_PROTOCOL_RCA 12
+#define IR_PROTOCOL_ITT 13
+
+#define IR_PROTOCOL 1
+#define IR_DEVICE 2
+#define IR_COMMAND 3
+
+#define IR_CAP_RECEIVE_BASEBAND 0
+#define IR_CAP_RECEIVE_36K 1
+#define IR_CAP_RECEIVE_38K 2
+#define IR_CAP_RECEIVE_40K 3
+#define IR_CAP_RECEIVE_56K 4
+#define IR_CAP_SEND_BASEBAND 5
+#define IR_CAP_SEND_36K 6
+#define IR_CAP_SEND_38K 7
+#define IR_CAP_SEND_40K 8
+#define IR_CAP_SEND_56K 9
+#define IR_CAP_XMITTER_1 10
+#define IR_CAP_XMITTER_2 11
+#define IR_CAP_XMITTER_3 12
+#define IR_CAP_XMITTER_4 13
+#define IR_CAP_RECEIVE_RAW 14
+#define IR_CAP_SEND_RAW 15
+#define IR_MAX 0x0f
+#define IR_CNT IR_MAX + 1
+
+struct ir_command {
+	__u32 protocol;
+	__u32 device;
+	__u32 command;
+	__u32 transmitters;
+};
+
+
 #ifdef __KERNEL__
 
 /*
@@ -986,6 +1039,7 @@ struct ff_effect {
  * @sndbit: bitmap of sound effects supported by the device
  * @ffbit: bitmap of force feedback effects supported by the device
  * @swbit: bitmap of switches present on the device
+ * @irbit: bitmap of capabilies of the IR hardware
  * @keycodemax: size of keycode table
  * @keycodesize: size of elements in keycode table
  * @keycode: map of scancodes to keycodes for this device
@@ -1058,6 +1112,7 @@ struct input_dev {
 	unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
 	unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
 	unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
+	unsigned long irbit[BITS_TO_LONGS(IR_CNT)];
 
 	unsigned int keycodemax;
 	unsigned int keycodesize;
@@ -1066,6 +1121,7 @@ struct input_dev {
 	int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);
 
 	struct ff_device *ff;
+	struct ir_device *ir;
 
 	unsigned int repeat_key;
 	struct timer_list timer;
@@ -1301,6 +1357,11 @@ static inline void input_report_switch(struct input_dev *dev, unsigned int code,
 	input_event(dev, EV_SW, code, !!value);
 }
 
+static inline void input_report_ir(struct input_dev *dev, unsigned int code, int value)
+{
+	input_event(dev, EV_IR, code, value);
+}
+
 static inline void input_sync(struct input_dev *dev)
 {
 	input_event(dev, EV_SYN, SYN_REPORT, 0);
@@ -1379,5 +1440,19 @@ int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file);
 int input_ff_create_memless(struct input_dev *dev, void *data,
 		int (*play_effect)(struct input_dev *, void *, struct ff_effect *));
 
+/**
+ * IR support functions
+ */
+
+typedef int (*send_func)(void *private, unsigned int *buffer, unsigned int count,
+		unsigned int frequency, unsigned int xmitters);
+
+int input_ir_create(struct input_dev *dev, void *private, send_func send);
+void input_ir_destroy(struct input_dev *dev);
+
+void input_ir_decode(struct input_dev *dev, unsigned int delta, unsigned int bit);
+int input_ir_send(struct input_dev *dev, struct ir_command *ir_command, struct file *file);
+int input_ir_register(struct input_dev *dev);
+
 #endif
 #endif
include/linux/mod_devicetable.h +3 -1
index 97b91d1..ea35367 100644
@@ -293,6 +293,7 @@ struct pcmcia_device_id {
 #define INPUT_DEVICE_ID_SND_MAX		0x07
 #define INPUT_DEVICE_ID_FF_MAX		0x7f
 #define INPUT_DEVICE_ID_SW_MAX		0x0f
+#define INPUT_DEVICE_ID_IR_MAX		0x0f
 
 #define INPUT_DEVICE_ID_MATCH_BUS	1
 #define INPUT_DEVICE_ID_MATCH_VENDOR	2
@@ -308,6 +309,7 @@ struct pcmcia_device_id {
 #define INPUT_DEVICE_ID_MATCH_SNDBIT	0x0400
 #define INPUT_DEVICE_ID_MATCH_FFBIT	0x0800
 #define INPUT_DEVICE_ID_MATCH_SWBIT	0x1000
+#define INPUT_DEVICE_ID_MATCH_IRBIT	0x2000
 
 struct input_device_id {
 
@@ -327,6 +329,7 @@ struct input_device_id {
 	kernel_ulong_t sndbit[INPUT_DEVICE_ID_SND_MAX / BITS_PER_LONG + 1];
 	kernel_ulong_t ffbit[INPUT_DEVICE_ID_FF_MAX / BITS_PER_LONG + 1];
 	kernel_ulong_t swbit[INPUT_DEVICE_ID_SW_MAX / BITS_PER_LONG + 1];
+	kernel_ulong_t irbit[INPUT_DEVICE_ID_IR_MAX / BITS_PER_LONG + 1];
 
 	kernel_ulong_t driver_info;
 };
 
--

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
author
#3 lore raw

Re: [RFC PATCH V4 1/6] Minimal changes to the core input system

Quoted 8 lines · Pavel Machek
Quoted 4 lines · Jon Smirl

Minimal changes to the core input system. The bulk of IR support loads as a module. These changes are passive if the rest of IR isn't loaded.

Jon Smirl
<[email protected]>

Apart from too long lines in changelog and missed Signed-off-by: it looks okay to me ;-).

I'm not looking to get it into the kernel yet, it still needs some more eyes looking at it to make sure the API are ok.

Signature · 2 lines
Jon Smirl
[email protected]
author
#4 lore raw

RFC PATCH v4 2/6 Core IR module

In reply to Jon Smirl

Changes to core input subsystem to allow send and receive of IR messages. Encode and decode state machines are provided for common IR porotocols such as Sony, JVC, NEC, Philips, etc.

Received IR messages generate event in the input queue. IR messages are sent using an input IOCTL.

---
 drivers/input/Kconfig      |    2 
 drivers/input/Makefile     |    1 
 drivers/input/ir/Kconfig   |   15 +
 drivers/input/ir/Makefile  |    8 +
 drivers/input/ir/ir-core.c |  683 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/input/ir/ir.h      |   48 +++
 6 files changed, 757 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/ir/Kconfig
 create mode 100644 drivers/input/ir/Makefile
 create mode 100644 drivers/input/ir/ir-core.c
 create mode 100644 drivers/input/ir/ir.h
drivers/input/Kconfig +2 -0
index 747633c..780d321 100644
@@ -172,6 +172,8 @@ source "drivers/input/touchscreen/Kconfig"
 
 source "drivers/input/misc/Kconfig"
 
+source "drivers/input/ir/Kconfig"
+
 endif
 
 menu "Hardware I/O ports"
drivers/input/Makefile +1 -0
index 6a1049b..85f5ef3 100644
@@ -21,6 +21,7 @@ obj-$(CONFIG_INPUT_JOYSTICK)	+= joystick/
 obj-$(CONFIG_INPUT_TABLET)	+= tablet/
 obj-$(CONFIG_INPUT_TOUCHSCREEN)	+= touchscreen/
 obj-$(CONFIG_INPUT_MISC)	+= misc/
+obj-$(CONFIG_INPUT_IR)		+= ir/
 
 obj-$(CONFIG_INPUT_APMPOWER)	+= apm-power.o
 
drivers/input/ir/Kconfig new file +15 -0
new file mode 100644
index 0000000..a6f3f25
@@ -0,0 +1,15 @@
+#
+# LIRC driver(s) configuration
+#
+menuconfig INPUT_IR
+	select CONFIGFS_FS
+	tristate "Infrared Remote (IR) receiver/transmitter drivers"
+	default n
+	help
+	  Say Y here, and all supported Infrared Remote Control IR
+	  receiver and transmitter drivers will be displayed. The receiver drivers
+	  allow control of your Linux system via remote control.
+
+if INPUT_IR
+
+endif
drivers/input/ir/Makefile new file +8 -0
new file mode 100644
index 0000000..6acb665
@@ -0,0 +1,8 @@
+# Makefile for the ir drivers.
+#
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_INPUT_IR)		+= ir.o
+ir-objs := ir-core.o
+
drivers/input/ir/ir-core.c new file +683 -0

683 lines not on this page · raw message

drivers/input/ir/ir.h new file +48 -0

48 lines not on this page · raw message

author
#5 lore raw

RFC PATCH v4 3/6 Configfs support for IR

In reply to Jon Smirl

Now uses configfs to build mappings from remote buttons to key strokes. When ir-core loads it creates /config/remotes. Make a directory for each remote you have; this will cause a new input devices to be created. Inside these directories make a directory for each key on the remote. In the key directory attributes fill in the protocol, device, command, keycode. Since this is configfs all of this can be easily scripted.

Now when a key is pressed on a remote, the configfs directories are searched for a match on protocol, device, command. If a matches is found, a key stroke corresponding to keycode is created and sent on the input device that was created when the directory for the remote was made.

The configfs directories are pretty flexible. You can use them to map multiple remotes to the same key stroke, or send a single button push to multiple apps.

---
 drivers/input/ir/Makefile      |    2 
 drivers/input/ir/ir-configfs.c |  333 ++++++++++++++++++++++++++++++++++++++++
 drivers/input/ir/ir-core.c     |   15 +-
 3 files changed, 339 insertions(+), 11 deletions(-)
 create mode 100644 drivers/input/ir/ir-configfs.c
drivers/input/ir/Makefile +1 -1
index 6acb665..2ccdda3 100644
@@ -4,5 +4,5 @@
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_INPUT_IR)		+= ir.o
-ir-objs := ir-core.o
+ir-objs := ir-core.o ir-configfs.o
 
drivers/input/ir/ir-configfs.c new file +333 -0

333 lines not on this page · raw message

drivers/input/ir/ir-core.c +5 -10
index 3a309fa..8e08f3f 100644
@@ -10,15 +10,6 @@
 
 #include "ir.h"
 
-void input_ir_translate(struct input_dev *dev, int protocol, int device, int command)
-{
-	/* generate the IR format event */
-	input_report_ir(dev, IR_PROTOCOL, protocol);
-	input_report_ir(dev, IR_DEVICE, device);
-	input_report_ir(dev, IR_COMMAND, command);
-	input_sync(dev);
-}
-
 static int encode_sony(struct ir_device *ir, struct ir_command *command)
 {
 	/* Sony SIRC IR code */
@@ -673,11 +664,15 @@ EXPORT_SYMBOL_GPL(input_ir_destroy);
 
 static int __init input_ir_init(void)
 {
-	return 0;
+	config_group_init(&input_ir_remotes.su_group);
+	mutex_init(&input_ir_remotes.su_mutex);
+
+	return configfs_register_subsystem(&input_ir_remotes);
 }
 module_init(input_ir_init);
 
 static void __exit input_ir_exit(void)
 {
+	configfs_unregister_subsystem(&input_ir_remotes);
 }
 module_exit(input_ir_exit);
#6 lore raw

Re: [RFC PATCH V4 3/6] Configfs support for IR

Quoted 37 lines · Jon Smirl

Now uses configfs to build mappings from remote buttons to key strokes. When ir-core loads it creates /config/remotes. Make a directory for each remote you have; this will cause a new input devices to be created. Inside these directories make a directory for each key on the remote. In the key directory attributes fill in the protocol, device, command, keycode. Since this is configfs all of this can be easily scripted.

Now when a key is pressed on a remote, the configfs directories are searched for a match on protocol, device, command. If a matches is found, a key stroke corresponding to keycode is created and sent on the input device that was created when the directory for the remote was made.

The configfs directories are pretty flexible. You can use them to map multiple remotes to the same key stroke, or send a single button push to multiple apps.

---
 drivers/input/ir/Makefile      |    2 
 drivers/input/ir/ir-configfs.c |  333 ++++++++++++++++++++++++++++++++++++++++
 drivers/input/ir/ir-core.c     |   15 +-
 3 files changed, 339 insertions(+), 11 deletions(-)
 create mode 100644 drivers/input/ir/ir-configfs.c
drivers/input/ir/Makefile +1 -1
index 6acb665..2ccdda3 100644
@@ -4,5 +4,5 @@
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_INPUT_IR)		+= ir.o
-ir-objs := ir-core.o
+ir-objs := ir-core.o ir-configfs.o
 
drivers/input/ir/ir-configfs.c new file +8 -0
new file mode 100644
index 0000000..0fec855
@@ -0,0 +1,333 @@
+/*
+ * Configfs routines for IR support
+ *
+ *   configfs root
+ *   --remotes
+ *   ----specific remote
+ *   ------keymap
+ *   --------protocol

drivers/input/ir/ir-configfs.c line 18

Quoted 10 lines
drivers/input/ir/ir-configfs.c new file +10 -0
+ *   --------device
+ *   --------command
+ *   --------keycode
+ *   ------repeat keymaps
+ *   --------....
+ *   ----another remote
+ *   ------more keymaps
+ *   --------....
+ *
+ * Copyright (C) 2008 Jon Smirl <[email protected]>

GPL?

Maybe those -s should be /s?

Pavel

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
author
#8 lore raw

RFC PATCH v4 4/6 GPT driver for in-kernel IR support.

In reply to Jon Smirl

GPT is a GPIO pin that is cable able of measuring the lenght of pulses. GPTs are common on embedded systems

---
 drivers/input/ir/Kconfig  |    6 +
 drivers/input/ir/Makefile |    3 +
 drivers/input/ir/ir-gpt.c |  224 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 233 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/ir/ir-gpt.c
drivers/input/ir/Kconfig +6 -0
index a6f3f25..172c0c6 100644
@@ -12,4 +12,10 @@ menuconfig INPUT_IR
 
 if INPUT_IR
 
+config IR_GPT
+	tristate "GPT Based IR Receiver"
+	default m
+	help
+	  Driver for GPT-based IR receiver found on Digispeaker
+
 endif
drivers/input/ir/Makefile +3 -0
index 2ccdda3..ab0da3f 100644
@@ -6,3 +6,6 @@
 obj-$(CONFIG_INPUT_IR)		+= ir.o
 ir-objs := ir-core.o ir-configfs.o
 
+
+obj-$(CONFIG_IR_GPT)		+= ir-gpt.o
+
drivers/input/ir/ir-gpt.c new file +224 -0

224 lines not on this page · raw message

author
#9 lore raw

RFC PATCH v4 5/6 Example of PowerPC device tree support for GPT based IR

In reply to Jon Smirl
---
 arch/powerpc/boot/dts/dspeak01.dts |   19 ++++++++-----------
 1 files changed, 8 insertions(+), 11 deletions(-)
arch/powerpc/boot/dts/dspeak01.dts +8 -11
index ec163c0..bde6b79 100644
@@ -131,16 +131,6 @@
 			#gpio-cells = <2>;
 		};
 
-		gpt7: timer@670 { /* General Purpose Timer in GPIO mode */
-			compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
-			cell-index = <7>;
-			reg = <0x670 0x10>;
-			interrupts = <0x1 0x10 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
-			gpio-controller;
-			#gpio-cells = <2>;
-		};
-
 		rtc@800 {	// Real time clock
 			compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
 			device_type = "rtc";
@@ -333,6 +323,14 @@
 			clock-handle = <&clock0>;
 		};
 
+		ir0@670 { /* General Purpose Timer 6 in Input mode */
+			compatible = "gpt-ir";
+			cell-index = <7>;
+			reg = <0x670 0x10>;
+			interrupts = <0x1 0x10 0x0>;
+			interrupt-parent = <&mpc5200_pic>;
+		};
+
 		/* This is only an example device to show the usage of gpios. It maps all available
 		 * gpios to the "gpio-provider" device.
 		 */
@@ -350,7 +348,6 @@
 				 &gpt4		0 0 /* timer4		61c		x2-16	   */
 				 &gpt5		0 0 /* timer5		44c		x7-11	   */
 				 &gpt6		0 0 /* timer6		60c		x8-15	   */
-				 &gpt7		0 0 /* timer7		36a		x17-9	   */
 				 >;
 		};
 	};
author
#10 lore raw

RFC PATCH v4 6/6 Microsoft mceusb2 driver for in-kernel IR subsystem

In reply to Jon Smirl

USB device commonly found on Microsoft Media Center boxes.

Hardware can send and recieve at all common IR frequencies - 36K, 38K, 40K, 56K

---
 drivers/input/ir/Kconfig      |    6 
 drivers/input/ir/Makefile     |    1 
 drivers/input/ir/ir-mceusb2.c |  744 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 751 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/ir/ir-mceusb2.c
drivers/input/ir/Kconfig +6 -0
index 172c0c6..b854900 100644
@@ -17,5 +17,11 @@ config IR_GPT
 	default m
 	help
 	  Driver for GPT-based IR receiver found on Digispeaker
+	  
+config IR_MCEUSB2
+	tristate "Microsoft Media Center Ed. Receiver, v2"
+	default m
+	help
+	  Driver for the Microsoft Media Center Ed. Receiver, v2
 
 endif
drivers/input/ir/Makefile +1 -0
index ab0da3f..0bdafb0 100644
@@ -8,4 +8,5 @@ ir-objs := ir-core.o ir-configfs.o
 
 
 obj-$(CONFIG_IR_GPT)		+= ir-gpt.o
+obj-$(CONFIG_IR_MCEUSB2)	+= ir-mceusb2.o
 
drivers/input/ir/ir-mceusb2.c new file +744 -0

744 lines not on this page · raw message

#11 lore raw
In reply to Jon Smirl
Quoted 1 line · Jon Smirl

New release of in-kernel IR support implementing evdev support. The goal of in-kernel IR is to integrate IR events into the evdev input event queue and maintain ordering of events from all input devices. Still looking for help with this project.

(Forgive me if this has already been asked or dealt with)

Have you contacted the LIRC developers? Is there any overlap between your projects?

Quoted 72 lines

Git tree: git://github.com/jonsmirl/digispeaker.git

ir-core is now a module. Minimal IR code is built into input, that code can't be separated from input. The rest of the core IR code is moved to a module. The IR code in input will be passive if IR-core isn't loaded.

Now uses configfs to build mappings from remote buttons to key strokes. When ir-core loads it creates /config/remotes. Make a directory for each remote you have; this will cause a new input devices to be created. Inside these directories make a directory for each key on the remote. In the key directory attributes fill in the protocol, device, command, keycode. Since this is configfs all of this can be easily scripted.

Now when a key is pressed on a remote, the configfs directories are searched for a match on protocol, device, command. If a matches is found, a key stroke corresponding to keycode is created and sent on the input device that was created when the directory for the remote was made.

The configfs directories are pretty flexible. You can use them to map multiple remotes to the same key stroke, or send a single button push to multiple apps.

Quoted 1 line

From last release...

Raw mode. There are three sysfs attributes - ir_raw, ir_carrier, ir_xmitter. Read from ir_raw to get the raw timing data from the IR device. Set carrier and active xmitters and then copy raw data to ir_raw to send. These attributes may be better on a debug switch. You would use raw mode when decoding a new protocol. After you figure out the new protocol, write an in-kernel encoder/decoder for it.

The in-kernel code is tiny, about 20K including a driver.

Quoted 1 line

From last post...

Note that user space IR device drivers can use the existing support in evdev to inject events into the input queue.

Send and receive are implemented. Received IR messages are decoded and sent to user space as input messages. Send is done via an IOCTL on the input device.

Two drivers are supplied. mceusb2 implements send and receive support for the Microsoft USB IR dongle.

The GPT driver implements receive only support for a GPT pin - GPT is a GPIO with a timer attached.

Code is only lightly tested. Encoders and decoders have not been written for all protocols. Repeat is not handled for any protocol. I'm looking for help. There are 15 more existing LIRC drivers.

---

Jon Smirl (6):
Microsoft mceusb2 driver for in-kernel IR subsystem Example of PowerPC device tree support for GPT based IR GPT driver for in-kernel IR support.
Configfs support for IR
Core IR module
Minimal changes to the core input system

 arch/powerpc/boot/dts/dspeak01.dts |   19 -
 drivers/input/Kconfig              |    2
 drivers/input/Makefile             |    1
 drivers/input/evdev.c              |   55 +++
 drivers/input/input.c              |   17 +
 drivers/input/ir/Kconfig           |   27 +
 drivers/input/ir/Makefile          |   12 +
 drivers/input/ir/ir-configfs.c     |  333 ++++++++++++++++
 drivers/input/ir/ir-core.c         |  678 +++++++++++++++++++++++++++++++++
 drivers/input/ir/ir-gpt.c          |  224 +++++++++++
 drivers/input/ir/ir-mceusb2.c      |  744 ++++++++++++++++++++++++++++++++++++
 drivers/input/ir/ir.h              |   48 ++
 include/linux/input.h              |   75 ++++
 include/linux/mod_devicetable.h    |    3
 14 files changed, 2227 insertions(+), 11 deletions(-)
 create mode 100644 drivers/input/ir/Kconfig
 create mode 100644 drivers/input/ir/Makefile
 create mode 100644 drivers/input/ir/ir-configfs.c
 create mode 100644 drivers/input/ir/ir-core.c
 create mode 100644 drivers/input/ir/ir-gpt.c
 create mode 100644 drivers/input/ir/ir-mceusb2.c
 create mode 100644 drivers/input/ir/ir.h

--
Jon Smirl
[email protected]
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

author
#12 lore raw
Quoted 7 lines · J.R. Mauro
Quoted 1 line · Jon Smirl

New release of in-kernel IR support implementing evdev support. The goal of in-kernel IR is to integrate IR events into the evdev input event queue and maintain ordering of events from all input devices. Still looking for help with this project.

(Forgive me if this has already been asked or dealt with)

Have you contacted the LIRC developers? Is there any overlap between your projects?

The LIRC people know about this. Pieces of the code are coming from the LIRC source base and being reworked for kernel inclusion.

LIRC needs a daemon to run and apps have to be modified to use it. This code runs all in-kernel and looks like keyboard input to apps.

LIRC developers and anyone else and encouraged to help with this code.

Signature · 2 lines
Jon Smirl
[email protected]
#13 lore raw
Quoted 11 lines · Jon Smirl
Quoted 7 lines · J.R. Mauro
Quoted 1 line · Jon Smirl

New release of in-kernel IR support implementing evdev support. The goal of in-kernel IR is to integrate IR events into the evdev input event queue and maintain ordering of events from all input devices. Still looking for help with this project.

(Forgive me if this has already been asked or dealt with)

Have you contacted the LIRC developers? Is there any overlap between your projects?

The LIRC people know about this. Pieces of the code are coming from the LIRC source base and being reworked for kernel inclusion.

Great, it's nice to see there's cooperation.

Quoted 5 lines

LIRC needs a daemon to run and apps have to be modified to use it. This code runs all in-kernel and looks like keyboard input to apps.

LIRC developers and anyone else and encouraged to help with this code.

What's involved in converting an LIRC driver into something usable with your framework?

Quoted 5 lines

--
Jon Smirl
[email protected]

author
#14 lore raw
Quoted 2 lines · J.R. Mauro

What's involved in converting an LIRC driver into something usable with your framework?

Look at either of the two drivers I posted. It is actually very simple. Drivers just send/receive arrays of pulse timings in milliseconds.

Signature · 2 lines
Jon Smirl
[email protected]