From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from gofer.mess.org ([80.229.237.210]:56131 "EHLO gofer.mess.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1033668AbdAFMtZ (ORCPT ); Fri, 6 Jan 2017 07:49:25 -0500 From: Sean Young To: linux-media@vger.kernel.org, Hans Verkuil Subject: [PATCH 8/9] [media] lirc: scancode rc devices should have a lirc device too Date: Fri, 6 Jan 2017 12:49:11 +0000 Message-Id: <82e144a977ecad8ed1f9b0b90b4246147c0e95a1.1483706563.git.sean@mess.org> In-Reply-To: References: In-Reply-To: References: Sender: linux-media-owner@vger.kernel.org List-ID: Now that the lirc interface supports scancodes, RC scancode devices can also have a lirc device. Note that this means that every rc device has a lirc device, including cec. Signed-off-by: Sean Young --- drivers/media/rc/ir-lirc-codec.c | 125 ++++++++++++++++++--------------------- drivers/media/rc/rc-core-priv.h | 15 ----- drivers/media/rc/rc-main.c | 16 +++-- include/media/rc-core.h | 4 ++ 4 files changed, 69 insertions(+), 91 deletions(-) diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index 6a15192..ea0896a 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -85,7 +85,7 @@ int ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev) } kfifo_put(&lirc->kfifo, sample); - wake_up_poll(&lirc->wait_poll, POLLIN); + wake_up_poll(&dev->wait_poll, POLLIN); return 0; } @@ -93,8 +93,7 @@ int ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev) static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, size_t n, loff_t *ppos) { - struct lirc_codec *lirc; - struct rc_dev *dev; + struct rc_dev *dev = lirc_get_pdata(file); unsigned int *txbuf = NULL; /* buffer with values to transmit */ struct ir_raw_event *raw = NULL; ssize_t ret = -EINVAL; @@ -106,18 +105,10 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, start = ktime_get(); - lirc = lirc_get_pdata(file); - if (!lirc) - return -EFAULT; - - dev = lirc->dev; - if (!dev) - return -EFAULT; - if (!dev->tx_ir) return -ENOTTY; - if (lirc->send_mode == LIRC_MODE_SCANCODE) { + if (dev->send_mode == LIRC_MODE_SCANCODE) { struct lirc_scancode scan; if (n != sizeof(scan)) @@ -185,7 +176,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, for (duration = i = 0; i < ret; i++) duration += txbuf[i]; - if (lirc->send_mode == LIRC_MODE_SCANCODE) + if (dev->send_mode == LIRC_MODE_SCANCODE) ret = n; else ret *= sizeof(unsigned int); @@ -210,20 +201,11 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { - struct lirc_codec *lirc; - struct rc_dev *dev; + struct rc_dev *dev = lirc_get_pdata(filep); u32 __user *argp = (u32 __user *)(arg); int ret = 0; __u32 val = 0, tmp; - lirc = lirc_get_pdata(filep); - if (!lirc) - return -EFAULT; - - dev = lirc->dev; - if (!dev) - return -EFAULT; - if (_IOC_DIR(cmd) & _IOC_WRITE) { ret = get_user(val, argp); if (ret) @@ -235,7 +217,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, if (dev->driver_type == RC_DRIVER_IR_RAW_TX) return -ENOTTY; - val = lirc->rec_mode; + val = dev->rec_mode; break; case LIRC_SET_REC_MODE: @@ -253,14 +235,14 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, break; } - lirc->rec_mode = val; + dev->rec_mode = val; return 0; case LIRC_GET_SEND_MODE: if (!dev->tx_ir) return -ENOTTY; - val = lirc->send_mode; + val = dev->send_mode; break; case LIRC_SET_SEND_MODE: @@ -270,7 +252,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, if (!(val == LIRC_MODE_PULSE || val == LIRC_MODE_SCANCODE)) return -EINVAL; - lirc->send_mode = val; + dev->send_mode = val; return 0; /* TX settings */ @@ -297,8 +279,8 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, /* RX settings */ case LIRC_SET_REC_CARRIER: - if (!dev->s_rx_carrier_range) - return -ENOSYS; + if (!dev->s_rx_carrier_range || !dev->raw) + return -ENOTTY; if (val <= 0) return -EINVAL; @@ -308,6 +290,9 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, val); case LIRC_SET_REC_CARRIER_RANGE: + if (!dev->raw) + return -ENOTTY; + if (val <= 0) return -EINVAL; @@ -360,7 +345,10 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, break; case LIRC_SET_REC_TIMEOUT_REPORTS: - lirc->send_timeout_reports = !!val; + if (!dev->raw) + return -ENOTTY; + + dev->raw->lirc.send_timeout_reports = !!val; break; default: @@ -376,17 +364,19 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, static unsigned int ir_lirc_poll_ir(struct file *filep, struct poll_table_struct *wait) { - struct lirc_codec *lirc = lirc_get_pdata(filep); + struct rc_dev *dev = lirc_get_pdata(filep); + struct lirc_driver *drv = dev->lirc_drv; unsigned int events = 0; - if (!lirc->drv->attached) + if (!drv->attached) return POLLERR; - poll_wait(filep, &lirc->wait_poll, wait); + poll_wait(filep, &dev->wait_poll, wait); - if (!lirc->drv->attached) + if (!drv->attached) events = POLLERR; - else if (!kfifo_is_empty(&lirc->kfifo)) + else if (!kfifo_is_empty(&dev->kfifo) || + (dev->raw && !kfifo_is_empty(&dev->raw->lirc.kfifo))) events = POLLIN | POLLRDNORM; return events; @@ -395,35 +385,35 @@ static unsigned int ir_lirc_poll_ir(struct file *filep, static ssize_t ir_lirc_read_ir(struct file *filep, char __user *buffer, size_t length, loff_t *ppos) { - struct lirc_codec *lirc = lirc_get_pdata(filep); + struct rc_dev *dev = lirc_get_pdata(filep); + struct lirc_driver *drv = dev->lirc_drv; + struct lirc_codec *lirc = &dev->raw->lirc; unsigned int copied; int ret; - if (!lirc->drv->attached) + if (!drv->attached) return -ENODEV; - if (lirc->rec_mode == LIRC_MODE_SCANCODE) { - struct rc_dev *rcdev = lirc->dev; - + if (dev->rec_mode == LIRC_MODE_SCANCODE) { if (length % sizeof(struct lirc_scancode)) return -EINVAL; do { - if (kfifo_is_empty(&rcdev->kfifo)) { + if (kfifo_is_empty(&dev->kfifo)) { if (filep->f_flags & O_NONBLOCK) return -EAGAIN; - ret = wait_event_interruptible(lirc->wait_poll, - !kfifo_is_empty(&rcdev->kfifo) || - !lirc->drv->attached); + ret = wait_event_interruptible(dev->wait_poll, + !kfifo_is_empty(&dev->kfifo) || + !drv->attached); if (ret) return ret; } - if (!lirc->drv->attached) + if (!drv->attached) return -ENODEV; - ret = kfifo_to_user(&rcdev->kfifo, buffer, length, + ret = kfifo_to_user(&dev->kfifo, buffer, length, &copied); if (ret) return ret; @@ -437,14 +427,14 @@ static ssize_t ir_lirc_read_ir(struct file *filep, char __user *buffer, if (filep->f_flags & O_NONBLOCK) return -EAGAIN; - ret = wait_event_interruptible(lirc->wait_poll, + ret = wait_event_interruptible(dev->wait_poll, !kfifo_is_empty(&lirc->kfifo) || - !lirc->drv->attached); + !drv->attached); if (ret) return ret; } - if (!lirc->drv->attached) + if (!drv->attached) return -ENODEV; ret = kfifo_to_user(&lirc->kfifo, buffer, length, @@ -459,10 +449,11 @@ static ssize_t ir_lirc_read_ir(struct file *filep, char __user *buffer, static int ir_lirc_open(void *data) { - struct lirc_codec *lirc = data; + struct rc_dev *dev = data; - kfifo_reset_out(&lirc->kfifo); - kfifo_reset_out(&lirc->dev->kfifo); + kfifo_reset_out(&dev->kfifo); + if (dev->raw) + kfifo_reset_out(&dev->raw->kfifo); return 0; } @@ -490,20 +481,22 @@ int ir_lirc_register(struct rc_dev *dev) { struct lirc_driver *drv; int rc = -ENOMEM; - unsigned long features; + unsigned long features = 0; drv = kzalloc(sizeof(*drv), GFP_KERNEL); if (!drv) return -ENOMEM; - features = LIRC_CAN_REC_SCANCODE; - dev->raw->lirc.rec_mode = LIRC_MODE_SCANCODE; + if (dev->driver_type != RC_DRIVER_IR_RAW_TX) { + features = LIRC_CAN_REC_SCANCODE; + dev->rec_mode = LIRC_MODE_SCANCODE; + } if (dev->driver_type == RC_DRIVER_IR_RAW) { features |= LIRC_CAN_REC_MODE2; - dev->raw->lirc.rec_mode = LIRC_MODE_MODE2; + dev->rec_mode = LIRC_MODE_MODE2; } if (dev->tx_ir) { - dev->raw->lirc.send_mode = LIRC_MODE_PULSE; + dev->send_mode = LIRC_MODE_PULSE; features |= LIRC_CAN_SEND_PULSE | LIRC_CAN_SEND_SCANCODE; if (dev->s_tx_mask) features |= LIRC_CAN_SET_TRANSMITTER_MASK; @@ -530,16 +523,17 @@ int ir_lirc_register(struct rc_dev *dev) dev->driver_name); drv->minor = -1; drv->features = features; - drv->data = &dev->raw->lirc; drv->set_use_inc = &ir_lirc_open; drv->set_use_dec = &ir_lirc_close; drv->code_length = sizeof(struct ir_raw_event) * 8; drv->fops = &lirc_fops; drv->dev = &dev->dev; + drv->data = dev; drv->rdev = dev; drv->owner = THIS_MODULE; - INIT_KFIFO(dev->raw->lirc.kfifo); - init_waitqueue_head(&dev->raw->lirc.wait_poll); + init_waitqueue_head(&dev->wait_poll); + if (dev->raw) + INIT_KFIFO(dev->raw->lirc.kfifo); drv->minor = lirc_register_driver(drv); if (drv->minor < 0) { @@ -547,8 +541,8 @@ int ir_lirc_register(struct rc_dev *dev) goto lirc_register_failed; } - dev->raw->lirc.drv = drv; - dev->raw->lirc.dev = dev; + dev->lirc_drv = drv; + return 0; lirc_register_failed: @@ -558,11 +552,8 @@ int ir_lirc_register(struct rc_dev *dev) int ir_lirc_unregister(struct rc_dev *dev) { - struct lirc_codec *lirc = &dev->raw->lirc; - - wake_up_poll(&lirc->wait_poll, POLLERR); - lirc_unregister_driver(lirc->drv->minor); + wake_up_poll(&dev->wait_poll, POLLERR); + lirc_unregister_driver(dev->lirc_drv->minor); return 0; } - diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index daf2429..fe7452f 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -126,18 +126,13 @@ struct ir_raw_event_ctrl { #endif #if IS_ENABLED(CONFIG_IR_LIRC_CODEC) struct lirc_codec { - struct rc_dev *dev; - struct lirc_driver *drv; DECLARE_KFIFO(kfifo, unsigned int, LIRCBUF_SIZE); - wait_queue_head_t wait_poll; int carrier_low; ktime_t gap_start; u64 gap_duration; bool gap; bool send_timeout_reports; - int send_mode; - int rec_mode; } lirc; #endif #if IS_ENABLED(CONFIG_IR_XMP_DECODER) @@ -149,16 +144,6 @@ struct ir_raw_event_ctrl { #endif }; -#if IS_ENABLED(CONFIG_IR_LIRC_CODEC) -static inline void ir_wakeup_poll(struct ir_raw_event_ctrl *ctrl) -{ - if (ctrl) - wake_up_poll(&ctrl->lirc.wait_poll, POLLIN); -} -#else -static inline void ir_wakeup_poll(struct ir_raw_event_ctrl *ctrl) {} -#endif - /* macros for IR decoders */ static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin) { diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 037ea45..19b8a4e 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -622,7 +622,7 @@ void rc_repeat(struct rc_dev *dev) }; if (kfifo_put(&dev->kfifo, sc)) - ir_wakeup_poll(dev->raw); + wake_up_poll(&dev->wait_poll, POLLIN); spin_lock_irqsave(&dev->keylock, flags); @@ -664,7 +664,7 @@ static void ir_do_keydown(struct rc_dev *dev, enum rc_type protocol, }; if (kfifo_put(&dev->kfifo, sc)) - ir_wakeup_poll(dev->raw); + wake_up_poll(&dev->wait_poll, POLLIN); if (new_event && dev->keypressed) ir_do_keyup(dev, false); @@ -1603,6 +1603,7 @@ struct rc_dev *rc_allocate_device(enum rc_driver_type type) spin_lock_init(&dev->rc_map.lock); spin_lock_init(&dev->keylock); INIT_KFIFO(dev->kfifo); + init_waitqueue_head(&dev->wait_poll); } mutex_init(&dev->lock); @@ -1791,11 +1792,9 @@ int rc_register_device(struct rc_dev *dev) goto out_rx; } - if (dev->driver_type != RC_DRIVER_SCANCODE) { - rc = ir_lirc_register(dev); - if (rc < 0) - goto out_raw; - } + rc = ir_lirc_register(dev); + if (rc) + goto out_raw; /* Allow the RC sysfs nodes to be accessible */ atomic_set(&dev->initialized, 1); @@ -1856,8 +1855,7 @@ void rc_unregister_device(struct rc_dev *dev) if (dev->driver_type == RC_DRIVER_IR_RAW) ir_raw_event_unregister(dev); - if (dev->driver_type != RC_DRIVER_SCANCODE) - ir_lirc_unregister(dev); + ir_lirc_unregister(dev); rc_free_rx_device(dev); diff --git a/include/media/rc-core.h b/include/media/rc-core.h index 5d7093d..071a50aad 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -161,6 +161,7 @@ struct rc_dev { struct rc_scancode_filter scancode_wakeup_filter; u32 scancode_mask; DECLARE_KFIFO(kfifo, struct lirc_scancode, 32); + wait_queue_head_t wait_poll; u32 users; void *priv; spinlock_t keylock; @@ -171,6 +172,9 @@ struct rc_dev { enum rc_type last_protocol; u32 last_scancode; u8 last_toggle; + struct lirc_driver *lirc_drv; + u8 rec_mode; + u8 send_mode; u32 timeout; u32 min_timeout; u32 max_timeout; -- 2.9.3