Re: [PATCH v2 18/25] media: lirc: implement reading scancode

2017-10-09 Thread Hans Verkuil
On 05/10/17 10:45, Sean Young wrote:
> This implements LIRC_MODE_SCANCODE reading from the lirc device. The
> scancode can be read from the input device too, but with this interface
> you get the rc protocol, toggle and repeat status in addition too just

too -> to

Regards,

Hans

> the scancode.
> 
> int main()
> {
>   int fd, mode, rc;
>   fd = open("/dev/lirc0", O_RDWR);
> 
>   mode = LIRC_MODE_SCANCODE;
>   if (ioctl(fd, LIRC_SET_REC_MODE, )) {
>   // kernel too old or lirc does not support transmit
>   }
>   struct lirc_scancode scancode;
>   while (read(fd, , sizeof(scancode)) == sizeof(scancode)) {
>   printf("protocol:%d scancode:0x%x toggle:%d repeat:%d\n",
>   scancode.rc_proto, scancode.scancode,
>   !!(scancode.flags & LIRC_SCANCODE_FLAG_TOGGLE),
>   !!(scancode.flags & LIRC_SCANCODE_FLAG_REPEAT));
>   }
>   close(fd);
> }
> 
> Note that the translated KEY_* is not included, that information is
> published to the input device.



[PATCH v2 18/25] media: lirc: implement reading scancode

2017-10-05 Thread Sean Young
This implements LIRC_MODE_SCANCODE reading from the lirc device. The
scancode can be read from the input device too, but with this interface
you get the rc protocol, toggle and repeat status in addition too just
the scancode.

int main()
{
int fd, mode, rc;
fd = open("/dev/lirc0", O_RDWR);

mode = LIRC_MODE_SCANCODE;
if (ioctl(fd, LIRC_SET_REC_MODE, )) {
// kernel too old or lirc does not support transmit
}
struct lirc_scancode scancode;
while (read(fd, , sizeof(scancode)) == sizeof(scancode)) {
printf("protocol:%d scancode:0x%x toggle:%d repeat:%d\n",
scancode.rc_proto, scancode.scancode,
!!(scancode.flags & LIRC_SCANCODE_FLAG_TOGGLE),
!!(scancode.flags & LIRC_SCANCODE_FLAG_REPEAT));
}
close(fd);
}

Note that the translated KEY_* is not included, that information is
published to the input device.

Signed-off-by: Sean Young 
---
 drivers/media/rc/ir-lirc-codec.c  | 102 +-
 drivers/media/rc/ir-mce_kbd-decoder.c |   5 ++
 drivers/media/rc/lirc_dev.c   |  13 +
 drivers/media/rc/rc-core-priv.h   |   3 +
 drivers/media/rc/rc-main.c|   6 ++
 include/media/rc-core.h   |   5 ++
 6 files changed, 119 insertions(+), 15 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index bb4691d8ef06..2544ddc078ca 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -88,6 +88,21 @@ void ir_lirc_raw_event(struct rc_dev *dev, struct 
ir_raw_event ev)
wake_up_poll(>wait_poll, POLLIN | POLLRDNORM);
 }
 
+/**
+ * ir_lirc_scancode_event() - Send scancode data to lirc to be relayed to
+ * userspace
+ * @dev:   the struct rc_dev descriptor of the device
+ * @lscthe struct lirc_scancode describing the decoded scancode
+ */
+void ir_lirc_scancode_event(struct rc_dev *dev, struct lirc_scancode *lsc)
+{
+   lsc->timestamp = ktime_get_ns();
+
+   if (kfifo_put(>scancodes, *lsc))
+   wake_up_poll(>wait_poll, POLLIN | POLLRDNORM);
+}
+EXPORT_SYMBOL_GPL(ir_lirc_scancode_event);
+
 static int ir_lirc_open(struct inode *inode, struct file *file)
 {
struct rc_dev *dev = container_of(inode->i_cdev, struct rc_dev,
@@ -114,6 +129,8 @@ static int ir_lirc_open(struct inode *inode, struct file 
*file)
 
if (dev->driver_type == RC_DRIVER_IR_RAW)
kfifo_reset_out(>rawir);
+   if (dev->driver_type != RC_DRIVER_IR_RAW_TX)
+   kfifo_reset_out(>scancodes);
 
dev->lirc_open++;
file->private_data = dev;
@@ -287,7 +304,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int 
cmd,
switch (cmd) {
case LIRC_GET_FEATURES:
if (dev->driver_type == RC_DRIVER_IR_RAW) {
-   val |= LIRC_CAN_REC_MODE2;
+   val |= LIRC_CAN_REC_MODE2 | LIRC_CAN_REC_SCANCODE;
if (dev->rx_resolution)
val |= LIRC_CAN_GET_REC_RESOLUTION;
}
@@ -325,15 +342,17 @@ static long ir_lirc_ioctl(struct file *filep, unsigned 
int cmd,
if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
return -ENOTTY;
 
-   val = LIRC_MODE_MODE2;
+   val = dev->rec_mode;
break;
 
case LIRC_SET_REC_MODE:
if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
return -ENOTTY;
 
-   if (val != LIRC_MODE_MODE2)
+   if (!(val == LIRC_MODE_MODE2 || val == LIRC_MODE_SCANCODE))
return -EINVAL;
+
+   dev->rec_mode = val;
return 0;
 
case LIRC_GET_SEND_MODE:
@@ -473,31 +492,31 @@ static unsigned int ir_lirc_poll(struct file *file,
 
poll_wait(file, >wait_poll, wait);
 
-   if (!rcdev->registered)
+   if (!rcdev->registered) {
events = POLLHUP | POLLERR;
-   else if (rcdev->driver_type == RC_DRIVER_IR_RAW &&
-!kfifo_is_empty(>rawir))
-   events = POLLIN | POLLRDNORM;
+   } else if (rcdev->driver_type != RC_DRIVER_IR_RAW_TX) {
+   if (rcdev->rec_mode == LIRC_MODE_SCANCODE &&
+   !kfifo_is_empty(>scancodes))
+   events = POLLIN | POLLRDNORM;
+
+   if (rcdev->rec_mode == LIRC_MODE_MODE2 &&
+   !kfifo_is_empty(>rawir))
+   events = POLLIN | POLLRDNORM;
+   }
 
return events;
 }
 
-static ssize_t ir_lirc_read(struct file *file, char __user *buffer,
-   size_t length, loff_t *ppos)
+static ssize_t ir_lirc_read_mode2(struct file *file, char __user *buffer,
+ size_t length)
 {
struct rc_dev *rcdev =