The lirc bridge exists as a raw decoder. We would like to make the bridge to also work for scancode drivers in further commits, so it cannot be a raw decoder. 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. Signed-off-by: Sean Young <sean@xxxxxxxx> --- drivers/media/rc/Kconfig | 15 +++-- drivers/media/rc/Makefile | 6 +- drivers/media/rc/ir-lirc-codec.c | 117 ++++++++++++--------------------------- drivers/media/rc/lirc_dev.c | 18 +----- drivers/media/rc/rc-core-priv.h | 38 ++++++------- drivers/media/rc/rc-ir-raw.c | 4 +- drivers/media/rc/rc-main.c | 21 +++++-- include/media/rc-core.h | 7 +++ 8 files changed, 92 insertions(+), 134 deletions(-) diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index ddfab25..efdd6f7 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -6,14 +6,8 @@ config 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 interface driver" depends on RC_CORE ---help--- @@ -24,7 +18,7 @@ config LIRC encoding for IR transmitting (aka "blasting"). config IR_LIRC_CODEC - tristate "Enable IR to LIRC bridge" + bool "Enable IR to LIRC bridge" depends on RC_CORE depends on LIRC default y @@ -33,7 +27,12 @@ config IR_LIRC_CODEC Enable this option to pass raw IR to and from userspace via the LIRC interface. +menuconfig RC_DECODERS + bool "Remote controller decoders" + depends on RC_CORE + default y +if RC_DECODERS config IR_NEC_DECODER tristate "Enable IR raw decoder for the NEC protocol" depends on RC_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 379a5c0..c8e7b38 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -1,9 +1,10 @@ -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 +rc-core-$(CONFIG_IR_LIRC_CODEC) += 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 @@ -12,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 diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index 17fd956..475f6af 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -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> @@ -30,15 +29,12 @@ * * 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) +int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) { - struct lirc_codec *lirc = &dev->raw->lirc; + struct lirc_driver *lirc = dev->lirc; int sample; - if (!(dev->enabled_protocols & RC_BIT_LIRC)) - return 0; - - if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf) + if (!lirc || !lirc->rbuf) return -EINVAL; /* Packet start */ @@ -59,14 +55,14 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) /* Packet end */ } else if (ev.timeout) { - if (lirc->gap) + if (dev->gap) return 0; - 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) + if (!dev->send_timeout_reports) return 0; sample = LIRC_TIMEOUT(ev.duration / 1000); @@ -75,21 +71,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.drv->rbuf, + gap_sample = LIRC_SPACE(dev->gap_duration); + lirc_buffer_write(lirc->rbuf, (unsigned char *) &gap_sample); - lirc->gap = false; + dev->gap = false; } sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) : @@ -98,9 +94,9 @@ 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.drv->rbuf, + lirc_buffer_write(lirc->rbuf, (unsigned char *) &sample); - wake_up(&dev->raw->lirc.drv->rbuf->wait_poll); + wake_up(&lirc->rbuf->wait_poll); return 0; } @@ -108,7 +104,6 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) 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; unsigned int *txbuf; /* buffer with values to transmit */ ssize_t ret = -EINVAL; @@ -120,8 +115,8 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, start = ktime_get(); - lirc = lirc_get_pdata(file); - if (!lirc) + dev = lirc_get_pdata(file); + if (!dev || !dev->lirc) return -EFAULT; if (n < sizeof(unsigned) || n % sizeof(unsigned)) @@ -135,12 +130,6 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, if (IS_ERR(txbuf)) return PTR_ERR(txbuf); - dev = lirc->dev; - if (!dev) { - ret = -EFAULT; - goto out; - } - if (!dev->tx_ir) { ret = -ENOSYS; goto out; @@ -183,18 +172,13 @@ out: static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { - struct lirc_codec *lirc; struct rc_dev *dev; 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) + dev = lirc_get_pdata(filep); + if (!dev || !dev->lirc) return -EFAULT; if (_IOC_DIR(cmd) & _IOC_WRITE) { @@ -253,14 +237,14 @@ 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: if (val <= 0) return -EINVAL; - dev->raw->lirc.carrier_low = val; + dev->carrier_low = val; return 0; case LIRC_GET_REC_RESOLUTION: @@ -306,7 +290,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, break; case LIRC_SET_REC_TIMEOUT_REPORTS: - lirc->send_timeout_reports = !!val; + dev->send_timeout_reports = !!val; break; default: @@ -343,7 +327,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_driver *drv; struct lirc_buffer *rbuf; @@ -390,7 +374,7 @@ static int ir_lirc_register(struct rc_dev *dev) dev->driver_name); drv->minor = -1; drv->features = features; - drv->data = &dev->raw->lirc; + drv->data = dev; drv->rbuf = rbuf; drv->set_use_inc = &ir_lirc_open; drv->set_use_dec = &ir_lirc_close; @@ -406,8 +390,7 @@ static int ir_lirc_register(struct rc_dev *dev) goto lirc_register_failed; } - dev->raw->lirc.drv = drv; - dev->raw->lirc.dev = dev; + dev->lirc = drv; return 0; lirc_register_failed: @@ -419,41 +402,11 @@ rbuf_alloc_failed: 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_driver(lirc->drv->minor); - lirc_buffer_free(lirc->drv->rbuf); - kfree(lirc->drv); - - return 0; -} - -static struct ir_raw_handler lirc_handler = { - .protocols = RC_BIT_LIRC, - .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) -{ - ir_raw_handler_unregister(&lirc_handler); + if (dev->lirc) { + lirc_unregister_driver(dev->lirc->minor); + lirc_buffer_free(dev->lirc->rbuf); + kfree(dev->lirc); + } } - -module_init(ir_lirc_codec_init); -module_exit(ir_lirc_codec_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jarod Wilson <jarod@xxxxxxxxxx>"); -MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); -MODULE_DESCRIPTION("LIRC IR handler bridge"); diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 4de0e85..44a61e81 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -39,8 +39,6 @@ #include <media/lirc.h> #include <media/lirc_dev.h> -static bool debug; - #define IRCTL_DEV_NAME "BaseRemoteCtl" #define NOPLUG -1 #define LOGHEAD "lirc_dev (%s[%d]): " @@ -785,8 +783,7 @@ ssize_t lirc_dev_fop_write(struct file *file, const char __user *buffer, } EXPORT_SYMBOL(lirc_dev_fop_write); - -static int __init lirc_dev_init(void) +int __init lirc_dev_init(void) { int retval; @@ -813,21 +810,10 @@ error: return retval; } - - -static void __exit lirc_dev_exit(void) +void __exit lirc_dev_exit(void) { class_destroy(lirc_class); unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES); printk(KERN_INFO "lirc_dev: 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"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index b68d4f76..732479d 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -26,7 +26,7 @@ struct ir_raw_handler { u64 protocols; /* which are handled by this handler */ int (*decode)(struct rc_dev *dev, struct ir_raw_event event); - /* 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_unregister)(struct rc_dev *dev); }; @@ -99,17 +99,6 @@ struct ir_raw_event_ctrl { unsigned count; unsigned wanted_bits; } mce_kbd; - struct lirc_codec { - struct rc_dev *dev; - struct lirc_driver *drv; - int carrier_low; - - ktime_t gap_start; - u64 gap_duration; - bool gap; - bool send_timeout_reports; - - } lirc; struct xmp_dec { int state; unsigned count; @@ -223,13 +212,6 @@ static inline void load_sharp_decode(void) { } static inline void load_mce_kbd_decode(void) { } #endif -/* from ir-lirc-codec.c */ -#ifdef CONFIG_IR_LIRC_CODEC_MODULE -#define load_lirc_codec() request_module_nowait("ir-lirc-codec") -#else -static inline void load_lirc_codec(void) { } -#endif - /* from ir-xmp-decoder.c */ #ifdef CONFIG_IR_XMP_DECODER_MODULE #define load_xmp_decode() request_module_nowait("ir-xmp-decoder") @@ -237,5 +219,23 @@ static inline void load_lirc_codec(void) { } static inline void load_xmp_decode(void) { } #endif +#ifdef CONFIG_IR_LIRC_CODEC +void ir_lirc_unregister(struct rc_dev *dev); +int ir_lirc_register(struct rc_dev *dev); +int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev); +#else +static inline void ir_lirc_unregister(struct rc_dev *dev) {} +static inline int ir_lirc_register(struct rc_dev *dev) { return 0; } +static inline int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) + { return 0; } +#endif + +#ifdef CONFIG_LIRC +int __init lirc_dev_init(void); +void __exit lirc_dev_exit(void); +#else +int __init lirc_dev_init(void) { return 0; } +void __exit lirc_dev_exit(void) {} +#endif #endif /* _RC_CORE_PRIV */ diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c index b732ac6..d298be7 100644 --- a/drivers/media/rc/rc-ir-raw.c +++ b/drivers/media/rc/rc-ir-raw.c @@ -57,6 +57,9 @@ static int ir_raw_event_thread(void *data) retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); spin_unlock_irq(&raw->lock); + if (raw->dev->lirc) + ir_lirc_decode(raw->dev, ev); + mutex_lock(&ir_raw_handler_lock); list_for_each_entry(handler, &ir_raw_handler_list, list) handler->decode(raw->dev, ev); @@ -360,7 +363,6 @@ void ir_raw_init(void) load_sanyo_decode(); load_sharp_decode(); load_mce_kbd_decode(); - load_lirc_codec(); load_xmp_decode(); /* If needed, we may later add some init code. In this case, diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index f8c5e47..128909c 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -732,7 +732,6 @@ int rc_open(struct rc_dev *rdev) return rval; } -EXPORT_SYMBOL_GPL(rc_open); static int ir_open(struct input_dev *idev) { @@ -752,7 +751,6 @@ void rc_close(struct rc_dev *rdev) mutex_unlock(&rdev->lock); } } -EXPORT_SYMBOL_GPL(rc_close); static void ir_close(struct input_dev *idev) { @@ -1419,15 +1417,17 @@ int rc_register_device(struct rc_dev *dev) mutex_lock(&dev->lock); if (rc < 0) goto out_input; + + rc = ir_lirc_register(dev); + if (rc < 0) + goto out_raw; } if (dev->change_protocol) { u64 rc_type = (1ll << rc_map->rc_type); - if (dev->driver_type == RC_DRIVER_IR_RAW) - rc_type |= RC_BIT_LIRC; rc = dev->change_protocol(dev, &rc_type); if (rc < 0) - goto out_raw; + goto out_lirc; dev->enabled_protocols = rc_type; } @@ -1441,6 +1441,8 @@ int rc_register_device(struct rc_dev *dev) return 0; +out_lirc: + ir_lirc_unregister(dev); out_raw: if (dev->driver_type == RC_DRIVER_IR_RAW) ir_raw_event_unregister(dev); @@ -1470,6 +1472,8 @@ void rc_unregister_device(struct rc_dev *dev) if (dev->driver_type == RC_DRIVER_IR_RAW) ir_raw_event_unregister(dev); + ir_lirc_unregister(dev); + /* Freeing the table should also call the stop callback */ ir_free_table(&dev->rc_map); IR_dprintk(1, "Freed keycode table\n"); @@ -1495,6 +1499,12 @@ static int __init rc_core_init(void) printk(KERN_ERR "rc_core: unable to register rc class\n"); return rc; } + rc = lirc_dev_init(); + if (rc) { + class_unregister(&rc_class); + printk(KERN_ERR "rc_core: unable to register lirc class\n"); + return rc; + } led_trigger_register_simple("rc-feedback", &led_feedback); rc_map_register(&empty_map); @@ -1507,6 +1517,7 @@ static void __exit rc_core_exit(void) class_unregister(&rc_class); led_trigger_unregister_simple(led_feedback); rc_map_unregister(&empty_map); + lirc_dev_exit(); } subsys_initcall(rc_core_init); diff --git a/include/media/rc-core.h b/include/media/rc-core.h index 2c7fbca..e3f217c 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -156,6 +156,13 @@ struct rc_dev { u32 max_timeout; u32 rx_resolution; u32 tx_resolution; + /* lirc state */ + struct lirc_driver *lirc; + int carrier_low; + ktime_t gap_start; + u64 gap_duration; + bool gap; + bool send_timeout_reports; int (*change_protocol)(struct rc_dev *dev, u64 *rc_type); int (*change_wakeup_protocol)(struct rc_dev *dev, u64 *rc_type); int (*open)(struct rc_dev *dev); -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html