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

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
...@@ -16,34 +16,21 @@ menuconfig RC_CORE ...@@ -16,34 +16,21 @@ menuconfig RC_CORE
if RC_CORE if RC_CORE
source "drivers/media/rc/keymaps/Kconfig" source "drivers/media/rc/keymaps/Kconfig"
menuconfig RC_DECODERS
bool "Remote controller decoders"
depends on RC_CORE
default y
if RC_DECODERS
config LIRC config LIRC
tristate "LIRC interface driver" bool "LIRC user interface"
depends on RC_CORE depends on RC_CORE
---help--- ---help---
Enable this option to build the Linux Infrared Remote Enable this option to enable the Linux Infrared Remote
Control (LIRC) core device interface driver. The LIRC Control user interface (e.g. /dev/lirc*). This interface
interface passes raw IR to and from userspace, where the passes raw IR to and from userspace, which is needed for
LIRC daemon handles protocol decoding for IR reception and IR transmitting (aka "blasting") and for the lirc daemon.
encoding for IR transmitting (aka "blasting").
config IR_LIRC_CODEC menuconfig RC_DECODERS
tristate "Enable IR to LIRC bridge" bool "Remote controller decoders"
depends on RC_CORE depends on RC_CORE
depends on LIRC
default y default y
---help--- if RC_DECODERS
Enable this option to pass raw IR to and from userspace via
the LIRC interface.
config IR_NEC_DECODER config IR_NEC_DECODER
tristate "Enable IR raw decoder for the NEC protocol" tristate "Enable IR raw decoder for the NEC protocol"
depends on RC_CORE depends on RC_CORE
......
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
rc-core-objs := rc-main.o rc-ir-raw.o
obj-y += keymaps/ obj-y += keymaps/
obj-$(CONFIG_RC_CORE) += rc-core.o 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_NEC_DECODER) += ir-nec-decoder.o
obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
...@@ -13,7 +13,6 @@ obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-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_SANYO_DECODER) += ir-sanyo-decoder.o
obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-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_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 obj-$(CONFIG_IR_XMP_DECODER) += ir-xmp-decoder.o
# stand-alone IR receivers/transmitters # stand-alone IR receivers/transmitters
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/module.h>
#include <media/lirc.h> #include <media/lirc.h>
#include <media/lirc_dev.h> #include <media/lirc_dev.h>
#include <media/rc-core.h> #include <media/rc-core.h>
...@@ -23,21 +22,15 @@ ...@@ -23,21 +22,15 @@
#define LIRCBUF_SIZE 256 #define LIRCBUF_SIZE 256
/** /**
* ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the * ir_lirc_raw_event() - Send raw IR data to lirc to be relayed to userspace
* lircd userspace daemon for decoding. *
* @dev: the struct rc_dev descriptor of the device * @dev: the struct rc_dev descriptor of the device
* @ev: the struct ir_raw_event descriptor of the pulse/space * @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; int sample;
if (!dev->raw->lirc.ldev || !dev->raw->lirc.ldev->buf)
return -EINVAL;
/* Packet start */ /* Packet start */
if (ev.reset) { if (ev.reset) {
/* Userspace expects a long space event before the start of /* 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) ...@@ -56,15 +49,15 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
/* Packet end */ /* Packet end */
} else if (ev.timeout) { } else if (ev.timeout) {
if (lirc->gap) if (dev->gap)
return 0; return;
lirc->gap_start = ktime_get(); dev->gap_start = ktime_get();
lirc->gap = true; dev->gap = true;
lirc->gap_duration = ev.duration; dev->gap_duration = ev.duration;
if (!lirc->send_timeout_reports) if (!dev->send_timeout_reports)
return 0; return;
sample = LIRC_TIMEOUT(ev.duration / 1000); sample = LIRC_TIMEOUT(ev.duration / 1000);
IR_dprintk(2, "timeout report (duration: %d)\n", sample); 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) ...@@ -72,21 +65,21 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
/* Normal sample */ /* Normal sample */
} else { } else {
if (lirc->gap) { if (dev->gap) {
int gap_sample; int gap_sample;
lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(), dev->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
lirc->gap_start)); dev->gap_start));
/* Convert to ms and cap by LIRC_VALUE_MASK */ /* Convert to ms and cap by LIRC_VALUE_MASK */
do_div(lirc->gap_duration, 1000); do_div(dev->gap_duration, 1000);
lirc->gap_duration = min(lirc->gap_duration, dev->gap_duration = min_t(u64, dev->gap_duration,
(u64)LIRC_VALUE_MASK); LIRC_VALUE_MASK);
gap_sample = LIRC_SPACE(lirc->gap_duration); gap_sample = LIRC_SPACE(dev->gap_duration);
lirc_buffer_write(dev->raw->lirc.ldev->buf, lirc_buffer_write(dev->lirc_dev->buf,
(unsigned char *)&gap_sample); (unsigned char *)&gap_sample);
lirc->gap = false; dev->gap = false;
} }
sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) : 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) ...@@ -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)); 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); (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, static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
size_t n, loff_t *ppos) size_t n, loff_t *ppos)
{ {
struct lirc_codec *lirc; struct rc_dev *dev = file->private_data;
struct rc_dev *dev;
unsigned int *txbuf = NULL; unsigned int *txbuf = NULL;
struct ir_raw_event *raw = NULL; struct ir_raw_event *raw = NULL;
ssize_t ret = -EINVAL; ssize_t ret = -EINVAL;
...@@ -118,22 +109,12 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, ...@@ -118,22 +109,12 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
start = ktime_get(); 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) { if (!dev->tx_ir) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
if (lirc->send_mode == LIRC_MODE_SCANCODE) { if (dev->send_mode == LIRC_MODE_SCANCODE) {
struct lirc_scancode scan; struct lirc_scancode scan;
if (n != sizeof(scan)) if (n != sizeof(scan))
...@@ -198,7 +179,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, ...@@ -198,7 +179,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
if (ret < 0) if (ret < 0)
goto out; goto out;
if (lirc->send_mode == LIRC_MODE_SCANCODE) { if (dev->send_mode == LIRC_MODE_SCANCODE) {
ret = n; ret = n;
} else { } else {
for (duration = i = 0; i < ret; i++) 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, ...@@ -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, static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
struct lirc_codec *lirc; struct rc_dev *dev = filep->private_data;
struct rc_dev *dev;
u32 __user *argp = (u32 __user *)(arg); u32 __user *argp = (u32 __user *)(arg);
int ret = 0; int ret = 0;
__u32 val = 0, tmp; __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) { if (_IOC_DIR(cmd) & _IOC_WRITE) {
ret = get_user(val, argp); ret = get_user(val, argp);
if (ret) if (ret)
...@@ -255,7 +227,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, ...@@ -255,7 +227,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
if (!dev->tx_ir) if (!dev->tx_ir)
return -ENOTTY; return -ENOTTY;
val = lirc->send_mode; val = dev->send_mode;
break; break;
case LIRC_SET_SEND_MODE: case LIRC_SET_SEND_MODE:
...@@ -265,7 +237,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, ...@@ -265,7 +237,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
if (!(val == LIRC_MODE_PULSE || val == LIRC_MODE_SCANCODE)) if (!(val == LIRC_MODE_PULSE || val == LIRC_MODE_SCANCODE))
return -EINVAL; return -EINVAL;
lirc->send_mode = val; dev->send_mode = val;
return 0; return 0;
/* TX settings */ /* TX settings */
...@@ -299,7 +271,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, ...@@ -299,7 +271,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
return -EINVAL; return -EINVAL;
return dev->s_rx_carrier_range(dev, return dev->s_rx_carrier_range(dev,
dev->raw->lirc.carrier_low, dev->carrier_low,
val); val);
case LIRC_SET_REC_CARRIER_RANGE: case LIRC_SET_REC_CARRIER_RANGE:
...@@ -309,7 +281,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, ...@@ -309,7 +281,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
if (val <= 0) if (val <= 0)
return -EINVAL; return -EINVAL;
dev->raw->lirc.carrier_low = val; dev->carrier_low = val;
return 0; return 0;
case LIRC_GET_REC_RESOLUTION: case LIRC_GET_REC_RESOLUTION:
...@@ -367,7 +339,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, ...@@ -367,7 +339,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
if (!dev->timeout) if (!dev->timeout)
return -ENOTTY; return -ENOTTY;
lirc->send_timeout_reports = !!val; dev->send_timeout_reports = !!val;
break; break;
default: default:
...@@ -394,7 +366,7 @@ static const struct file_operations lirc_fops = { ...@@ -394,7 +366,7 @@ static const struct file_operations lirc_fops = {
.llseek = no_llseek, .llseek = no_llseek,
}; };
static int ir_lirc_register(struct rc_dev *dev) int ir_lirc_register(struct rc_dev *dev)
{ {
struct lirc_dev *ldev; struct lirc_dev *ldev;
int rc = -ENOMEM; int rc = -ENOMEM;
...@@ -436,7 +408,6 @@ static int ir_lirc_register(struct rc_dev *dev) ...@@ -436,7 +408,6 @@ static int ir_lirc_register(struct rc_dev *dev)
snprintf(ldev->name, sizeof(ldev->name), "ir-lirc-codec (%s)", snprintf(ldev->name, sizeof(ldev->name), "ir-lirc-codec (%s)",
dev->driver_name); dev->driver_name);
ldev->features = features; ldev->features = features;
ldev->data = &dev->raw->lirc;
ldev->buf = NULL; ldev->buf = NULL;
ldev->chunk_size = sizeof(int); ldev->chunk_size = sizeof(int);
ldev->buffer_size = LIRCBUF_SIZE; ldev->buffer_size = LIRCBUF_SIZE;
...@@ -449,10 +420,8 @@ static int ir_lirc_register(struct rc_dev *dev) ...@@ -449,10 +420,8 @@ static int ir_lirc_register(struct rc_dev *dev)
if (rc < 0) if (rc < 0)
goto out; goto out;
dev->raw->lirc.send_mode = LIRC_MODE_PULSE; dev->send_mode = LIRC_MODE_PULSE;
dev->lirc_dev = ldev;
dev->raw->lirc.ldev = ldev;
dev->raw->lirc.dev = dev;
return 0; return 0;
out: out:
...@@ -460,40 +429,8 @@ static int ir_lirc_register(struct rc_dev *dev) ...@@ -460,40 +429,8 @@ static int ir_lirc_register(struct rc_dev *dev)
return rc; return rc;
} }
static int ir_lirc_unregister(struct rc_dev *dev) void 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); lirc_unregister_device(dev->lirc_dev);
dev->lirc_dev = NULL;
printk(KERN_INFO "IR LIRC bridge handler initialized\n");
return 0;
}
static void __exit ir_lirc_codec_exit(void)
{
ir_raw_handler_unregister(&lirc_handler);
} }
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");
...@@ -358,9 +358,6 @@ static int ir_mce_kbd_register(struct rc_dev *dev) ...@@ -358,9 +358,6 @@ static int ir_mce_kbd_register(struct rc_dev *dev)
struct input_dev *idev; struct input_dev *idev;
int i, ret; int i, ret;
if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
return 0;
idev = input_allocate_device(); idev = input_allocate_device();
if (!idev) if (!idev)
return -ENOMEM; return -ENOMEM;
...@@ -415,9 +412,6 @@ static int ir_mce_kbd_unregister(struct rc_dev *dev) ...@@ -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 mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd;
struct input_dev *idev = mce_kbd->idev; 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); del_timer_sync(&mce_kbd->rx_timeout);
input_unregister_device(idev); input_unregister_device(idev);
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <linux/cdev.h> #include <linux/cdev.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <media/rc-core.h> #include "rc-core-priv.h"
#include <media/lirc.h> #include <media/lirc.h>
#include <media/lirc_dev.h> #include <media/lirc_dev.h>
...@@ -236,7 +236,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) ...@@ -236,7 +236,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
d->open++; d->open++;
lirc_init_pdata(inode, file); file->private_data = d->rdev;
nonseekable_open(inode, file); nonseekable_open(inode, file);
mutex_unlock(&d->mutex); mutex_unlock(&d->mutex);
...@@ -250,11 +250,12 @@ EXPORT_SYMBOL(lirc_dev_fop_open); ...@@ -250,11 +250,12 @@ EXPORT_SYMBOL(lirc_dev_fop_open);
int lirc_dev_fop_close(struct inode *inode, struct file *file) 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); mutex_lock(&d->mutex);
rc_close(d->rdev); rc_close(rcdev);
d->open--; d->open--;
mutex_unlock(&d->mutex); mutex_unlock(&d->mutex);
...@@ -265,7 +266,8 @@ EXPORT_SYMBOL(lirc_dev_fop_close); ...@@ -265,7 +266,8 @@ EXPORT_SYMBOL(lirc_dev_fop_close);
unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) 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; unsigned int ret;
if (!d->attached) if (!d->attached)
...@@ -290,7 +292,8 @@ EXPORT_SYMBOL(lirc_dev_fop_poll); ...@@ -290,7 +292,8 @@ EXPORT_SYMBOL(lirc_dev_fop_poll);
long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 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; __u32 mode;
int result; int result;
...@@ -349,7 +352,8 @@ ssize_t lirc_dev_fop_read(struct file *file, ...@@ -349,7 +352,8 @@ ssize_t lirc_dev_fop_read(struct file *file,
size_t length, size_t length,
loff_t *ppos) 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; unsigned char *buf;
int ret, written = 0; int ret, written = 0;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
...@@ -448,24 +452,7 @@ ssize_t lirc_dev_fop_read(struct file *file, ...@@ -448,24 +452,7 @@ ssize_t lirc_dev_fop_read(struct file *file,
} }
EXPORT_SYMBOL(lirc_dev_fop_read); EXPORT_SYMBOL(lirc_dev_fop_read);
void lirc_init_pdata(struct inode *inode, struct file *file) int __init lirc_dev_init(void)
{
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 retval; int retval;
...@@ -489,16 +476,8 @@ static int __init lirc_dev_init(void) ...@@ -489,16 +476,8 @@ static int __init lirc_dev_init(void)
return 0; return 0;
} }
static void __exit lirc_dev_exit(void) void __exit lirc_dev_exit(void)
{ {
class_destroy(lirc_class); class_destroy(lirc_class);
unregister_chrdev_region(lirc_base_dev, LIRC_MAX_DEVICES); 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");
...@@ -12,6 +12,20 @@ ...@@ -12,6 +12,20 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <media/rc-core.h> #include <media/rc-core.h>
/**
* rc_open - Opens a RC device
*
* @rdev: pointer to struct rc_dev.
*/
int rc_open(struct rc_dev *rdev);
/**
* rc_close - Closes a RC device
*
* @rdev: pointer to struct rc_dev.
*/
void rc_close(struct rc_dev *rdev);
struct ir_raw_handler { struct ir_raw_handler {
struct list_head list; struct list_head list;
...@@ -21,7 +35,7 @@ struct ir_raw_handler { ...@@ -21,7 +35,7 @@ struct ir_raw_handler {
struct ir_raw_event *events, unsigned int max); struct ir_raw_event *events, unsigned int max);
u32 carrier; u32 carrier;
/* These two should only be used by the lirc decoder */ /* These two should only be used by the mce kbd decoder */
int (*raw_register)(struct rc_dev *dev); int (*raw_register)(struct rc_dev *dev);
int (*raw_unregister)(struct rc_dev *dev); int (*raw_unregister)(struct rc_dev *dev);
}; };
...@@ -95,17 +109,6 @@ struct ir_raw_event_ctrl { ...@@ -95,17 +109,6 @@ struct ir_raw_event_ctrl {
unsigned count; unsigned count;
unsigned wanted_bits; unsigned wanted_bits;
} mce_kbd; } mce_kbd;
struct lirc_codec {
struct rc_dev *dev;
struct lirc_dev *ldev;
int carrier_low;
ktime_t gap_start;
u64 gap_duration;
bool gap;
bool send_timeout_reports;
u8 send_mode;
} lirc;
struct xmp_dec { struct xmp_dec {
int state; int state;
unsigned count; unsigned count;
...@@ -264,6 +267,24 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); ...@@ -264,6 +267,24 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
void ir_raw_load_modules(u64 *protocols); void ir_raw_load_modules(u64 *protocols);
void ir_raw_init(void); void ir_raw_init(void);
/*
* lirc interface
*/
#ifdef CONFIG_LIRC
int lirc_dev_init(void);
void lirc_dev_exit(void);
void ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev);
int ir_lirc_register(struct rc_dev *dev);
void ir_lirc_unregister(struct rc_dev *dev);
#else
static inline int lirc_dev_init(void) { return 0; }
static inline void lirc_dev_exit(void) {}
static inline void ir_lirc_raw_event(struct rc_dev *dev,
struct ir_raw_event ev) { }
static inline int ir_lirc_register(struct rc_dev *dev) { return 0; }
static inline void ir_lirc_unregister(struct rc_dev *dev) { }
#endif
/* /*
* Decoder initialization code * Decoder initialization code
* *
......
...@@ -31,6 +31,7 @@ static int ir_raw_event_thread(void *data) ...@@ -31,6 +31,7 @@ static int ir_raw_event_thread(void *data)
if (raw->dev->enabled_protocols & if (raw->dev->enabled_protocols &
handler->protocols || !handler->protocols) handler->protocols || !handler->protocols)
handler->decode(raw->dev, ev); handler->decode(raw->dev, ev);
ir_lirc_raw_event(raw->dev, ev);
raw->prev_ev = ev; raw->prev_ev = ev;
} }
mutex_unlock(&ir_raw_handler_lock); mutex_unlock(&ir_raw_handler_lock);
...@@ -521,16 +522,9 @@ EXPORT_SYMBOL(ir_raw_encode_carrier); ...@@ -521,16 +522,9 @@ EXPORT_SYMBOL(ir_raw_encode_carrier);
*/ */
int ir_raw_event_prepare(struct rc_dev *dev) int ir_raw_event_prepare(struct rc_dev *dev)
{ {
static bool raw_init; /* 'false' default value, raw decoders loaded? */
if (!dev) if (!dev)
return -EINVAL; return -EINVAL;
if (!raw_init) {
request_module("ir-lirc-codec");
raw_init = true;
}
dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL); dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL);
if (!dev->raw) if (!dev->raw)
return -ENOMEM; return -ENOMEM;
...@@ -548,19 +542,11 @@ int ir_raw_event_register(struct rc_dev *dev) ...@@ -548,19 +542,11 @@ int ir_raw_event_register(struct rc_dev *dev)
struct ir_raw_handler *handler; struct ir_raw_handler *handler;
struct task_struct *thread; struct task_struct *thread;
/* thread = kthread_run(ir_raw_event_thread, dev->raw, "rc%u", dev->minor);
* raw transmitters do not need any event registration if (IS_ERR(thread))
* because the event is coming from userspace return PTR_ERR(thread);
*/
if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
thread = kthread_run(ir_raw_event_thread, dev->raw, "rc%u",
dev->minor);
if (IS_ERR(thread)) dev->raw->thread = thread;
return PTR_ERR(thread);
dev->raw->thread = thread;
}
mutex_lock(&ir_raw_handler_lock); mutex_lock(&ir_raw_handler_lock);
list_add_tail(&dev->raw->list, &ir_raw_client_list); list_add_tail(&dev->raw->list, &ir_raw_client_list);
......
...@@ -846,7 +846,6 @@ int rc_open(struct rc_dev *rdev) ...@@ -846,7 +846,6 @@ int rc_open(struct rc_dev *rdev)
return rval; return rval;
} }
EXPORT_SYMBOL_GPL(rc_open);
static int ir_open(struct input_dev *idev) static int ir_open(struct input_dev *idev)
{ {
...@@ -866,7 +865,6 @@ void rc_close(struct rc_dev *rdev) ...@@ -866,7 +865,6 @@ void rc_close(struct rc_dev *rdev)
mutex_unlock(&rdev->lock); mutex_unlock(&rdev->lock);
} }
} }
EXPORT_SYMBOL_GPL(rc_close);
static void ir_close(struct input_dev *idev) static void ir_close(struct input_dev *idev)
{ {
...@@ -941,23 +939,6 @@ struct rc_filter_attribute { ...@@ -941,23 +939,6 @@ struct rc_filter_attribute {
.mask = (_mask), \ .mask = (_mask), \
} }
static bool lirc_is_present(void)
{
#if defined(CONFIG_LIRC_MODULE)
struct module *lirc;
mutex_lock(&module_mutex);
lirc = find_module("lirc_dev");
mutex_unlock(&module_mutex);
return lirc ? true : false;
#elif defined(CONFIG_LIRC)
return true;
#else
return false;
#endif
}
/** /**
* show_protocols() - shows the current IR protocol(s) * show_protocols() - shows the current IR protocol(s)
* @device: the device descriptor * @device: the device descriptor
...@@ -1002,8 +983,10 @@ static ssize_t show_protocols(struct device *device, ...@@ -1002,8 +983,10 @@ static ssize_t show_protocols(struct device *device,
allowed &= ~proto_names[i].type; allowed &= ~proto_names[i].type;
} }
if (dev->driver_type == RC_DRIVER_IR_RAW && lirc_is_present()) #ifdef CONFIG_LIRC
if (dev->driver_type == RC_DRIVER_IR_RAW)
tmp += sprintf(tmp, "[lirc] "); tmp += sprintf(tmp, "[lirc] ");
#endif
if (tmp != buf) if (tmp != buf)
tmp--; tmp--;
...@@ -1759,8 +1742,7 @@ int rc_register_device(struct rc_dev *dev) ...@@ -1759,8 +1742,7 @@ int rc_register_device(struct rc_dev *dev)
dev->sysfs_groups[attr++] = &rc_dev_wakeup_filter_attr_grp; dev->sysfs_groups[attr++] = &rc_dev_wakeup_filter_attr_grp;
dev->sysfs_groups[attr++] = NULL; dev->sysfs_groups[attr++] = NULL;
if (dev->driver_type == RC_DRIVER_IR_RAW || if (dev->driver_type == RC_DRIVER_IR_RAW) {
dev->driver_type == RC_DRIVER_IR_RAW_TX) {
rc = ir_raw_event_prepare(dev); rc = ir_raw_event_prepare(dev);
if (rc < 0) if (rc < 0)
goto out_minor; goto out_minor;
...@@ -1787,19 +1769,28 @@ int rc_register_device(struct rc_dev *dev) ...@@ -1787,19 +1769,28 @@ int rc_register_device(struct rc_dev *dev)
goto out_dev; goto out_dev;
} }
if (dev->driver_type == RC_DRIVER_IR_RAW || /* Ensure that the lirc kfifo is setup before we start the thread */
dev->driver_type == RC_DRIVER_IR_RAW_TX) { if (dev->driver_type != RC_DRIVER_SCANCODE) {
rc = ir_raw_event_register(dev); rc = ir_lirc_register(dev);
if (rc < 0) if (rc < 0)
goto out_rx; goto out_rx;
} }
if (dev->driver_type == RC_DRIVER_IR_RAW) {
rc = ir_raw_event_register(dev);
if (rc < 0)
goto out_lirc;
}
IR_dprintk(1, "Registered rc%u (driver: %s)\n", IR_dprintk(1, "Registered rc%u (driver: %s)\n",
dev->minor, dev->minor,
dev->driver_name ? dev->driver_name : "unknown"); dev->driver_name ? dev->driver_name : "unknown");
return 0; return 0;
out_lirc:
if (dev->driver_type != RC_DRIVER_SCANCODE)
ir_lirc_unregister(dev);
out_rx: out_rx:
rc_free_rx_device(dev); rc_free_rx_device(dev);
out_dev: out_dev:
...@@ -1853,6 +1844,9 @@ void rc_unregister_device(struct rc_dev *dev) ...@@ -1853,6 +1844,9 @@ void rc_unregister_device(struct rc_dev *dev)
rc_free_rx_device(dev); rc_free_rx_device(dev);
if (dev->driver_type != RC_DRIVER_SCANCODE)
ir_lirc_unregister(dev);
device_del(&dev->dev); device_del(&dev->dev);
ida_simple_remove(&rc_ida, dev->minor); ida_simple_remove(&rc_ida, dev->minor);
...@@ -1875,6 +1869,13 @@ static int __init rc_core_init(void) ...@@ -1875,6 +1869,13 @@ static int __init rc_core_init(void)
return rc; return rc;
} }
rc = lirc_dev_init();
if (rc) {
pr_err("rc_core: unable to init lirc\n");
class_unregister(&rc_class);
return 0;
}
led_trigger_register_simple("rc-feedback", &led_feedback); led_trigger_register_simple("rc-feedback", &led_feedback);
rc_map_register(&empty_map); rc_map_register(&empty_map);
...@@ -1883,6 +1884,7 @@ static int __init rc_core_init(void) ...@@ -1883,6 +1884,7 @@ static int __init rc_core_init(void)
static void __exit rc_core_exit(void) static void __exit rc_core_exit(void)
{ {
lirc_dev_exit();
class_unregister(&rc_class); class_unregister(&rc_class);
led_trigger_unregister_simple(led_feedback); led_trigger_unregister_simple(led_feedback);
rc_map_unregister(&empty_map); rc_map_unregister(&empty_map);
......
...@@ -121,7 +121,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, ...@@ -121,7 +121,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
* Only used if @rbuf is NULL. * Only used if @rbuf is NULL.
* @chunk_size: Size of each FIFO buffer. * @chunk_size: Size of each FIFO buffer.
* Only used if @rbuf is NULL. * Only used if @rbuf is NULL.
* @data: private per-driver data
* @buf: if %NULL, lirc_dev will allocate and manage the buffer, * @buf: if %NULL, lirc_dev will allocate and manage the buffer,
* otherwise allocated by the caller which will * otherwise allocated by the caller which will
* have to write to the buffer by other means, like irq's * have to write to the buffer by other means, like irq's
...@@ -146,7 +145,6 @@ struct lirc_dev { ...@@ -146,7 +145,6 @@ struct lirc_dev {
struct lirc_buffer *buf; struct lirc_buffer *buf;
bool buf_internal; bool buf_internal;
void *data;
struct rc_dev *rdev; struct rc_dev *rdev;
const struct file_operations *fops; const struct file_operations *fops;
struct module *owner; struct module *owner;
...@@ -168,14 +166,6 @@ int lirc_register_device(struct lirc_dev *d); ...@@ -168,14 +166,6 @@ int lirc_register_device(struct lirc_dev *d);
void lirc_unregister_device(struct lirc_dev *d); void lirc_unregister_device(struct lirc_dev *d);
/* Must be called in the open fop before lirc_get_pdata() can be used */
void lirc_init_pdata(struct inode *inode, struct file *file);
/* Returns the private data stored in the lirc_dev
* associated with the given device file pointer.
*/
void *lirc_get_pdata(struct file *file);
/* default file operations /* default file operations
* used by drivers if they override only some operations * used by drivers if they override only some operations
*/ */
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/kfifo.h> #include <linux/kfifo.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <media/lirc_dev.h>
#include <media/rc-map.h> #include <media/rc-map.h>
extern int rc_core_debug; extern int rc_core_debug;
...@@ -115,6 +116,15 @@ enum rc_filter_type { ...@@ -115,6 +116,15 @@ enum rc_filter_type {
* @max_timeout: maximum timeout supported by device * @max_timeout: maximum timeout supported by device
* @rx_resolution : resolution (in ns) of input sampler * @rx_resolution : resolution (in ns) of input sampler
* @tx_resolution: resolution (in ns) of output sampler * @tx_resolution: resolution (in ns) of output sampler
* @lirc_dev: lirc char device
* @carrier_low: when setting the carrier range, first the low end must be
* set with an ioctl and then the high end with another ioctl
* @gap_start: time when gap starts
* @gap_duration: duration of initial gap
* @gap: true if we're in a gap
* @send_timeout_reports: report timeouts in lirc raw IR.
* @send_mode: lirc mode for sending, either LIRC_MODE_SCANCODE or
* LIRC_MODE_PULSE
* @change_protocol: allow changing the protocol used on hardware decoders * @change_protocol: allow changing the protocol used on hardware decoders
* @open: callback to allow drivers to enable polling/irq when IR input device * @open: callback to allow drivers to enable polling/irq when IR input device
* is opened. * is opened.
...@@ -174,6 +184,15 @@ struct rc_dev { ...@@ -174,6 +184,15 @@ struct rc_dev {
u32 max_timeout; u32 max_timeout;
u32 rx_resolution; u32 rx_resolution;
u32 tx_resolution; u32 tx_resolution;
#ifdef CONFIG_LIRC
struct lirc_dev *lirc_dev;
int carrier_low;
ktime_t gap_start;
u64 gap_duration;
bool gap;
bool send_timeout_reports;
u8 send_mode;
#endif
int (*change_protocol)(struct rc_dev *dev, u64 *rc_proto); int (*change_protocol)(struct rc_dev *dev, u64 *rc_proto);
int (*open)(struct rc_dev *dev); int (*open)(struct rc_dev *dev);
void (*close)(struct rc_dev *dev); void (*close)(struct rc_dev *dev);
...@@ -248,20 +267,6 @@ int devm_rc_register_device(struct device *parent, struct rc_dev *dev); ...@@ -248,20 +267,6 @@ int devm_rc_register_device(struct device *parent, struct rc_dev *dev);
*/ */
void rc_unregister_device(struct rc_dev *dev); void rc_unregister_device(struct rc_dev *dev);
/**
* rc_open - Opens a RC device
*
* @rdev: pointer to struct rc_dev.
*/
int rc_open(struct rc_dev *rdev);
/**
* rc_close - Closes a RC device
*
* @rdev: pointer to struct rc_dev.
*/
void rc_close(struct rc_dev *rdev);
void rc_repeat(struct rc_dev *dev); void rc_repeat(struct rc_dev *dev);
void rc_keydown(struct rc_dev *dev, enum rc_proto protocol, u32 scancode, void rc_keydown(struct rc_dev *dev, enum rc_proto protocol, u32 scancode,
u8 toggle); u8 toggle);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment