[PATCH 8/9] [media] lirc: scancode rc devices should have a lirc device too

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <sean@xxxxxxxx>
---
 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

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux