Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a60d64b1 authored by Sean Young's avatar Sean Young Committed by Mauro Carvalho Chehab
Browse files

media: lirc: lirc interface should not be a raw decoder



The lirc user interface exists as a raw decoder, which does not make
much sense for transmit-only devices.

In addition, we want to have lirc char devices for devices which do not
use raw IR, i.e. scancode only devices.

Note that rc-code, lirc_dev, ir-lirc-codec are now calling functions of
each other, so they've been merged into one module rc-core to avoid
circular dependencies.

Since ir-lirc-codec no longer exists as separate codec module, there is no
need for RC_DRIVER_IR_RAW_TX type drivers to call ir_raw_event_register().

Signed-off-by: default avatarSean Young <sean@mess.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 0d39ab0b
Loading
Loading
Loading
Loading
+8 −21
Original line number Diff line number Diff line
@@ -16,34 +16,21 @@ menuconfig RC_CORE
if RC_CORE
source "drivers/media/rc/keymaps/Kconfig"

menuconfig RC_DECODERS
        bool "Remote controller decoders"
	depends on RC_CORE
	default y

if RC_DECODERS
config LIRC
	tristate "LIRC interface driver"
	bool "LIRC user interface"
	depends on RC_CORE

	---help---
	   Enable this option to build the Linux Infrared Remote
	   Control (LIRC) core device interface driver. The LIRC
	   interface passes raw IR to and from userspace, where the
	   LIRC daemon handles protocol decoding for IR reception and
	   encoding for IR transmitting (aka "blasting").
	   Enable this option to enable the Linux Infrared Remote
	   Control user interface (e.g. /dev/lirc*). This interface
	   passes raw IR to and from userspace, which is needed for
	   IR transmitting (aka "blasting") and for the lirc daemon.

config IR_LIRC_CODEC
	tristate "Enable IR to LIRC bridge"
menuconfig RC_DECODERS
        bool "Remote controller decoders"
	depends on RC_CORE
	depends on LIRC
	default y

	---help---
	   Enable this option to pass raw IR to and from userspace via
	   the LIRC interface.


if RC_DECODERS
config IR_NEC_DECODER
	tristate "Enable IR raw decoder for the NEC protocol"
	depends on RC_CORE
+2 −3
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0
rc-core-objs	:= rc-main.o rc-ir-raw.o

obj-y += keymaps/

obj-$(CONFIG_RC_CORE) += rc-core.o
obj-$(CONFIG_LIRC) += lirc_dev.o
rc-core-y := rc-main.o rc-ir-raw.o
rc-core-$(CONFIG_LIRC) += lirc_dev.o ir-lirc-codec.o
obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
@@ -13,7 +13,6 @@ obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o
obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-decoder.o
obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
obj-$(CONFIG_IR_XMP_DECODER) += ir-xmp-decoder.o

# stand-alone IR receivers/transmitters
+36 −99
Original line number Diff line number Diff line
@@ -14,7 +14,6 @@

#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/module.h>
#include <media/lirc.h>
#include <media/lirc_dev.h>
#include <media/rc-core.h>
@@ -23,21 +22,15 @@
#define LIRCBUF_SIZE 256

/**
 * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the
 *		      lircd userspace daemon for decoding.
 * ir_lirc_raw_event() - Send raw IR data to lirc to be relayed to userspace
 *
 * @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 lirc interfaces aren't wired up.
 */
static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
void ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev)
{
	struct lirc_codec *lirc = &dev->raw->lirc;
	int sample;

	if (!dev->raw->lirc.ldev || !dev->raw->lirc.ldev->buf)
		return -EINVAL;

	/* Packet start */
	if (ev.reset) {
		/* Userspace expects a long space event before the start of
@@ -56,15 +49,15 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
	/* Packet end */
	} else if (ev.timeout) {

		if (lirc->gap)
			return 0;
		if (dev->gap)
			return;

		lirc->gap_start = ktime_get();
		lirc->gap = true;
		lirc->gap_duration = ev.duration;
		dev->gap_start = ktime_get();
		dev->gap = true;
		dev->gap_duration = ev.duration;

		if (!lirc->send_timeout_reports)
			return 0;
		if (!dev->send_timeout_reports)
			return;

		sample = LIRC_TIMEOUT(ev.duration / 1000);
		IR_dprintk(2, "timeout report (duration: %d)\n", sample);
@@ -72,21 +65,21 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
	/* Normal sample */
	} else {

		if (lirc->gap) {
		if (dev->gap) {
			int gap_sample;

			lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
				lirc->gap_start));
			dev->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
							 dev->gap_start));

			/* Convert to ms and cap by LIRC_VALUE_MASK */
			do_div(lirc->gap_duration, 1000);
			lirc->gap_duration = min(lirc->gap_duration,
							(u64)LIRC_VALUE_MASK);
			do_div(dev->gap_duration, 1000);
			dev->gap_duration = min_t(u64, dev->gap_duration,
						  LIRC_VALUE_MASK);

			gap_sample = LIRC_SPACE(lirc->gap_duration);
			lirc_buffer_write(dev->raw->lirc.ldev->buf,
			gap_sample = LIRC_SPACE(dev->gap_duration);
			lirc_buffer_write(dev->lirc_dev->buf,
					  (unsigned char *)&gap_sample);
			lirc->gap = false;
			dev->gap = false;
		}

		sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) :
@@ -95,18 +88,16 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
			   TO_US(ev.duration), TO_STR(ev.pulse));
	}

	lirc_buffer_write(dev->raw->lirc.ldev->buf,
	lirc_buffer_write(dev->lirc_dev->buf,
			  (unsigned char *) &sample);
	wake_up(&dev->raw->lirc.ldev->buf->wait_poll);

	return 0;
	wake_up(&dev->lirc_dev->buf->wait_poll);
}

static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
				   size_t n, loff_t *ppos)
{
	struct lirc_codec *lirc;
	struct rc_dev *dev;
	struct rc_dev *dev = file->private_data;
	unsigned int *txbuf = NULL;
	struct ir_raw_event *raw = NULL;
	ssize_t ret = -EINVAL;
@@ -118,22 +109,12 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,

	start = ktime_get();

	lirc = lirc_get_pdata(file);
	if (!lirc)
		return -EFAULT;

	dev = lirc->dev;
	if (!dev) {
		ret = -EFAULT;
		goto out;
	}

	if (!dev->tx_ir) {
		ret = -EINVAL;
		goto out;
	}

	if (lirc->send_mode == LIRC_MODE_SCANCODE) {
	if (dev->send_mode == LIRC_MODE_SCANCODE) {
		struct lirc_scancode scan;

		if (n != sizeof(scan))
@@ -198,7 +179,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
	if (ret < 0)
		goto out;

	if (lirc->send_mode == LIRC_MODE_SCANCODE) {
	if (dev->send_mode == LIRC_MODE_SCANCODE) {
		ret = n;
	} else {
		for (duration = i = 0; i < ret; i++)
@@ -228,20 +209,11 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
			unsigned long arg)
{
	struct lirc_codec *lirc;
	struct rc_dev *dev;
	struct rc_dev *dev = filep->private_data;
	u32 __user *argp = (u32 __user *)(arg);
	int ret = 0;
	__u32 val = 0, tmp;

	lirc = lirc_get_pdata(filep);
	if (!lirc)
		return -EFAULT;

	dev = lirc->dev;
	if (!dev)
		return -EFAULT;

	if (_IOC_DIR(cmd) & _IOC_WRITE) {
		ret = get_user(val, argp);
		if (ret)
@@ -255,7 +227,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
		if (!dev->tx_ir)
			return -ENOTTY;

		val = lirc->send_mode;
		val = dev->send_mode;
		break;

	case LIRC_SET_SEND_MODE:
@@ -265,7 +237,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
		if (!(val == LIRC_MODE_PULSE || val == LIRC_MODE_SCANCODE))
			return -EINVAL;

		lirc->send_mode = val;
		dev->send_mode = val;
		return 0;

	/* TX settings */
@@ -299,7 +271,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
			return -EINVAL;

		return dev->s_rx_carrier_range(dev,
					       dev->raw->lirc.carrier_low,
					       dev->carrier_low,
					       val);

	case LIRC_SET_REC_CARRIER_RANGE:
@@ -309,7 +281,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
		if (val <= 0)
			return -EINVAL;

		dev->raw->lirc.carrier_low = val;
		dev->carrier_low = val;
		return 0;

	case LIRC_GET_REC_RESOLUTION:
@@ -367,7 +339,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
		if (!dev->timeout)
			return -ENOTTY;

		lirc->send_timeout_reports = !!val;
		dev->send_timeout_reports = !!val;
		break;

	default:
@@ -394,7 +366,7 @@ static const struct file_operations lirc_fops = {
	.llseek		= no_llseek,
};

static int ir_lirc_register(struct rc_dev *dev)
int ir_lirc_register(struct rc_dev *dev)
{
	struct lirc_dev *ldev;
	int rc = -ENOMEM;
@@ -436,7 +408,6 @@ static int ir_lirc_register(struct rc_dev *dev)
	snprintf(ldev->name, sizeof(ldev->name), "ir-lirc-codec (%s)",
		 dev->driver_name);
	ldev->features = features;
	ldev->data = &dev->raw->lirc;
	ldev->buf = NULL;
	ldev->chunk_size = sizeof(int);
	ldev->buffer_size = LIRCBUF_SIZE;
@@ -449,10 +420,8 @@ static int ir_lirc_register(struct rc_dev *dev)
	if (rc < 0)
		goto out;

	dev->raw->lirc.send_mode = LIRC_MODE_PULSE;

	dev->raw->lirc.ldev = ldev;
	dev->raw->lirc.dev = dev;
	dev->send_mode = LIRC_MODE_PULSE;
	dev->lirc_dev = ldev;
	return 0;

out:
@@ -460,40 +429,8 @@ static int ir_lirc_register(struct rc_dev *dev)
	return rc;
}

static int ir_lirc_unregister(struct rc_dev *dev)
{
	struct lirc_codec *lirc = &dev->raw->lirc;

	lirc_unregister_device(lirc->ldev);
	lirc->ldev = NULL;

	return 0;
}

static struct ir_raw_handler lirc_handler = {
	.protocols	= 0,
	.decode		= ir_lirc_decode,
	.raw_register	= ir_lirc_register,
	.raw_unregister	= ir_lirc_unregister,
};

static int __init ir_lirc_codec_init(void)
{
	ir_raw_handler_register(&lirc_handler);

	printk(KERN_INFO "IR LIRC bridge handler initialized\n");
	return 0;
}

static void __exit ir_lirc_codec_exit(void)
void ir_lirc_unregister(struct rc_dev *dev)
{
	ir_raw_handler_unregister(&lirc_handler);
	lirc_unregister_device(dev->lirc_dev);
	dev->lirc_dev = NULL;
}

module_init(ir_lirc_codec_init);
module_exit(ir_lirc_codec_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
MODULE_DESCRIPTION("LIRC IR handler bridge");
+0 −6
Original line number Diff line number Diff line
@@ -358,9 +358,6 @@ static int ir_mce_kbd_register(struct rc_dev *dev)
	struct input_dev *idev;
	int i, ret;

	if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
		return 0;

	idev = input_allocate_device();
	if (!idev)
		return -ENOMEM;
@@ -415,9 +412,6 @@ static int ir_mce_kbd_unregister(struct rc_dev *dev)
	struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd;
	struct input_dev *idev = mce_kbd->idev;

	if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
		return 0;

	del_timer_sync(&mce_kbd->rx_timeout);
	input_unregister_device(idev);

+13 −34
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@
#include <linux/cdev.h>
#include <linux/idr.h>

#include <media/rc-core.h>
#include "rc-core-priv.h"
#include <media/lirc.h>
#include <media/lirc_dev.h>

@@ -236,7 +236,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)

	d->open++;

	lirc_init_pdata(inode, file);
	file->private_data = d->rdev;
	nonseekable_open(inode, file);
	mutex_unlock(&d->mutex);

@@ -250,11 +250,12 @@ EXPORT_SYMBOL(lirc_dev_fop_open);

int lirc_dev_fop_close(struct inode *inode, struct file *file)
{
	struct lirc_dev *d = file->private_data;
	struct rc_dev *rcdev = file->private_data;
	struct lirc_dev *d = rcdev->lirc_dev;

	mutex_lock(&d->mutex);

	rc_close(d->rdev);
	rc_close(rcdev);
	d->open--;

	mutex_unlock(&d->mutex);
@@ -265,7 +266,8 @@ EXPORT_SYMBOL(lirc_dev_fop_close);

unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
{
	struct lirc_dev *d = file->private_data;
	struct rc_dev *rcdev = file->private_data;
	struct lirc_dev *d = rcdev->lirc_dev;
	unsigned int ret;

	if (!d->attached)
@@ -290,7 +292,8 @@ EXPORT_SYMBOL(lirc_dev_fop_poll);

long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	struct lirc_dev *d = file->private_data;
	struct rc_dev *rcdev = file->private_data;
	struct lirc_dev *d = rcdev->lirc_dev;
	__u32 mode;
	int result;

@@ -349,7 +352,8 @@ ssize_t lirc_dev_fop_read(struct file *file,
			  size_t length,
			  loff_t *ppos)
{
	struct lirc_dev *d = file->private_data;
	struct rc_dev *rcdev = file->private_data;
	struct lirc_dev *d = rcdev->lirc_dev;
	unsigned char *buf;
	int ret, written = 0;
	DECLARE_WAITQUEUE(wait, current);
@@ -448,24 +452,7 @@ ssize_t lirc_dev_fop_read(struct file *file,
}
EXPORT_SYMBOL(lirc_dev_fop_read);

void lirc_init_pdata(struct inode *inode, struct file *file)
{
	struct lirc_dev *d = container_of(inode->i_cdev, struct lirc_dev, cdev);

	file->private_data = d;
}
EXPORT_SYMBOL(lirc_init_pdata);

void *lirc_get_pdata(struct file *file)
{
	struct lirc_dev *d = file->private_data;

	return d->data;
}
EXPORT_SYMBOL(lirc_get_pdata);


static int __init lirc_dev_init(void)
int __init lirc_dev_init(void)
{
	int retval;

@@ -489,16 +476,8 @@ static int __init lirc_dev_init(void)
	return 0;
}

static void __exit lirc_dev_exit(void)
void __exit lirc_dev_exit(void)
{
	class_destroy(lirc_class);
	unregister_chrdev_region(lirc_base_dev, LIRC_MAX_DEVICES);
	pr_info("module unloaded\n");
}

module_init(lirc_dev_init);
module_exit(lirc_dev_exit);

MODULE_DESCRIPTION("LIRC base driver module");
MODULE_AUTHOR("Artur Lipowski");
MODULE_LICENSE("GPL");
Loading