* [PATCH] [media] lirc: introduce LIRC_SET_POLL_MODE
2017-03-02 13:31 ` [PATCH v3 17/19] [media] lirc: implement reading scancode Sean Young
@ 2017-03-06 16:16 ` Sean Young
0 siblings, 0 replies; 2+ messages in thread
From: Sean Young @ 2017-03-06 16:16 UTC (permalink / raw)
To: linux-media; +Cc: linux-api
If you want to poll for both decoded scancodes and raw IR, then this
ioctl will help you.
int fd = open("/dev/lirc0", O_RDONLY | O_NONBLOCK);
for (;;) {
unsigned mode = LIRC_MODE_SCANCODE | LIRC_MODE_MODE2;
ioctl(fd, LIRC_SET_POLL_MODE, &mode);
poll(&((struct pollfd){ .fd = fd, .events = POLLIN }), 1, -1);
mode = LIRC_MODE_SCANCODE;
ioctl(fd, LIRC_SET_REC_MODE, &mode);
struct lirc_scancode sc;
if (read(fd, &sc, sizeof(sc)) == sizeof(sc)) {
printf("scancode protocol:%d scancode:%llx\n",
sc.rc_type, sc.scancode);
}
mode = LIRC_MODE_MODE2;
ioctl(fd, LIRC_SET_REC_MODE, &mode);
unsigned sample;
if (read(fd, &sample, sizeof(sample)) == sizeof(sample)) {
if (LIRC_IS_SPACE(sample))
printf("space %u\n", LIRC_VAL(sample)));
if (LIRC_IS_PULSE(sample))
printf("pulse %u\n", LIRC_VAL(sample)));
}
}
Note that LIRC_SET_REC_MODE will also affect the poll mode, so you
must set it again before calling poll.
Signed-off-by: Sean Young <sean@mess.org>
---
Documentation/media/uapi/rc/lirc-func.rst | 1 +
Documentation/media/uapi/rc/lirc-set-poll-mode.rst | 44 ++++++++++++++++++++++
drivers/media/rc/ir-lirc-codec.c | 29 ++++++++++++--
drivers/media/rc/rc-core-priv.h | 1 +
include/uapi/linux/lirc.h | 9 +++++
5 files changed, 80 insertions(+), 4 deletions(-)
create mode 100644 Documentation/media/uapi/rc/lirc-set-poll-mode.rst
diff --git a/Documentation/media/uapi/rc/lirc-func.rst b/Documentation/media/uapi/rc/lirc-func.rst
index 9b5a772..3ae92af 100644
--- a/Documentation/media/uapi/rc/lirc-func.rst
+++ b/Documentation/media/uapi/rc/lirc-func.rst
@@ -26,3 +26,4 @@ LIRC Function Reference
lirc-set-rec-timeout-reports
lirc-set-measure-carrier-mode
lirc-set-wideband-receiver
+ lirc-set-poll-mode
diff --git a/Documentation/media/uapi/rc/lirc-set-poll-mode.rst b/Documentation/media/uapi/rc/lirc-set-poll-mode.rst
new file mode 100644
index 0000000..56112bb
--- /dev/null
+++ b/Documentation/media/uapi/rc/lirc-set-poll-mode.rst
@@ -0,0 +1,44 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _lirc_set_poll_mode:
+
+**********************************************
+ioctls LIRC_SET_POLL_MODE
+**********************************************
+
+Name
+====
+
+LIRC_SET_POLL_MODE - Set poll modes
+
+Synopsis
+========
+
+.. c:function:: int ioctl( int fd, LIRC_SET_POLL_MODE, __u32 modes)
+ :name: LIRC_SET_POLL_MODE
+
+Arguments
+=========
+
+``fd``
+ File descriptor returned by open().
+
+``modes``
+ Bitmask with enabled poll lirc modes
+
+Description
+===========
+
+Set lirc modes for which read readiness is reported by poll. Only
+:ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>` and
+:ref:`LIRC_MODE_SCANCODE <lirc-mode-scancode>` are supported.
+Use :ref:`lirc_get_features` to find out which modes the driver supports.
+
+Note that using :ref:`lirc-set-rec-mode` resets the poll mode.
+
+Return Value
+============
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 960703a..a2a2229 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -258,6 +258,24 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
}
lirc->rec_mode = val;
+ lirc->poll_mode = val;
+ return 0;
+
+ case LIRC_SET_POLL_MODE:
+ switch (dev->driver_type) {
+ case RC_DRIVER_SCANCODE:
+ if (val != LIRC_MODE_SCANCODE)
+ return -EINVAL;
+ break;
+ case RC_DRIVER_IR_RAW:
+ if (val & ~(LIRC_MODE_SCANCODE | LIRC_MODE_MODE2))
+ return -EINVAL;
+ break;
+ default:
+ return -ENOTTY;
+ }
+
+ lirc->poll_mode = val;
return 0;
case LIRC_GET_SEND_MODE:
@@ -396,11 +414,12 @@ static unsigned int ir_lirc_poll(struct file *filep,
if (!lirc->drv.attached) {
events = POLLHUP;
- } else if (lirc->rec_mode == LIRC_MODE_SCANCODE) {
- if (!kfifo_is_empty(&lirc->scancodes))
+ } else {
+ if ((lirc->poll_mode & LIRC_MODE_SCANCODE) &&
+ !kfifo_is_empty(&lirc->scancodes))
events = POLLIN | POLLRDNORM;
- } else if (lirc->rec_mode == LIRC_MODE_MODE2) {
- if (!kfifo_is_empty(&lirc->rawir))
+ if ((lirc->poll_mode & LIRC_MODE_MODE2) &&
+ !kfifo_is_empty(&lirc->rawir))
events = POLLIN | POLLRDNORM;
}
@@ -512,11 +531,13 @@ int ir_lirc_register(struct rc_dev *dev)
if (dev->driver_type == RC_DRIVER_SCANCODE) {
features |= LIRC_CAN_REC_SCANCODE;
+ node->poll_mode = LIRC_MODE_SCANCODE;
node->rec_mode = LIRC_MODE_SCANCODE;
} else if (dev->driver_type == RC_DRIVER_IR_RAW) {
features |= LIRC_CAN_REC_MODE2 | LIRC_CAN_REC_SCANCODE;
if (dev->rx_resolution)
features |= LIRC_CAN_GET_REC_RESOLUTION;
+ node->poll_mode = LIRC_MODE_MODE2;
node->rec_mode = LIRC_MODE_MODE2;
}
if (dev->tx_ir) {
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index b73222a..d630009 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -51,6 +51,7 @@ struct lirc_node {
u64 gap_duration;
bool gap;
bool send_timeout_reports;
+ int poll_mode;
int send_mode;
int rec_mode;
};
diff --git a/include/uapi/linux/lirc.h b/include/uapi/linux/lirc.h
index d04fc62..70e8a71 100644
--- a/include/uapi/linux/lirc.h
+++ b/include/uapi/linux/lirc.h
@@ -134,6 +134,15 @@
#define LIRC_SET_WIDEBAND_RECEIVER _IOW('i', 0x00000023, __u32)
/*
+ * For raw IR devices, both raw IR (LIRC_MODE_MODE2) and decodes scancodes
+ * (LIRC_MODE_SCANCODE) can be read. By default, poll will show read
+ * ready for the last mode set by LIRC_SET_REC_MODE. Use LIRC_SET_POLL_MODE
+ * LIRC_MODE_SCANCODE | LIRC_MODE_MODE2 to show read ready for both
+ * modes.
+ */
+#define LIRC_SET_POLL_MODE _IOW('i', 0x00000024, __u32)
+
+/*
* struct lirc_scancode - decoded scancodes with protocol
* @timestamp: Timestamp in nanoseconds using CLOCK_MONOTONIC when IR
* was decoded.
--
2.9.3
^ permalink raw reply related [flat|nested] 2+ messages in thread