From de226ec8a6ac10e65fcc689a28761c966986e6a6 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:31:19 -0300 Subject: [media] media: lirc_dev: clarify error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If an error is generated, it is more logical to error out ASAP. Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 9080e39ea391..5e3c4779d866 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -286,7 +286,7 @@ EXPORT_SYMBOL(lirc_unregister_driver); int lirc_dev_fop_open(struct inode *inode, struct file *file) { struct irctl *ir; - int retval = 0; + int retval; if (iminor(inode) >= MAX_IRCTL_DEVICES) { pr_err("open result for %d is -ENODEV\n", iminor(inode)); @@ -327,9 +327,11 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) ir->open++; -error: nonseekable_open(inode, file); + return 0; + +error: return retval; } EXPORT_SYMBOL(lirc_dev_fop_open); -- cgit v1.2.3 From c3c6dd750e0b8dcee0306b9c5a45708922debbbe Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:31:24 -0300 Subject: [media] media: lirc_dev: remove support for manually specifying minor number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All users of lirc_register_driver() uses dynamic minor allocation, therefore we can remove the ability to explicitly request a given number. This changes the function prototype of lirc_unregister_driver() to also take a struct lirc_driver pointer as the sole argument. Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ir-lirc-codec.c | 9 ++--- drivers/media/rc/lirc_dev.c | 68 +++++++++------------------------ drivers/staging/media/lirc/lirc_zilog.c | 14 +++---- include/media/lirc_dev.h | 20 +++++----- 4 files changed, 34 insertions(+), 77 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index d2223c04e9ad..58bff7a75d5b 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -382,7 +382,6 @@ static int ir_lirc_register(struct rc_dev *dev) snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", dev->driver_name); - drv->minor = -1; drv->features = features; drv->data = &dev->raw->lirc; drv->rbuf = NULL; @@ -394,11 +393,9 @@ static int ir_lirc_register(struct rc_dev *dev) drv->rdev = dev; drv->owner = THIS_MODULE; - drv->minor = lirc_register_driver(drv); - if (drv->minor < 0) { - rc = -ENODEV; + rc = lirc_register_driver(drv); + if (rc < 0) goto out; - } dev->raw->lirc.drv = drv; dev->raw->lirc.dev = dev; @@ -413,7 +410,7 @@ static int ir_lirc_unregister(struct rc_dev *dev) { struct lirc_codec *lirc = &dev->raw->lirc; - lirc_unregister_driver(lirc->drv->minor); + lirc_unregister_driver(lirc->drv); kfree(lirc->drv); lirc->drv = NULL; diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 5e3c4779d866..f1d8c1ef072e 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -29,7 +29,6 @@ #include #include -#define NOPLUG -1 #define LOGHEAD "lirc_dev (%s[%d]): " static dev_t lirc_base_dev; @@ -114,7 +113,7 @@ out: int lirc_register_driver(struct lirc_driver *d) { struct irctl *ir; - int minor; + unsigned int minor; int err; if (!d) { @@ -132,12 +131,6 @@ int lirc_register_driver(struct lirc_driver *d) return -EINVAL; } - if (d->minor >= MAX_IRCTL_DEVICES) { - dev_err(d->dev, "minor must be between 0 and %d!\n", - MAX_IRCTL_DEVICES - 1); - return -EBADRQC; - } - if (d->code_length < 1 || d->code_length > (BUFLEN * 8)) { dev_err(d->dev, "code length must be less than %d bits\n", BUFLEN * 8); @@ -152,21 +145,14 @@ int lirc_register_driver(struct lirc_driver *d) mutex_lock(&lirc_dev_lock); - minor = d->minor; + /* find first free slot for driver */ + for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++) + if (!irctls[minor]) + break; - if (minor < 0) { - /* find first free slot for driver */ - for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++) - if (!irctls[minor]) - break; - if (minor == MAX_IRCTL_DEVICES) { - dev_err(d->dev, "no free slots for drivers!\n"); - err = -ENOMEM; - goto out_lock; - } - } else if (irctls[minor]) { - dev_err(d->dev, "minor (%d) just registered!\n", minor); - err = -EBUSY; + if (minor == MAX_IRCTL_DEVICES) { + dev_err(d->dev, "no free slots for drivers!\n"); + err = -ENOMEM; goto out_lock; } @@ -178,6 +164,7 @@ int lirc_register_driver(struct lirc_driver *d) mutex_init(&ir->irctl_lock); irctls[minor] = ir; + d->irctl = ir; d->minor = minor; /* some safety check 8-) */ @@ -225,7 +212,7 @@ int lirc_register_driver(struct lirc_driver *d) dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n", ir->d.name, ir->d.minor); - return minor; + return 0; out_cdev: cdev_del(&ir->cdev); @@ -238,38 +225,24 @@ out_lock: } EXPORT_SYMBOL(lirc_register_driver); -int lirc_unregister_driver(int minor) +void lirc_unregister_driver(struct lirc_driver *d) { struct irctl *ir; - if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { - pr_err("minor (%d) must be between 0 and %d!\n", - minor, MAX_IRCTL_DEVICES - 1); - return -EBADRQC; - } + if (!d || !d->irctl) + return; - ir = irctls[minor]; - if (!ir) { - pr_err("failed to get irctl\n"); - return -ENOENT; - } + ir = d->irctl; mutex_lock(&lirc_dev_lock); - if (ir->d.minor != minor) { - dev_err(ir->d.dev, "lirc_dev: minor %d device not registered\n", - minor); - mutex_unlock(&lirc_dev_lock); - return -ENOENT; - } - dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n", - ir->d.name, ir->d.minor); + d->name, d->minor); ir->attached = 0; if (ir->open) { dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n", - ir->d.name, ir->d.minor); + d->name, d->minor); wake_up_interruptible(&ir->buf->wait_poll); } @@ -278,8 +251,6 @@ int lirc_unregister_driver(int minor) device_del(&ir->dev); cdev_del(&ir->cdev); put_device(&ir->dev); - - return 0; } EXPORT_SYMBOL(lirc_unregister_driver); @@ -306,11 +277,6 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor); - if (ir->d.minor == NOPLUG) { - retval = -ENODEV; - goto error; - } - if (ir->open) { retval = -EBUSY; goto error; @@ -403,7 +369,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n", ir->d.name, ir->d.minor, cmd); - if (ir->d.minor == NOPLUG || !ir->attached) { + if (!ir->attached) { dev_err(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n", ir->d.name, ir->d.minor); return -ENODEV; diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index 71af13bd0ebd..efcbfef1980e 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -183,10 +183,7 @@ static void release_ir_device(struct kref *ref) * ir->open_count == 0 - happens on final close() * ir_lock, tx_ref_lock, rx_ref_lock, all released */ - if (ir->l.minor >= 0) { - lirc_unregister_driver(ir->l.minor); - ir->l.minor = -1; - } + lirc_unregister_driver(&ir->l); if (kfifo_initialized(&ir->rbuf.fifo)) lirc_buffer_free(&ir->rbuf); @@ -1385,7 +1382,6 @@ static const struct file_operations lirc_fops = { static struct lirc_driver lirc_template = { .name = "lirc_zilog", - .minor = -1, .code_length = 13, .buffer_size = BUFLEN / 2, .chunk_size = 2, @@ -1599,14 +1595,14 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) } /* register with lirc */ - ir->l.minor = lirc_register_driver(&ir->l); - if (ir->l.minor < 0) { + ret = lirc_register_driver(&ir->l); + if (ret < 0) { dev_err(tx->ir->l.dev, "%s: lirc_register_driver() failed: %i\n", - __func__, ir->l.minor); - ret = -EBADRQC; + __func__, ret); goto out_put_xx; } + dev_info(ir->l.dev, "IR unit on %s (i2c-%d) registered as lirc%d and ready\n", adap->name, adap->nr, ir->l.minor); diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 86d15a9b6c01..1bb9890744fa 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -116,10 +116,8 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, * * @name: this string will be used for logs * - * @minor: indicates minor device (/dev/lirc) number for - * registered driver if caller fills it with negative - * value, then the first free minor number will be used - * (if available). + * @minor: the minor device (/dev/lircX) number for a registered + * driver. * * @code_length: length of the remote control key code expressed in bits. * @@ -157,10 +155,12 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, * device. * * @owner: the module owning this struct + * + * @irctl: the struct irctl for this LIRC device. */ struct lirc_driver { char name[40]; - int minor; + unsigned int minor; __u32 code_length; unsigned int buffer_size; /* in chunks holding one code each */ __u32 features; @@ -175,19 +175,17 @@ struct lirc_driver { const struct file_operations *fops; struct device *dev; struct module *owner; + struct irctl *irctl; }; /* following functions can be called ONLY from user context * - * returns negative value on error or minor number - * of the registered device if success + * returns negative value on error or zero * contents of the structure pointed by p is copied */ -extern int lirc_register_driver(struct lirc_driver *d); +int lirc_register_driver(struct lirc_driver *d); -/* returns negative value on error or 0 if success -*/ -extern int lirc_unregister_driver(int minor); +void lirc_unregister_driver(struct lirc_driver *d); /* Returns the private data stored in the lirc_driver * associated with the given device file pointer. -- cgit v1.2.3 From 0510d81081498eae2a8bf9d116cc03492fab5894 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:31:35 -0300 Subject: [media] media: lirc_dev: use cdev_device_add() helper function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace calls to cdev_add() and device_add() with the cdev_device_add() helper function. Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index f1d8c1ef072e..057983b8ec53 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -193,17 +193,11 @@ int lirc_register_driver(struct lirc_driver *d) cdev_init(&ir->cdev, d->fops); ir->cdev.owner = ir->d.owner; - ir->cdev.kobj.parent = &ir->dev.kobj; - - err = cdev_add(&ir->cdev, ir->dev.devt, 1); - if (err) - goto out_free_dev; - ir->attached = 1; - err = device_add(&ir->dev); + err = cdev_device_add(&ir->cdev, &ir->dev); if (err) - goto out_cdev; + goto out_dev; mutex_unlock(&lirc_dev_lock); @@ -214,9 +208,7 @@ int lirc_register_driver(struct lirc_driver *d) return 0; -out_cdev: - cdev_del(&ir->cdev); -out_free_dev: +out_dev: put_device(&ir->dev); out_lock: mutex_unlock(&lirc_dev_lock); @@ -248,8 +240,7 @@ void lirc_unregister_driver(struct lirc_driver *d) mutex_unlock(&lirc_dev_lock); - device_del(&ir->dev); - cdev_del(&ir->cdev); + cdev_device_del(&ir->cdev, &ir->dev); put_device(&ir->dev); } EXPORT_SYMBOL(lirc_unregister_driver); -- cgit v1.2.3 From 615cd3fe6cccb950b46728120009a1805cce908e Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:31:40 -0300 Subject: [media] media: lirc_dev: make better use of file->private_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By making better use of file->private_data in lirc_dev we can avoid digging around in the irctls[] array, thereby simplifying the code. External drivers need to use lirc_get_pdata() instead of mucking around in file->private_data. The newly introduced lirc_init_pdata() function isn't very elegant, but it's a stopgap measure which can be removed once lirc_zilog is converted to rc-core. Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 70 ++++++++++----------------------- drivers/staging/media/lirc/lirc_zilog.c | 53 +++++-------------------- include/media/lirc_dev.h | 3 ++ 3 files changed, 33 insertions(+), 93 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 057983b8ec53..ffa203eb2045 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -247,36 +247,18 @@ EXPORT_SYMBOL(lirc_unregister_driver); int lirc_dev_fop_open(struct inode *inode, struct file *file) { - struct irctl *ir; + struct irctl *ir = container_of(inode->i_cdev, struct irctl, cdev); int retval; - if (iminor(inode) >= MAX_IRCTL_DEVICES) { - pr_err("open result for %d is -ENODEV\n", iminor(inode)); - return -ENODEV; - } - - if (mutex_lock_interruptible(&lirc_dev_lock)) - return -ERESTARTSYS; - - ir = irctls[iminor(inode)]; - mutex_unlock(&lirc_dev_lock); - - if (!ir) { - retval = -ENODEV; - goto error; - } - dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor); - if (ir->open) { - retval = -EBUSY; - goto error; - } + if (ir->open) + return -EBUSY; if (ir->d.rdev) { retval = rc_open(ir->d.rdev); if (retval) - goto error; + return retval; } if (ir->buf) @@ -284,25 +266,18 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) ir->open++; + lirc_init_pdata(inode, file); nonseekable_open(inode, file); return 0; - -error: - return retval; } EXPORT_SYMBOL(lirc_dev_fop_open); int lirc_dev_fop_close(struct inode *inode, struct file *file) { - struct irctl *ir = irctls[iminor(inode)]; + struct irctl *ir = file->private_data; int ret; - if (!ir) { - pr_err("called with invalid irctl\n"); - return -EINVAL; - } - ret = mutex_lock_killable(&lirc_dev_lock); WARN_ON(ret); @@ -318,14 +293,9 @@ EXPORT_SYMBOL(lirc_dev_fop_close); unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) { - struct irctl *ir = irctls[iminor(file_inode(file))]; + struct irctl *ir = file->private_data; unsigned int ret; - if (!ir) { - pr_err("called with invalid irctl\n"); - return POLLERR; - } - if (!ir->attached) return POLLHUP | POLLERR; @@ -348,14 +318,9 @@ EXPORT_SYMBOL(lirc_dev_fop_poll); long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + struct irctl *ir = file->private_data; __u32 mode; int result = 0; - struct irctl *ir = irctls[iminor(file_inode(file))]; - - if (!ir) { - pr_err("no irctl found!\n"); - return -ENODEV; - } dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n", ir->d.name, ir->d.minor, cmd); @@ -432,16 +397,11 @@ ssize_t lirc_dev_fop_read(struct file *file, size_t length, loff_t *ppos) { - struct irctl *ir = irctls[iminor(file_inode(file))]; + struct irctl *ir = file->private_data; unsigned char *buf; int ret = 0, written = 0; DECLARE_WAITQUEUE(wait, current); - if (!ir) { - pr_err("called with invalid irctl\n"); - return -ENODEV; - } - if (!LIRC_CAN_REC(ir->d.features)) return -EINVAL; @@ -532,9 +492,19 @@ out_unlocked: } EXPORT_SYMBOL(lirc_dev_fop_read); +void lirc_init_pdata(struct inode *inode, struct file *file) +{ + struct irctl *ir = container_of(inode->i_cdev, struct irctl, cdev); + + file->private_data = ir; +} +EXPORT_SYMBOL(lirc_init_pdata); + void *lirc_get_pdata(struct file *file) { - return irctls[iminor(file_inode(file))]->d.data; + struct irctl *ir = file->private_data; + + return ir->d.data; } EXPORT_SYMBOL(lirc_get_pdata); diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index efcbfef1980e..c4a4c2f93ae8 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -879,7 +879,7 @@ out: static ssize_t read(struct file *filep, char __user *outbuf, size_t n, loff_t *ppos) { - struct IR *ir = filep->private_data; + struct IR *ir = lirc_get_pdata(filep); struct IR_rx *rx; struct lirc_buffer *rbuf = ir->l.rbuf; int ret = 0, written = 0, retries = 0; @@ -1089,7 +1089,7 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key) static ssize_t write(struct file *filep, const char __user *buf, size_t n, loff_t *ppos) { - struct IR *ir = filep->private_data; + struct IR *ir = lirc_get_pdata(filep); struct IR_tx *tx; size_t i; int failures = 0; @@ -1197,7 +1197,7 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n, /* copied from lirc_dev */ static unsigned int poll(struct file *filep, poll_table *wait) { - struct IR *ir = filep->private_data; + struct IR *ir = lirc_get_pdata(filep); struct IR_rx *rx; struct lirc_buffer *rbuf = ir->l.rbuf; unsigned int ret; @@ -1230,7 +1230,7 @@ static unsigned int poll(struct file *filep, poll_table *wait) static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { - struct IR *ir = filep->private_data; + struct IR *ir = lirc_get_pdata(filep); unsigned long __user *uptr = (unsigned long __user *)arg; int result; unsigned long mode, features; @@ -1280,46 +1280,18 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) return result; } -static struct IR *get_ir_device_by_minor(unsigned int minor) -{ - struct IR *ir; - struct IR *ret = NULL; - - mutex_lock(&ir_devices_lock); - - if (!list_empty(&ir_devices_list)) { - list_for_each_entry(ir, &ir_devices_list, list) { - if (ir->l.minor == minor) { - ret = get_ir_device(ir, true); - break; - } - } - } - - mutex_unlock(&ir_devices_lock); - return ret; -} - /* - * Open the IR device. Get hold of our IR structure and - * stash it in private_data for the file + * Open the IR device. */ static int open(struct inode *node, struct file *filep) { struct IR *ir; - unsigned int minor = MINOR(node->i_rdev); - - /* find our IR struct */ - ir = get_ir_device_by_minor(minor); - if (!ir) - return -ENODEV; + lirc_init_pdata(node, filep); + ir = lirc_get_pdata(filep); atomic_inc(&ir->open_count); - /* stash our IR struct */ - filep->private_data = ir; - nonseekable_open(node, filep); return 0; } @@ -1327,14 +1299,7 @@ static int open(struct inode *node, struct file *filep) /* Close the IR device */ static int close(struct inode *node, struct file *filep) { - /* find our IR struct */ - struct IR *ir = filep->private_data; - - if (!ir) { - pr_err("ir: %s: no private_data attached to the file!\n", - __func__); - return -ENODEV; - } + struct IR *ir = lirc_get_pdata(filep); atomic_dec(&ir->open_count); @@ -1489,6 +1454,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) */ ir->l.rbuf = &ir->rbuf; ir->l.dev = &adap->dev; + /* This will be returned by lirc_get_pdata() */ + ir->l.data = ir; ret = lirc_buffer_init(ir->l.rbuf, ir->l.chunk_size, ir->l.buffer_size); if (ret) diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 1bb9890744fa..d07a53232ffc 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -187,6 +187,9 @@ int lirc_register_driver(struct lirc_driver *d); void lirc_unregister_driver(struct lirc_driver *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_driver * associated with the given device file pointer. */ -- cgit v1.2.3 From b145ef94f63e02c2615ffde61a376b53f3367bc6 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:31:45 -0300 Subject: [media] media: lirc_dev: make chunk_size and buffer_size mandatory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make setting chunk_size and buffer_size mandatory for drivers which expect lirc_dev to allocate the lirc_buffer (i.e. ir-lirc-codec) and don't set them in lirc-zilog (which creates its own buffer). Also remove an unnecessary copy of chunk_size in struct irctl (the same information is already available from struct lirc_buffer). Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 26 +++++++++++++------------- drivers/staging/media/lirc/lirc_zilog.c | 5 +---- include/media/lirc_dev.h | 9 +++++---- 3 files changed, 19 insertions(+), 21 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index ffa203eb2045..1915ffc52955 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -41,7 +41,6 @@ struct irctl { struct mutex irctl_lock; struct lirc_buffer *buf; bool buf_internal; - unsigned int chunk_size; struct device dev; struct cdev cdev; @@ -74,16 +73,8 @@ static void lirc_release(struct device *ld) static int lirc_allocate_buffer(struct irctl *ir) { int err = 0; - int bytes_in_key; - unsigned int chunk_size; - unsigned int buffer_size; struct lirc_driver *d = &ir->d; - bytes_in_key = BITS_TO_LONGS(d->code_length) + - (d->code_length % 8 ? 1 : 0); - buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key; - chunk_size = d->chunk_size ? d->chunk_size : bytes_in_key; - if (d->rbuf) { ir->buf = d->rbuf; ir->buf_internal = false; @@ -94,7 +85,7 @@ static int lirc_allocate_buffer(struct irctl *ir) goto out; } - err = lirc_buffer_init(ir->buf, chunk_size, buffer_size); + err = lirc_buffer_init(ir->buf, d->chunk_size, d->buffer_size); if (err) { kfree(ir->buf); ir->buf = NULL; @@ -104,7 +95,6 @@ static int lirc_allocate_buffer(struct irctl *ir) ir->buf_internal = true; d->rbuf = ir->buf; } - ir->chunk_size = ir->buf->chunk_size; out: return err; @@ -131,6 +121,16 @@ int lirc_register_driver(struct lirc_driver *d) return -EINVAL; } + if (!d->rbuf && d->chunk_size < 1) { + pr_err("chunk_size must be set!\n"); + return -EINVAL; + } + + if (!d->rbuf && d->buffer_size < 1) { + pr_err("buffer_size must be set!\n"); + return -EINVAL; + } + if (d->code_length < 1 || d->code_length > (BUFLEN * 8)) { dev_err(d->dev, "code length must be less than %d bits\n", BUFLEN * 8); @@ -407,7 +407,7 @@ ssize_t lirc_dev_fop_read(struct file *file, dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor); - buf = kzalloc(ir->chunk_size, GFP_KERNEL); + buf = kzalloc(ir->buf->chunk_size, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -420,7 +420,7 @@ ssize_t lirc_dev_fop_read(struct file *file, goto out_locked; } - if (length % ir->chunk_size) { + if (length % ir->buf->chunk_size) { ret = -EINVAL; goto out_locked; } diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index c4a4c2f93ae8..780b2d9f2f4b 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -1348,8 +1348,6 @@ static const struct file_operations lirc_fops = { static struct lirc_driver lirc_template = { .name = "lirc_zilog", .code_length = 13, - .buffer_size = BUFLEN / 2, - .chunk_size = 2, .fops = &lirc_fops, .owner = THIS_MODULE, }; @@ -1456,8 +1454,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir->l.dev = &adap->dev; /* This will be returned by lirc_get_pdata() */ ir->l.data = ir; - ret = lirc_buffer_init(ir->l.rbuf, - ir->l.chunk_size, ir->l.buffer_size); + ret = lirc_buffer_init(ir->l.rbuf, 2, BUFLEN / 2); if (ret) goto out_put_ir; } diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index d07a53232ffc..8e3894e2d2c8 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -121,13 +121,14 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, * * @code_length: length of the remote control key code expressed in bits. * - * @buffer_size: Number of FIFO buffers with @chunk_size size. If zero, - * creates a buffer with BUFLEN size (16 bytes). - * * @features: lirc compatible hardware features, like LIRC_MODE_RAW, * LIRC_CAN\_\*, as defined at include/media/lirc.h. * + * @buffer_size: Number of FIFO buffers with @chunk_size size. + * Only used if @rbuf is NULL. + * * @chunk_size: Size of each FIFO buffer. + * Only used if @rbuf is NULL. * * @data: it may point to any driver data and this pointer will * be passed to all callback functions. @@ -162,9 +163,9 @@ struct lirc_driver { char name[40]; unsigned int minor; __u32 code_length; - unsigned int buffer_size; /* in chunks holding one code each */ __u32 features; + unsigned int buffer_size; /* in chunks holding one code each */ unsigned int chunk_size; void *data; -- cgit v1.2.3 From 3bce5572364899970cbe908d98c51d1bc743b2f8 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:31:55 -0300 Subject: [media] media: lirc_dev: change irctl->attached to be a boolean MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "attached" member of struct irctl is a boolean value, so let the code reflect that. Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 1915ffc52955..b07d0ab37d6b 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -35,7 +35,7 @@ static dev_t lirc_base_dev; struct irctl { struct lirc_driver d; - int attached; + bool attached; int open; struct mutex irctl_lock; @@ -193,7 +193,7 @@ int lirc_register_driver(struct lirc_driver *d) cdev_init(&ir->cdev, d->fops); ir->cdev.owner = ir->d.owner; - ir->attached = 1; + ir->attached = true; err = cdev_device_add(&ir->cdev, &ir->dev); if (err) @@ -231,7 +231,7 @@ void lirc_unregister_driver(struct lirc_driver *d) dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n", d->name, d->minor); - ir->attached = 0; + ir->attached = false; if (ir->open) { dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n", d->name, d->minor); -- cgit v1.2.3 From 3381b779a736f4908a64b603ce339ab067e01de7 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Fri, 30 Jun 2017 05:41:57 -0300 Subject: [media] media: lirc_dev: sanitize locking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the irctl mutex for all device operations and only use lirc_dev_lock to protect the irctls array. Also, make sure that the device is alive early in each fops function before doing anything else. Since this patch touches nearly every line where the irctl mutex is taken/released, it also renames the mutex at the same time (the name irctl_lock will be misleading once struct irctl goes away in later patches). [mchehab@s-opensource.com: fix a merge conflict] Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 165 +++++++++++++++++++++++++------------------- 1 file changed, 93 insertions(+), 72 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index b07d0ab37d6b..c83fffec0681 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -38,7 +38,7 @@ struct irctl { bool attached; int open; - struct mutex irctl_lock; + struct mutex mutex; /* protect from simultaneous accesses */ struct lirc_buffer *buf; bool buf_internal; @@ -46,6 +46,7 @@ struct irctl { struct cdev cdev; }; +/* This mutex protects the irctls array */ static DEFINE_MUTEX(lirc_dev_lock); static struct irctl *irctls[MAX_IRCTL_DEVICES]; @@ -53,20 +54,25 @@ static struct irctl *irctls[MAX_IRCTL_DEVICES]; /* Only used for sysfs but defined to void otherwise */ static struct class *lirc_class; -static void lirc_release(struct device *ld) +static void lirc_free_buffer(struct irctl *ir) { - struct irctl *ir = container_of(ld, struct irctl, dev); - put_device(ir->dev.parent); if (ir->buf_internal) { lirc_buffer_free(ir->buf); kfree(ir->buf); + ir->buf = NULL; } +} + +static void lirc_release(struct device *ld) +{ + struct irctl *ir = container_of(ld, struct irctl, dev); mutex_lock(&lirc_dev_lock); irctls[ir->d.minor] = NULL; mutex_unlock(&lirc_dev_lock); + lirc_free_buffer(ir); kfree(ir); } @@ -143,6 +149,28 @@ int lirc_register_driver(struct lirc_driver *d) return -EBADRQC; } + /* some safety check 8-) */ + d->name[sizeof(d->name) - 1] = '\0'; + + if (d->features == 0) + d->features = LIRC_CAN_REC_LIRCCODE; + + ir = kzalloc(sizeof(*ir), GFP_KERNEL); + if (!ir) + return -ENOMEM; + + mutex_init(&ir->mutex); + ir->d = *d; + + if (LIRC_CAN_REC(d->features)) { + err = lirc_allocate_buffer(ir); + if (err) { + kfree(ir); + return err; + } + d->rbuf = ir->buf; + } + mutex_lock(&lirc_dev_lock); /* find first free slot for driver */ @@ -152,37 +180,18 @@ int lirc_register_driver(struct lirc_driver *d) if (minor == MAX_IRCTL_DEVICES) { dev_err(d->dev, "no free slots for drivers!\n"); - err = -ENOMEM; - goto out_lock; - } - - ir = kzalloc(sizeof(struct irctl), GFP_KERNEL); - if (!ir) { - err = -ENOMEM; - goto out_lock; + mutex_unlock(&lirc_dev_lock); + lirc_free_buffer(ir); + kfree(ir); + return -ENOMEM; } - mutex_init(&ir->irctl_lock); irctls[minor] = ir; d->irctl = ir; d->minor = minor; + ir->d.minor = minor; - /* some safety check 8-) */ - d->name[sizeof(d->name)-1] = '\0'; - - if (d->features == 0) - d->features = LIRC_CAN_REC_LIRCCODE; - - ir->d = *d; - - if (LIRC_CAN_REC(d->features)) { - err = lirc_allocate_buffer(irctls[minor]); - if (err) { - kfree(ir); - goto out_lock; - } - d->rbuf = ir->buf; - } + mutex_unlock(&lirc_dev_lock); device_initialize(&ir->dev); ir->dev.devt = MKDEV(MAJOR(lirc_base_dev), ir->d.minor); @@ -196,10 +205,10 @@ int lirc_register_driver(struct lirc_driver *d) ir->attached = true; err = cdev_device_add(&ir->cdev, &ir->dev); - if (err) - goto out_dev; - - mutex_unlock(&lirc_dev_lock); + if (err) { + put_device(&ir->dev); + return err; + } get_device(ir->dev.parent); @@ -207,13 +216,6 @@ int lirc_register_driver(struct lirc_driver *d) ir->d.name, ir->d.minor); return 0; - -out_dev: - put_device(&ir->dev); -out_lock: - mutex_unlock(&lirc_dev_lock); - - return err; } EXPORT_SYMBOL(lirc_register_driver); @@ -226,11 +228,13 @@ void lirc_unregister_driver(struct lirc_driver *d) ir = d->irctl; - mutex_lock(&lirc_dev_lock); - dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n", d->name, d->minor); + cdev_device_del(&ir->cdev, &ir->dev); + + mutex_lock(&ir->mutex); + ir->attached = false; if (ir->open) { dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n", @@ -238,9 +242,8 @@ void lirc_unregister_driver(struct lirc_driver *d) wake_up_interruptible(&ir->buf->wait_poll); } - mutex_unlock(&lirc_dev_lock); + mutex_unlock(&ir->mutex); - cdev_device_del(&ir->cdev, &ir->dev); put_device(&ir->dev); } EXPORT_SYMBOL(lirc_unregister_driver); @@ -252,13 +255,24 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor); - if (ir->open) - return -EBUSY; + retval = mutex_lock_interruptible(&ir->mutex); + if (retval) + return retval; + + if (!ir->attached) { + retval = -ENODEV; + goto out; + } + + if (ir->open) { + retval = -EBUSY; + goto out; + } if (ir->d.rdev) { retval = rc_open(ir->d.rdev); if (retval) - return retval; + goto out; } if (ir->buf) @@ -268,24 +282,26 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) lirc_init_pdata(inode, file); nonseekable_open(inode, file); + mutex_unlock(&ir->mutex); return 0; + +out: + mutex_unlock(&ir->mutex); + return retval; } EXPORT_SYMBOL(lirc_dev_fop_open); int lirc_dev_fop_close(struct inode *inode, struct file *file) { struct irctl *ir = file->private_data; - int ret; - ret = mutex_lock_killable(&lirc_dev_lock); - WARN_ON(ret); + mutex_lock(&ir->mutex); rc_close(ir->d.rdev); - ir->open--; - if (!ret) - mutex_unlock(&lirc_dev_lock); + + mutex_unlock(&ir->mutex); return 0; } @@ -320,19 +336,20 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct irctl *ir = file->private_data; __u32 mode; - int result = 0; + int result; dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n", ir->d.name, ir->d.minor, cmd); + result = mutex_lock_interruptible(&ir->mutex); + if (result) + return result; + if (!ir->attached) { - dev_err(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n", - ir->d.name, ir->d.minor); - return -ENODEV; + result = -ENODEV; + goto out; } - mutex_lock(&ir->irctl_lock); - switch (cmd) { case LIRC_GET_FEATURES: result = put_user(ir->d.features, (__u32 __user *)arg); @@ -386,8 +403,8 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) result = -ENOTTY; } - mutex_unlock(&ir->irctl_lock); - +out: + mutex_unlock(&ir->mutex); return result; } EXPORT_SYMBOL(lirc_dev_fop_ioctl); @@ -399,27 +416,31 @@ ssize_t lirc_dev_fop_read(struct file *file, { struct irctl *ir = file->private_data; unsigned char *buf; - int ret = 0, written = 0; + int ret, written = 0; DECLARE_WAITQUEUE(wait, current); - if (!LIRC_CAN_REC(ir->d.features)) - return -EINVAL; - dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor); buf = kzalloc(ir->buf->chunk_size, GFP_KERNEL); if (!buf) return -ENOMEM; - if (mutex_lock_interruptible(&ir->irctl_lock)) { - ret = -ERESTARTSYS; - goto out_unlocked; + ret = mutex_lock_interruptible(&ir->mutex); + if (ret) { + kfree(buf); + return ret; } + if (!ir->attached) { ret = -ENODEV; goto out_locked; } + if (!LIRC_CAN_REC(ir->d.features)) { + ret = -EINVAL; + goto out_locked; + } + if (length % ir->buf->chunk_size) { ret = -EINVAL; goto out_locked; @@ -454,13 +475,13 @@ ssize_t lirc_dev_fop_read(struct file *file, break; } - mutex_unlock(&ir->irctl_lock); + mutex_unlock(&ir->mutex); set_current_state(TASK_INTERRUPTIBLE); schedule(); set_current_state(TASK_RUNNING); - if (mutex_lock_interruptible(&ir->irctl_lock)) { - ret = -ERESTARTSYS; + ret = mutex_lock_interruptible(&ir->mutex); + if (ret) { remove_wait_queue(&ir->buf->wait_poll, &wait); goto out_unlocked; } @@ -483,7 +504,7 @@ ssize_t lirc_dev_fop_read(struct file *file, remove_wait_queue(&ir->buf->wait_poll, &wait); out_locked: - mutex_unlock(&ir->irctl_lock); + mutex_unlock(&ir->mutex); out_unlocked: kfree(buf); -- cgit v1.2.3 From 46c8f4771154eb0dc21f5f2bc2640a33e8fe1d02 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:32:05 -0300 Subject: [media] media: lirc_dev: use an IDA instead of an array to keep track of registered devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the kernel-provided IDA simplifies the code and makes it possible to remove the lirc_dev_lock mutex. Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 36 ++++++++++++------------------------ include/media/lirc_dev.h | 1 - 2 files changed, 12 insertions(+), 25 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index c83fffec0681..a2c5ed0181c1 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -46,10 +47,9 @@ struct irctl { struct cdev cdev; }; -/* This mutex protects the irctls array */ -static DEFINE_MUTEX(lirc_dev_lock); - -static struct irctl *irctls[MAX_IRCTL_DEVICES]; +/* Used to keep track of allocated lirc devices */ +#define LIRC_MAX_DEVICES 256 +static DEFINE_IDA(lirc_ida); /* Only used for sysfs but defined to void otherwise */ static struct class *lirc_class; @@ -69,9 +69,6 @@ static void lirc_release(struct device *ld) { struct irctl *ir = container_of(ld, struct irctl, dev); - mutex_lock(&lirc_dev_lock); - irctls[ir->d.minor] = NULL; - mutex_unlock(&lirc_dev_lock); lirc_free_buffer(ir); kfree(ir); } @@ -109,7 +106,7 @@ out: int lirc_register_driver(struct lirc_driver *d) { struct irctl *ir; - unsigned int minor; + int minor; int err; if (!d) { @@ -171,28 +168,17 @@ int lirc_register_driver(struct lirc_driver *d) d->rbuf = ir->buf; } - mutex_lock(&lirc_dev_lock); - - /* find first free slot for driver */ - for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++) - if (!irctls[minor]) - break; - - if (minor == MAX_IRCTL_DEVICES) { - dev_err(d->dev, "no free slots for drivers!\n"); - mutex_unlock(&lirc_dev_lock); + minor = ida_simple_get(&lirc_ida, 0, LIRC_MAX_DEVICES, GFP_KERNEL); + if (minor < 0) { lirc_free_buffer(ir); kfree(ir); - return -ENOMEM; + return minor; } - irctls[minor] = ir; d->irctl = ir; d->minor = minor; ir->d.minor = minor; - mutex_unlock(&lirc_dev_lock); - device_initialize(&ir->dev); ir->dev.devt = MKDEV(MAJOR(lirc_base_dev), ir->d.minor); ir->dev.class = lirc_class; @@ -206,6 +192,7 @@ int lirc_register_driver(struct lirc_driver *d) err = cdev_device_add(&ir->cdev, &ir->dev); if (err) { + ida_simple_remove(&lirc_ida, minor); put_device(&ir->dev); return err; } @@ -244,6 +231,7 @@ void lirc_unregister_driver(struct lirc_driver *d) mutex_unlock(&ir->mutex); + ida_simple_remove(&lirc_ida, d->minor); put_device(&ir->dev); } EXPORT_SYMBOL(lirc_unregister_driver); @@ -540,7 +528,7 @@ static int __init lirc_dev_init(void) return PTR_ERR(lirc_class); } - retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES, + retval = alloc_chrdev_region(&lirc_base_dev, 0, LIRC_MAX_DEVICES, "BaseRemoteCtl"); if (retval) { class_destroy(lirc_class); @@ -557,7 +545,7 @@ static int __init lirc_dev_init(void) static void __exit lirc_dev_exit(void) { class_destroy(lirc_class); - unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES); + unregister_chrdev_region(lirc_base_dev, LIRC_MAX_DEVICES); pr_info("module unloaded\n"); } diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 8e3894e2d2c8..51c15c050e85 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -9,7 +9,6 @@ #ifndef _LINUX_LIRC_DEV_H #define _LINUX_LIRC_DEV_H -#define MAX_IRCTL_DEVICES 8 #define BUFLEN 16 #include -- cgit v1.2.3 From 5ddc9c098dc3f91243840cec12a2170e9ab9f33a Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Thu, 21 Sep 2017 16:13:34 -0300 Subject: [media] media: rename struct lirc_driver to struct lirc_dev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is in preparation for the later patches which do away with struct irctl entirely. Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ir-lirc-codec.c | 52 ++++++++++++++++----------------- drivers/media/rc/lirc_dev.c | 12 ++++---- drivers/media/rc/rc-core-priv.h | 2 +- drivers/staging/media/lirc/lirc_zilog.c | 12 ++++---- include/media/lirc_dev.h | 48 +++++++++--------------------- 5 files changed, 52 insertions(+), 74 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index 58bff7a75d5b..2d591168c991 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) struct lirc_codec *lirc = &dev->raw->lirc; int sample; - if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf) + if (!dev->raw->lirc.ldev || !dev->raw->lirc.ldev->rbuf) return -EINVAL; /* Packet start */ @@ -84,8 +84,8 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) (u64)LIRC_VALUE_MASK); gap_sample = LIRC_SPACE(lirc->gap_duration); - lirc_buffer_write(dev->raw->lirc.drv->rbuf, - (unsigned char *) &gap_sample); + lirc_buffer_write(dev->raw->lirc.ldev->rbuf, + (unsigned char *)&gap_sample); lirc->gap = false; } @@ -95,9 +95,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(dev->raw->lirc.ldev->rbuf, (unsigned char *) &sample); - wake_up(&dev->raw->lirc.drv->rbuf->wait_poll); + wake_up(&dev->raw->lirc.ldev->rbuf->wait_poll); return 0; } @@ -343,12 +343,12 @@ static const struct file_operations lirc_fops = { static int ir_lirc_register(struct rc_dev *dev) { - struct lirc_driver *drv; + struct lirc_dev *ldev; int rc = -ENOMEM; unsigned long features = 0; - drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); - if (!drv) + ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); + if (!ldev) return rc; if (dev->driver_type != RC_DRIVER_IR_RAW_TX) { @@ -380,29 +380,29 @@ static int ir_lirc_register(struct rc_dev *dev) if (dev->max_timeout) features |= LIRC_CAN_SET_REC_TIMEOUT; - snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", + snprintf(ldev->name, sizeof(ldev->name), "ir-lirc-codec (%s)", dev->driver_name); - drv->features = features; - drv->data = &dev->raw->lirc; - drv->rbuf = NULL; - drv->code_length = sizeof(struct ir_raw_event) * 8; - drv->chunk_size = sizeof(int); - drv->buffer_size = LIRCBUF_SIZE; - drv->fops = &lirc_fops; - drv->dev = &dev->dev; - drv->rdev = dev; - drv->owner = THIS_MODULE; - - rc = lirc_register_driver(drv); + ldev->features = features; + ldev->data = &dev->raw->lirc; + ldev->rbuf = NULL; + ldev->code_length = sizeof(struct ir_raw_event) * 8; + ldev->chunk_size = sizeof(int); + ldev->buffer_size = LIRCBUF_SIZE; + ldev->fops = &lirc_fops; + ldev->dev = &dev->dev; + ldev->rdev = dev; + ldev->owner = THIS_MODULE; + + rc = lirc_register_device(ldev); if (rc < 0) goto out; - dev->raw->lirc.drv = drv; + dev->raw->lirc.ldev = ldev; dev->raw->lirc.dev = dev; return 0; out: - kfree(drv); + kfree(ldev); return rc; } @@ -410,9 +410,9 @@ static int ir_lirc_unregister(struct rc_dev *dev) { struct lirc_codec *lirc = &dev->raw->lirc; - lirc_unregister_driver(lirc->drv); - kfree(lirc->drv); - lirc->drv = NULL; + lirc_unregister_device(lirc->ldev); + kfree(lirc->ldev); + lirc->ldev = NULL; return 0; } diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index a2c5ed0181c1..e381a1c04bea 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -35,7 +35,7 @@ static dev_t lirc_base_dev; struct irctl { - struct lirc_driver d; + struct lirc_dev d; bool attached; int open; @@ -76,7 +76,7 @@ static void lirc_release(struct device *ld) static int lirc_allocate_buffer(struct irctl *ir) { int err = 0; - struct lirc_driver *d = &ir->d; + struct lirc_dev *d = &ir->d; if (d->rbuf) { ir->buf = d->rbuf; @@ -103,7 +103,7 @@ out: return err; } -int lirc_register_driver(struct lirc_driver *d) +int lirc_register_device(struct lirc_dev *d) { struct irctl *ir; int minor; @@ -204,9 +204,9 @@ int lirc_register_driver(struct lirc_driver *d) return 0; } -EXPORT_SYMBOL(lirc_register_driver); +EXPORT_SYMBOL(lirc_register_device); -void lirc_unregister_driver(struct lirc_driver *d) +void lirc_unregister_device(struct lirc_dev *d) { struct irctl *ir; @@ -234,7 +234,7 @@ void lirc_unregister_driver(struct lirc_driver *d) ida_simple_remove(&lirc_ida, d->minor); put_device(&ir->dev); } -EXPORT_SYMBOL(lirc_unregister_driver); +EXPORT_SYMBOL(lirc_unregister_device); int lirc_dev_fop_open(struct inode *inode, struct file *file) { diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index 7da9c96cb058..ae4dd0c27731 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -106,7 +106,7 @@ struct ir_raw_event_ctrl { } mce_kbd; struct lirc_codec { struct rc_dev *dev; - struct lirc_driver *drv; + struct lirc_dev *ldev; int carrier_low; ktime_t gap_start; diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index 780b2d9f2f4b..0766e5029bd7 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -100,7 +100,7 @@ struct IR { struct list_head list; /* FIXME spinlock access to l.features */ - struct lirc_driver l; + struct lirc_dev l; struct lirc_buffer rbuf; struct mutex ir_lock; @@ -183,7 +183,7 @@ static void release_ir_device(struct kref *ref) * ir->open_count == 0 - happens on final close() * ir_lock, tx_ref_lock, rx_ref_lock, all released */ - lirc_unregister_driver(&ir->l); + lirc_unregister_device(&ir->l); if (kfifo_initialized(&ir->rbuf.fifo)) lirc_buffer_free(&ir->rbuf); @@ -1345,7 +1345,7 @@ static const struct file_operations lirc_fops = { .release = close }; -static struct lirc_driver lirc_template = { +static struct lirc_dev lirc_template = { .name = "lirc_zilog", .code_length = 13, .fops = &lirc_fops, @@ -1441,7 +1441,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) spin_lock_init(&ir->rx_ref_lock); /* set lirc_dev stuff */ - memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); + memcpy(&ir->l, &lirc_template, sizeof(struct lirc_dev)); /* * FIXME this is a pointer reference to us, but no refcount. * @@ -1559,10 +1559,10 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) } /* register with lirc */ - ret = lirc_register_driver(&ir->l); + ret = lirc_register_device(&ir->l); if (ret < 0) { dev_err(tx->ir->l.dev, - "%s: lirc_register_driver() failed: %i\n", + "%s: lirc_register_device() failed: %i\n", __func__, ret); goto out_put_xx; } diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 51c15c050e85..d16d6e0ef8da 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -111,54 +111,32 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, } /** - * struct lirc_driver - Defines the parameters on a LIRC driver - * - * @name: this string will be used for logs - * - * @minor: the minor device (/dev/lircX) number for a registered - * driver. - * - * @code_length: length of the remote control key code expressed in bits. + * struct lirc_dev - represents a LIRC device * + * @name: used for logging + * @minor: the minor device (/dev/lircX) number for the device + * @code_length: length of a remote control key code expressed in bits * @features: lirc compatible hardware features, like LIRC_MODE_RAW, * LIRC_CAN\_\*, as defined at include/media/lirc.h. - * * @buffer_size: Number of FIFO buffers with @chunk_size size. * Only used if @rbuf is NULL. - * * @chunk_size: Size of each FIFO buffer. * Only used if @rbuf is NULL. - * - * @data: it may point to any driver data and this pointer will - * be passed to all callback functions. - * + * @data: private per-driver data * @min_timeout: Minimum timeout for record. Valid only if * LIRC_CAN_SET_REC_TIMEOUT is defined. - * * @max_timeout: Maximum timeout for record. Valid only if * LIRC_CAN_SET_REC_TIMEOUT is defined. - * * @rbuf: if not NULL, it will be used as a read buffer, you will * have to write to the buffer by other means, like irq's * (see also lirc_serial.c). - * - * @rdev: Pointed to struct rc_dev associated with the LIRC - * device. - * - * @fops: file_operations for drivers which don't fit the current - * driver model. - * Some ioctl's can be directly handled by lirc_dev if the - * driver's ioctl function is NULL or if it returns - * -ENOIOCTLCMD (see also lirc_serial.c). - * - * @dev: pointer to the struct device associated with the LIRC - * device. - * + * @rdev: &struct rc_dev associated with the device + * @fops: &struct file_operations for the device + * @dev: &struct device assigned to the device * @owner: the module owning this struct - * - * @irctl: the struct irctl for this LIRC device. + * @irctl: &struct irctl assigned to the device */ -struct lirc_driver { +struct lirc_dev { char name[40]; unsigned int minor; __u32 code_length; @@ -183,14 +161,14 @@ struct lirc_driver { * returns negative value on error or zero * contents of the structure pointed by p is copied */ -int lirc_register_driver(struct lirc_driver *d); +int lirc_register_device(struct lirc_dev *d); -void lirc_unregister_driver(struct lirc_driver *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_driver +/* Returns the private data stored in the lirc_dev * associated with the given device file pointer. */ void *lirc_get_pdata(struct file *file); -- cgit v1.2.3 From 6ecccc379b7334c02f90a401dafea6fce5c91310 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:32:15 -0300 Subject: [media] media: lirc_dev: introduce lirc_allocate_device and lirc_free_device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce two new functions so that the API for lirc_dev matches that of the rc-core and input subsystems. This means that lirc_dev structs are managed using the usual four functions: lirc_allocate_device lirc_free_device lirc_register_device lirc_unregister_device The functions are pretty simplistic at this point, later patches will put more flesh on the bones of both. Signed-off-by: David Härdeman Signed-off-by: Sean Young --- drivers/media/rc/ir-lirc-codec.c | 2 +- drivers/media/rc/lirc_dev.c | 13 +++++++++++++ include/media/lirc_dev.h | 9 ++++----- 3 files changed, 18 insertions(+), 6 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index 2d591168c991..d5c155a5a547 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -347,7 +347,7 @@ static int ir_lirc_register(struct rc_dev *dev) int rc = -ENOMEM; unsigned long features = 0; - ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); + ldev = lirc_allocate_device(); if (!ldev) return rc; diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index e381a1c04bea..a6005f70de5a 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -103,6 +103,19 @@ out: return err; } +struct lirc_dev * +lirc_allocate_device(void) +{ + return kzalloc(sizeof(struct lirc_dev), GFP_KERNEL); +} +EXPORT_SYMBOL(lirc_allocate_device); + +void lirc_free_device(struct lirc_dev *d) +{ + kfree(d); +} +EXPORT_SYMBOL(lirc_free_device); + int lirc_register_device(struct lirc_dev *d) { struct irctl *ir; diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index d16d6e0ef8da..4b0dc640e142 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -156,11 +156,10 @@ struct lirc_dev { struct irctl *irctl; }; -/* following functions can be called ONLY from user context - * - * returns negative value on error or zero - * contents of the structure pointed by p is copied - */ +struct lirc_dev *lirc_allocate_device(void); + +void lirc_free_device(struct lirc_dev *d); + int lirc_register_device(struct lirc_dev *d); void lirc_unregister_device(struct lirc_dev *d); -- cgit v1.2.3 From b15e39379fe8700fe0ec849a5c5ee2b44cd16381 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:32:36 -0300 Subject: [media] media: lirc_dev: merge struct irctl into struct lirc_dev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The use of two separate structs (lirc_dev aka lirc_driver and irctl) makes it much harder to follow the proper lifetime of the various structs and necessitates hacks such as keeping a copy of struct lirc_dev inside struct irctl. Merging the two structs means that lirc_dev can properly manage the lifetime of the resulting struct and simplifies the code at the same time. [mchehab@s-opensource.com: fix merge conflict] Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ir-lirc-codec.c | 15 +- drivers/media/rc/lirc_dev.c | 314 ++++++++++++++------------------ drivers/staging/media/lirc/lirc_zilog.c | 20 +- include/media/lirc_dev.h | 26 ++- 4 files changed, 175 insertions(+), 200 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index d5c155a5a547..bd046c41a53a 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -35,7 +35,7 @@ static int ir_lirc_decode(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->rbuf) + if (!dev->raw->lirc.ldev || !dev->raw->lirc.ldev->buf) return -EINVAL; /* Packet start */ @@ -84,7 +84,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) (u64)LIRC_VALUE_MASK); gap_sample = LIRC_SPACE(lirc->gap_duration); - lirc_buffer_write(dev->raw->lirc.ldev->rbuf, + lirc_buffer_write(dev->raw->lirc.ldev->buf, (unsigned char *)&gap_sample); lirc->gap = false; } @@ -95,9 +95,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.ldev->rbuf, + lirc_buffer_write(dev->raw->lirc.ldev->buf, (unsigned char *) &sample); - wake_up(&dev->raw->lirc.ldev->rbuf->wait_poll); + wake_up(&dev->raw->lirc.ldev->buf->wait_poll); return 0; } @@ -384,12 +384,12 @@ static int ir_lirc_register(struct rc_dev *dev) dev->driver_name); ldev->features = features; ldev->data = &dev->raw->lirc; - ldev->rbuf = NULL; + ldev->buf = NULL; ldev->code_length = sizeof(struct ir_raw_event) * 8; ldev->chunk_size = sizeof(int); ldev->buffer_size = LIRCBUF_SIZE; ldev->fops = &lirc_fops; - ldev->dev = &dev->dev; + ldev->dev.parent = &dev->dev; ldev->rdev = dev; ldev->owner = THIS_MODULE; @@ -402,7 +402,7 @@ static int ir_lirc_register(struct rc_dev *dev) return 0; out: - kfree(ldev); + lirc_free_device(ldev); return rc; } @@ -411,7 +411,6 @@ static int ir_lirc_unregister(struct rc_dev *dev) struct lirc_codec *lirc = &dev->raw->lirc; lirc_unregister_device(lirc->ldev); - kfree(lirc->ldev); lirc->ldev = NULL; return 0; diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index a6005f70de5a..e9dae8621670 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -34,19 +34,6 @@ static dev_t lirc_base_dev; -struct irctl { - struct lirc_dev d; - bool attached; - int open; - - struct mutex mutex; /* protect from simultaneous accesses */ - struct lirc_buffer *buf; - bool buf_internal; - - struct device dev; - struct cdev cdev; -}; - /* Used to keep track of allocated lirc devices */ #define LIRC_MAX_DEVICES 256 static DEFINE_IDA(lirc_ida); @@ -54,71 +41,74 @@ static DEFINE_IDA(lirc_ida); /* Only used for sysfs but defined to void otherwise */ static struct class *lirc_class; -static void lirc_free_buffer(struct irctl *ir) +static void lirc_release_device(struct device *ld) { - put_device(ir->dev.parent); - - if (ir->buf_internal) { - lirc_buffer_free(ir->buf); - kfree(ir->buf); - ir->buf = NULL; - } -} + struct lirc_dev *d = container_of(ld, struct lirc_dev, dev); -static void lirc_release(struct device *ld) -{ - struct irctl *ir = container_of(ld, struct irctl, dev); + put_device(d->dev.parent); - lirc_free_buffer(ir); - kfree(ir); + if (d->buf_internal) { + lirc_buffer_free(d->buf); + kfree(d->buf); + d->buf = NULL; + } + kfree(d); + module_put(THIS_MODULE); } -static int lirc_allocate_buffer(struct irctl *ir) +static int lirc_allocate_buffer(struct lirc_dev *d) { - int err = 0; - struct lirc_dev *d = &ir->d; + int err; - if (d->rbuf) { - ir->buf = d->rbuf; - ir->buf_internal = false; - } else { - ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); - if (!ir->buf) { - err = -ENOMEM; - goto out; - } + if (d->buf) { + d->buf_internal = false; + return 0; + } - err = lirc_buffer_init(ir->buf, d->chunk_size, d->buffer_size); - if (err) { - kfree(ir->buf); - ir->buf = NULL; - goto out; - } + d->buf = kmalloc(sizeof(*d->buf), GFP_KERNEL); + if (!d->buf) + return -ENOMEM; - ir->buf_internal = true; - d->rbuf = ir->buf; + err = lirc_buffer_init(d->buf, d->chunk_size, d->buffer_size); + if (err) { + kfree(d->buf); + d->buf = NULL; + return err; } -out: - return err; + d->buf_internal = true; + return 0; } struct lirc_dev * lirc_allocate_device(void) { - return kzalloc(sizeof(struct lirc_dev), GFP_KERNEL); + struct lirc_dev *d; + + d = kzalloc(sizeof(*d), GFP_KERNEL); + if (d) { + mutex_init(&d->mutex); + device_initialize(&d->dev); + d->dev.class = lirc_class; + d->dev.release = lirc_release_device; + __module_get(THIS_MODULE); + } + + return d; } EXPORT_SYMBOL(lirc_allocate_device); void lirc_free_device(struct lirc_dev *d) { - kfree(d); + if (!d) + return; + + put_device(&d->dev); } EXPORT_SYMBOL(lirc_free_device); int lirc_register_device(struct lirc_dev *d) { - struct irctl *ir; int minor; int err; @@ -127,8 +117,8 @@ int lirc_register_device(struct lirc_dev *d) return -EBADRQC; } - if (!d->dev) { - pr_err("dev pointer not filled in!\n"); + if (!d->dev.parent) { + pr_err("dev parent pointer not filled in!\n"); return -EINVAL; } @@ -137,25 +127,25 @@ int lirc_register_device(struct lirc_dev *d) return -EINVAL; } - if (!d->rbuf && d->chunk_size < 1) { + if (!d->buf && d->chunk_size < 1) { pr_err("chunk_size must be set!\n"); return -EINVAL; } - if (!d->rbuf && d->buffer_size < 1) { + if (!d->buf && d->buffer_size < 1) { pr_err("buffer_size must be set!\n"); return -EINVAL; } if (d->code_length < 1 || d->code_length > (BUFLEN * 8)) { - dev_err(d->dev, "code length must be less than %d bits\n", - BUFLEN * 8); + dev_err(&d->dev, "code length must be less than %d bits\n", + BUFLEN * 8); return -EBADRQC; } - if (!d->rbuf && !(d->fops && d->fops->read && - d->fops->poll && d->fops->unlocked_ioctl)) { - dev_err(d->dev, "undefined read, poll, ioctl\n"); + if (!d->buf && !(d->fops && d->fops->read && + d->fops->poll && d->fops->unlocked_ioctl)) { + dev_err(&d->dev, "undefined read, poll, ioctl\n"); return -EBADRQC; } @@ -165,55 +155,34 @@ int lirc_register_device(struct lirc_dev *d) if (d->features == 0) d->features = LIRC_CAN_REC_LIRCCODE; - ir = kzalloc(sizeof(*ir), GFP_KERNEL); - if (!ir) - return -ENOMEM; - - mutex_init(&ir->mutex); - ir->d = *d; - if (LIRC_CAN_REC(d->features)) { - err = lirc_allocate_buffer(ir); - if (err) { - kfree(ir); + err = lirc_allocate_buffer(d); + if (err) return err; - } - d->rbuf = ir->buf; } minor = ida_simple_get(&lirc_ida, 0, LIRC_MAX_DEVICES, GFP_KERNEL); - if (minor < 0) { - lirc_free_buffer(ir); - kfree(ir); + if (minor < 0) return minor; - } - d->irctl = ir; d->minor = minor; - ir->d.minor = minor; - - device_initialize(&ir->dev); - ir->dev.devt = MKDEV(MAJOR(lirc_base_dev), ir->d.minor); - ir->dev.class = lirc_class; - ir->dev.parent = d->dev; - ir->dev.release = lirc_release; - dev_set_name(&ir->dev, "lirc%d", ir->d.minor); + d->dev.devt = MKDEV(MAJOR(lirc_base_dev), d->minor); + dev_set_name(&d->dev, "lirc%d", d->minor); - cdev_init(&ir->cdev, d->fops); - ir->cdev.owner = ir->d.owner; - ir->attached = true; + cdev_init(&d->cdev, d->fops); + d->cdev.owner = d->owner; + d->attached = true; - err = cdev_device_add(&ir->cdev, &ir->dev); + err = cdev_device_add(&d->cdev, &d->dev); if (err) { ida_simple_remove(&lirc_ida, minor); - put_device(&ir->dev); return err; } - get_device(ir->dev.parent); + get_device(d->dev.parent); - dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n", - ir->d.name, ir->d.minor); + dev_info(&d->dev, "lirc_dev: driver %s registered at minor = %d\n", + d->name, d->minor); return 0; } @@ -221,88 +190,83 @@ EXPORT_SYMBOL(lirc_register_device); void lirc_unregister_device(struct lirc_dev *d) { - struct irctl *ir; - - if (!d || !d->irctl) + if (!d) return; - ir = d->irctl; - - dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n", + dev_dbg(&d->dev, "lirc_dev: driver %s unregistered from minor = %d\n", d->name, d->minor); - cdev_device_del(&ir->cdev, &ir->dev); - - mutex_lock(&ir->mutex); + mutex_lock(&d->mutex); - ir->attached = false; - if (ir->open) { - dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n", + d->attached = false; + if (d->open) { + dev_dbg(&d->dev, LOGHEAD "releasing opened driver\n", d->name, d->minor); - wake_up_interruptible(&ir->buf->wait_poll); + wake_up_interruptible(&d->buf->wait_poll); } - mutex_unlock(&ir->mutex); + mutex_unlock(&d->mutex); + cdev_device_del(&d->cdev, &d->dev); ida_simple_remove(&lirc_ida, d->minor); - put_device(&ir->dev); + put_device(&d->dev); } EXPORT_SYMBOL(lirc_unregister_device); int lirc_dev_fop_open(struct inode *inode, struct file *file) { - struct irctl *ir = container_of(inode->i_cdev, struct irctl, cdev); + struct lirc_dev *d = container_of(inode->i_cdev, struct lirc_dev, cdev); int retval; - dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor); + dev_dbg(&d->dev, LOGHEAD "open called\n", d->name, d->minor); - retval = mutex_lock_interruptible(&ir->mutex); + retval = mutex_lock_interruptible(&d->mutex); if (retval) return retval; - if (!ir->attached) { + if (!d->attached) { retval = -ENODEV; goto out; } - if (ir->open) { + if (d->open) { retval = -EBUSY; goto out; } - if (ir->d.rdev) { - retval = rc_open(ir->d.rdev); + if (d->rdev) { + retval = rc_open(d->rdev); if (retval) goto out; } - if (ir->buf) - lirc_buffer_clear(ir->buf); + if (d->buf) + lirc_buffer_clear(d->buf); - ir->open++; + d->open++; lirc_init_pdata(inode, file); nonseekable_open(inode, file); - mutex_unlock(&ir->mutex); + mutex_unlock(&d->mutex); return 0; out: - mutex_unlock(&ir->mutex); + mutex_unlock(&d->mutex); return retval; } EXPORT_SYMBOL(lirc_dev_fop_open); int lirc_dev_fop_close(struct inode *inode, struct file *file) { - struct irctl *ir = file->private_data; + struct lirc_dev *d = file->private_data; - mutex_lock(&ir->mutex); + mutex_lock(&d->mutex); - rc_close(ir->d.rdev); - ir->open--; + rc_close(d->rdev); + d->open--; - mutex_unlock(&ir->mutex); + mutex_unlock(&d->mutex); return 0; } @@ -310,24 +274,24 @@ EXPORT_SYMBOL(lirc_dev_fop_close); unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) { - struct irctl *ir = file->private_data; + struct lirc_dev *d = file->private_data; unsigned int ret; - if (!ir->attached) + if (!d->attached) return POLLHUP | POLLERR; - if (ir->buf) { - poll_wait(file, &ir->buf->wait_poll, wait); + if (d->buf) { + poll_wait(file, &d->buf->wait_poll, wait); - if (lirc_buffer_empty(ir->buf)) + if (lirc_buffer_empty(d->buf)) ret = 0; else ret = POLLIN | POLLRDNORM; - } else + } else { ret = POLLERR; + } - dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n", - ir->d.name, ir->d.minor, ret); + dev_dbg(&d->dev, LOGHEAD "poll result = %d\n", d->name, d->minor, ret); return ret; } @@ -335,44 +299,44 @@ EXPORT_SYMBOL(lirc_dev_fop_poll); long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct irctl *ir = file->private_data; + struct lirc_dev *d = file->private_data; __u32 mode; int result; - dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n", - ir->d.name, ir->d.minor, cmd); + dev_dbg(&d->dev, LOGHEAD "ioctl called (0x%x)\n", + d->name, d->minor, cmd); - result = mutex_lock_interruptible(&ir->mutex); + result = mutex_lock_interruptible(&d->mutex); if (result) return result; - if (!ir->attached) { + if (!d->attached) { result = -ENODEV; goto out; } switch (cmd) { case LIRC_GET_FEATURES: - result = put_user(ir->d.features, (__u32 __user *)arg); + result = put_user(d->features, (__u32 __user *)arg); break; case LIRC_GET_REC_MODE: - if (!LIRC_CAN_REC(ir->d.features)) { + if (!LIRC_CAN_REC(d->features)) { result = -ENOTTY; break; } result = put_user(LIRC_REC2MODE - (ir->d.features & LIRC_CAN_REC_MASK), + (d->features & LIRC_CAN_REC_MASK), (__u32 __user *)arg); break; case LIRC_SET_REC_MODE: - if (!LIRC_CAN_REC(ir->d.features)) { + if (!LIRC_CAN_REC(d->features)) { result = -ENOTTY; break; } result = get_user(mode, (__u32 __user *)arg); - if (!result && !(LIRC_MODE2REC(mode) & ir->d.features)) + if (!result && !(LIRC_MODE2REC(mode) & d->features)) result = -EINVAL; /* * FIXME: We should actually set the mode somehow but @@ -380,32 +344,32 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) */ break; case LIRC_GET_LENGTH: - result = put_user(ir->d.code_length, (__u32 __user *)arg); + result = put_user(d->code_length, (__u32 __user *)arg); break; case LIRC_GET_MIN_TIMEOUT: - if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || - ir->d.min_timeout == 0) { + if (!(d->features & LIRC_CAN_SET_REC_TIMEOUT) || + d->min_timeout == 0) { result = -ENOTTY; break; } - result = put_user(ir->d.min_timeout, (__u32 __user *)arg); + result = put_user(d->min_timeout, (__u32 __user *)arg); break; case LIRC_GET_MAX_TIMEOUT: - if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || - ir->d.max_timeout == 0) { + if (!(d->features & LIRC_CAN_SET_REC_TIMEOUT) || + d->max_timeout == 0) { result = -ENOTTY; break; } - result = put_user(ir->d.max_timeout, (__u32 __user *)arg); + result = put_user(d->max_timeout, (__u32 __user *)arg); break; default: result = -ENOTTY; } out: - mutex_unlock(&ir->mutex); + mutex_unlock(&d->mutex); return result; } EXPORT_SYMBOL(lirc_dev_fop_ioctl); @@ -415,34 +379,34 @@ ssize_t lirc_dev_fop_read(struct file *file, size_t length, loff_t *ppos) { - struct irctl *ir = file->private_data; + struct lirc_dev *d = file->private_data; unsigned char *buf; int ret, written = 0; DECLARE_WAITQUEUE(wait, current); - dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor); - - buf = kzalloc(ir->buf->chunk_size, GFP_KERNEL); + buf = kzalloc(d->buf->chunk_size, GFP_KERNEL); if (!buf) return -ENOMEM; - ret = mutex_lock_interruptible(&ir->mutex); + dev_dbg(&d->dev, LOGHEAD "read called\n", d->name, d->minor); + + ret = mutex_lock_interruptible(&d->mutex); if (ret) { kfree(buf); return ret; } - if (!ir->attached) { + if (!d->attached) { ret = -ENODEV; goto out_locked; } - if (!LIRC_CAN_REC(ir->d.features)) { + if (!LIRC_CAN_REC(d->features)) { ret = -EINVAL; goto out_locked; } - if (length % ir->buf->chunk_size) { + if (length % d->buf->chunk_size) { ret = -EINVAL; goto out_locked; } @@ -452,14 +416,14 @@ ssize_t lirc_dev_fop_read(struct file *file, * to avoid losing scan code (in case when queue is awaken somewhere * between while condition checking and scheduling) */ - add_wait_queue(&ir->buf->wait_poll, &wait); + add_wait_queue(&d->buf->wait_poll, &wait); /* * while we didn't provide 'length' bytes, device is opened in blocking * mode and 'copy_to_user' is happy, wait for data. */ while (written < length && ret == 0) { - if (lirc_buffer_empty(ir->buf)) { + if (lirc_buffer_empty(d->buf)) { /* According to the read(2) man page, 'written' can be * returned as less than 'length', instead of blocking * again, returning -EWOULDBLOCK, or returning @@ -476,36 +440,36 @@ ssize_t lirc_dev_fop_read(struct file *file, break; } - mutex_unlock(&ir->mutex); + mutex_unlock(&d->mutex); set_current_state(TASK_INTERRUPTIBLE); schedule(); set_current_state(TASK_RUNNING); - ret = mutex_lock_interruptible(&ir->mutex); + ret = mutex_lock_interruptible(&d->mutex); if (ret) { - remove_wait_queue(&ir->buf->wait_poll, &wait); + remove_wait_queue(&d->buf->wait_poll, &wait); goto out_unlocked; } - if (!ir->attached) { + if (!d->attached) { ret = -ENODEV; goto out_locked; } } else { - lirc_buffer_read(ir->buf, buf); + lirc_buffer_read(d->buf, buf); ret = copy_to_user((void __user *)buffer+written, buf, - ir->buf->chunk_size); + d->buf->chunk_size); if (!ret) - written += ir->buf->chunk_size; + written += d->buf->chunk_size; else ret = -EFAULT; } } - remove_wait_queue(&ir->buf->wait_poll, &wait); + remove_wait_queue(&d->buf->wait_poll, &wait); out_locked: - mutex_unlock(&ir->mutex); + mutex_unlock(&d->mutex); out_unlocked: kfree(buf); @@ -516,17 +480,17 @@ EXPORT_SYMBOL(lirc_dev_fop_read); void lirc_init_pdata(struct inode *inode, struct file *file) { - struct irctl *ir = container_of(inode->i_cdev, struct irctl, cdev); + struct lirc_dev *d = container_of(inode->i_cdev, struct lirc_dev, cdev); - file->private_data = ir; + file->private_data = d; } EXPORT_SYMBOL(lirc_init_pdata); void *lirc_get_pdata(struct file *file) { - struct irctl *ir = file->private_data; + struct lirc_dev *d = file->private_data; - return ir->d.data; + return d->data; } EXPORT_SYMBOL(lirc_get_pdata); diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index 00e8c8f224b7..6bd0717bf76e 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -184,10 +184,8 @@ static void release_ir_device(struct kref *ref) * ir->open_count == 0 - happens on final close() * ir_lock, tx_ref_lock, rx_ref_lock, all released */ - if (ir->l) { + if (ir->l) lirc_unregister_device(ir->l); - lirc_free_device(ir->l); - } if (kfifo_initialized(&ir->rbuf.fifo)) lirc_buffer_free(&ir->rbuf); @@ -318,7 +316,7 @@ static int add_to_buf(struct IR *ir) int ret; int failures = 0; unsigned char sendbuf[1] = { 0 }; - struct lirc_buffer *rbuf = ir->l->rbuf; + struct lirc_buffer *rbuf = ir->l->buf; struct IR_rx *rx; struct IR_tx *tx; @@ -464,7 +462,7 @@ static int add_to_buf(struct IR *ir) static int lirc_thread(void *arg) { struct IR *ir = arg; - struct lirc_buffer *rbuf = ir->l->rbuf; + struct lirc_buffer *rbuf = ir->l->buf; dev_dbg(ir->dev, "poll thread started\n"); @@ -885,7 +883,7 @@ static ssize_t read(struct file *filep, char __user *outbuf, size_t n, { struct IR *ir = lirc_get_pdata(filep); struct IR_rx *rx; - struct lirc_buffer *rbuf = ir->l->rbuf; + struct lirc_buffer *rbuf = ir->l->buf; int ret = 0, written = 0, retries = 0; unsigned int m; DECLARE_WAITQUEUE(wait, current); @@ -1203,7 +1201,7 @@ static unsigned int poll(struct file *filep, poll_table *wait) { struct IR *ir = lirc_get_pdata(filep); struct IR_rx *rx; - struct lirc_buffer *rbuf = ir->l->rbuf; + struct lirc_buffer *rbuf = ir->l->buf; unsigned int ret; dev_dbg(ir->dev, "%s called\n", __func__); @@ -1449,6 +1447,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir->l->code_length = 13; ir->l->fops = &lirc_fops; ir->l->owner = THIS_MODULE; + ir->l->dev.parent = &adap->dev; /* * FIXME this is a pointer reference to us, but no refcount. @@ -1456,13 +1455,12 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) * This OK for now, since lirc_dev currently won't touch this * buffer as we provide our own lirc_fops. * - * Currently our own lirc_fops rely on this ir->l->rbuf pointer + * Currently our own lirc_fops rely on this ir->l->buf pointer */ - ir->l->rbuf = &ir->rbuf; - ir->l->dev = &adap->dev; + ir->l->buf = &ir->rbuf; /* This will be returned by lirc_get_pdata() */ ir->l->data = ir; - ret = lirc_buffer_init(ir->l->rbuf, 2, BUFLEN / 2); + ret = lirc_buffer_init(ir->l->buf, 2, BUFLEN / 2); if (ret) { lirc_free_device(ir->l); ir->l = NULL; diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 4b0dc640e142..981dcabd5fd5 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -17,6 +17,8 @@ #include #include #include +#include +#include struct lirc_buffer { wait_queue_head_t wait_poll; @@ -127,14 +129,19 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, * LIRC_CAN_SET_REC_TIMEOUT is defined. * @max_timeout: Maximum timeout for record. Valid only if * LIRC_CAN_SET_REC_TIMEOUT is defined. - * @rbuf: if not NULL, it will be used as a read buffer, you will + * @buf: if %NULL, lirc_dev will allocate and manage the buffer, + * otherwise allocated by the caller which will * have to write to the buffer by other means, like irq's * (see also lirc_serial.c). + * @buf_internal: whether lirc_dev has allocated the read buffer or not * @rdev: &struct rc_dev associated with the device * @fops: &struct file_operations for the device - * @dev: &struct device assigned to the device * @owner: the module owning this struct - * @irctl: &struct irctl assigned to the device + * @attached: if the device is still live + * @open: open count for the device's chardev + * @mutex: serialises file_operations calls + * @dev: &struct device assigned to the device + * @cdev: &struct cdev assigned to the device */ struct lirc_dev { char name[40]; @@ -144,16 +151,23 @@ struct lirc_dev { unsigned int buffer_size; /* in chunks holding one code each */ unsigned int chunk_size; + struct lirc_buffer *buf; + bool buf_internal; void *data; int min_timeout; int max_timeout; - struct lirc_buffer *rbuf; struct rc_dev *rdev; const struct file_operations *fops; - struct device *dev; struct module *owner; - struct irctl *irctl; + + bool attached; + int open; + + struct mutex mutex; /* protect from simultaneous accesses */ + + struct device dev; + struct cdev cdev; }; struct lirc_dev *lirc_allocate_device(void); -- cgit v1.2.3 From 5fad16b5969b43a9722bbe3b288e40bff0003504 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 13 Aug 2017 05:54:44 -0300 Subject: [media] media: rc: constify usb_device_id usb_device_id are not supposed to change at runtime. All functions working with usb_device_id provided by work with const usb_device_id. So mark the non-const structs as const. Signed-off-by: Arvind Yadav Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ati_remote.c | 2 +- drivers/media/rc/igorplugusb.c | 2 +- drivers/media/rc/imon.c | 2 +- drivers/media/rc/mceusb.c | 2 +- drivers/media/rc/redrat3.c | 2 +- drivers/media/rc/streamzap.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c index d0871d60a723..8e82610ffaad 100644 --- a/drivers/media/rc/ati_remote.c +++ b/drivers/media/rc/ati_remote.c @@ -198,7 +198,7 @@ static const struct ati_receiver_type type_firefly = { .default_keymap = RC_MAP_SNAPSTREAM_FIREFLY }; -static struct usb_device_id ati_remote_table[] = { +static const struct usb_device_id ati_remote_table[] = { { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_ati diff --git a/drivers/media/rc/igorplugusb.c b/drivers/media/rc/igorplugusb.c index a5ea86be8f44..4b715eb995f8 100644 --- a/drivers/media/rc/igorplugusb.c +++ b/drivers/media/rc/igorplugusb.c @@ -245,7 +245,7 @@ static void igorplugusb_disconnect(struct usb_interface *intf) usb_free_urb(ir->urb); } -static struct usb_device_id igorplugusb_table[] = { +static const struct usb_device_id igorplugusb_table[] = { /* Igor Plug USB (Atmel's Manufact. ID) */ { USB_DEVICE(0x03eb, 0x0002) }, /* Fit PC2 Infrared Adapter */ diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 7b3f31cc63d2..b93dc6e1f1bf 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -346,7 +346,7 @@ static const struct imon_usb_dev_descr imon_ir_raw = { * devices use the SoundGraph vendor ID (0x15c2). This driver only supports * the ffdc and later devices, which do onboard decoding. */ -static struct usb_device_id imon_usb_id_table[] = { +static const struct usb_device_id imon_usb_id_table[] = { /* * Several devices with this same device ID, all use iMON_PAD.inf * SoundGraph iMON PAD (IR & VFD) diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index bf7aaff3aa37..67c1ff099eb4 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -249,7 +249,7 @@ static const struct mceusb_model mceusb_model[] = { }, }; -static struct usb_device_id mceusb_dev_table[] = { +static const struct usb_device_id mceusb_dev_table[] = { /* Original Microsoft MCE IR Transceiver (often HP-branded) */ { USB_DEVICE(VENDOR_MICROSOFT, 0x006d), .driver_info = MCE_GEN1 }, diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index 6784cb9fc4e7..6bfc24885b5c 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c @@ -186,7 +186,7 @@ struct redrat3_error { } __packed; /* table of devices that work with this driver */ -static struct usb_device_id redrat3_dev_table[] = { +static const struct usb_device_id redrat3_dev_table[] = { /* Original version of the RedRat3 */ {USB_DEVICE(USB_RR3USB_VENDOR_ID, USB_RR3USB_PRODUCT_ID)}, /* Second Version/release of the RedRat3 - RetRat3-II */ diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index f03a174ddf9d..4eebfcfc10f3 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -43,7 +43,7 @@ #define USB_STREAMZAP_PRODUCT_ID 0x0000 /* table of devices that work with this driver */ -static struct usb_device_id streamzap_table[] = { +static const struct usb_device_id streamzap_table[] = { /* Streamzap Remote Control */ { USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) }, /* Terminating entry */ -- cgit v1.2.3 From f03f02f9d261902a5761f02ff03a0620ed4f9d0d Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 19 Aug 2017 05:22:15 -0300 Subject: [media] media: rc: make device_type const Make this const as it is only stored in the type field of a device structure, which is const. Done using Coccinelle. Signed-off-by: Bhumika Goyal Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 981cccd6b988..33bddba6e541 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -1529,7 +1529,7 @@ static const struct attribute_group rc_dev_wakeup_filter_attr_grp = { .attrs = rc_dev_wakeup_filter_attrs, }; -static struct device_type rc_dev_type = { +static const struct device_type rc_dev_type = { .release = rc_dev_release, .uevent = rc_dev_uevent, }; -- cgit v1.2.3 From 3e70b256a6b6a549bdbbd5d70895ff8147c7cf7d Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 29 Aug 2017 07:40:07 -0300 Subject: [media] media: imon: delete an error message for a failed memory allocation Omit an extra message for a memory allocation failure in this function. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/imon.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index b93dc6e1f1bf..188cf1b4ebb1 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -2311,10 +2311,9 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf, int ret = -ENOMEM; ictx = kzalloc(sizeof(struct imon_context), GFP_KERNEL); - if (!ictx) { - dev_err(dev, "%s: kzalloc failed for context", __func__); + if (!ictx) goto exit; - } + rx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!rx_urb) goto rx_urb_alloc_failed; -- cgit v1.2.3 From 6805454b9ceaf526f18193d89aeab0c00715dca3 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 29 Aug 2017 16:04:20 -0300 Subject: [media] media: img-ir: delete an error message for a failed memory allocation Omit an extra message for a memory allocation failure in this function. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/img-ir/img-ir-core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/img-ir/img-ir-core.c b/drivers/media/rc/img-ir/img-ir-core.c index 03fe080278df..bcbabeeab12a 100644 --- a/drivers/media/rc/img-ir/img-ir-core.c +++ b/drivers/media/rc/img-ir/img-ir-core.c @@ -92,10 +92,9 @@ static int img_ir_probe(struct platform_device *pdev) /* Private driver data */ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(&pdev->dev, "cannot allocate device data\n"); + if (!priv) return -ENOMEM; - } + platform_set_drvdata(pdev, priv); priv->dev = &pdev->dev; spin_lock_init(&priv->lock); -- cgit v1.2.3 From efdc16adb7d37a57b4d07833bbab73a0a1aed476 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Fri, 1 Sep 2017 08:34:50 -0300 Subject: [media] media: rc: avermedia keymap for a800 The keymap is missing one key, and correct another. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/rc-avermedia-m135a.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/keymaps/rc-avermedia-m135a.c b/drivers/media/rc/keymaps/rc-avermedia-m135a.c index 9882e2cde975..6d5a73b7ccec 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-m135a.c +++ b/drivers/media/rc/keymaps/rc-avermedia-m135a.c @@ -43,7 +43,8 @@ static struct rc_map_table avermedia_m135a[] = { { 0x0213, KEY_RIGHT }, /* -> or L */ { 0x0212, KEY_LEFT }, /* <- or R */ - { 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */ + { 0x0215, KEY_MENU }, + { 0x0217, KEY_CAMERA }, /* Capturar Imagem or Snapshot */ { 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */ { 0x0303, KEY_CHANNELUP }, -- cgit v1.2.3 From 831c4c81e8ceba7d34b7fc66da1693bc4b9e7e11 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Fri, 1 Sep 2017 09:55:59 -0300 Subject: [media] media: rc: ensure that protocols are enabled for scancode drivers rc scancode drivers without change_protocol should have all protocols enabled at all time. This was only true for cec and ir-kbd-i2c. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/cec-core.c | 1 - drivers/media/i2c/ir-kbd-i2c.c | 1 - drivers/media/rc/rc-main.c | 3 +++ 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c index e3a1fb6d6690..5870da6a567f 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c @@ -277,7 +277,6 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, adap->rc->input_id.version = 1; adap->rc->driver_name = CEC_NAME; adap->rc->allowed_protocols = RC_PROTO_BIT_CEC; - adap->rc->enabled_protocols = RC_PROTO_BIT_CEC; adap->rc->priv = adap; adap->rc->map_name = RC_MAP_CEC; adap->rc->timeout = MS_TO_NS(100); diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index a374e2a0ac3d..8b5f7d0435e4 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -460,7 +460,6 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) */ rc->map_name = ir->ir_codes; rc->allowed_protocols = rc_proto; - rc->enabled_protocols = rc_proto; if (!rc->driver_name) rc->driver_name = MODULE_NAME; diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 33bddba6e541..127f3215cd84 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -1638,6 +1638,9 @@ static int rc_prepare_rx_device(struct rc_dev *dev) rc_proto = BIT_ULL(rc_map->rc_proto); + if (dev->driver_type == RC_DRIVER_SCANCODE && !dev->change_protocol) + dev->enabled_protocols = dev->allowed_protocols; + if (dev->change_protocol) { rc = dev->change_protocol(dev, &rc_proto); if (rc < 0) -- cgit v1.2.3 From 6d75db305b8a964bfec337ca5f3c2cd5047b9bb1 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Fri, 1 Sep 2017 11:30:50 -0300 Subject: [media] media: rc: if protocols can't be changed, don't be writable If the protocols of an rc device cannot be changed, ensure the sysfs file is not writable. This makes it possible to detect this from userspace, so ir-keytable can deal with case without giving an error. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-main.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 127f3215cd84..42ac3490b5f8 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -1487,7 +1487,10 @@ static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) /* * Static device attribute struct with the sysfs attributes for IR's */ -static DEVICE_ATTR(protocols, 0644, show_protocols, store_protocols); +static struct device_attribute dev_attr_ro_protocols = +__ATTR(protocols, 0444, show_protocols, NULL); +static struct device_attribute dev_attr_rw_protocols = +__ATTR(protocols, 0644, show_protocols, store_protocols); static DEVICE_ATTR(wakeup_protocols, 0644, show_wakeup_protocols, store_wakeup_protocols); static RC_FILTER_ATTR(filter, S_IRUGO|S_IWUSR, @@ -1499,13 +1502,22 @@ static RC_FILTER_ATTR(wakeup_filter, S_IRUGO|S_IWUSR, static RC_FILTER_ATTR(wakeup_filter_mask, S_IRUGO|S_IWUSR, show_filter, store_filter, RC_FILTER_WAKEUP, true); -static struct attribute *rc_dev_protocol_attrs[] = { - &dev_attr_protocols.attr, +static struct attribute *rc_dev_rw_protocol_attrs[] = { + &dev_attr_rw_protocols.attr, NULL, }; -static const struct attribute_group rc_dev_protocol_attr_grp = { - .attrs = rc_dev_protocol_attrs, +static const struct attribute_group rc_dev_rw_protocol_attr_grp = { + .attrs = rc_dev_rw_protocol_attrs, +}; + +static struct attribute *rc_dev_ro_protocol_attrs[] = { + &dev_attr_ro_protocols.attr, + NULL, +}; + +static const struct attribute_group rc_dev_ro_protocol_attr_grp = { + .attrs = rc_dev_ro_protocol_attrs, }; static struct attribute *rc_dev_filter_attrs[] = { @@ -1732,8 +1744,10 @@ int rc_register_device(struct rc_dev *dev) dev_set_drvdata(&dev->dev, dev); dev->dev.groups = dev->sysfs_groups; - if (dev->driver_type != RC_DRIVER_IR_RAW_TX) - dev->sysfs_groups[attr++] = &rc_dev_protocol_attr_grp; + if (dev->driver_type == RC_DRIVER_SCANCODE && !dev->change_protocol) + dev->sysfs_groups[attr++] = &rc_dev_ro_protocol_attr_grp; + else if (dev->driver_type != RC_DRIVER_IR_RAW_TX) + dev->sysfs_groups[attr++] = &rc_dev_rw_protocol_attr_grp; if (dev->s_filter) dev->sysfs_groups[attr++] = &rc_dev_filter_attr_grp; if (dev->s_wakeup_filter) -- cgit v1.2.3 From b9f407e31c50730784f70ec2deec71491395565f Mon Sep 17 00:00:00 2001 From: Sean Young Date: Fri, 1 Sep 2017 11:34:23 -0300 Subject: [media] media: rc: include device name in rc udev event This name is also stored in the input's device name, but that is not available in TX only hardware (no input device). Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 42ac3490b5f8..8c828fee4f5a 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -1480,6 +1480,8 @@ static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name); if (dev->driver_name) ADD_HOTPLUG_VAR("DRV_NAME=%s", dev->driver_name); + if (dev->device_name) + ADD_HOTPLUG_VAR("DEV_NAME=%s", dev->device_name); return 0; } -- cgit v1.2.3 From 771f87268e8cd0e50719eb20f0b613ec4b2a19ec Mon Sep 17 00:00:00 2001 From: Sean Young Date: Wed, 6 Sep 2017 08:19:06 -0300 Subject: [media] media: vp7045: port TwinhanDTV Alpha to rc-core Only the nec protocol is understood, but then it doesn't pass on the full scancode and it ignores the nec repeats its own remote sends, so holding buttons does not work. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/rc-twinhan1027.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb-remote.c | 1 + drivers/media/usb/dvb-usb/dvb-usb.h | 1 + drivers/media/usb/dvb-usb/vp7045.c | 88 +++++------------------------- 4 files changed, 18 insertions(+), 74 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/keymaps/rc-twinhan1027.c b/drivers/media/rc/keymaps/rc-twinhan1027.c index 2275b37c61d2..78bb3143a1a8 100644 --- a/drivers/media/rc/keymaps/rc-twinhan1027.c +++ b/drivers/media/rc/keymaps/rc-twinhan1027.c @@ -66,7 +66,7 @@ static struct rc_map_list twinhan_vp1027_map = { .map = { .scan = twinhan_vp1027, .size = ARRAY_SIZE(twinhan_vp1027), - .rc_proto = RC_PROTO_UNKNOWN, /* Legacy IR type */ + .rc_proto = RC_PROTO_NEC, .name = RC_MAP_TWINHAN_VP1027_DVBS, } }; diff --git a/drivers/media/usb/dvb-usb/dvb-usb-remote.c b/drivers/media/usb/dvb-usb/dvb-usb-remote.c index b027d378102a..bf7dcd6b03e0 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c @@ -283,6 +283,7 @@ static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d) dev->input_phys = d->rc_phys; dev->dev.parent = &d->udev->dev; dev->priv = d; + dev->scancode_mask = d->props.rc.core.scancode_mask; err = rc_register_device(dev); if (err < 0) { diff --git a/drivers/media/usb/dvb-usb/dvb-usb.h b/drivers/media/usb/dvb-usb/dvb-usb.h index 72468fdffa18..1da9e47553f5 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb.h +++ b/drivers/media/usb/dvb-usb/dvb-usb.h @@ -207,6 +207,7 @@ struct dvb_rc { int (*rc_query) (struct dvb_usb_device *d); int rc_interval; bool bulk_mode; /* uses bulk mode */ + u32 scancode_mask; }; /** diff --git a/drivers/media/usb/dvb-usb/vp7045.c b/drivers/media/usb/dvb-usb/vp7045.c index 13340af0d39c..2527b88beb87 100644 --- a/drivers/media/usb/dvb-usb/vp7045.c +++ b/drivers/media/usb/dvb-usb/vp7045.c @@ -97,82 +97,22 @@ static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff) return vp7045_usb_op(d,SET_TUNER_POWER,&v,1,NULL,0,150); } -/* remote control stuff */ - -/* The keymapping struct. Somehow this should be loaded to the driver, but - * currently it is hardcoded. */ -static struct rc_map_table rc_map_vp7045_table[] = { - { 0x0016, KEY_POWER }, - { 0x0010, KEY_MUTE }, - { 0x0003, KEY_1 }, - { 0x0001, KEY_2 }, - { 0x0006, KEY_3 }, - { 0x0009, KEY_4 }, - { 0x001d, KEY_5 }, - { 0x001f, KEY_6 }, - { 0x000d, KEY_7 }, - { 0x0019, KEY_8 }, - { 0x001b, KEY_9 }, - { 0x0015, KEY_0 }, - { 0x0005, KEY_CHANNELUP }, - { 0x0002, KEY_CHANNELDOWN }, - { 0x001e, KEY_VOLUMEUP }, - { 0x000a, KEY_VOLUMEDOWN }, - { 0x0011, KEY_RECORD }, - { 0x0017, KEY_FAVORITES }, /* Heart symbol - Channel list. */ - { 0x0014, KEY_PLAY }, - { 0x001a, KEY_STOP }, - { 0x0040, KEY_REWIND }, - { 0x0012, KEY_FASTFORWARD }, - { 0x000e, KEY_PREVIOUS }, /* Recall - Previous channel. */ - { 0x004c, KEY_PAUSE }, - { 0x004d, KEY_SCREEN }, /* Full screen mode. */ - { 0x0054, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ - { 0x000c, KEY_CANCEL }, /* Cancel */ - { 0x001c, KEY_EPG }, /* EPG */ - { 0x0000, KEY_TAB }, /* Tab */ - { 0x0048, KEY_INFO }, /* Preview */ - { 0x0004, KEY_LIST }, /* RecordList */ - { 0x000f, KEY_TEXT }, /* Teletext */ - { 0x0041, KEY_PREVIOUSSONG }, - { 0x0042, KEY_NEXTSONG }, - { 0x004b, KEY_UP }, - { 0x0051, KEY_DOWN }, - { 0x004e, KEY_LEFT }, - { 0x0052, KEY_RIGHT }, - { 0x004f, KEY_ENTER }, - { 0x0013, KEY_CANCEL }, - { 0x004a, KEY_CLEAR }, - { 0x0054, KEY_PRINT }, /* Capture */ - { 0x0043, KEY_SUBTITLE }, /* Subtitle/CC */ - { 0x0008, KEY_VIDEO }, /* A/V */ - { 0x0007, KEY_SLEEP }, /* Hibernate */ - { 0x0045, KEY_ZOOM }, /* Zoom+ */ - { 0x0018, KEY_RED}, - { 0x0053, KEY_GREEN}, - { 0x005e, KEY_YELLOW}, - { 0x005f, KEY_BLUE} -}; - -static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +static int vp7045_rc_query(struct dvb_usb_device *d) { u8 key; - int i; vp7045_usb_op(d,RC_VAL_READ,NULL,0,&key,1,20); deb_rc("remote query key: %x %d\n",key,key); - if (key == 0x44) { - *state = REMOTE_NO_KEY_PRESSED; - return 0; + if (key != 0x44) { + /* + * The 8 bit address isn't available, but since the remote uses + * address 0 we'll use that. nec repeats are ignored too, even + * though the remote sends them. + */ + rc_keydown(d->rc_dev, RC_PROTO_NEC, RC_SCANCODE_NEC(0, key), 0); } - for (i = 0; i < ARRAY_SIZE(rc_map_vp7045_table); i++) - if (rc5_data(&rc_map_vp7045_table[i]) == key) { - *state = REMOTE_KEY_PRESSED; - *event = rc_map_vp7045_table[i].keycode; - break; - } return 0; } @@ -265,11 +205,13 @@ static struct dvb_usb_device_properties vp7045_properties = { .power_ctrl = vp7045_power_ctrl, .read_mac_address = vp7045_read_mac_addr, - .rc.legacy = { - .rc_interval = 400, - .rc_map_table = rc_map_vp7045_table, - .rc_map_size = ARRAY_SIZE(rc_map_vp7045_table), - .rc_query = vp7045_rc_query, + .rc.core = { + .rc_interval = 400, + .rc_codes = RC_MAP_TWINHAN_VP1027_DVBS, + .module_name = KBUILD_MODNAME, + .rc_query = vp7045_rc_query, + .allowed_protos = RC_PROTO_BIT_NEC, + .scancode_mask = 0xff, }, .num_device_descs = 2, -- cgit v1.2.3 From c25895c7d6c957124ceb3b090b7eaa68b1d3bf54 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 5 Sep 2017 09:07:50 -0300 Subject: [media] media: imon: make two const arrays static, reduces object code size Don't populate the const arrays vfd_packet6 and fp_packet on the stack, instead make them static. Makes the object code smaller by over 600 bytes: Before: text data bss dec hex filename 43794 17920 1024 62738 f512 drivers/media/rc/imon.o After: text data bss dec hex filename 42994 18080 1024 62098 f292 drivers/media/rc/imon.o Signed-off-by: Colin Ian King Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/imon.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 188cf1b4ebb1..b83ad6d483aa 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -943,7 +943,7 @@ static ssize_t vfd_write(struct file *file, const char __user *buf, int seq; int retval = 0; struct imon_context *ictx; - const unsigned char vfd_packet6[] = { + static const unsigned char vfd_packet6[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; ictx = file->private_data; @@ -2047,8 +2047,8 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx) { struct rc_dev *rdev; int ret; - const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x88 }; + static const unsigned char fp_packet[] = { + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88 }; rdev = rc_allocate_device(ictx->dev_descr->flags & IMON_IR_RAW ? RC_DRIVER_IR_RAW : RC_DRIVER_SCANCODE); -- cgit v1.2.3 From 94d40b2ff2fb2cb1763d7afb96360a0eb95f1493 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 7 Sep 2017 20:34:35 -0300 Subject: [media] media: rc: gpio-ir-recv: use helper variable to access device info Using explicit struct device variable makes code a bit more readable. Signed-off-by: Ladislav Michl Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/gpio-ir-recv.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 7248b3662285..741a68c192ce 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -95,18 +95,18 @@ err_get_value: static int gpio_ir_recv_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct gpio_rc_dev *gpio_dev; struct rc_dev *rcdev; - const struct gpio_ir_recv_platform_data *pdata = - pdev->dev.platform_data; + const struct gpio_ir_recv_platform_data *pdata = dev->platform_data; int rc; if (pdev->dev.of_node) { struct gpio_ir_recv_platform_data *dtpdata = - devm_kzalloc(&pdev->dev, sizeof(*dtpdata), GFP_KERNEL); + devm_kzalloc(dev, sizeof(*dtpdata), GFP_KERNEL); if (!dtpdata) return -ENOMEM; - rc = gpio_ir_recv_get_devtree_pdata(&pdev->dev, dtpdata); + rc = gpio_ir_recv_get_devtree_pdata(dev, dtpdata); if (rc) return rc; pdata = dtpdata; @@ -135,7 +135,7 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) rcdev->input_id.vendor = 0x0001; rcdev->input_id.product = 0x0001; rcdev->input_id.version = 0x0100; - rcdev->dev.parent = &pdev->dev; + rcdev->dev.parent = dev; rcdev->driver_name = GPIO_IR_DRIVER_NAME; rcdev->min_timeout = 1; rcdev->timeout = IR_DEFAULT_TIMEOUT; @@ -159,7 +159,7 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) rc = rc_register_device(rcdev); if (rc < 0) { - dev_err(&pdev->dev, "failed to register rc device\n"); + dev_err(dev, "failed to register rc device (%d)\n", rc); goto err_register_rc_device; } -- cgit v1.2.3 From 08d94274b8d0c25551b29a069334d8e627333a82 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 7 Sep 2017 20:35:22 -0300 Subject: [media] media: rc: gpio-ir-recv: use devm_kzalloc Use of devm_kzalloc simplifies error unwinding. Signed-off-by: Ladislav Michl Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/gpio-ir-recv.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 741a68c192ce..6fe7e7c14fe4 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -118,15 +118,13 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) if (pdata->gpio_nr < 0) return -EINVAL; - gpio_dev = kzalloc(sizeof(struct gpio_rc_dev), GFP_KERNEL); + gpio_dev = devm_kzalloc(dev, sizeof(*gpio_dev), GFP_KERNEL); if (!gpio_dev) return -ENOMEM; rcdev = rc_allocate_device(RC_DRIVER_IR_RAW); - if (!rcdev) { - rc = -ENOMEM; - goto err_allocate_device; - } + if (!rcdev) + return -ENOMEM; rcdev->priv = gpio_dev; rcdev->device_name = GPIO_IR_DEVICE_NAME; @@ -182,8 +180,6 @@ err_gpio_direction_input: gpio_free(pdata->gpio_nr); err_gpio_request: rc_free_device(rcdev); -err_allocate_device: - kfree(gpio_dev); return rc; } @@ -194,7 +190,6 @@ static int gpio_ir_recv_remove(struct platform_device *pdev) free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev); rc_unregister_device(gpio_dev->rcdev); gpio_free(gpio_dev->gpio_nr); - kfree(gpio_dev); return 0; } -- cgit v1.2.3 From f4940b563feff6f2514fc8c5309b844b0540a4cb Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 7 Sep 2017 20:36:11 -0300 Subject: [media] media: rc: gpio-ir-recv: use devm_rc_allocate_device Use of devm_rc_allocate_device simplifies error unwinding. Signed-off-by: Ladislav Michl Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/gpio-ir-recv.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 6fe7e7c14fe4..98dcb8399506 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -122,7 +122,7 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) if (!gpio_dev) return -ENOMEM; - rcdev = rc_allocate_device(RC_DRIVER_IR_RAW); + rcdev = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW); if (!rcdev) return -ENOMEM; @@ -150,7 +150,7 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv"); if (rc < 0) - goto err_gpio_request; + return rc; rc = gpio_direction_input(pdata->gpio_nr); if (rc < 0) goto err_gpio_direction_input; @@ -178,8 +178,6 @@ err_request_irq: err_register_rc_device: err_gpio_direction_input: gpio_free(pdata->gpio_nr); -err_gpio_request: - rc_free_device(rcdev); return rc; } -- cgit v1.2.3 From fcca09edb9f6e406de6014e3f1c2695b15b52abb Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 7 Sep 2017 20:36:39 -0300 Subject: [media] media: rc: gpio-ir-recv: use devm_gpio_request_one Use of devm_gpio_request_one simplifies error unwinding. Signed-off-by: Ladislav Michl Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/gpio-ir-recv.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 98dcb8399506..77044d664371 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -148,12 +148,10 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) gpio_dev->gpio_nr = pdata->gpio_nr; gpio_dev->active_low = pdata->active_low; - rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv"); + rc = devm_gpio_request_one(dev, pdata->gpio_nr, GPIOF_DIR_IN, + "gpio-ir-recv"); if (rc < 0) return rc; - rc = gpio_direction_input(pdata->gpio_nr); - if (rc < 0) - goto err_gpio_direction_input; rc = rc_register_device(rcdev); if (rc < 0) { @@ -176,8 +174,6 @@ err_request_irq: rc_unregister_device(rcdev); rcdev = NULL; err_register_rc_device: -err_gpio_direction_input: - gpio_free(pdata->gpio_nr); return rc; } @@ -187,7 +183,6 @@ static int gpio_ir_recv_remove(struct platform_device *pdev) free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev); rc_unregister_device(gpio_dev->rcdev); - gpio_free(gpio_dev->gpio_nr); return 0; } -- cgit v1.2.3 From 52ea79910720c56420f58771b9790e257764e006 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 7 Sep 2017 20:37:07 -0300 Subject: [media] media: rc: gpio-ir-recv: use devm_rc_register_device Use of devm_rc_register_device simplifies error unwinding. Signed-off-by: Ladislav Michl Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/gpio-ir-recv.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 77044d664371..ae5f9099c8a6 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -153,10 +153,10 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) if (rc < 0) return rc; - rc = rc_register_device(rcdev); + rc = devm_rc_register_device(dev, rcdev); if (rc < 0) { dev_err(dev, "failed to register rc device (%d)\n", rc); - goto err_register_rc_device; + return rc; } platform_set_drvdata(pdev, gpio_dev); @@ -171,9 +171,6 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) return 0; err_request_irq: - rc_unregister_device(rcdev); - rcdev = NULL; -err_register_rc_device: return rc; } @@ -182,7 +179,6 @@ static int gpio_ir_recv_remove(struct platform_device *pdev) struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev); - rc_unregister_device(gpio_dev->rcdev); return 0; } -- cgit v1.2.3 From 375929f9f48356e862789c72ddc1175d89866f44 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 7 Sep 2017 20:37:36 -0300 Subject: [media] media: rc: gpio-ir-recv: do not allow threaded interrupt handler Requesting any context irq is not actually great idea since threaded interrupt handler is run at too unpredictable time which turns timing information wrong. Fix it by requesting regular interrupt. Signed-off-by: Ladislav Michl Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/gpio-ir-recv.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index ae5f9099c8a6..d82ddf906695 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -161,10 +161,9 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gpio_dev); - rc = request_any_context_irq(gpio_to_irq(pdata->gpio_nr), - gpio_ir_recv_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - "gpio-ir-recv-irq", gpio_dev); + rc = request_irq(gpio_to_irq(pdata->gpio_nr), gpio_ir_recv_irq, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + "gpio-ir-recv-irq", gpio_dev); if (rc < 0) goto err_request_irq; -- cgit v1.2.3 From 1a2a60b1af1293e8ee7780691ef90a8aa68991c1 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 7 Sep 2017 20:38:20 -0300 Subject: [media] media: rc: gpio-ir-recv: use devm_request_irq Use of devm_request_irq simplifies error unwinding and as free_irq was the last user of driver remove function, remove it too. Signed-off-by: Ladislav Michl Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/gpio-ir-recv.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index d82ddf906695..fe0dd2443af0 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -161,24 +161,10 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gpio_dev); - rc = request_irq(gpio_to_irq(pdata->gpio_nr), gpio_ir_recv_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - "gpio-ir-recv-irq", gpio_dev); - if (rc < 0) - goto err_request_irq; - - return 0; - -err_request_irq: - return rc; -} - -static int gpio_ir_recv_remove(struct platform_device *pdev) -{ - struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); - - free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev); - return 0; + return devm_request_irq(dev, gpio_to_irq(pdata->gpio_nr), + gpio_ir_recv_irq, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + "gpio-ir-recv-irq", gpio_dev); } #ifdef CONFIG_PM @@ -216,7 +202,6 @@ static const struct dev_pm_ops gpio_ir_recv_pm_ops = { static struct platform_driver gpio_ir_recv_driver = { .probe = gpio_ir_recv_probe, - .remove = gpio_ir_recv_remove, .driver = { .name = GPIO_IR_DRIVER_NAME, .of_match_table = of_match_ptr(gpio_ir_recv_of_match), -- cgit v1.2.3 From 916d1c9fd457a11e1f1fed70f123f461da72a56d Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 7 Sep 2017 20:39:14 -0300 Subject: [media] media: rc: gpio-ir-recv: use KBUILD_MODNAME There already is standard macro providing driver name, use it. Signed-off-by: Ladislav Michl Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/gpio-ir-recv.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index fe0dd2443af0..b78195f06354 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -23,7 +23,6 @@ #include #include -#define GPIO_IR_DRIVER_NAME "gpio-rc-recv" #define GPIO_IR_DEVICE_NAME "gpio_ir_recv" struct gpio_rc_dev { @@ -134,7 +133,7 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) rcdev->input_id.product = 0x0001; rcdev->input_id.version = 0x0100; rcdev->dev.parent = dev; - rcdev->driver_name = GPIO_IR_DRIVER_NAME; + rcdev->driver_name = KBUILD_MODNAME; rcdev->min_timeout = 1; rcdev->timeout = IR_DEFAULT_TIMEOUT; rcdev->max_timeout = 10 * IR_DEFAULT_TIMEOUT; @@ -203,7 +202,7 @@ static const struct dev_pm_ops gpio_ir_recv_pm_ops = { static struct platform_driver gpio_ir_recv_driver = { .probe = gpio_ir_recv_probe, .driver = { - .name = GPIO_IR_DRIVER_NAME, + .name = KBUILD_MODNAME, .of_match_table = of_match_ptr(gpio_ir_recv_of_match), #ifdef CONFIG_PM .pm = &gpio_ir_recv_pm_ops, -- cgit v1.2.3 From 5c95878f618cf4f3eb0a4c7ff54a09ca6d4d0426 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 7 Sep 2017 20:39:45 -0300 Subject: [media] media: rc: gpio-ir-recv: remove gpio_ir_recv_platform_data gpio_ir_recv_platform_data are not used anywhere in kernel tree, so remove it. Signed-off-by: Ladislav Michl Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/gpio-ir-recv.c | 92 +++++++----------------- include/linux/platform_data/media/gpio-ir-recv.h | 23 ------ 2 files changed, 26 insertions(+), 89 deletions(-) delete mode 100644 include/linux/platform_data/media/gpio-ir-recv.h (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index b78195f06354..2634b81cbe7e 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -21,7 +21,6 @@ #include #include #include -#include #define GPIO_IR_DEVICE_NAME "gpio_ir_recv" @@ -31,45 +30,6 @@ struct gpio_rc_dev { bool active_low; }; -#ifdef CONFIG_OF -/* - * Translate OpenFirmware node properties into platform_data - */ -static int gpio_ir_recv_get_devtree_pdata(struct device *dev, - struct gpio_ir_recv_platform_data *pdata) -{ - struct device_node *np = dev->of_node; - enum of_gpio_flags flags; - int gpio; - - gpio = of_get_gpio_flags(np, 0, &flags); - if (gpio < 0) { - if (gpio != -EPROBE_DEFER) - dev_err(dev, "Failed to get gpio flags (%d)\n", gpio); - return gpio; - } - - pdata->gpio_nr = gpio; - pdata->active_low = (flags & OF_GPIO_ACTIVE_LOW); - /* probe() takes care of map_name == NULL or allowed_protos == 0 */ - pdata->map_name = of_get_property(np, "linux,rc-map-name", NULL); - pdata->allowed_protos = 0; - - return 0; -} - -static const struct of_device_id gpio_ir_recv_of_match[] = { - { .compatible = "gpio-ir-receiver", }, - { }, -}; -MODULE_DEVICE_TABLE(of, gpio_ir_recv_of_match); - -#else /* !CONFIG_OF */ - -#define gpio_ir_recv_get_devtree_pdata(dev, pdata) (-ENOSYS) - -#endif - static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) { struct gpio_rc_dev *gpio_dev = dev_id; @@ -95,32 +55,29 @@ err_get_value: static int gpio_ir_recv_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; struct gpio_rc_dev *gpio_dev; + enum of_gpio_flags flags; struct rc_dev *rcdev; - const struct gpio_ir_recv_platform_data *pdata = dev->platform_data; int rc; - if (pdev->dev.of_node) { - struct gpio_ir_recv_platform_data *dtpdata = - devm_kzalloc(dev, sizeof(*dtpdata), GFP_KERNEL); - if (!dtpdata) - return -ENOMEM; - rc = gpio_ir_recv_get_devtree_pdata(dev, dtpdata); - if (rc) - return rc; - pdata = dtpdata; - } - - if (!pdata) - return -EINVAL; - - if (pdata->gpio_nr < 0) - return -EINVAL; + if (!np) + return -ENODEV; gpio_dev = devm_kzalloc(dev, sizeof(*gpio_dev), GFP_KERNEL); if (!gpio_dev) return -ENOMEM; + rc = of_get_gpio_flags(np, 0, &flags); + if (rc < 0) { + if (rc != -EPROBE_DEFER) + dev_err(dev, "Failed to get gpio flags (%d)\n", rc); + return rc; + } + + gpio_dev->gpio_nr = rc; + gpio_dev->active_low = (flags & OF_GPIO_ACTIVE_LOW); + rcdev = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW); if (!rcdev) return -ENOMEM; @@ -137,17 +94,14 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) rcdev->min_timeout = 1; rcdev->timeout = IR_DEFAULT_TIMEOUT; rcdev->max_timeout = 10 * IR_DEFAULT_TIMEOUT; - if (pdata->allowed_protos) - rcdev->allowed_protocols = pdata->allowed_protos; - else - rcdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; - rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY; + rcdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; + rcdev->map_name = of_get_property(np, "linux,rc-map-name", NULL); + if (!rcdev->map_name) + rcdev->map_name = RC_MAP_EMPTY; gpio_dev->rcdev = rcdev; - gpio_dev->gpio_nr = pdata->gpio_nr; - gpio_dev->active_low = pdata->active_low; - rc = devm_gpio_request_one(dev, pdata->gpio_nr, GPIOF_DIR_IN, + rc = devm_gpio_request_one(dev, gpio_dev->gpio_nr, GPIOF_DIR_IN, "gpio-ir-recv"); if (rc < 0) return rc; @@ -160,7 +114,7 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gpio_dev); - return devm_request_irq(dev, gpio_to_irq(pdata->gpio_nr), + return devm_request_irq(dev, gpio_to_irq(gpio_dev->gpio_nr), gpio_ir_recv_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "gpio-ir-recv-irq", gpio_dev); @@ -199,6 +153,12 @@ static const struct dev_pm_ops gpio_ir_recv_pm_ops = { }; #endif +static const struct of_device_id gpio_ir_recv_of_match[] = { + { .compatible = "gpio-ir-receiver", }, + { }, +}; +MODULE_DEVICE_TABLE(of, gpio_ir_recv_of_match); + static struct platform_driver gpio_ir_recv_driver = { .probe = gpio_ir_recv_probe, .driver = { diff --git a/include/linux/platform_data/media/gpio-ir-recv.h b/include/linux/platform_data/media/gpio-ir-recv.h deleted file mode 100644 index 0c298f569d5a..000000000000 --- a/include/linux/platform_data/media/gpio-ir-recv.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __GPIO_IR_RECV_H__ -#define __GPIO_IR_RECV_H__ - -struct gpio_ir_recv_platform_data { - int gpio_nr; - bool active_low; - u64 allowed_protos; - const char *map_name; -}; - -#endif /* __GPIO_IR_RECV_H__ */ -- cgit v1.2.3 From eed008e605d13ee4fb64668350be58999e85aac7 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 7 Sep 2017 20:41:32 -0300 Subject: [media] media: rc: gpio-ir-recv: use gpiolib API Gpiolib API is preferred way to access gpios. Signed-off-by: Ladislav Michl Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/gpio-ir-recv.c | 59 +++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 38 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 2634b81cbe7e..24641a9079da 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -26,29 +26,19 @@ struct gpio_rc_dev { struct rc_dev *rcdev; - int gpio_nr; - bool active_low; + struct gpio_desc *gpiod; + int irq; }; static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) { + int val; struct gpio_rc_dev *gpio_dev = dev_id; - int gval; - int rc = 0; - gval = gpio_get_value(gpio_dev->gpio_nr); + val = gpiod_get_value(gpio_dev->gpiod); + if (val >= 0) + ir_raw_event_store_edge(gpio_dev->rcdev, val == 1); - if (gval < 0) - goto err_get_value; - - if (gpio_dev->active_low) - gval = !gval; - - rc = ir_raw_event_store_edge(gpio_dev->rcdev, gval == 1); - if (rc < 0) - goto err_get_value; - -err_get_value: return IRQ_HANDLED; } @@ -57,7 +47,6 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct gpio_rc_dev *gpio_dev; - enum of_gpio_flags flags; struct rc_dev *rcdev; int rc; @@ -68,15 +57,17 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) if (!gpio_dev) return -ENOMEM; - rc = of_get_gpio_flags(np, 0, &flags); - if (rc < 0) { + gpio_dev->gpiod = devm_gpiod_get(dev, NULL, GPIOD_IN); + if (IS_ERR(gpio_dev->gpiod)) { + rc = PTR_ERR(gpio_dev->gpiod); + /* Just try again if this happens */ if (rc != -EPROBE_DEFER) - dev_err(dev, "Failed to get gpio flags (%d)\n", rc); + dev_err(dev, "error getting gpio (%d)\n", rc); return rc; } - - gpio_dev->gpio_nr = rc; - gpio_dev->active_low = (flags & OF_GPIO_ACTIVE_LOW); + gpio_dev->irq = gpiod_to_irq(gpio_dev->gpiod); + if (gpio_dev->irq < 0) + return gpio_dev->irq; rcdev = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW); if (!rcdev) @@ -101,11 +92,6 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) gpio_dev->rcdev = rcdev; - rc = devm_gpio_request_one(dev, gpio_dev->gpio_nr, GPIOF_DIR_IN, - "gpio-ir-recv"); - if (rc < 0) - return rc; - rc = devm_rc_register_device(dev, rcdev); if (rc < 0) { dev_err(dev, "failed to register rc device (%d)\n", rc); @@ -114,8 +100,7 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gpio_dev); - return devm_request_irq(dev, gpio_to_irq(gpio_dev->gpio_nr), - gpio_ir_recv_irq, + return devm_request_irq(dev, gpio_dev->irq, gpio_ir_recv_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "gpio-ir-recv-irq", gpio_dev); } @@ -123,26 +108,24 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) #ifdef CONFIG_PM static int gpio_ir_recv_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); + struct gpio_rc_dev *gpio_dev = dev_get_drvdata(dev); if (device_may_wakeup(dev)) - enable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr)); + enable_irq_wake(gpio_dev->irq); else - disable_irq(gpio_to_irq(gpio_dev->gpio_nr)); + disable_irq(gpio_dev->irq); return 0; } static int gpio_ir_recv_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); + struct gpio_rc_dev *gpio_dev = dev_get_drvdata(dev); if (device_may_wakeup(dev)) - disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr)); + disable_irq_wake(gpio_dev->irq); else - enable_irq(gpio_to_irq(gpio_dev->gpio_nr)); + enable_irq(gpio_dev->irq); return 0; } -- cgit v1.2.3 From 8ca01d4f9588bd58722a388400896c11e4343047 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Fri, 8 Sep 2017 13:33:36 -0300 Subject: [media] media: rc: Use bsearch library function Replace self coded binary search, by existing library version. Signed-off-by: Thomas Meyer Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-main.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 8c828fee4f5a..e0901a2a1ec9 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -15,6 +15,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include #include #include @@ -460,6 +461,18 @@ static int ir_setkeytable(struct rc_dev *dev, return rc; } +static int rc_map_cmp(const void *key, const void *elt) +{ + const unsigned int *scancode = key; + const struct rc_map_table *e = elt; + + if (*scancode < e->scancode) + return -1; + else if (*scancode > e->scancode) + return 1; + return 0; +} + /** * ir_lookup_by_scancode() - locate mapping by scancode * @rc_map: the struct rc_map to search @@ -472,21 +485,14 @@ static int ir_setkeytable(struct rc_dev *dev, static unsigned int ir_lookup_by_scancode(const struct rc_map *rc_map, unsigned int scancode) { - int start = 0; - int end = rc_map->len - 1; - int mid; - - while (start <= end) { - mid = (start + end) / 2; - if (rc_map->scan[mid].scancode < scancode) - start = mid + 1; - else if (rc_map->scan[mid].scancode > scancode) - end = mid - 1; - else - return mid; - } + struct rc_map_table *res; - return -1U; + res = bsearch(&scancode, rc_map->scan, rc_map->len, + sizeof(struct rc_map_table), rc_map_cmp); + if (!res) + return -1U; + else + return res - rc_map->scan; } /** -- cgit v1.2.3 From 5573d124292a01afaecb7612773c21321ffcd6d2 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 8 Sep 2017 13:39:29 -0300 Subject: [media] media: default for RC_CORE should be n The Linus policy on Kconfig is that the default should be no for all new devices. I.e the user rebuild a new kernel from an old config should not by default get a larger kernel. Fixes: b4c184e506a4 ("[media] media: reorganize the main Kconfig items") Signed-off-by: Stephen Hemminger Acked-by: Geert Uytterhoeven Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index d9ce8ff55d0c..467cf2bdbd42 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -2,7 +2,6 @@ menuconfig RC_CORE tristate "Remote Controller support" depends on INPUT - default y ---help--- Enable support for Remote Controllers on Linux. This is needed in order to support several video capture adapters, -- cgit v1.2.3 From d7a6795b1d7cce8c6dcfd67d3348ba68ade9d397 Mon Sep 17 00:00:00 2001 From: Marc Gonzalez Date: Mon, 18 Sep 2017 11:31:41 -0300 Subject: [media] media: rc: Delete duplicate debug message ir_setkeytable() and ir_create_table() print the same debug message. Delete the one in ir_setkeytable() Signed-off-by: Marc Gonzalez Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-main.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index e0901a2a1ec9..cb78e5702bef 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -440,9 +440,6 @@ static int ir_setkeytable(struct rc_dev *dev, if (rc) return rc; - IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", - rc_map->size, rc_map->alloc); - for (i = 0; i < from->size; i++) { index = ir_establish_scancode(dev, rc_map, from->scan[i].scancode, false); -- cgit v1.2.3 From a8c779eb056e9874c6278151ade857c3ac227db9 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 29 Aug 2017 07:45:59 -0300 Subject: [media] imon: Improve a size determination in two functions Replace the specification of data structures by pointer dereferences as the parameter for the operator "sizeof" to make the corresponding size determination a bit safer according to the Linux coding style convention. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/imon.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index b83ad6d483aa..9724fe8110e3 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -602,8 +602,7 @@ static int send_packet(struct imon_context *ictx) ictx->tx_urb->actual_length = 0; } else { /* fill request into kmalloc'ed space: */ - control_req = kmalloc(sizeof(struct usb_ctrlrequest), - GFP_KERNEL); + control_req = kmalloc(sizeof(*control_req), GFP_KERNEL); if (control_req == NULL) return -ENOMEM; @@ -2310,7 +2309,7 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf, struct usb_host_interface *iface_desc; int ret = -ENOMEM; - ictx = kzalloc(sizeof(struct imon_context), GFP_KERNEL); + ictx = kzalloc(sizeof(*ictx), GFP_KERNEL); if (!ictx) goto exit; -- cgit v1.2.3 From c1301077213d4dca34f01fc372b64d3c4a49a437 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 5 Oct 2017 09:11:06 -0300 Subject: [media] media: rc: fix gpio-ir-receiver build failure The 0-day robot reports: drivers/media/rc/gpio-ir-recv.c: In function 'gpio_ir_recv_irq': >> drivers/media/rc/gpio-ir-recv.c:38:8: error: implicit declaration of function 'gpiod_get_value' [-Werror=implicit-function-declaration] Fixes: eed008e605d1 ("[media] media: rc: gpio-ir-recv: use gpiolib API") For some reason only partial patch was applied. Also include gpio/consumer.h otherwise compile test fails. Reported-by: kbuild test robot Signed-off-by: Ladislav Michl Acked-by: Sean Young --- drivers/media/rc/Kconfig | 1 + drivers/media/rc/gpio-ir-recv.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 467cf2bdbd42..451cba1fe9bf 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -392,6 +392,7 @@ config RC_LOOPBACK config IR_GPIO_CIR tristate "GPIO IR remote control" depends on RC_CORE + depends on (OF && GPIOLIB) || COMPILE_TEST ---help--- Say Y if you want to use GPIO based IR Receiver. diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 24641a9079da..3d99b51384ac 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 2265425fd9c512cc9977516b5fe78d03ad9311a7 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 08:31:30 -0400 Subject: media: lirc_dev: remove min_timeout and max_timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are no users of this functionality (ir-lirc-codec.c has its own implementation and lirc_zilog.c doesn't use it) so remove it. This only affects users of the lirc kapi, not rc-core drivers. Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 18 ------------------ include/media/lirc_dev.h | 6 ------ 2 files changed, 24 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index e9dae8621670..e16d1138ca48 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -346,24 +346,6 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LIRC_GET_LENGTH: result = put_user(d->code_length, (__u32 __user *)arg); break; - case LIRC_GET_MIN_TIMEOUT: - if (!(d->features & LIRC_CAN_SET_REC_TIMEOUT) || - d->min_timeout == 0) { - result = -ENOTTY; - break; - } - - result = put_user(d->min_timeout, (__u32 __user *)arg); - break; - case LIRC_GET_MAX_TIMEOUT: - if (!(d->features & LIRC_CAN_SET_REC_TIMEOUT) || - d->max_timeout == 0) { - result = -ENOTTY; - break; - } - - result = put_user(d->max_timeout, (__u32 __user *)arg); - break; default: result = -ENOTTY; } diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 981dcabd5fd5..857da67bd931 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -125,10 +125,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, * @chunk_size: Size of each FIFO buffer. * Only used if @rbuf is NULL. * @data: private per-driver data - * @min_timeout: Minimum timeout for record. Valid only if - * LIRC_CAN_SET_REC_TIMEOUT is defined. - * @max_timeout: Maximum timeout for record. Valid only if - * LIRC_CAN_SET_REC_TIMEOUT is defined. * @buf: if %NULL, lirc_dev will allocate and manage the buffer, * otherwise allocated by the caller which will * have to write to the buffer by other means, like irq's @@ -155,8 +151,6 @@ struct lirc_dev { bool buf_internal; void *data; - int min_timeout; - int max_timeout; struct rc_dev *rdev; const struct file_operations *fops; struct module *owner; -- cgit v1.2.3 From 829bbf268894d0866bb9dd2b1e430cfa5c5f0779 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sun, 1 Oct 2017 16:38:29 -0400 Subject: media: rc: nec decoder should not send both repeat and keycode When receiving an nec repeat, rc_repeat() is called and then rc_keydown() with the last decoded scancode. That last call is redundant. Fixes: 265a2988d202 ("media: rc-core: consistent use of rc_repeat()") Cc: # v4.14 Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ir-nec-decoder.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c index 817c18f2ddd1..a95d09acc22a 100644 --- a/drivers/media/rc/ir-nec-decoder.c +++ b/drivers/media/rc/ir-nec-decoder.c @@ -87,8 +87,6 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) data->state = STATE_BIT_PULSE; return 0; } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) { - rc_repeat(dev); - IR_dprintk(1, "Repeat last key\n"); data->state = STATE_TRAILER_PULSE; return 0; } @@ -151,19 +149,26 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) break; - address = bitrev8((data->bits >> 24) & 0xff); - not_address = bitrev8((data->bits >> 16) & 0xff); - command = bitrev8((data->bits >> 8) & 0xff); - not_command = bitrev8((data->bits >> 0) & 0xff); + if (data->count == NEC_NBITS) { + address = bitrev8((data->bits >> 24) & 0xff); + not_address = bitrev8((data->bits >> 16) & 0xff); + command = bitrev8((data->bits >> 8) & 0xff); + not_command = bitrev8((data->bits >> 0) & 0xff); + + scancode = ir_nec_bytes_to_scancode(address, + not_address, + command, + not_command, + &rc_proto); - scancode = ir_nec_bytes_to_scancode(address, not_address, - command, not_command, - &rc_proto); + if (data->is_nec_x) + data->necx_repeat = true; - if (data->is_nec_x) - data->necx_repeat = true; + rc_keydown(dev, rc_proto, scancode, 0); + } else { + rc_repeat(dev); + } - rc_keydown(dev, rc_proto, scancode, 0); data->state = STATE_INACTIVE; return 0; } -- cgit v1.2.3 From 5288879390388af654da3bb9cdc2c409abf6b4f3 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Thu, 5 Oct 2017 17:30:57 -0400 Subject: media: rc: gpio-ir-tx does not work without devicetree or gpiolib If the kernel is built without device tree, this driver cannot be used and without gpiolib it cannot control any gpio pin. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 451cba1fe9bf..946d2ec419db 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -403,6 +403,7 @@ config IR_GPIO_TX tristate "GPIO IR Bit Banging Transmitter" depends on RC_CORE depends on LIRC + depends on (OF && GPIOLIB) || COMPILE_TEST ---help--- Say Y if you want to a GPIO based IR transmitter. This is a bit banging driver. -- cgit v1.2.3 From 2d726aaab2831866846dadbc675f484305041ee9 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Thu, 5 Oct 2017 17:30:58 -0400 Subject: media: rc: pwm-ir-tx needs OF Without device tree, there is no way to use this driver. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 946d2ec419db..88c8ecd13044 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -416,6 +416,7 @@ config IR_PWM_TX depends on RC_CORE depends on LIRC depends on PWM + depends on OF || COMPILE_TEST ---help--- Say Y if you want to use a PWM based IR transmitter. This is more power efficient than the bit banging gpio driver. -- cgit v1.2.3 From a840f3c7fb426382b4b2204bc01bf8b474875fcc Mon Sep 17 00:00:00 2001 From: Sean Young Date: Thu, 5 Oct 2017 17:30:59 -0400 Subject: media: rc: hix5hd2 drivers needs OF Without device tree, there is no way to use this driver. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 88c8ecd13044..94db0ed1df54 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -178,6 +178,7 @@ config IR_ENE config IR_HIX5HD2 tristate "Hisilicon hix5hd2 IR remote control" depends on RC_CORE + depends on OF || COMPILE_TEST help Say Y here if you want to use hisilicon hix5hd2 remote control. To compile this driver as a module, choose M here: the module will be -- cgit v1.2.3 From 5248e34b3fa39cdd80ab41f73c545d0bf5428b47 Mon Sep 17 00:00:00 2001 From: Marc Gonzalez Date: Fri, 6 Oct 2017 08:33:41 -0400 Subject: media: rc: Add tango keymap Add a keymap for the Sigma Designs Vantage (dev board) remote control. Signed-off-by: Marc Gonzalez Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/Makefile | 1 + drivers/media/rc/keymaps/rc-tango.c | 92 +++++++++++++++++++++++++++++++++++++ include/media/rc-map.h | 1 + 3 files changed, 94 insertions(+) create mode 100644 drivers/media/rc/keymaps/rc-tango.c (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index af6496d709fb..3c1e31321e21 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -88,6 +88,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-reddo.o \ rc-snapstream-firefly.o \ rc-streamzap.o \ + rc-tango.o \ rc-tbs-nec.o \ rc-technisat-ts35.o \ rc-technisat-usb2.o \ diff --git a/drivers/media/rc/keymaps/rc-tango.c b/drivers/media/rc/keymaps/rc-tango.c new file mode 100644 index 000000000000..1c6e8875d46f --- /dev/null +++ b/drivers/media/rc/keymaps/rc-tango.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2017 Sigma Designs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include +#include + +static struct rc_map_table tango_table[] = { + { 0x4cb4a, KEY_POWER }, + { 0x4cb48, KEY_FILE }, + { 0x4cb0f, KEY_SETUP }, + { 0x4cb4d, KEY_SUSPEND }, + { 0x4cb4e, KEY_VOLUMEUP }, + { 0x4cb44, KEY_EJECTCD }, + { 0x4cb13, KEY_TV }, + { 0x4cb51, KEY_MUTE }, + { 0x4cb52, KEY_VOLUMEDOWN }, + + { 0x4cb41, KEY_1 }, + { 0x4cb03, KEY_2 }, + { 0x4cb42, KEY_3 }, + { 0x4cb45, KEY_4 }, + { 0x4cb07, KEY_5 }, + { 0x4cb46, KEY_6 }, + { 0x4cb55, KEY_7 }, + { 0x4cb17, KEY_8 }, + { 0x4cb56, KEY_9 }, + { 0x4cb1b, KEY_0 }, + { 0x4cb59, KEY_DELETE }, + { 0x4cb5a, KEY_CAPSLOCK }, + + { 0x4cb47, KEY_BACK }, + { 0x4cb05, KEY_SWITCHVIDEOMODE }, + { 0x4cb06, KEY_UP }, + { 0x4cb43, KEY_LEFT }, + { 0x4cb01, KEY_RIGHT }, + { 0x4cb0a, KEY_DOWN }, + { 0x4cb02, KEY_ENTER }, + { 0x4cb4b, KEY_INFO }, + { 0x4cb09, KEY_HOME }, + + { 0x4cb53, KEY_MENU }, + { 0x4cb12, KEY_PREVIOUS }, + { 0x4cb50, KEY_PLAY }, + { 0x4cb11, KEY_NEXT }, + { 0x4cb4f, KEY_TITLE }, + { 0x4cb0e, KEY_REWIND }, + { 0x4cb4c, KEY_STOP }, + { 0x4cb0d, KEY_FORWARD }, + { 0x4cb57, KEY_MEDIA_REPEAT }, + { 0x4cb16, KEY_ANGLE }, + { 0x4cb54, KEY_PAUSE }, + { 0x4cb15, KEY_SLOW }, + { 0x4cb5b, KEY_TIME }, + { 0x4cb1a, KEY_AUDIO }, + { 0x4cb58, KEY_SUBTITLE }, + { 0x4cb19, KEY_ZOOM }, + + { 0x4cb5f, KEY_RED }, + { 0x4cb1e, KEY_GREEN }, + { 0x4cb5c, KEY_YELLOW }, + { 0x4cb1d, KEY_BLUE }, +}; + +static struct rc_map_list tango_map = { + .map = { + .scan = tango_table, + .size = ARRAY_SIZE(tango_table), + .rc_proto = RC_PROTO_NECX, + .name = RC_MAP_TANGO, + } +}; + +static int __init init_rc_map_tango(void) +{ + return rc_map_register(&tango_map); +} + +static void __exit exit_rc_map_tango(void) +{ + rc_map_unregister(&tango_map); +} + +module_init(init_rc_map_tango) +module_exit(exit_rc_map_tango) + +MODULE_AUTHOR("Sigma Designs"); +MODULE_LICENSE("GPL"); diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 2a160e6e823c..b4ddcb62c993 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -300,6 +300,7 @@ struct rc_map *rc_map_get(const char *name); #define RC_MAP_REDDO "rc-reddo" #define RC_MAP_SNAPSTREAM_FIREFLY "rc-snapstream-firefly" #define RC_MAP_STREAMZAP "rc-streamzap" +#define RC_MAP_TANGO "rc-tango" #define RC_MAP_TBS_NEC "rc-tbs-nec" #define RC_MAP_TECHNISAT_TS35 "rc-technisat-ts35" #define RC_MAP_TECHNISAT_USB2 "rc-technisat-usb2" -- cgit v1.2.3 From d345527331f0ceef1070d4d2f5c41edb4174c6af Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Fri, 6 Oct 2017 08:37:50 -0400 Subject: media: rc: Add driver for tango HW IR decoder The tango HW IR decoder supports NEC, RC-5, RC-6 protocols. Signed-off-by: Mans Rullgard Signed-off-by: Marc Gonzalez Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/Kconfig | 10 ++ drivers/media/rc/Makefile | 1 + drivers/media/rc/tango-ir.c | 281 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 292 insertions(+) create mode 100644 drivers/media/rc/tango-ir.c (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 94db0ed1df54..bde3c271fb88 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -472,6 +472,16 @@ config IR_SIR To compile this driver as a module, choose M here: the module will be called sir-ir. +config IR_TANGO + tristate "Sigma Designs SMP86xx IR decoder" + depends on RC_CORE + depends on ARCH_TANGO || COMPILE_TEST + ---help--- + Adds support for the HW IR decoder embedded on Sigma Designs + Tango-based systems (SMP86xx, SMP87xx). + The HW decoder supports NEC, RC-5, RC-6 IR protocols. + When compiled as a module, look for tango-ir. + config IR_ZX tristate "ZTE ZX IR remote control" depends on RC_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 9bc6a3980ed0..643797dc971b 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -44,3 +44,4 @@ obj-$(CONFIG_IR_SERIAL) += serial_ir.o obj-$(CONFIG_IR_SIR) += sir_ir.o obj-$(CONFIG_IR_MTK) += mtk-cir.o obj-$(CONFIG_IR_ZX) += zx-irdec.o +obj-$(CONFIG_IR_TANGO) += tango-ir.o diff --git a/drivers/media/rc/tango-ir.c b/drivers/media/rc/tango-ir.c new file mode 100644 index 000000000000..9d4c17230c3a --- /dev/null +++ b/drivers/media/rc/tango-ir.c @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2015 Mans Rullgard + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "tango-ir" + +#define IR_NEC_CTRL 0x00 +#define IR_NEC_DATA 0x04 +#define IR_CTRL 0x08 +#define IR_RC5_CLK_DIV 0x0c +#define IR_RC5_DATA 0x10 +#define IR_INT 0x14 + +#define NEC_TIME_BASE 560 +#define RC5_TIME_BASE 1778 + +#define RC6_CTRL 0x00 +#define RC6_CLKDIV 0x04 +#define RC6_DATA0 0x08 +#define RC6_DATA1 0x0c +#define RC6_DATA2 0x10 +#define RC6_DATA3 0x14 +#define RC6_DATA4 0x18 + +#define RC6_CARRIER 36000 +#define RC6_TIME_BASE 16 + +#define NEC_CAP(n) ((n) << 24) +#define GPIO_SEL(n) ((n) << 16) +#define DISABLE_NEC (BIT(4) | BIT(8)) +#define ENABLE_RC5 (BIT(0) | BIT(9)) +#define ENABLE_RC6 (BIT(0) | BIT(7)) +#define ACK_IR_INT (BIT(0) | BIT(1)) +#define ACK_RC6_INT (BIT(31)) + +#define NEC_ANY (RC_PROTO_BIT_NEC | RC_PROTO_BIT_NECX | RC_PROTO_BIT_NEC32) + +struct tango_ir { + void __iomem *rc5_base; + void __iomem *rc6_base; + struct rc_dev *rc; + struct clk *clk; +}; + +static void tango_ir_handle_nec(struct tango_ir *ir) +{ + u32 v, code; + enum rc_proto proto; + + v = readl_relaxed(ir->rc5_base + IR_NEC_DATA); + if (!v) { + rc_repeat(ir->rc); + return; + } + + code = ir_nec_bytes_to_scancode(v, v >> 8, v >> 16, v >> 24, &proto); + rc_keydown(ir->rc, proto, code, 0); +} + +static void tango_ir_handle_rc5(struct tango_ir *ir) +{ + u32 data, field, toggle, addr, cmd, code; + + data = readl_relaxed(ir->rc5_base + IR_RC5_DATA); + if (data & BIT(31)) + return; + + field = data >> 12 & 1; + toggle = data >> 11 & 1; + addr = data >> 6 & 0x1f; + cmd = (data & 0x3f) | (field ^ 1) << 6; + + code = RC_SCANCODE_RC5(addr, cmd); + rc_keydown(ir->rc, RC_PROTO_RC5, code, toggle); +} + +static void tango_ir_handle_rc6(struct tango_ir *ir) +{ + u32 data0, data1, toggle, mode, addr, cmd, code; + + data0 = readl_relaxed(ir->rc6_base + RC6_DATA0); + data1 = readl_relaxed(ir->rc6_base + RC6_DATA1); + + mode = data0 >> 1 & 7; + if (mode != 0) + return; + + toggle = data0 & 1; + addr = data0 >> 16; + cmd = data1; + + code = RC_SCANCODE_RC6_0(addr, cmd); + rc_keydown(ir->rc, RC_PROTO_RC6_0, code, toggle); +} + +static irqreturn_t tango_ir_irq(int irq, void *dev_id) +{ + struct tango_ir *ir = dev_id; + unsigned int rc5_stat; + unsigned int rc6_stat; + + rc5_stat = readl_relaxed(ir->rc5_base + IR_INT); + writel_relaxed(rc5_stat, ir->rc5_base + IR_INT); + + rc6_stat = readl_relaxed(ir->rc6_base + RC6_CTRL); + writel_relaxed(rc6_stat, ir->rc6_base + RC6_CTRL); + + if (!(rc5_stat & 3) && !(rc6_stat & BIT(31))) + return IRQ_NONE; + + if (rc5_stat & BIT(0)) + tango_ir_handle_rc5(ir); + + if (rc5_stat & BIT(1)) + tango_ir_handle_nec(ir); + + if (rc6_stat & BIT(31)) + tango_ir_handle_rc6(ir); + + return IRQ_HANDLED; +} + +static int tango_change_protocol(struct rc_dev *dev, u64 *rc_type) +{ + struct tango_ir *ir = dev->priv; + u32 rc5_ctrl = DISABLE_NEC; + u32 rc6_ctrl = 0; + + if (*rc_type & NEC_ANY) + rc5_ctrl = 0; + + if (*rc_type & RC_PROTO_BIT_RC5) + rc5_ctrl |= ENABLE_RC5; + + if (*rc_type & RC_PROTO_BIT_RC6_0) + rc6_ctrl = ENABLE_RC6; + + writel_relaxed(rc5_ctrl, ir->rc5_base + IR_CTRL); + writel_relaxed(rc6_ctrl, ir->rc6_base + RC6_CTRL); + + return 0; +} + +static int tango_ir_probe(struct platform_device *pdev) +{ + const char *map_name = RC_MAP_TANGO; + struct device *dev = &pdev->dev; + struct rc_dev *rc; + struct tango_ir *ir; + struct resource *rc5_res; + struct resource *rc6_res; + u64 clkrate, clkdiv; + int irq, err; + u32 val; + + rc5_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!rc5_res) + return -EINVAL; + + rc6_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!rc6_res) + return -EINVAL; + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) + return -EINVAL; + + ir = devm_kzalloc(dev, sizeof(*ir), GFP_KERNEL); + if (!ir) + return -ENOMEM; + + ir->rc5_base = devm_ioremap_resource(dev, rc5_res); + if (IS_ERR(ir->rc5_base)) + return PTR_ERR(ir->rc5_base); + + ir->rc6_base = devm_ioremap_resource(dev, rc6_res); + if (IS_ERR(ir->rc6_base)) + return PTR_ERR(ir->rc6_base); + + ir->clk = devm_clk_get(dev, NULL); + if (IS_ERR(ir->clk)) + return PTR_ERR(ir->clk); + + rc = devm_rc_allocate_device(dev, RC_DRIVER_SCANCODE); + if (!rc) + return -ENOMEM; + + of_property_read_string(dev->of_node, "linux,rc-map-name", &map_name); + + rc->device_name = DRIVER_NAME; + rc->driver_name = DRIVER_NAME; + rc->input_phys = DRIVER_NAME "/input0"; + rc->map_name = map_name; + rc->allowed_protocols = NEC_ANY | RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_0; + rc->change_protocol = tango_change_protocol; + rc->priv = ir; + ir->rc = rc; + + err = clk_prepare_enable(ir->clk); + if (err) + return err; + + clkrate = clk_get_rate(ir->clk); + + clkdiv = clkrate * NEC_TIME_BASE; + do_div(clkdiv, 1000000); + + val = NEC_CAP(31) | GPIO_SEL(12) | clkdiv; + writel_relaxed(val, ir->rc5_base + IR_NEC_CTRL); + + clkdiv = clkrate * RC5_TIME_BASE; + do_div(clkdiv, 1000000); + + writel_relaxed(DISABLE_NEC, ir->rc5_base + IR_CTRL); + writel_relaxed(clkdiv, ir->rc5_base + IR_RC5_CLK_DIV); + writel_relaxed(ACK_IR_INT, ir->rc5_base + IR_INT); + + clkdiv = clkrate * RC6_TIME_BASE; + do_div(clkdiv, RC6_CARRIER); + + writel_relaxed(ACK_RC6_INT, ir->rc6_base + RC6_CTRL); + writel_relaxed((clkdiv >> 2) << 18 | clkdiv, ir->rc6_base + RC6_CLKDIV); + + err = devm_request_irq(dev, irq, tango_ir_irq, IRQF_SHARED, + dev_name(dev), ir); + if (err) + goto err_clk; + + err = devm_rc_register_device(dev, rc); + if (err) + goto err_clk; + + platform_set_drvdata(pdev, ir); + return 0; + +err_clk: + clk_disable_unprepare(ir->clk); + return err; +} + +static int tango_ir_remove(struct platform_device *pdev) +{ + struct tango_ir *ir = platform_get_drvdata(pdev); + + clk_disable_unprepare(ir->clk); + return 0; +} + +static const struct of_device_id tango_ir_dt_ids[] = { + { .compatible = "sigma,smp8642-ir" }, + { } +}; +MODULE_DEVICE_TABLE(of, tango_ir_dt_ids); + +static struct platform_driver tango_ir_driver = { + .probe = tango_ir_probe, + .remove = tango_ir_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = tango_ir_dt_ids, + }, +}; +module_platform_driver(tango_ir_driver); + +MODULE_DESCRIPTION("SMP86xx IR decoder driver"); +MODULE_AUTHOR("Mans Rullgard "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 3e45067f94bbd61dec0619b1c32744eb0de480c8 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sun, 8 Oct 2017 14:18:52 -0400 Subject: media: rc: check for integer overflow The ioctl LIRC_SET_REC_TIMEOUT would set a timeout of 704ns if called with a timeout of 4294968us. Cc: Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ir-lirc-codec.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index bd046c41a53a..8f2f37412fc5 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -298,11 +298,14 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, if (!dev->max_timeout) return -ENOTTY; + /* Check for multiply overflow */ + if (val > U32_MAX / 1000) + return -EINVAL; + tmp = val * 1000; - if (tmp < dev->min_timeout || - tmp > dev->max_timeout) - return -EINVAL; + if (tmp < dev->min_timeout || tmp > dev->max_timeout) + return -EINVAL; if (dev->s_timeout) ret = dev->s_timeout(dev, tmp); -- cgit v1.2.3 From 950db1a80e6349a25f9af594a45ab45eed5a0020 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Mon, 9 Oct 2017 04:30:06 -0400 Subject: media: rc: ir-spi needs OF Without device tree, there is no way to use this driver. Signed-off-by: Sean Young Acked-by: Andi Shyti Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index bde3c271fb88..afb3456d4e20 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -286,6 +286,7 @@ config IR_REDRAT3 config IR_SPI tristate "SPI connected IR LED" depends on SPI && LIRC + depends on OF || COMPILE_TEST ---help--- Say Y if you want to use an IR LED connected through SPI bus. -- cgit v1.2.3 From 58fd55e838276a0c13d1dc7c387f90f25063cbf3 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 9 Oct 2017 20:14:48 +0200 Subject: media: imon: Fix null-ptr-deref in imon_probe It seems that the return value of usb_ifnum_to_if() can be NULL and needs to be checked. Signed-off-by: Arvind Yadav Tested-by: Andrey Konovalov Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/imon.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 9724fe8110e3..9fef8cc17114 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -2515,6 +2515,11 @@ static int imon_probe(struct usb_interface *interface, mutex_lock(&driver_lock); first_if = usb_ifnum_to_if(usbdev, 0); + if (!first_if) { + ret = -ENODEV; + goto fail; + } + first_if_ctx = usb_get_intfdata(first_if); if (ifnum == 0) { -- cgit v1.2.3 From 7dc31b82dd5da5eb596f9091b67326742135732c Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 17 Oct 2017 01:10:36 +0200 Subject: media: serial_ir: Convert timers to use timer_setup() In preparation for unconditionally passing the struct timer_list pointer to all timer callbacks, switch to using the new timer_setup() and from_timer() to pass the timer pointer explicitly. Cc: Mauro Carvalho Chehab Signed-off-by: Kees Cook Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/serial_ir.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/serial_ir.c b/drivers/media/rc/serial_ir.c index 8b66926bc16a..8bf5637b3a69 100644 --- a/drivers/media/rc/serial_ir.c +++ b/drivers/media/rc/serial_ir.c @@ -470,7 +470,7 @@ static int hardware_init_port(void) return 0; } -static void serial_ir_timeout(unsigned long arg) +static void serial_ir_timeout(struct timer_list *unused) { DEFINE_IR_RAW_EVENT(ev); @@ -540,8 +540,7 @@ static int serial_ir_probe(struct platform_device *dev) serial_ir.rcdev = rcdev; - setup_timer(&serial_ir.timeout_timer, serial_ir_timeout, - (unsigned long)&serial_ir); + timer_setup(&serial_ir.timeout_timer, serial_ir_timeout, 0); result = devm_request_irq(&dev->dev, irq, serial_ir_irq_handler, share_irq ? IRQF_SHARED : 0, -- cgit v1.2.3 From ce5aa6d205576904552b98e4e6ca88d8d285849f Mon Sep 17 00:00:00 2001 From: Younian Wang Date: Thu, 19 Oct 2017 21:43:29 +0200 Subject: media: rc/keymaps: add support for RC of hisilicon TV demo boards This is a NEC protocol type remote controller distributed with hisilicon TV demo boards. Signed-off-by: Younian Wang Signed-off-by: Jiancheng Xue Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/Makefile | 1 + drivers/media/rc/keymaps/rc-hisi-tv-demo.c | 81 ++++++++++++++++++++++++++++++ include/media/rc-map.h | 1 + 3 files changed, 83 insertions(+) create mode 100644 drivers/media/rc/keymaps/rc-hisi-tv-demo.c (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index 3c1e31321e21..ba471f09102a 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-geekbox.o \ rc-genius-tvgo-a11mce.o \ rc-gotview7135.o \ + rc-hisi-tv-demo.o \ rc-imon-mce.o \ rc-imon-pad.o \ rc-iodata-bctv7e.o \ diff --git a/drivers/media/rc/keymaps/rc-hisi-tv-demo.c b/drivers/media/rc/keymaps/rc-hisi-tv-demo.c new file mode 100644 index 000000000000..4816e3a4a18d --- /dev/null +++ b/drivers/media/rc/keymaps/rc-hisi-tv-demo.c @@ -0,0 +1,81 @@ +/* + * Keytable for remote controller of HiSilicon tv demo board. + * + * Copyright (c) 2017 HiSilicon Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include + +static struct rc_map_table hisi_tv_demo_keymap[] = { + { 0x00000092, KEY_1}, + { 0x00000093, KEY_2}, + { 0x000000cc, KEY_3}, + { 0x0000009f, KEY_4}, + { 0x0000008e, KEY_5}, + { 0x0000008f, KEY_6}, + { 0x000000c8, KEY_7}, + { 0x00000094, KEY_8}, + { 0x0000008a, KEY_9}, + { 0x0000008b, KEY_0}, + { 0x000000ce, KEY_ENTER}, + { 0x000000ca, KEY_UP}, + { 0x00000099, KEY_LEFT}, + { 0x00000084, KEY_PAGEUP}, + { 0x000000c1, KEY_RIGHT}, + { 0x000000d2, KEY_DOWN}, + { 0x00000089, KEY_PAGEDOWN}, + { 0x000000d1, KEY_MUTE}, + { 0x00000098, KEY_VOLUMEDOWN}, + { 0x00000090, KEY_VOLUMEUP}, + { 0x0000009c, KEY_POWER}, + { 0x000000d6, KEY_STOP}, + { 0x00000097, KEY_MENU}, + { 0x000000cb, KEY_BACK}, + { 0x000000da, KEY_PLAYPAUSE}, + { 0x00000080, KEY_INFO}, + { 0x000000c3, KEY_REWIND}, + { 0x00000087, KEY_HOMEPAGE}, + { 0x000000d0, KEY_FASTFORWARD}, + { 0x000000c4, KEY_SOUND}, + { 0x00000082, BTN_1}, + { 0x000000c7, BTN_2}, + { 0x00000086, KEY_PROGRAM}, + { 0x000000d9, KEY_SUBTITLE}, + { 0x00000085, KEY_ZOOM}, + { 0x0000009b, KEY_RED}, + { 0x0000009a, KEY_GREEN}, + { 0x000000c0, KEY_YELLOW}, + { 0x000000c2, KEY_BLUE}, + { 0x0000009d, KEY_CHANNELDOWN}, + { 0x000000cf, KEY_CHANNELUP}, +}; + +static struct rc_map_list hisi_tv_demo_map = { + .map = { + .scan = hisi_tv_demo_keymap, + .size = ARRAY_SIZE(hisi_tv_demo_keymap), + .rc_proto = RC_PROTO_NEC, + .name = RC_MAP_HISI_TV_DEMO, + } +}; + +static int __init init_rc_map_hisi_tv_demo(void) +{ + return rc_map_register(&hisi_tv_demo_map); +} + +static void __exit exit_rc_map_hisi_tv_demo(void) +{ + rc_map_unregister(&hisi_tv_demo_map); +} + +module_init(init_rc_map_hisi_tv_demo) +module_exit(exit_rc_map_hisi_tv_demo) + +MODULE_LICENSE("GPL v2"); diff --git a/include/media/rc-map.h b/include/media/rc-map.h index b4ddcb62c993..6d2172b6a0ed 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -258,6 +258,7 @@ struct rc_map *rc_map_get(const char *name); #define RC_MAP_GENIUS_TVGO_A11MCE "rc-genius-tvgo-a11mce" #define RC_MAP_GOTVIEW7135 "rc-gotview7135" #define RC_MAP_HAUPPAUGE_NEW "rc-hauppauge" +#define RC_MAP_HISI_TV_DEMO "rc-hisi-tv-demo" #define RC_MAP_IMON_MCE "rc-imon-mce" #define RC_MAP_IMON_PAD "rc-imon-pad" #define RC_MAP_IODATA_BCTV7E "rc-iodata-bctv7e" -- cgit v1.2.3 From c62cf662a2cbaa1f5ad2a5e1998b4662ed15a316 Mon Sep 17 00:00:00 2001 From: Younian Wang Date: Thu, 19 Oct 2017 21:43:30 +0200 Subject: media: rc/keymaps: add support for RC of hisilicon poplar board This is a NEC protocol type remote controller distributed with 96boards poplar@tocoding board. Signed-off-by: Younian Wang Signed-off-by: Jiancheng Xue Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/Makefile | 1 + drivers/media/rc/keymaps/rc-hisi-poplar.c | 69 +++++++++++++++++++++++++++++++ include/media/rc-map.h | 1 + 3 files changed, 71 insertions(+) create mode 100644 drivers/media/rc/keymaps/rc-hisi-poplar.c (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index ba471f09102a..3f196232904f 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-geekbox.o \ rc-genius-tvgo-a11mce.o \ rc-gotview7135.o \ + rc-hisi-poplar.o \ rc-hisi-tv-demo.o \ rc-imon-mce.o \ rc-imon-pad.o \ diff --git a/drivers/media/rc/keymaps/rc-hisi-poplar.c b/drivers/media/rc/keymaps/rc-hisi-poplar.c new file mode 100644 index 000000000000..78728bc7f63a --- /dev/null +++ b/drivers/media/rc/keymaps/rc-hisi-poplar.c @@ -0,0 +1,69 @@ +/* + * Keytable for remote controller of HiSilicon poplar board. + * + * Copyright (c) 2017 HiSilicon Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include + +static struct rc_map_table hisi_poplar_keymap[] = { + { 0x0000b292, KEY_1}, + { 0x0000b293, KEY_2}, + { 0x0000b2cc, KEY_3}, + { 0x0000b28e, KEY_4}, + { 0x0000b28f, KEY_5}, + { 0x0000b2c8, KEY_6}, + { 0x0000b28a, KEY_7}, + { 0x0000b28b, KEY_8}, + { 0x0000b2c4, KEY_9}, + { 0x0000b287, KEY_0}, + { 0x0000b282, KEY_HOMEPAGE}, + { 0x0000b2ca, KEY_UP}, + { 0x0000b299, KEY_LEFT}, + { 0x0000b2c1, KEY_RIGHT}, + { 0x0000b2d2, KEY_DOWN}, + { 0x0000b2c5, KEY_DELETE}, + { 0x0000b29c, KEY_MUTE}, + { 0x0000b281, KEY_VOLUMEDOWN}, + { 0x0000b280, KEY_VOLUMEUP}, + { 0x0000b2dc, KEY_POWER}, + { 0x0000b29a, KEY_MENU}, + { 0x0000b28d, KEY_SETUP}, + { 0x0000b2c5, KEY_BACK}, + { 0x0000b295, KEY_PLAYPAUSE}, + { 0x0000b2ce, KEY_ENTER}, + { 0x0000b285, KEY_CHANNELUP}, + { 0x0000b286, KEY_CHANNELDOWN}, + { 0x0000b2da, KEY_NUMERIC_STAR}, + { 0x0000b2d0, KEY_NUMERIC_POUND}, +}; + +static struct rc_map_list hisi_poplar_map = { + .map = { + .scan = hisi_poplar_keymap, + .size = ARRAY_SIZE(hisi_poplar_keymap), + .rc_proto = RC_PROTO_NEC, + .name = RC_MAP_HISI_POPLAR, + } +}; + +static int __init init_rc_map_hisi_poplar(void) +{ + return rc_map_register(&hisi_poplar_map); +} + +static void __exit exit_rc_map_hisi_poplar(void) +{ + rc_map_unregister(&hisi_poplar_map); +} + +module_init(init_rc_map_hisi_poplar) +module_exit(exit_rc_map_hisi_poplar) + +MODULE_LICENSE("GPL v2"); diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 6d2172b6a0ed..cc59c72ac282 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -258,6 +258,7 @@ struct rc_map *rc_map_get(const char *name); #define RC_MAP_GENIUS_TVGO_A11MCE "rc-genius-tvgo-a11mce" #define RC_MAP_GOTVIEW7135 "rc-gotview7135" #define RC_MAP_HAUPPAUGE_NEW "rc-hauppauge" +#define RC_MAP_HISI_POPLAR "rc-hisi-poplar" #define RC_MAP_HISI_TV_DEMO "rc-hisi-tv-demo" #define RC_MAP_IMON_MCE "rc-imon-mce" #define RC_MAP_IMON_PAD "rc-imon-pad" -- cgit v1.2.3 From b17ec78a42713a477151e9a78c07eb7dea0e10e9 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 24 Oct 2017 11:23:14 -0400 Subject: media: rc: Convert timers to use timer_setup() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for unconditionally passing the struct timer_list pointer to all timer callbacks, switch to using the new timer_setup() and from_timer() to pass the timer pointer explicitly. Cc: Maxim Levitsky Cc: James Hogan Cc: Hans Verkuil Cc: "Antti Seppälä" Cc: Heiner Kallweit Cc: "David Härdeman" Cc: Andi Shyti Signed-off-by: Kees Cook Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ene_ir.c | 7 +++---- drivers/media/rc/igorplugusb.c | 6 +++--- drivers/media/rc/img-ir/img-ir-hw.c | 13 ++++++------- drivers/media/rc/img-ir/img-ir-raw.c | 6 +++--- drivers/media/rc/imon.c | 7 +++---- drivers/media/rc/ir-mce_kbd-decoder.c | 7 +++---- drivers/media/rc/rc-ir-raw.c | 8 ++++---- drivers/media/rc/rc-main.c | 7 +++---- drivers/media/rc/sir_ir.c | 4 ++-- 9 files changed, 30 insertions(+), 35 deletions(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index af7ba23e16e1..71b8c9bbf6c4 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c @@ -670,9 +670,9 @@ exit: } /* timer to simulate tx done interrupt */ -static void ene_tx_irqsim(unsigned long data) +static void ene_tx_irqsim(struct timer_list *t) { - struct ene_device *dev = (struct ene_device *)data; + struct ene_device *dev = from_timer(dev, t, tx_sim_timer); unsigned long flags; spin_lock_irqsave(&dev->hw_lock, flags); @@ -1045,8 +1045,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) if (!dev->hw_learning_and_tx_capable && txsim) { dev->hw_learning_and_tx_capable = true; - setup_timer(&dev->tx_sim_timer, ene_tx_irqsim, - (long unsigned int)dev); + timer_setup(&dev->tx_sim_timer, ene_tx_irqsim, 0); pr_warn("Simulation of TX activated\n"); } diff --git a/drivers/media/rc/igorplugusb.c b/drivers/media/rc/igorplugusb.c index 4b715eb995f8..f563ddd7f739 100644 --- a/drivers/media/rc/igorplugusb.c +++ b/drivers/media/rc/igorplugusb.c @@ -137,9 +137,9 @@ static void igorplugusb_cmd(struct igorplugusb *ir, int cmd) dev_err(ir->dev, "submit urb failed: %d", ret); } -static void igorplugusb_timer(unsigned long data) +static void igorplugusb_timer(struct timer_list *t) { - struct igorplugusb *ir = (struct igorplugusb *)data; + struct igorplugusb *ir = from_timer(ir, t, timer); igorplugusb_cmd(ir, GET_INFRACODE); } @@ -174,7 +174,7 @@ static int igorplugusb_probe(struct usb_interface *intf, ir->dev = &intf->dev; - setup_timer(&ir->timer, igorplugusb_timer, (unsigned long)ir); + timer_setup(&ir->timer, igorplugusb_timer, 0); ir->request.bRequest = GET_INFRACODE; ir->request.bRequestType = USB_TYPE_VENDOR | USB_DIR_IN; diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index 82fdf4cc0824..f54bc5d23893 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -867,9 +867,9 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw) } /* timer function to end waiting for repeat. */ -static void img_ir_end_timer(unsigned long arg) +static void img_ir_end_timer(struct timer_list *t) { - struct img_ir_priv *priv = (struct img_ir_priv *)arg; + struct img_ir_priv *priv = from_timer(priv, t, hw.end_timer); spin_lock_irq(&priv->lock); img_ir_end_repeat(priv); @@ -881,9 +881,9 @@ static void img_ir_end_timer(unsigned long arg) * cleared when invalid interrupts were generated due to a quirk in the * img-ir decoder. */ -static void img_ir_suspend_timer(unsigned long arg) +static void img_ir_suspend_timer(struct timer_list *t) { - struct img_ir_priv *priv = (struct img_ir_priv *)arg; + struct img_ir_priv *priv = from_timer(priv, t, hw.suspend_timer); spin_lock_irq(&priv->lock); /* @@ -1055,9 +1055,8 @@ int img_ir_probe_hw(struct img_ir_priv *priv) img_ir_probe_hw_caps(priv); /* Set up the end timer */ - setup_timer(&hw->end_timer, img_ir_end_timer, (unsigned long)priv); - setup_timer(&hw->suspend_timer, img_ir_suspend_timer, - (unsigned long)priv); + timer_setup(&hw->end_timer, img_ir_end_timer, 0); + timer_setup(&hw->suspend_timer, img_ir_suspend_timer, 0); /* Register a clock notifier */ if (!IS_ERR(priv->clk)) { diff --git a/drivers/media/rc/img-ir/img-ir-raw.c b/drivers/media/rc/img-ir/img-ir-raw.c index 64714efc1145..6e545680d3b6 100644 --- a/drivers/media/rc/img-ir/img-ir-raw.c +++ b/drivers/media/rc/img-ir/img-ir-raw.c @@ -67,9 +67,9 @@ void img_ir_isr_raw(struct img_ir_priv *priv, u32 irq_status) * order to be assured of the final space. If there are no edges for a certain * time we use this timer to emit a final sample to satisfy them. */ -static void img_ir_echo_timer(unsigned long arg) +static void img_ir_echo_timer(struct timer_list *t) { - struct img_ir_priv *priv = (struct img_ir_priv *)arg; + struct img_ir_priv *priv = from_timer(priv, t, raw.timer); spin_lock_irq(&priv->lock); @@ -107,7 +107,7 @@ int img_ir_probe_raw(struct img_ir_priv *priv) int error; /* Set up the echo timer */ - setup_timer(&raw->timer, img_ir_echo_timer, (unsigned long)priv); + timer_setup(&raw->timer, img_ir_echo_timer, 0); /* Allocate raw decoder */ raw->rdev = rdev = rc_allocate_device(RC_DRIVER_IR_RAW); diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 9fef8cc17114..b25b35b3f6da 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -1090,9 +1090,9 @@ static void usb_tx_callback(struct urb *urb) /** * report touchscreen input */ -static void imon_touch_display_timeout(unsigned long data) +static void imon_touch_display_timeout(struct timer_list *t) { - struct imon_context *ictx = (struct imon_context *)data; + struct imon_context *ictx = from_timer(ictx, t, ttimer); if (ictx->display_type != IMON_DISPLAY_TYPE_VGA) return; @@ -2411,8 +2411,7 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf, mutex_lock(&ictx->lock); if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { - setup_timer(&ictx->ttimer, imon_touch_display_timeout, - (unsigned long)ictx); + timer_setup(&ictx->ttimer, imon_touch_display_timeout, 0); } ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf)); diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c index 7c572a643656..69d6264d54e6 100644 --- a/drivers/media/rc/ir-mce_kbd-decoder.c +++ b/drivers/media/rc/ir-mce_kbd-decoder.c @@ -115,9 +115,9 @@ static unsigned char kbd_keycodes[256] = { KEY_RESERVED }; -static void mce_kbd_rx_timeout(unsigned long data) +static void mce_kbd_rx_timeout(struct timer_list *t) { - struct mce_kbd_dec *mce_kbd = (struct mce_kbd_dec *)data; + struct mce_kbd_dec *mce_kbd = from_timer(mce_kbd, t, rx_timeout); int i; unsigned char maskcode; @@ -389,8 +389,7 @@ static int ir_mce_kbd_register(struct rc_dev *dev) set_bit(EV_MSC, idev->evbit); set_bit(MSC_SCAN, idev->mscbit); - setup_timer(&mce_kbd->rx_timeout, mce_kbd_rx_timeout, - (unsigned long)mce_kbd); + timer_setup(&mce_kbd->rx_timeout, mce_kbd_rx_timeout, 0); input_set_drvdata(idev, mce_kbd); diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c index 503bc425a187..f6e5ba4fbb49 100644 --- a/drivers/media/rc/rc-ir-raw.c +++ b/drivers/media/rc/rc-ir-raw.c @@ -471,9 +471,10 @@ int ir_raw_encode_scancode(enum rc_proto protocol, u32 scancode, } EXPORT_SYMBOL(ir_raw_encode_scancode); -static void edge_handle(unsigned long arg) +static void edge_handle(struct timer_list *t) { - struct rc_dev *dev = (struct rc_dev *)arg; + struct ir_raw_event_ctrl *raw = from_timer(raw, t, edge_handle); + struct rc_dev *dev = raw->dev; ktime_t interval = ktime_sub(ktime_get(), dev->raw->last_event); if (ktime_to_ns(interval) >= dev->timeout) { @@ -513,8 +514,7 @@ int ir_raw_event_prepare(struct rc_dev *dev) dev->raw->dev = dev; dev->change_protocol = change_protocol; - setup_timer(&dev->raw->edge_handle, edge_handle, - (unsigned long)dev); + timer_setup(&dev->raw->edge_handle, edge_handle, 0); INIT_KFIFO(dev->raw->kfifo); return 0; diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index cb78e5702bef..17950e29d4e3 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -630,9 +630,9 @@ EXPORT_SYMBOL_GPL(rc_keyup); * This routine will generate a keyup event some time after a keydown event * is generated when no further activity has been detected. */ -static void ir_timer_keyup(unsigned long cookie) +static void ir_timer_keyup(struct timer_list *t) { - struct rc_dev *dev = (struct rc_dev *)cookie; + struct rc_dev *dev = from_timer(dev, t, timer_keyup); unsigned long flags; /* @@ -1570,8 +1570,7 @@ struct rc_dev *rc_allocate_device(enum rc_driver_type type) dev->input_dev->setkeycode = ir_setkeycode; input_set_drvdata(dev->input_dev, dev); - setup_timer(&dev->timer_keyup, ir_timer_keyup, - (unsigned long)dev); + timer_setup(&dev->timer_keyup, ir_timer_keyup, 0); spin_lock_init(&dev->rc_map.lock); spin_lock_init(&dev->keylock); diff --git a/drivers/media/rc/sir_ir.c b/drivers/media/rc/sir_ir.c index bc906fb128d5..76120664b700 100644 --- a/drivers/media/rc/sir_ir.c +++ b/drivers/media/rc/sir_ir.c @@ -120,7 +120,7 @@ static void add_read_queue(int flag, unsigned long val) } /* SECTION: Hardware */ -static void sir_timeout(unsigned long data) +static void sir_timeout(struct timer_list *unused) { /* * if last received signal was a pulse, but receiving stopped @@ -321,7 +321,7 @@ static int sir_ir_probe(struct platform_device *dev) rcdev->timeout = IR_DEFAULT_TIMEOUT; rcdev->dev.parent = &sir_ir_dev->dev; - setup_timer(&timerlist, sir_timeout, 0); + timer_setup(&timerlist, sir_timeout, 0); /* get I/O port access and IRQ line */ if (!devm_request_region(&sir_ir_dev->dev, io, 8, KBUILD_MODNAME)) { -- cgit v1.2.3 From 47f42f3e21182171686efec7fae48da9411fb1a0 Mon Sep 17 00:00:00 2001 From: Oleh Kravchenko Date: Sat, 28 Oct 2017 09:38:16 -0400 Subject: media: rc: mceusb: add support for 1b80:d3b2 Evromedia USB Full Hybrid Full HD (1b80:d3b2) has IR on Interface 0. Remote controller supplied with this tuner fully compatible with RC_MAP_MSI_DIGIVOX_III. Signed-off-by: Oleh Kravchenko Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/mceusb.c | 9 +++++++++ drivers/media/usb/cx231xx/cx231xx-cards.c | 1 - 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 67c1ff099eb4..948699408764 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -188,6 +188,7 @@ enum mceusb_model_type { TIVO_KIT, MCE_GEN2_NO_TX, HAUPPAUGE_CX_HYBRID_TV, + EVROMEDIA_FULL_HYBRID_FULLHD, }; struct mceusb_model { @@ -247,6 +248,11 @@ static const struct mceusb_model mceusb_model[] = { .mce_gen2 = 1, .rc_map = RC_MAP_TIVO, }, + [EVROMEDIA_FULL_HYBRID_FULLHD] = { + .name = "Evromedia USB Full Hybrid Full HD", + .no_tx = 1, + .rc_map = RC_MAP_MSI_DIGIVOX_III, + }, }; static const struct usb_device_id mceusb_dev_table[] = { @@ -398,6 +404,9 @@ static const struct usb_device_id mceusb_dev_table[] = { .driver_info = HAUPPAUGE_CX_HYBRID_TV }, /* Adaptec / HP eHome Receiver */ { USB_DEVICE(VENDOR_ADAPTEC, 0x0094) }, + /* Evromedia USB Full Hybrid Full HD */ + { USB_DEVICE(0x1b80, 0xd3b2), + .driver_info = EVROMEDIA_FULL_HYBRID_FULLHD }, /* Terminating entry */ { } diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 9b742d569fb5..f124b677d5a0 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -847,7 +847,6 @@ struct cx231xx_board cx231xx_boards[] = { .demod_addr = 0x64, /* 0xc8 >> 1 */ .demod_i2c_master = I2C_1_MUX_3, .has_dvb = 1, - .ir_i2c_master = I2C_0, .norm = V4L2_STD_PAL, .output_mode = OUT_MODE_VIP11, .tuner_addr = 0x60, /* 0xc0 >> 1 */ -- cgit v1.2.3 From ad596b68ad26bc2d3da9a0be3c5c21a265f5edcb Mon Sep 17 00:00:00 2001 From: Oleh Kravchenko Date: Sat, 28 Oct 2017 09:38:17 -0400 Subject: media: rc: Add Astrometa T2hybrid keymap module Add the keymap module for Astrometa T2hybrid remote control commands. Signed-off-by: Oleh Kravchenko Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/Makefile | 1 + drivers/media/rc/keymaps/rc-astrometa-t2hybrid.c | 70 ++++++++++++++++++++++++ include/media/rc-map.h | 1 + 3 files changed, 72 insertions(+) create mode 100644 drivers/media/rc/keymaps/rc-astrometa-t2hybrid.c (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index 3f196232904f..039a631b348e 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-alink-dtu-m.o \ rc-anysee.o \ rc-apac-viewcomp.o \ + rc-astrometa-t2hybrid.o \ rc-asus-pc39.o \ rc-asus-ps3-100.o \ rc-ati-tv-wonder-hd-600.o \ diff --git a/drivers/media/rc/keymaps/rc-astrometa-t2hybrid.c b/drivers/media/rc/keymaps/rc-astrometa-t2hybrid.c new file mode 100644 index 000000000000..51690960fec4 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-astrometa-t2hybrid.c @@ -0,0 +1,70 @@ +/* + * Keytable for the Astrometa T2hybrid remote controller + * + * Copyright (C) 2017 Oleh Kravchenko + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +static struct rc_map_table t2hybrid[] = { + { 0x4d, KEY_POWER2 }, + { 0x54, KEY_VIDEO }, /* Source */ + { 0x16, KEY_MUTE }, + + { 0x4c, KEY_RECORD }, + { 0x05, KEY_CHANNELUP }, + { 0x0c, KEY_TIME}, /* Timeshift */ + + { 0x0a, KEY_VOLUMEDOWN }, + { 0x40, KEY_ZOOM }, /* Fullscreen */ + { 0x1e, KEY_VOLUMEUP }, + + { 0x12, KEY_0 }, + { 0x02, KEY_CHANNELDOWN }, + { 0x1c, KEY_AGAIN }, /* Recall */ + + { 0x09, KEY_1 }, + { 0x1d, KEY_2 }, + { 0x1f, KEY_3 }, + + { 0x0d, KEY_4 }, + { 0x19, KEY_5 }, + { 0x1b, KEY_6 }, + + { 0x11, KEY_7 }, + { 0x15, KEY_8 }, + { 0x17, KEY_9 }, +}; + +static struct rc_map_list t2hybrid_map = { + .map = { + .scan = t2hybrid, + .size = ARRAY_SIZE(t2hybrid), + .rc_proto = RC_PROTO_NEC, + .name = RC_MAP_ASTROMETA_T2HYBRID, + } +}; + +static int __init init_rc_map_t2hybrid(void) +{ + return rc_map_register(&t2hybrid_map); +} + +static void __exit exit_rc_map_t2hybrid(void) +{ + rc_map_unregister(&t2hybrid_map); +} + +module_init(init_rc_map_t2hybrid) +module_exit(exit_rc_map_t2hybrid) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Oleh Kravchenko "); diff --git a/include/media/rc-map.h b/include/media/rc-map.h index cc59c72ac282..72197cb43781 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -211,6 +211,7 @@ struct rc_map *rc_map_get(const char *name); #define RC_MAP_ALINK_DTU_M "rc-alink-dtu-m" #define RC_MAP_ANYSEE "rc-anysee" #define RC_MAP_APAC_VIEWCOMP "rc-apac-viewcomp" +#define RC_MAP_ASTROMETA_T2HYBRID "rc-astrometa-t2hybrid" #define RC_MAP_ASUS_PC39 "rc-asus-pc39" #define RC_MAP_ASUS_PS3_100 "rc-asus-ps3-100" #define RC_MAP_ATI_TV_WONDER_HD_600 "rc-ati-tv-wonder-hd-600" -- cgit v1.2.3 From 8ff19cdbeee49e4148deb958d7af9ab389e94cac Mon Sep 17 00:00:00 2001 From: Oleh Kravchenko Date: Sat, 28 Oct 2017 09:38:18 -0400 Subject: media: rc: mceusb: add support for 15f4:0135 Astrometa T2hybrid (15f4:0135) has IR on Interface 0. Signed-off-by: Oleh Kravchenko Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/mceusb.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/media/rc') diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 948699408764..a9187b0b46a1 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -189,6 +189,7 @@ enum mceusb_model_type { MCE_GEN2_NO_TX, HAUPPAUGE_CX_HYBRID_TV, EVROMEDIA_FULL_HYBRID_FULLHD, + ASTROMETA_T2HYBRID, }; struct mceusb_model { @@ -253,6 +254,11 @@ static const struct mceusb_model mceusb_model[] = { .no_tx = 1, .rc_map = RC_MAP_MSI_DIGIVOX_III, }, + [ASTROMETA_T2HYBRID] = { + .name = "Astrometa T2Hybrid", + .no_tx = 1, + .rc_map = RC_MAP_ASTROMETA_T2HYBRID, + } }; static const struct usb_device_id mceusb_dev_table[] = { @@ -407,6 +413,9 @@ static const struct usb_device_id mceusb_dev_table[] = { /* Evromedia USB Full Hybrid Full HD */ { USB_DEVICE(0x1b80, 0xd3b2), .driver_info = EVROMEDIA_FULL_HYBRID_FULLHD }, + /* Astrometa T2hybrid */ + { USB_DEVICE(0x15f4, 0x0135), + .driver_info = ASTROMETA_T2HYBRID }, /* Terminating entry */ { } -- cgit v1.2.3