From: Sean Young <sean@mess.org>
To: linux-media@vger.kernel.org, Hans Verkuil <hverkuil@xs4all.nl>
Subject: [PATCH 8/9] [media] lirc: scancode rc devices should have a lirc device too
Date: Fri, 6 Jan 2017 12:49:11 +0000 [thread overview]
Message-ID: <82e144a977ecad8ed1f9b0b90b4246147c0e95a1.1483706563.git.sean@mess.org> (raw)
In-Reply-To: <cover.1483706563.git.sean@mess.org>
In-Reply-To: <cover.1483706563.git.sean@mess.org>
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@mess.org>
---
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
next prev parent reply other threads:[~2017-01-06 12:49 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-06 12:49 [PATCH 0/9] Teach lirc how to send and receive scancodes Sean Young
2017-01-06 12:49 ` [PATCH 1/9] [media] lirc: lirc interface should not be a raw decoder Sean Young
2017-01-06 12:49 ` [PATCH 2/9] [media] lirc: exorcise struct irctl Sean Young
2017-01-06 12:49 ` [PATCH 3/9] [media] lirc: use plain kfifo rather than lirc_buffer Sean Young
2017-01-06 12:49 ` [PATCH 4/9] [media] lirc: implement scancode sending Sean Young
2017-01-06 12:49 ` [PATCH 5/9] [media] rc: use the correct carrier for scancode transmit Sean Young
2017-01-06 12:49 ` [PATCH 6/9] [media] rc: auto load encoder if necessary Sean Young
2017-01-06 12:49 ` [PATCH 7/9] [media] lirc: implement reading scancode Sean Young
2017-01-06 12:49 ` Sean Young [this message]
2017-01-06 12:49 ` [PATCH 9/9] [media] lirc: LIRC_MODE_SCANCODE documentation Sean Young
2017-01-29 22:35 ` [PATCH 0/9] Teach lirc how to send and receive scancodes Sean Young
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=82e144a977ecad8ed1f9b0b90b4246147c0e95a1.1483706563.git.sean@mess.org \
--to=sean@mess.org \
--cc=hverkuil@xs4all.nl \
--cc=linux-media@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).