diff options
Diffstat (limited to 'drivers/media/rc/lirc_dev.c')
| -rw-r--r-- | drivers/media/rc/lirc_dev.c | 70 |
1 files changed, 44 insertions, 26 deletions
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index fd237ab120b..dc5cbffcd5a 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -35,10 +35,11 @@ #include <linux/device.h> #include <linux/cdev.h> +#include <media/rc-core.h> #include <media/lirc.h> #include <media/lirc_dev.h> -static int debug; +static bool debug; #define IRCTL_DEV_NAME "BaseRemoteCtl" #define NOPLUG -1 @@ -55,6 +56,8 @@ struct irctl { struct lirc_buffer *buf; unsigned int chunk_size; + struct cdev *cdev; + struct task_struct *task; long jiffies_to_wait; }; @@ -62,7 +65,6 @@ struct irctl { static DEFINE_MUTEX(lirc_dev_lock); static struct irctl *irctls[MAX_IRCTL_DEVICES]; -static struct cdev cdevs[MAX_IRCTL_DEVICES]; /* Only used for sysfs but defined to void otherwise */ static struct class *lirc_class; @@ -151,7 +153,7 @@ static int lirc_thread(void *irctl) } -static struct file_operations lirc_dev_fops = { +static const struct file_operations lirc_dev_fops = { .owner = THIS_MODULE, .read = lirc_dev_fop_read, .write = lirc_dev_fop_write, @@ -167,9 +169,13 @@ static struct file_operations lirc_dev_fops = { static int lirc_cdev_add(struct irctl *ir) { - int retval; + int retval = -ENOMEM; struct lirc_driver *d = &ir->d; - struct cdev *cdev = &cdevs[d->minor]; + struct cdev *cdev; + + cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); + if (!cdev) + goto err_out; if (d->fops) { cdev_init(cdev, d->fops); @@ -180,12 +186,20 @@ static int lirc_cdev_add(struct irctl *ir) } retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor); if (retval) - return retval; + goto err_out; retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); - if (retval) + if (retval) { kobject_put(&cdev->kobj); + goto err_out; + } + ir->cdev = cdev; + + return 0; + +err_out: + kfree(cdev); return retval; } @@ -214,7 +228,7 @@ int lirc_register_driver(struct lirc_driver *d) if (MAX_IRCTL_DEVICES <= d->minor) { dev_err(d->dev, "lirc_dev: lirc_register_driver: " "\"minor\" must be between 0 and %d (%d)!\n", - MAX_IRCTL_DEVICES-1, d->minor); + MAX_IRCTL_DEVICES - 1, d->minor); err = -EBADRQC; goto out; } @@ -369,7 +383,7 @@ int lirc_unregister_driver(int minor) if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between " - "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1); + "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES - 1); return -EBADRQC; } @@ -380,7 +394,7 @@ int lirc_unregister_driver(int minor) return -ENOENT; } - cdev = &cdevs[minor]; + cdev = ir->cdev; mutex_lock(&lirc_dev_lock); @@ -410,6 +424,7 @@ int lirc_unregister_driver(int minor) } else { lirc_irctl_cleanup(ir); cdev_del(cdev); + kfree(cdev); kfree(ir); irctls[minor] = NULL; } @@ -453,7 +468,13 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) goto error; } - cdev = &cdevs[iminor(inode)]; + if (ir->d.rdev) { + retval = rc_open(ir->d.rdev); + if (retval) + goto error; + } + + cdev = ir->cdev; if (try_module_get(cdev->owner)) { ir->open++; retval = ir->d.set_use_inc(ir->d.data); @@ -484,17 +505,22 @@ EXPORT_SYMBOL(lirc_dev_fop_open); int lirc_dev_fop_close(struct inode *inode, struct file *file) { struct irctl *ir = irctls[iminor(inode)]; - struct cdev *cdev = &cdevs[iminor(inode)]; + struct cdev *cdev; if (!ir) { printk(KERN_ERR "%s: called with invalid irctl\n", __func__); return -EINVAL; } + cdev = ir->cdev; + dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor); WARN_ON(mutex_lock_killable(&lirc_dev_lock)); + if (ir->d.rdev) + rc_close(ir->d.rdev); + ir->open--; if (ir->attached) { ir->d.set_use_dec(ir->d.data); @@ -503,6 +529,7 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file) lirc_irctl_cleanup(ir); cdev_del(cdev); irctls[ir->d.minor] = NULL; + kfree(cdev); kfree(ir); } @@ -514,7 +541,7 @@ EXPORT_SYMBOL(lirc_dev_fop_close); unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) { - struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; + struct irctl *ir = irctls[iminor(file_inode(file))]; unsigned int ret; if (!ir) { @@ -548,7 +575,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { __u32 mode; int result = 0; - struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; + struct irctl *ir = irctls[iminor(file_inode(file))]; if (!ir) { printk(KERN_ERR "lirc_dev: %s: no irctl found!\n", __func__); @@ -633,7 +660,7 @@ ssize_t lirc_dev_fop_read(struct file *file, size_t length, loff_t *ppos) { - struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; + struct irctl *ir = irctls[iminor(file_inode(file))]; unsigned char *buf; int ret = 0, written = 0; DECLARE_WAITQUEUE(wait, current); @@ -735,16 +762,7 @@ EXPORT_SYMBOL(lirc_dev_fop_read); void *lirc_get_pdata(struct file *file) { - void *data = NULL; - - if (file && file->f_dentry && file->f_dentry->d_inode && - file->f_dentry->d_inode->i_rdev) { - struct irctl *ir; - ir = irctls[iminor(file->f_dentry->d_inode)]; - data = ir->d.data; - } - - return data; + return irctls[iminor(file_inode(file))]->d.data; } EXPORT_SYMBOL(lirc_get_pdata); @@ -752,7 +770,7 @@ EXPORT_SYMBOL(lirc_get_pdata); ssize_t lirc_dev_fop_write(struct file *file, const char __user *buffer, size_t length, loff_t *ppos) { - struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; + struct irctl *ir = irctls[iminor(file_inode(file))]; if (!ir) { printk(KERN_ERR "%s: called with invalid irctl\n", __func__); |
