All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/26] lirc scancode interface, and more
@ 2017-10-10  7:17 Sean Young
  2017-10-10  7:17 ` [PATCH v3 01/26] media: lirc: implement scancode sending Sean Young
                   ` (26 more replies)
  0 siblings, 27 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:17 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Hans Verkuil, Andy Walls, linux-media

Introduce lirc scancode mode, use that to port lirc_zilog to rc-core
using that interface, and then remove the lirc kernel api.

In summary:
 - This removes the lirc staging directory.
 - lirc IR TX can use in-kernel encoders for scancode encoding
 - lirc_zilog uses the same interface
 - lirc kapi (not uapi!) is gone
 - The reading lirc scancode gives more information (e.g. protocol,
   toggle, repeat). So you can determine what protocol variant a remotes uses
 - Line count is actually down and code cleaner (imo)

v2:
 - Add MAINTAINERS entries
 - Fixes for nec repeat
 - Validate scancode for tx
 - Minor bugfixes

v3:
 - Review comments from Hans Verkuil
 - Documented and fixed rc_validate_scancode()
 - Fix a bug in kfifo on arm 32-bit
 - this inferface won't be used for cec remote control passthrough

Sean Young (26):
  media: lirc: implement scancode sending
  media: lirc: use the correct carrier for scancode transmit
  media: rc: auto load encoder if necessary
  media: lirc_zilog: remove receiver
  media: lirc_zilog: fix variable types and other ugliness
  media: lirc_zilog: port to rc-core using scancode tx interface
  media: promote lirc_zilog out of staging
  media: lirc: remove LIRCCODE and LIRC_GET_LENGTH
  media: lirc: lirc interface should not be a raw decoder
  media: lirc: validate scancode for transmit
  media: rc: document and fix rc_validate_scancode()
  media: lirc: merge lirc_dev_fop_ioctl and ir_lirc_ioctl
  media: lirc: use kfifo rather than lirc_buffer for raw IR
  media: lirc: move lirc_dev->attached to rc_dev->registered
  media: lirc: do not call rc_close() on unregistered devices
  media: lirc: create rc-core open and close lirc functions
  media: lirc: remove name from lirc_dev
  media: lirc: remove last remnants of lirc kapi
  media: lirc: implement reading scancode
  media: rc: ensure lirc device receives nec repeats
  media: lirc: document LIRC_MODE_SCANCODE
  media: lirc: introduce LIRC_SET_POLL_MODES
  media: lirc: scancode rc devices should have a lirc device too
  media: MAINTAINERS: remove lirc staging area
  media: MAINTAINERS: add entry for zilog_ir
  kfifo: DECLARE_KIFO_PTR(fifo, u64) does not work on arm 32 bit

 Documentation/media/kapi/rc-core.rst               |    5 -
 Documentation/media/lirc.h.rst.exceptions          |   31 +
 Documentation/media/uapi/rc/lirc-dev-intro.rst     |   68 +-
 Documentation/media/uapi/rc/lirc-func.rst          |    2 +-
 Documentation/media/uapi/rc/lirc-get-features.rst  |   17 +-
 Documentation/media/uapi/rc/lirc-get-length.rst    |   44 -
 Documentation/media/uapi/rc/lirc-get-rec-mode.rst  |    5 +-
 Documentation/media/uapi/rc/lirc-get-send-mode.rst |    2 +-
 Documentation/media/uapi/rc/lirc-read.rst          |   15 +-
 .../media/uapi/rc/lirc-set-poll-modes.rst          |   52 +
 Documentation/media/uapi/rc/lirc-write.rst         |   19 +-
 MAINTAINERS                                        |   12 +-
 drivers/media/rc/Kconfig                           |   41 +-
 drivers/media/rc/Makefile                          |    6 +-
 drivers/media/rc/ir-jvc-decoder.c                  |    1 +
 drivers/media/rc/ir-lirc-codec.c                   |  566 ++++---
 drivers/media/rc/ir-mce_kbd-decoder.c              |   12 +-
 drivers/media/rc/ir-nec-decoder.c                  |    1 +
 drivers/media/rc/ir-rc5-decoder.c                  |    1 +
 drivers/media/rc/ir-rc6-decoder.c                  |    1 +
 drivers/media/rc/ir-sanyo-decoder.c                |    1 +
 drivers/media/rc/ir-sharp-decoder.c                |    1 +
 drivers/media/rc/ir-sony-decoder.c                 |    1 +
 drivers/media/rc/lirc_dev.c                        |  489 +-----
 drivers/media/rc/rc-core-priv.h                    |   54 +-
 drivers/media/rc/rc-ir-raw.c                       |   56 +-
 drivers/media/rc/rc-main.c                         |  166 +-
 drivers/media/rc/zilog_ir.c                        |  742 +++++++++
 drivers/staging/media/Kconfig                      |    3 -
 drivers/staging/media/Makefile                     |    1 -
 drivers/staging/media/lirc/Kconfig                 |   21 -
 drivers/staging/media/lirc/Makefile                |    6 -
 drivers/staging/media/lirc/TODO                    |   36 -
 drivers/staging/media/lirc/lirc_zilog.c            | 1653 --------------------
 include/linux/kfifo.h                              |    3 +-
 include/media/lirc_dev.h                           |  192 ---
 include/media/rc-core.h                            |   55 +-
 include/media/rc-map.h                             |   54 +-
 include/uapi/linux/lirc.h                          |   91 ++
 39 files changed, 1734 insertions(+), 2792 deletions(-)
 delete mode 100644 Documentation/media/uapi/rc/lirc-get-length.rst
 create mode 100644 Documentation/media/uapi/rc/lirc-set-poll-modes.rst
 create mode 100644 drivers/media/rc/zilog_ir.c
 delete mode 100644 drivers/staging/media/lirc/Kconfig
 delete mode 100644 drivers/staging/media/lirc/Makefile
 delete mode 100644 drivers/staging/media/lirc/TODO
 delete mode 100644 drivers/staging/media/lirc/lirc_zilog.c
 delete mode 100644 include/media/lirc_dev.h

-- 
2.13.6

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 01/26] media: lirc: implement scancode sending
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
@ 2017-10-10  7:17 ` Sean Young
  2017-10-10  7:17 ` [PATCH v3 02/26] media: lirc: use the correct carrier for scancode transmit Sean Young
                   ` (25 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:17 UTC (permalink / raw)
  To: linux-media

This introduces a new lirc mode: scancode. Any device which can send raw IR
can now also send scancodes.

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

        mode = LIRC_MODE_SCANCODE;
	if (ioctl(fd, LIRC_SET_SEND_MODE, &mode)) {
		// kernel too old or lirc does not support transmit
	}
	struct lirc_scancode scancode = {
		.scancode = 0x1e3d,
		.rc_proto = RC_PROTO_RC5,
	};
	write(fd, &scancode, sizeof(scancode));
	close(fd);
}

The other fields of lirc_scancode must be set to 0.

Note that toggle (rc5, rc6) and repeats (nec) are not implemented. Nor is
there a method for holding down a key for a period.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/ir-lirc-codec.c | 99 +++++++++++++++++++++++++++++-----------
 drivers/media/rc/rc-core-priv.h  |  2 +-
 include/media/rc-map.h           | 54 +---------------------
 include/uapi/linux/lirc.h        | 82 +++++++++++++++++++++++++++++++++
 4 files changed, 156 insertions(+), 81 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 8f2f37412fc5..2c89b4474e31 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -107,7 +107,8 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 {
 	struct lirc_codec *lirc;
 	struct rc_dev *dev;
-	unsigned int *txbuf; /* buffer with values to transmit */
+	unsigned int *txbuf = NULL;
+	struct ir_raw_event *raw = NULL;
 	ssize_t ret = -EINVAL;
 	size_t count;
 	ktime_t start;
@@ -121,16 +122,50 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 	if (!lirc)
 		return -EFAULT;
 
-	if (n < sizeof(unsigned) || n % sizeof(unsigned))
-		return -EINVAL;
+	if (lirc->send_mode == LIRC_MODE_SCANCODE) {
+		struct lirc_scancode scan;
 
-	count = n / sizeof(unsigned);
-	if (count > LIRCBUF_SIZE || count % 2 == 0)
-		return -EINVAL;
+		if (n != sizeof(scan))
+			return -EINVAL;
 
-	txbuf = memdup_user(buf, n);
-	if (IS_ERR(txbuf))
-		return PTR_ERR(txbuf);
+		if (copy_from_user(&scan, buf, sizeof(scan)))
+			return -EFAULT;
+
+		if (scan.flags || scan.keycode || scan.timestamp)
+			return -EINVAL;
+
+		raw = kmalloc_array(LIRCBUF_SIZE, sizeof(*raw), GFP_KERNEL);
+		if (!raw)
+			return -ENOMEM;
+
+		ret = ir_raw_encode_scancode(scan.rc_proto, scan.scancode,
+					     raw, LIRCBUF_SIZE);
+		if (ret < 0)
+			goto out;
+
+		count = ret;
+
+		txbuf = kmalloc_array(count, sizeof(unsigned int), GFP_KERNEL);
+		if (!txbuf) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		for (i = 0; i < count; i++)
+			/* Convert from NS to US */
+			txbuf[i] = DIV_ROUND_UP(raw[i].duration, 1000);
+	} else {
+		if (n < sizeof(unsigned int) || n % sizeof(unsigned int))
+			return -EINVAL;
+
+		count = n / sizeof(unsigned int);
+		if (count > LIRCBUF_SIZE || count % 2 == 0)
+			return -EINVAL;
+
+		txbuf = memdup_user(buf, n);
+		if (IS_ERR(txbuf))
+			return PTR_ERR(txbuf);
+	}
 
 	dev = lirc->dev;
 	if (!dev) {
@@ -156,24 +191,30 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 	if (ret < 0)
 		goto out;
 
-	for (duration = i = 0; i < ret; i++)
-		duration += txbuf[i];
-
-	ret *= sizeof(unsigned int);
-
-	/*
-	 * The lircd gap calculation expects the write function to
-	 * wait for the actual IR signal to be transmitted before
-	 * returning.
-	 */
-	towait = ktime_us_delta(ktime_add_us(start, duration), ktime_get());
-	if (towait > 0) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(usecs_to_jiffies(towait));
+	if (lirc->send_mode == LIRC_MODE_SCANCODE) {
+		ret = n;
+	} else {
+		for (duration = i = 0; i < ret; i++)
+			duration += txbuf[i];
+
+		ret *= sizeof(unsigned int);
+
+		/*
+		 * The lircd gap calculation expects the write function to
+		 * wait for the actual IR signal to be transmitted before
+		 * returning.
+		 */
+		towait = ktime_us_delta(ktime_add_us(start, duration),
+					ktime_get());
+		if (towait > 0) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(usecs_to_jiffies(towait));
+		}
 	}
 
 out:
 	kfree(txbuf);
+	kfree(raw);
 	return ret;
 }
 
@@ -202,20 +243,22 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 
 	switch (cmd) {
 
-	/* legacy support */
+	/* mode support */
 	case LIRC_GET_SEND_MODE:
 		if (!dev->tx_ir)
 			return -ENOTTY;
 
-		val = LIRC_MODE_PULSE;
+		val = lirc->send_mode;
 		break;
 
 	case LIRC_SET_SEND_MODE:
 		if (!dev->tx_ir)
 			return -ENOTTY;
 
-		if (val != LIRC_MODE_PULSE)
+		if (!(val == LIRC_MODE_PULSE || val == LIRC_MODE_SCANCODE))
 			return -EINVAL;
+
+		lirc->send_mode = val;
 		return 0;
 
 	/* TX settings */
@@ -361,7 +404,7 @@ static int ir_lirc_register(struct rc_dev *dev)
 	}
 
 	if (dev->tx_ir) {
-		features |= LIRC_CAN_SEND_PULSE;
+		features |= LIRC_CAN_SEND_PULSE | LIRC_CAN_SEND_SCANCODE;
 		if (dev->s_tx_mask)
 			features |= LIRC_CAN_SET_TRANSMITTER_MASK;
 		if (dev->s_tx_carrier)
@@ -400,6 +443,8 @@ static int ir_lirc_register(struct rc_dev *dev)
 	if (rc < 0)
 		goto out;
 
+	dev->raw->lirc.send_mode = LIRC_MODE_PULSE;
+
 	dev->raw->lirc.ldev = ldev;
 	dev->raw->lirc.dev = dev;
 	return 0;
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index ae4dd0c27731..43eabea9f152 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -113,7 +113,7 @@ struct ir_raw_event_ctrl {
 		u64 gap_duration;
 		bool gap;
 		bool send_timeout_reports;
-
+		u8 send_mode;
 	} lirc;
 	struct xmp_dec {
 		int state;
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index b4ddcb62c993..2547b321463e 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -10,59 +10,7 @@
  */
 
 #include <linux/input.h>
-
-/**
- * enum rc_proto - the Remote Controller protocol
- *
- * @RC_PROTO_UNKNOWN: Protocol not known
- * @RC_PROTO_OTHER: Protocol known but proprietary
- * @RC_PROTO_RC5: Philips RC5 protocol
- * @RC_PROTO_RC5X_20: Philips RC5x 20 bit protocol
- * @RC_PROTO_RC5_SZ: StreamZap variant of RC5
- * @RC_PROTO_JVC: JVC protocol
- * @RC_PROTO_SONY12: Sony 12 bit protocol
- * @RC_PROTO_SONY15: Sony 15 bit protocol
- * @RC_PROTO_SONY20: Sony 20 bit protocol
- * @RC_PROTO_NEC: NEC protocol
- * @RC_PROTO_NECX: Extended NEC protocol
- * @RC_PROTO_NEC32: NEC 32 bit protocol
- * @RC_PROTO_SANYO: Sanyo protocol
- * @RC_PROTO_MCIR2_KBD: RC6-ish MCE keyboard
- * @RC_PROTO_MCIR2_MSE: RC6-ish MCE mouse
- * @RC_PROTO_RC6_0: Philips RC6-0-16 protocol
- * @RC_PROTO_RC6_6A_20: Philips RC6-6A-20 protocol
- * @RC_PROTO_RC6_6A_24: Philips RC6-6A-24 protocol
- * @RC_PROTO_RC6_6A_32: Philips RC6-6A-32 protocol
- * @RC_PROTO_RC6_MCE: MCE (Philips RC6-6A-32 subtype) protocol
- * @RC_PROTO_SHARP: Sharp protocol
- * @RC_PROTO_XMP: XMP protocol
- * @RC_PROTO_CEC: CEC protocol
- */
-enum rc_proto {
-	RC_PROTO_UNKNOWN	= 0,
-	RC_PROTO_OTHER		= 1,
-	RC_PROTO_RC5		= 2,
-	RC_PROTO_RC5X_20	= 3,
-	RC_PROTO_RC5_SZ		= 4,
-	RC_PROTO_JVC		= 5,
-	RC_PROTO_SONY12		= 6,
-	RC_PROTO_SONY15		= 7,
-	RC_PROTO_SONY20		= 8,
-	RC_PROTO_NEC		= 9,
-	RC_PROTO_NECX		= 10,
-	RC_PROTO_NEC32		= 11,
-	RC_PROTO_SANYO		= 12,
-	RC_PROTO_MCIR2_KBD	= 13,
-	RC_PROTO_MCIR2_MSE	= 14,
-	RC_PROTO_RC6_0		= 15,
-	RC_PROTO_RC6_6A_20	= 16,
-	RC_PROTO_RC6_6A_24	= 17,
-	RC_PROTO_RC6_6A_32	= 18,
-	RC_PROTO_RC6_MCE	= 19,
-	RC_PROTO_SHARP		= 20,
-	RC_PROTO_XMP		= 21,
-	RC_PROTO_CEC		= 22,
-};
+#include <uapi/linux/lirc.h>
 
 #define RC_PROTO_BIT_NONE		0ULL
 #define RC_PROTO_BIT_UNKNOWN		BIT_ULL(RC_PROTO_UNKNOWN)
diff --git a/include/uapi/linux/lirc.h b/include/uapi/linux/lirc.h
index 991ab4570b8e..fed779546017 100644
--- a/include/uapi/linux/lirc.h
+++ b/include/uapi/linux/lirc.h
@@ -46,12 +46,14 @@
 #define LIRC_MODE_RAW                  0x00000001
 #define LIRC_MODE_PULSE                0x00000002
 #define LIRC_MODE_MODE2                0x00000004
+#define LIRC_MODE_SCANCODE             0x00000008
 #define LIRC_MODE_LIRCCODE             0x00000010
 
 
 #define LIRC_CAN_SEND_RAW              LIRC_MODE2SEND(LIRC_MODE_RAW)
 #define LIRC_CAN_SEND_PULSE            LIRC_MODE2SEND(LIRC_MODE_PULSE)
 #define LIRC_CAN_SEND_MODE2            LIRC_MODE2SEND(LIRC_MODE_MODE2)
+#define LIRC_CAN_SEND_SCANCODE         LIRC_MODE2SEND(LIRC_MODE_SCANCODE)
 #define LIRC_CAN_SEND_LIRCCODE         LIRC_MODE2SEND(LIRC_MODE_LIRCCODE)
 
 #define LIRC_CAN_SEND_MASK             0x0000003f
@@ -63,6 +65,7 @@
 #define LIRC_CAN_REC_RAW               LIRC_MODE2REC(LIRC_MODE_RAW)
 #define LIRC_CAN_REC_PULSE             LIRC_MODE2REC(LIRC_MODE_PULSE)
 #define LIRC_CAN_REC_MODE2             LIRC_MODE2REC(LIRC_MODE_MODE2)
+#define LIRC_CAN_REC_SCANCODE          LIRC_MODE2REC(LIRC_MODE_SCANCODE)
 #define LIRC_CAN_REC_LIRCCODE          LIRC_MODE2REC(LIRC_MODE_LIRCCODE)
 
 #define LIRC_CAN_REC_MASK              LIRC_MODE2REC(LIRC_CAN_SEND_MASK)
@@ -130,4 +133,83 @@
 
 #define LIRC_SET_WIDEBAND_RECEIVER     _IOW('i', 0x00000023, __u32)
 
+/*
+ * struct lirc_scancode - decoded scancode with protocol for use with
+ *	LIRC_MODE_SCANCODE
+ *
+ * @timestamp: Timestamp in nanoseconds using CLOCK_MONOTONIC when IR
+ *	was decoded.
+ * @flags: should be 0 for transmit. When receiving scancodes,
+ *	LIRC_SCANCODE_FLAG_TOGGLE or LIRC_SCANCODE_FLAG_REPEAT can be set
+ *	depending on the protocol
+ * @rc_proto: see enum rc_proto
+ * @keycode: the translated keycode. Set to 0 for transmit.
+ * @scancode: the scancode received or to be sent
+ */
+struct lirc_scancode {
+	__u64	timestamp;
+	__u16	flags;
+	__u16	rc_proto;
+	__u32	keycode;
+	__u64	scancode;
+};
+
+/* Set if the toggle bit of rc-5 or rc-6 is enabled */
+#define LIRC_SCANCODE_FLAG_TOGGLE	1
+/* Set if this is a nec or sanyo repeat */
+#define LIRC_SCANCODE_FLAG_REPEAT	2
+
+/**
+ * enum rc_proto - the Remote Controller protocol
+ *
+ * @RC_PROTO_UNKNOWN: Protocol not known
+ * @RC_PROTO_OTHER: Protocol known but proprietary
+ * @RC_PROTO_RC5: Philips RC5 protocol
+ * @RC_PROTO_RC5X_20: Philips RC5x 20 bit protocol
+ * @RC_PROTO_RC5_SZ: StreamZap variant of RC5
+ * @RC_PROTO_JVC: JVC protocol
+ * @RC_PROTO_SONY12: Sony 12 bit protocol
+ * @RC_PROTO_SONY15: Sony 15 bit protocol
+ * @RC_PROTO_SONY20: Sony 20 bit protocol
+ * @RC_PROTO_NEC: NEC protocol
+ * @RC_PROTO_NECX: Extended NEC protocol
+ * @RC_PROTO_NEC32: NEC 32 bit protocol
+ * @RC_PROTO_SANYO: Sanyo protocol
+ * @RC_PROTO_MCIR2_KBD: RC6-ish MCE keyboard
+ * @RC_PROTO_MCIR2_MSE: RC6-ish MCE mouse
+ * @RC_PROTO_RC6_0: Philips RC6-0-16 protocol
+ * @RC_PROTO_RC6_6A_20: Philips RC6-6A-20 protocol
+ * @RC_PROTO_RC6_6A_24: Philips RC6-6A-24 protocol
+ * @RC_PROTO_RC6_6A_32: Philips RC6-6A-32 protocol
+ * @RC_PROTO_RC6_MCE: MCE (Philips RC6-6A-32 subtype) protocol
+ * @RC_PROTO_SHARP: Sharp protocol
+ * @RC_PROTO_XMP: XMP protocol
+ * @RC_PROTO_CEC: CEC protocol
+ */
+enum rc_proto {
+	RC_PROTO_UNKNOWN	= 0,
+	RC_PROTO_OTHER		= 1,
+	RC_PROTO_RC5		= 2,
+	RC_PROTO_RC5X_20	= 3,
+	RC_PROTO_RC5_SZ		= 4,
+	RC_PROTO_JVC		= 5,
+	RC_PROTO_SONY12		= 6,
+	RC_PROTO_SONY15		= 7,
+	RC_PROTO_SONY20		= 8,
+	RC_PROTO_NEC		= 9,
+	RC_PROTO_NECX		= 10,
+	RC_PROTO_NEC32		= 11,
+	RC_PROTO_SANYO		= 12,
+	RC_PROTO_MCIR2_KBD	= 13,
+	RC_PROTO_MCIR2_MSE	= 14,
+	RC_PROTO_RC6_0		= 15,
+	RC_PROTO_RC6_6A_20	= 16,
+	RC_PROTO_RC6_6A_24	= 17,
+	RC_PROTO_RC6_6A_32	= 18,
+	RC_PROTO_RC6_MCE	= 19,
+	RC_PROTO_SHARP		= 20,
+	RC_PROTO_XMP		= 21,
+	RC_PROTO_CEC		= 22,
+};
+
 #endif
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 02/26] media: lirc: use the correct carrier for scancode transmit
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
  2017-10-10  7:17 ` [PATCH v3 01/26] media: lirc: implement scancode sending Sean Young
@ 2017-10-10  7:17 ` Sean Young
  2017-10-10  7:17 ` [PATCH v3 03/26] media: rc: auto load encoder if necessary Sean Young
                   ` (24 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:17 UTC (permalink / raw)
  To: linux-media

If the lirc device supports it, set the carrier for the protocol.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/ir-jvc-decoder.c     |  1 +
 drivers/media/rc/ir-lirc-codec.c      |  7 +++++++
 drivers/media/rc/ir-mce_kbd-decoder.c |  1 +
 drivers/media/rc/ir-nec-decoder.c     |  1 +
 drivers/media/rc/ir-rc5-decoder.c     |  1 +
 drivers/media/rc/ir-rc6-decoder.c     |  1 +
 drivers/media/rc/ir-sanyo-decoder.c   |  1 +
 drivers/media/rc/ir-sharp-decoder.c   |  1 +
 drivers/media/rc/ir-sony-decoder.c    |  1 +
 drivers/media/rc/rc-core-priv.h       |  1 +
 drivers/media/rc/rc-ir-raw.c          | 30 ++++++++++++++++++++++++++++++
 include/media/rc-core.h               |  1 +
 12 files changed, 47 insertions(+)

diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c
index e2bd68c42edf..2ae20dfc0e61 100644
--- a/drivers/media/rc/ir-jvc-decoder.c
+++ b/drivers/media/rc/ir-jvc-decoder.c
@@ -212,6 +212,7 @@ static struct ir_raw_handler jvc_handler = {
 	.protocols	= RC_PROTO_BIT_JVC,
 	.decode		= ir_jvc_decode,
 	.encode		= ir_jvc_encode,
+	.carrier	= 38000,
 };
 
 static int __init ir_jvc_decode_init(void)
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 2c89b4474e31..a5369978e56f 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -154,6 +154,13 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 		for (i = 0; i < count; i++)
 			/* Convert from NS to US */
 			txbuf[i] = DIV_ROUND_UP(raw[i].duration, 1000);
+
+		if (dev->s_tx_carrier) {
+			int carrier = ir_raw_encode_carrier(scan.rc_proto);
+
+			if (carrier > 0)
+				dev->s_tx_carrier(dev, carrier);
+		}
 	} else {
 		if (n < sizeof(unsigned int) || n % sizeof(unsigned int))
 			return -EINVAL;
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 7c572a643656..efa3b735dcc4 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -474,6 +474,7 @@ static struct ir_raw_handler mce_kbd_handler = {
 	.encode		= ir_mce_kbd_encode,
 	.raw_register	= ir_mce_kbd_register,
 	.raw_unregister	= ir_mce_kbd_unregister,
+	.carrier	= 36000,
 };
 
 static int __init ir_mce_kbd_decode_init(void)
diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index a95d09acc22a..4ace5648866d 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -264,6 +264,7 @@ static struct ir_raw_handler nec_handler = {
 							RC_PROTO_BIT_NEC32,
 	.decode		= ir_nec_decode,
 	.encode		= ir_nec_encode,
+	.carrier	= 38000,
 };
 
 static int __init ir_nec_decode_init(void)
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 1292f534de43..cd1c4ee5fcd4 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -282,6 +282,7 @@ static struct ir_raw_handler rc5_handler = {
 							RC_PROTO_BIT_RC5_SZ,
 	.decode		= ir_rc5_decode,
 	.encode		= ir_rc5_encode,
+	.carrier	= 36000,
 };
 
 static int __init ir_rc5_decode_init(void)
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index 5d0d2fe3b7a7..665025303c28 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -408,6 +408,7 @@ static struct ir_raw_handler rc6_handler = {
 			  RC_PROTO_BIT_RC6_MCE,
 	.decode		= ir_rc6_decode,
 	.encode		= ir_rc6_encode,
+	.carrier	= 36000,
 };
 
 static int __init ir_rc6_decode_init(void)
diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
index 758c60956850..723e7d75a593 100644
--- a/drivers/media/rc/ir-sanyo-decoder.c
+++ b/drivers/media/rc/ir-sanyo-decoder.c
@@ -218,6 +218,7 @@ static struct ir_raw_handler sanyo_handler = {
 	.protocols	= RC_PROTO_BIT_SANYO,
 	.decode		= ir_sanyo_decode,
 	.encode		= ir_sanyo_encode,
+	.carrier	= 38000,
 };
 
 static int __init ir_sanyo_decode_init(void)
diff --git a/drivers/media/rc/ir-sharp-decoder.c b/drivers/media/rc/ir-sharp-decoder.c
index ed43a4212479..73174081e843 100644
--- a/drivers/media/rc/ir-sharp-decoder.c
+++ b/drivers/media/rc/ir-sharp-decoder.c
@@ -226,6 +226,7 @@ static struct ir_raw_handler sharp_handler = {
 	.protocols	= RC_PROTO_BIT_SHARP,
 	.decode		= ir_sharp_decode,
 	.encode		= ir_sharp_encode,
+	.carrier	= 38000,
 };
 
 static int __init ir_sharp_decode_init(void)
diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c
index a47ced763031..e4bcff21c025 100644
--- a/drivers/media/rc/ir-sony-decoder.c
+++ b/drivers/media/rc/ir-sony-decoder.c
@@ -221,6 +221,7 @@ static struct ir_raw_handler sony_handler = {
 							RC_PROTO_BIT_SONY20,
 	.decode		= ir_sony_decode,
 	.encode		= ir_sony_encode,
+	.carrier	= 40000,
 };
 
 static int __init ir_sony_decode_init(void)
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 43eabea9f152..3cf09408df6c 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -29,6 +29,7 @@ struct ir_raw_handler {
 	int (*decode)(struct rc_dev *dev, struct ir_raw_event event);
 	int (*encode)(enum rc_proto protocol, u32 scancode,
 		      struct ir_raw_event *events, unsigned int max);
+	u32 carrier;
 
 	/* These two should only be used by the lirc decoder */
 	int (*raw_register)(struct rc_dev *dev);
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 503bc425a187..0814e08a280b 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -492,6 +492,36 @@ static void edge_handle(unsigned long arg)
 	ir_raw_event_handle(dev);
 }
 
+/**
+ * ir_raw_encode_carrier() - Get carrier used for protocol
+ *
+ * @protocol:		protocol
+ *
+ * Attempts to find the carrier for the specified protocol
+ *
+ * Returns:	The carrier in Hz
+ *		-EINVAL if the protocol is invalid, or if no
+ *		compatible encoder was found.
+ */
+int ir_raw_encode_carrier(enum rc_proto protocol)
+{
+	struct ir_raw_handler *handler;
+	int ret = -EINVAL;
+	u64 mask = BIT_ULL(protocol);
+
+	mutex_lock(&ir_raw_handler_lock);
+	list_for_each_entry(handler, &ir_raw_handler_list, list) {
+		if (handler->protocols & mask && handler->encode) {
+			ret = handler->carrier;
+			break;
+		}
+	}
+	mutex_unlock(&ir_raw_handler_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(ir_raw_encode_carrier);
+
 /*
  * Used to (un)register raw event clients
  */
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 314a1edb6189..ca48632ec8e2 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -309,6 +309,7 @@ int ir_raw_event_store_with_filter(struct rc_dev *dev,
 void ir_raw_event_set_idle(struct rc_dev *dev, bool idle);
 int ir_raw_encode_scancode(enum rc_proto protocol, u32 scancode,
 			   struct ir_raw_event *events, unsigned int max);
+int ir_raw_encode_carrier(enum rc_proto protocol);
 
 static inline void ir_raw_event_reset(struct rc_dev *dev)
 {
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 03/26] media: rc: auto load encoder if necessary
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
  2017-10-10  7:17 ` [PATCH v3 01/26] media: lirc: implement scancode sending Sean Young
  2017-10-10  7:17 ` [PATCH v3 02/26] media: lirc: use the correct carrier for scancode transmit Sean Young
@ 2017-10-10  7:17 ` Sean Young
  2017-10-10  7:17 ` [PATCH v3 04/26] media: lirc_zilog: remove receiver Sean Young
                   ` (23 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:17 UTC (permalink / raw)
  To: linux-media

When sending scancodes, load the encoder if we need it.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/rc-core-priv.h | 1 +
 drivers/media/rc/rc-ir-raw.c    | 2 ++
 drivers/media/rc/rc-main.c      | 2 +-
 3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 3cf09408df6c..d29b1b1ef4b7 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -271,6 +271,7 @@ void ir_raw_event_free(struct rc_dev *dev);
 void ir_raw_event_unregister(struct rc_dev *dev);
 int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
 void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
+void ir_raw_load_modules(u64 *protocols);
 void ir_raw_init(void);
 
 /*
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 0814e08a280b..b84201cb012a 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -457,6 +457,8 @@ int ir_raw_encode_scancode(enum rc_proto protocol, u32 scancode,
 	int ret = -EINVAL;
 	u64 mask = 1ULL << protocol;
 
+	ir_raw_load_modules(&mask);
+
 	mutex_lock(&ir_raw_handler_lock);
 	list_for_each_entry(handler, &ir_raw_handler_list, list) {
 		if (handler->protocols & mask && handler->encode) {
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index cb78e5702bef..62102b3ef5aa 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1081,7 +1081,7 @@ static int parse_protocol_change(u64 *protocols, const char *buf)
 	return count;
 }
 
-static void ir_raw_load_modules(u64 *protocols)
+void ir_raw_load_modules(u64 *protocols)
 {
 	u64 available;
 	int i, ret;
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 04/26] media: lirc_zilog: remove receiver
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (2 preceding siblings ...)
  2017-10-10  7:17 ` [PATCH v3 03/26] media: rc: auto load encoder if necessary Sean Young
@ 2017-10-10  7:17 ` Sean Young
  2017-10-11 19:43   ` Andy Walls
  2017-10-10  7:17 ` [PATCH v3 05/26] media: lirc_zilog: fix variable types and other ugliness Sean Young
                   ` (22 subsequent siblings)
  26 siblings, 1 reply; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:17 UTC (permalink / raw)
  To: linux-media, Andy Walls

The ir-kbd-i2c module already handles this very well.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/staging/media/lirc/lirc_zilog.c | 901 +++-----------------------------
 1 file changed, 76 insertions(+), 825 deletions(-)

diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
index 6bd0717bf76e..757b3fc247ac 100644
--- a/drivers/staging/media/lirc/lirc_zilog.c
+++ b/drivers/staging/media/lirc/lirc_zilog.c
@@ -64,28 +64,7 @@
 /* Max transfer size done by I2C transfer functions */
 #define MAX_XFER_SIZE  64
 
-struct IR;
-
-struct IR_rx {
-	struct kref ref;
-	struct IR *ir;
-
-	/* RX device */
-	struct mutex client_lock;
-	struct i2c_client *c;
-
-	/* RX polling thread data */
-	struct task_struct *task;
-
-	/* RX read data */
-	unsigned char b[3];
-	bool hdpvr_data_fmt;
-};
-
 struct IR_tx {
-	struct kref ref;
-	struct IR *ir;
-
 	/* TX device */
 	struct mutex client_lock;
 	struct i2c_client *c;
@@ -93,39 +72,9 @@ struct IR_tx {
 	/* TX additional actions needed */
 	int need_boot;
 	bool post_tx_ready_poll;
-};
-
-struct IR {
-	struct kref ref;
-	struct list_head list;
-
-	/* FIXME spinlock access to l->features */
 	struct lirc_dev *l;
-	struct lirc_buffer rbuf;
-
-	struct mutex ir_lock;
-	atomic_t open_count;
-
-	struct device *dev;
-	struct i2c_adapter *adapter;
-
-	spinlock_t rx_ref_lock; /* struct IR_rx kref get()/put() */
-	struct IR_rx *rx;
-
-	spinlock_t tx_ref_lock; /* struct IR_tx kref get()/put() */
-	struct IR_tx *tx;
 };
 
-/* IR transceiver instance object list */
-/*
- * This lock is used for the following:
- * a. ir_devices_list access, insertions, deletions
- * b. struct IR kref get()s and put()s
- * c. serialization of ir_probe() for the two i2c_clients for a Z8
- */
-static DEFINE_MUTEX(ir_devices_lock);
-static LIST_HEAD(ir_devices_list);
-
 /* Block size for IR transmitter */
 #define TX_BLOCK_SIZE	99
 
@@ -153,348 +102,8 @@ struct tx_data_struct {
 static struct tx_data_struct *tx_data;
 static struct mutex tx_data_lock;
 
-
 /* module parameters */
 static bool debug;	/* debug output */
-static bool tx_only;	/* only handle the IR Tx function */
-
-
-/* struct IR reference counting */
-static struct IR *get_ir_device(struct IR *ir, bool ir_devices_lock_held)
-{
-	if (ir_devices_lock_held) {
-		kref_get(&ir->ref);
-	} else {
-		mutex_lock(&ir_devices_lock);
-		kref_get(&ir->ref);
-		mutex_unlock(&ir_devices_lock);
-	}
-	return ir;
-}
-
-static void release_ir_device(struct kref *ref)
-{
-	struct IR *ir = container_of(ref, struct IR, ref);
-
-	/*
-	 * Things should be in this state by now:
-	 * ir->rx set to NULL and deallocated - happens before ir->rx->ir put()
-	 * ir->rx->task kthread stopped - happens before ir->rx->ir put()
-	 * ir->tx set to NULL and deallocated - happens before ir->tx->ir put()
-	 * ir->open_count ==  0 - happens on final close()
-	 * ir_lock, tx_ref_lock, rx_ref_lock, all released
-	 */
-	if (ir->l)
-		lirc_unregister_device(ir->l);
-
-	if (kfifo_initialized(&ir->rbuf.fifo))
-		lirc_buffer_free(&ir->rbuf);
-	list_del(&ir->list);
-	kfree(ir);
-}
-
-static int put_ir_device(struct IR *ir, bool ir_devices_lock_held)
-{
-	int released;
-
-	if (ir_devices_lock_held)
-		return kref_put(&ir->ref, release_ir_device);
-
-	mutex_lock(&ir_devices_lock);
-	released = kref_put(&ir->ref, release_ir_device);
-	mutex_unlock(&ir_devices_lock);
-
-	return released;
-}
-
-/* struct IR_rx reference counting */
-static struct IR_rx *get_ir_rx(struct IR *ir)
-{
-	struct IR_rx *rx;
-
-	spin_lock(&ir->rx_ref_lock);
-	rx = ir->rx;
-	if (rx)
-		kref_get(&rx->ref);
-	spin_unlock(&ir->rx_ref_lock);
-	return rx;
-}
-
-static void destroy_rx_kthread(struct IR_rx *rx, bool ir_devices_lock_held)
-{
-	/* end up polling thread */
-	if (!IS_ERR_OR_NULL(rx->task)) {
-		kthread_stop(rx->task);
-		rx->task = NULL;
-		/* Put the ir ptr that ir_probe() gave to the rx poll thread */
-		put_ir_device(rx->ir, ir_devices_lock_held);
-	}
-}
-
-static void release_ir_rx(struct kref *ref)
-{
-	struct IR_rx *rx = container_of(ref, struct IR_rx, ref);
-	struct IR *ir = rx->ir;
-
-	/*
-	 * This release function can't do all the work, as we want
-	 * to keep the rx_ref_lock a spinlock, and killing the poll thread
-	 * and releasing the ir reference can cause a sleep.  That work is
-	 * performed by put_ir_rx()
-	 */
-	ir->l->features &= ~LIRC_CAN_REC_LIRCCODE;
-	/* Don't put_ir_device(rx->ir) here; lock can't be freed yet */
-	ir->rx = NULL;
-	/* Don't do the kfree(rx) here; we still need to kill the poll thread */
-}
-
-static int put_ir_rx(struct IR_rx *rx, bool ir_devices_lock_held)
-{
-	int released;
-	struct IR *ir = rx->ir;
-
-	spin_lock(&ir->rx_ref_lock);
-	released = kref_put(&rx->ref, release_ir_rx);
-	spin_unlock(&ir->rx_ref_lock);
-	/* Destroy the rx kthread while not holding the spinlock */
-	if (released) {
-		destroy_rx_kthread(rx, ir_devices_lock_held);
-		kfree(rx);
-		/* Make sure we're not still in a poll_table somewhere */
-		wake_up_interruptible(&ir->rbuf.wait_poll);
-	}
-	/* Do a reference put() for the rx->ir reference, if we released rx */
-	if (released)
-		put_ir_device(ir, ir_devices_lock_held);
-	return released;
-}
-
-/* struct IR_tx reference counting */
-static struct IR_tx *get_ir_tx(struct IR *ir)
-{
-	struct IR_tx *tx;
-
-	spin_lock(&ir->tx_ref_lock);
-	tx = ir->tx;
-	if (tx)
-		kref_get(&tx->ref);
-	spin_unlock(&ir->tx_ref_lock);
-	return tx;
-}
-
-static void release_ir_tx(struct kref *ref)
-{
-	struct IR_tx *tx = container_of(ref, struct IR_tx, ref);
-	struct IR *ir = tx->ir;
-
-	ir->l->features &= ~LIRC_CAN_SEND_LIRCCODE;
-	/* Don't put_ir_device(tx->ir) here, so our lock doesn't get freed */
-	ir->tx = NULL;
-	kfree(tx);
-}
-
-static int put_ir_tx(struct IR_tx *tx, bool ir_devices_lock_held)
-{
-	int released;
-	struct IR *ir = tx->ir;
-
-	spin_lock(&ir->tx_ref_lock);
-	released = kref_put(&tx->ref, release_ir_tx);
-	spin_unlock(&ir->tx_ref_lock);
-	/* Do a reference put() for the tx->ir reference, if we released tx */
-	if (released)
-		put_ir_device(ir, ir_devices_lock_held);
-	return released;
-}
-
-static int add_to_buf(struct IR *ir)
-{
-	__u16 code;
-	unsigned char codes[2];
-	unsigned char keybuf[6];
-	int got_data = 0;
-	int ret;
-	int failures = 0;
-	unsigned char sendbuf[1] = { 0 };
-	struct lirc_buffer *rbuf = ir->l->buf;
-	struct IR_rx *rx;
-	struct IR_tx *tx;
-
-	if (lirc_buffer_full(rbuf)) {
-		dev_dbg(ir->dev, "buffer overflow\n");
-		return -EOVERFLOW;
-	}
-
-	rx = get_ir_rx(ir);
-	if (!rx)
-		return -ENXIO;
-
-	/* Ensure our rx->c i2c_client remains valid for the duration */
-	mutex_lock(&rx->client_lock);
-	if (!rx->c) {
-		mutex_unlock(&rx->client_lock);
-		put_ir_rx(rx, false);
-		return -ENXIO;
-	}
-
-	tx = get_ir_tx(ir);
-
-	/*
-	 * service the device as long as it is returning
-	 * data and we have space
-	 */
-	do {
-		if (kthread_should_stop()) {
-			ret = -ENODATA;
-			break;
-		}
-
-		/*
-		 * Lock i2c bus for the duration.  RX/TX chips interfere so
-		 * this is worth it
-		 */
-		mutex_lock(&ir->ir_lock);
-
-		if (kthread_should_stop()) {
-			mutex_unlock(&ir->ir_lock);
-			ret = -ENODATA;
-			break;
-		}
-
-		/*
-		 * Send random "poll command" (?)  Windows driver does this
-		 * and it is a good point to detect chip failure.
-		 */
-		ret = i2c_master_send(rx->c, sendbuf, 1);
-		if (ret != 1) {
-			dev_err(ir->dev, "i2c_master_send failed with %d\n",
-				ret);
-			if (failures >= 3) {
-				mutex_unlock(&ir->ir_lock);
-				dev_err(ir->dev,
-					"unable to read from the IR chip after 3 resets, giving up\n");
-				break;
-			}
-
-			/* Looks like the chip crashed, reset it */
-			dev_err(ir->dev,
-				"polling the IR receiver chip failed, trying reset\n");
-
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			if (kthread_should_stop()) {
-				mutex_unlock(&ir->ir_lock);
-				ret = -ENODATA;
-				break;
-			}
-			schedule_timeout((100 * HZ + 999) / 1000);
-			if (tx)
-				tx->need_boot = 1;
-
-			++failures;
-			mutex_unlock(&ir->ir_lock);
-			ret = 0;
-			continue;
-		}
-
-		if (kthread_should_stop()) {
-			mutex_unlock(&ir->ir_lock);
-			ret = -ENODATA;
-			break;
-		}
-		ret = i2c_master_recv(rx->c, keybuf, sizeof(keybuf));
-		mutex_unlock(&ir->ir_lock);
-		if (ret != sizeof(keybuf)) {
-			dev_err(ir->dev,
-				"i2c_master_recv failed with %d -- keeping last read buffer\n",
-				ret);
-		} else {
-			rx->b[0] = keybuf[3];
-			rx->b[1] = keybuf[4];
-			rx->b[2] = keybuf[5];
-			dev_dbg(ir->dev,
-				"key (0x%02x/0x%02x)\n",
-				rx->b[0], rx->b[1]);
-		}
-
-		/* key pressed ? */
-		if (rx->hdpvr_data_fmt) {
-			if (got_data && (keybuf[0] == 0x80)) {
-				ret = 0;
-				break;
-			} else if (got_data && (keybuf[0] == 0x00)) {
-				ret = -ENODATA;
-				break;
-			}
-		} else if ((rx->b[0] & 0x80) == 0) {
-			ret = got_data ? 0 : -ENODATA;
-			break;
-		}
-
-		/* look what we have */
-		code = (((__u16)rx->b[0] & 0x7f) << 6) | (rx->b[1] >> 2);
-
-		codes[0] = (code >> 8) & 0xff;
-		codes[1] = code & 0xff;
-
-		/* return it */
-		lirc_buffer_write(rbuf, codes);
-		++got_data;
-		ret = 0;
-	} while (!lirc_buffer_full(rbuf));
-
-	mutex_unlock(&rx->client_lock);
-	if (tx)
-		put_ir_tx(tx, false);
-	put_ir_rx(rx, false);
-	return ret;
-}
-
-/*
- * Main function of the polling thread -- from lirc_dev.
- * We don't fit the LIRC model at all anymore.  This is horrible, but
- * basically we have a single RX/TX device with a nasty failure mode
- * that needs to be accounted for across the pair.  lirc lets us provide
- * fops, but prevents us from using the internal polling, etc. if we do
- * so.  Hence the replication.  Might be neater to extend the LIRC model
- * to account for this but I'd think it's a very special case of seriously
- * messed up hardware.
- */
-static int lirc_thread(void *arg)
-{
-	struct IR *ir = arg;
-	struct lirc_buffer *rbuf = ir->l->buf;
-
-	dev_dbg(ir->dev, "poll thread started\n");
-
-	while (!kthread_should_stop()) {
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		/* if device not opened, we can sleep half a second */
-		if (atomic_read(&ir->open_count) == 0) {
-			schedule_timeout(HZ / 2);
-			continue;
-		}
-
-		/*
-		 * This is ~113*2 + 24 + jitter (2*repeat gap + code length).
-		 * We use this interval as the chip resets every time you poll
-		 * it (bad!).  This is therefore just sufficient to catch all
-		 * of the button presses.  It makes the remote much more
-		 * responsive.  You can see the difference by running irw and
-		 * holding down a button.  With 100ms, the old polling
-		 * interval, you'll notice breaks in the repeat sequence
-		 * corresponding to lost keypresses.
-		 */
-		schedule_timeout((260 * HZ) / 1000);
-		if (kthread_should_stop())
-			break;
-		if (!add_to_buf(ir))
-			wake_up_interruptible(&rbuf->wait_poll);
-	}
-
-	dev_dbg(ir->dev, "poll thread ended\n");
-	return 0;
-}
 
 /* safe read of a uint32 (always network byte order) */
 static int read_uint32(unsigned char **data,
@@ -645,10 +254,10 @@ static int send_data_block(struct IR_tx *tx, unsigned char *data_block)
 		buf[0] = (unsigned char)(i + 1);
 		for (j = 0; j < tosend; ++j)
 			buf[1 + j] = data_block[i + j];
-		dev_dbg(tx->ir->dev, "%*ph", 5, buf);
+		dev_dbg(&tx->l->dev, "%*ph", 5, buf);
 		ret = i2c_master_send(tx->c, buf, tosend + 1);
 		if (ret != tosend + 1) {
-			dev_err(tx->ir->dev,
+			dev_err(&tx->l->dev,
 				"i2c_master_send failed with %d\n", ret);
 			return ret < 0 ? ret : -EFAULT;
 		}
@@ -673,7 +282,7 @@ static int send_boot_data(struct IR_tx *tx)
 	buf[1] = 0x20;
 	ret = i2c_master_send(tx->c, buf, 2);
 	if (ret != 2) {
-		dev_err(tx->ir->dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->l->dev, "i2c_master_send failed with %d\n", ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
@@ -690,22 +299,22 @@ static int send_boot_data(struct IR_tx *tx)
 	}
 
 	if (ret != 1) {
-		dev_err(tx->ir->dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->l->dev, "i2c_master_send failed with %d\n", ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
 	/* Here comes the firmware version... (hopefully) */
 	ret = i2c_master_recv(tx->c, buf, 4);
 	if (ret != 4) {
-		dev_err(tx->ir->dev, "i2c_master_recv failed with %d\n", ret);
+		dev_err(&tx->l->dev, "i2c_master_recv failed with %d\n", ret);
 		return 0;
 	}
 	if ((buf[0] != 0x80) && (buf[0] != 0xa0)) {
-		dev_err(tx->ir->dev, "unexpected IR TX init response: %02x\n",
+		dev_err(&tx->l->dev, "unexpected IR TX init response: %02x\n",
 			buf[0]);
 		return 0;
 	}
-	dev_notice(tx->ir->dev,
+	dev_notice(&tx->l->dev,
 		   "Zilog/Hauppauge IR blaster firmware version %d.%d.%d loaded\n",
 		   buf[1], buf[2], buf[3]);
 
@@ -750,15 +359,15 @@ static int fw_load(struct IR_tx *tx)
 	}
 
 	/* Request codeset data file */
-	ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx->ir->dev);
+	ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", &tx->l->dev);
 	if (ret != 0) {
-		dev_err(tx->ir->dev,
+		dev_err(&tx->l->dev,
 			"firmware haup-ir-blaster.bin not available (%d)\n",
 			ret);
 		ret = ret < 0 ? ret : -EFAULT;
 		goto out;
 	}
-	dev_dbg(tx->ir->dev, "firmware of size %zu loaded\n", fw_entry->size);
+	dev_dbg(&tx->l->dev, "firmware of size %zu loaded\n", fw_entry->size);
 
 	/* Parse the file */
 	tx_data = vmalloc(sizeof(*tx_data));
@@ -786,7 +395,7 @@ static int fw_load(struct IR_tx *tx)
 	if (!read_uint8(&data, tx_data->endp, &version))
 		goto corrupt;
 	if (version != 1) {
-		dev_err(tx->ir->dev,
+		dev_err(&tx->l->dev,
 			"unsupported code set file version (%u, expected 1) -- please upgrade to a newer driver\n",
 			version);
 		fw_unload_locked();
@@ -803,7 +412,7 @@ static int fw_load(struct IR_tx *tx)
 			 &tx_data->num_code_sets))
 		goto corrupt;
 
-	dev_dbg(tx->ir->dev, "%u IR blaster codesets loaded\n",
+	dev_dbg(&tx->l->dev, "%u IR blaster codesets loaded\n",
 		tx_data->num_code_sets);
 
 	tx_data->code_sets = vmalloc(
@@ -868,7 +477,7 @@ static int fw_load(struct IR_tx *tx)
 	goto out;
 
 corrupt:
-	dev_err(tx->ir->dev, "firmware is corrupt\n");
+	dev_err(&tx->l->dev, "firmware is corrupt\n");
 	fw_unload_locked();
 	ret = -EFAULT;
 
@@ -877,94 +486,6 @@ static int fw_load(struct IR_tx *tx)
 	return ret;
 }
 
-/* copied from lirc_dev */
-static ssize_t read(struct file *filep, char __user *outbuf, size_t n,
-		    loff_t *ppos)
-{
-	struct IR *ir = lirc_get_pdata(filep);
-	struct IR_rx *rx;
-	struct lirc_buffer *rbuf = ir->l->buf;
-	int ret = 0, written = 0, retries = 0;
-	unsigned int m;
-	DECLARE_WAITQUEUE(wait, current);
-
-	dev_dbg(ir->dev, "read called\n");
-	if (n % rbuf->chunk_size) {
-		dev_dbg(ir->dev, "read result = -EINVAL\n");
-		return -EINVAL;
-	}
-
-	rx = get_ir_rx(ir);
-	if (!rx)
-		return -ENXIO;
-
-	/*
-	 * we add ourselves to the task queue before buffer check
-	 * to avoid losing scan code (in case when queue is awaken somewhere
-	 * between while condition checking and scheduling)
-	 */
-	add_wait_queue(&rbuf->wait_poll, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-
-	/*
-	 * while we didn't provide 'length' bytes, device is opened in blocking
-	 * mode and 'copy_to_user' is happy, wait for data.
-	 */
-	while (written < n && ret == 0) {
-		if (lirc_buffer_empty(rbuf)) {
-			/*
-			 * According to the read(2) man page, 'written' can be
-			 * returned as less than 'n', instead of blocking
-			 * again, returning -EWOULDBLOCK, or returning
-			 * -ERESTARTSYS
-			 */
-			if (written)
-				break;
-			if (filep->f_flags & O_NONBLOCK) {
-				ret = -EWOULDBLOCK;
-				break;
-			}
-			if (signal_pending(current)) {
-				ret = -ERESTARTSYS;
-				break;
-			}
-			schedule();
-			set_current_state(TASK_INTERRUPTIBLE);
-		} else {
-			unsigned char buf[MAX_XFER_SIZE];
-
-			if (rbuf->chunk_size > sizeof(buf)) {
-				dev_err(ir->dev,
-					"chunk_size is too big (%d)!\n",
-					rbuf->chunk_size);
-				ret = -EINVAL;
-				break;
-			}
-			m = lirc_buffer_read(rbuf, buf);
-			if (m == rbuf->chunk_size) {
-				ret = copy_to_user(outbuf + written, buf,
-						   rbuf->chunk_size);
-				written += rbuf->chunk_size;
-			} else {
-				retries++;
-			}
-			if (retries >= 5) {
-				dev_err(ir->dev, "Buffer read failed!\n");
-				ret = -EIO;
-			}
-		}
-	}
-
-	remove_wait_queue(&rbuf->wait_poll, &wait);
-	put_ir_rx(rx, false);
-	set_current_state(TASK_RUNNING);
-
-	dev_dbg(ir->dev, "read result = %d (%s)\n", ret,
-		ret ? "Error" : "OK");
-
-	return ret ? ret : written;
-}
-
 /* send a keypress to the IR TX device */
 static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 {
@@ -976,7 +497,7 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	ret = get_key_data(data_block, code, key);
 
 	if (ret == -EPROTO) {
-		dev_err(tx->ir->dev,
+		dev_err(&tx->l->dev,
 			"failed to get data for code %u, key %u -- check lircd.conf entries\n",
 			code, key);
 		return ret;
@@ -994,7 +515,7 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	buf[1] = 0x40;
 	ret = i2c_master_send(tx->c, buf, 2);
 	if (ret != 2) {
-		dev_err(tx->ir->dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->l->dev, "i2c_master_send failed with %d\n", ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
@@ -1007,18 +528,18 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	}
 
 	if (ret != 1) {
-		dev_err(tx->ir->dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->l->dev, "i2c_master_send failed with %d\n", ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
 	/* Send finished download? */
 	ret = i2c_master_recv(tx->c, buf, 1);
 	if (ret != 1) {
-		dev_err(tx->ir->dev, "i2c_master_recv failed with %d\n", ret);
+		dev_err(&tx->l->dev, "i2c_master_recv failed with %d\n", ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 	if (buf[0] != 0xA0) {
-		dev_err(tx->ir->dev, "unexpected IR TX response #1: %02x\n",
+		dev_err(&tx->l->dev, "unexpected IR TX response #1: %02x\n",
 			buf[0]);
 		return -EFAULT;
 	}
@@ -1028,7 +549,7 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	buf[1] = 0x80;
 	ret = i2c_master_send(tx->c, buf, 2);
 	if (ret != 2) {
-		dev_err(tx->ir->dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->l->dev, "i2c_master_send failed with %d\n", ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
@@ -1038,7 +559,7 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	 * going to skip this whole mess and say we're done on the HD PVR
 	 */
 	if (!tx->post_tx_ready_poll) {
-		dev_dbg(tx->ir->dev, "sent code %u, key %u\n", code, key);
+		dev_dbg(&tx->l->dev, "sent code %u, key %u\n", code, key);
 		return 0;
 	}
 
@@ -1054,12 +575,12 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 		ret = i2c_master_send(tx->c, buf, 1);
 		if (ret == 1)
 			break;
-		dev_dbg(tx->ir->dev,
+		dev_dbg(&tx->l->dev,
 			"NAK expected: i2c_master_send failed with %d (try %d)\n",
 			ret, i + 1);
 	}
 	if (ret != 1) {
-		dev_err(tx->ir->dev,
+		dev_err(&tx->l->dev,
 			"IR TX chip never got ready: last i2c_master_send failed with %d\n",
 			ret);
 		return ret < 0 ? ret : -EFAULT;
@@ -1068,17 +589,17 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	/* Seems to be an 'ok' response */
 	i = i2c_master_recv(tx->c, buf, 1);
 	if (i != 1) {
-		dev_err(tx->ir->dev, "i2c_master_recv failed with %d\n", ret);
+		dev_err(&tx->l->dev, "i2c_master_recv failed with %d\n", ret);
 		return -EFAULT;
 	}
 	if (buf[0] != 0x80) {
-		dev_err(tx->ir->dev, "unexpected IR TX response #2: %02x\n",
+		dev_err(&tx->l->dev, "unexpected IR TX response #2: %02x\n",
 			buf[0]);
 		return -EFAULT;
 	}
 
 	/* Oh good, it worked */
-	dev_dbg(tx->ir->dev, "sent code %u, key %u\n", code, key);
+	dev_dbg(&tx->l->dev, "sent code %u, key %u\n", code, key);
 	return 0;
 }
 
@@ -1091,8 +612,7 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 static ssize_t write(struct file *filep, const char __user *buf, size_t n,
 		     loff_t *ppos)
 {
-	struct IR *ir = lirc_get_pdata(filep);
-	struct IR_tx *tx;
+	struct IR_tx *tx = lirc_get_pdata(filep);
 	size_t i;
 	int failures = 0;
 
@@ -1100,31 +620,20 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n,
 	if (n % sizeof(int))
 		return -EINVAL;
 
-	/* Get a struct IR_tx reference */
-	tx = get_ir_tx(ir);
-	if (!tx)
-		return -ENXIO;
-
 	/* Ensure our tx->c i2c_client remains valid for the duration */
 	mutex_lock(&tx->client_lock);
 	if (!tx->c) {
 		mutex_unlock(&tx->client_lock);
-		put_ir_tx(tx, false);
 		return -ENXIO;
 	}
 
-	/* Lock i2c bus for the duration */
-	mutex_lock(&ir->ir_lock);
-
 	/* Send each keypress */
 	for (i = 0; i < n;) {
 		int ret = 0;
 		int command;
 
 		if (copy_from_user(&command, buf + i, sizeof(command))) {
-			mutex_unlock(&ir->ir_lock);
 			mutex_unlock(&tx->client_lock);
-			put_ir_tx(tx, false);
 			return -EFAULT;
 		}
 
@@ -1133,9 +642,7 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n,
 			/* Make sure we have the 'firmware' loaded, first */
 			ret = fw_load(tx);
 			if (ret != 0) {
-				mutex_unlock(&ir->ir_lock);
 				mutex_unlock(&tx->client_lock);
-				put_ir_tx(tx, false);
 				if (ret != -ENOMEM)
 					ret = -EIO;
 				return ret;
@@ -1151,9 +658,7 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n,
 			ret = send_code(tx, (unsigned int)command >> 16,
 					    (unsigned int)command & 0xFFFF);
 			if (ret == -EPROTO) {
-				mutex_unlock(&ir->ir_lock);
 				mutex_unlock(&tx->client_lock);
-				put_ir_tx(tx, false);
 				return ret;
 			}
 		}
@@ -1164,15 +669,13 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n,
 		 */
 		if (ret != 0) {
 			/* Looks like the chip crashed, reset it */
-			dev_err(tx->ir->dev,
+			dev_err(&tx->l->dev,
 				"sending to the IR transmitter chip failed, trying reset\n");
 
 			if (failures >= 3) {
-				dev_err(tx->ir->dev,
+				dev_err(&tx->l->dev,
 					"unable to send to the IR chip after 3 resets, giving up\n");
-				mutex_unlock(&ir->ir_lock);
 				mutex_unlock(&tx->client_lock);
-				put_ir_tx(tx, false);
 				return ret;
 			}
 			set_current_state(TASK_UNINTERRUPTIBLE);
@@ -1184,60 +687,21 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n,
 		}
 	}
 
-	/* Release i2c bus */
-	mutex_unlock(&ir->ir_lock);
-
 	mutex_unlock(&tx->client_lock);
 
-	/* Give back our struct IR_tx reference */
-	put_ir_tx(tx, false);
-
 	/* All looks good */
 	return n;
 }
 
-/* copied from lirc_dev */
-static unsigned int poll(struct file *filep, poll_table *wait)
-{
-	struct IR *ir = lirc_get_pdata(filep);
-	struct IR_rx *rx;
-	struct lirc_buffer *rbuf = ir->l->buf;
-	unsigned int ret;
-
-	dev_dbg(ir->dev, "%s called\n", __func__);
-
-	rx = get_ir_rx(ir);
-	if (!rx) {
-		/*
-		 * Revisit this, if our poll function ever reports writeable
-		 * status for Tx
-		 */
-		dev_dbg(ir->dev, "%s result = POLLERR\n", __func__);
-		return POLLERR;
-	}
-
-	/*
-	 * Add our lirc_buffer's wait_queue to the poll_table. A wake up on
-	 * that buffer's wait queue indicates we may have a new poll status.
-	 */
-	poll_wait(filep, &rbuf->wait_poll, wait);
-
-	/* Indicate what ops could happen immediately without blocking */
-	ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN | POLLRDNORM);
-
-	dev_dbg(ir->dev, "%s result = %s\n", __func__,
-		ret ? "POLLIN|POLLRDNORM" : "none");
-	return ret;
-}
 
 static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 {
-	struct IR *ir = lirc_get_pdata(filep);
+	struct IR_tx *tx = lirc_get_pdata(filep);
 	unsigned long __user *uptr = (unsigned long __user *)arg;
 	int result;
 	unsigned long mode, features;
 
-	features = ir->l->features;
+	features = tx->l->features;
 
 	switch (cmd) {
 	case LIRC_GET_LENGTH:
@@ -1287,13 +751,7 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
  */
 static int open(struct inode *node, struct file *filep)
 {
-	struct IR *ir;
-
 	lirc_init_pdata(node, filep);
-	ir = lirc_get_pdata(filep);
-
-	atomic_inc(&ir->open_count);
-
 	nonseekable_open(node, filep);
 	return 0;
 }
@@ -1301,25 +759,16 @@ static int open(struct inode *node, struct file *filep)
 /* Close the IR device */
 static int close(struct inode *node, struct file *filep)
 {
-	struct IR *ir = lirc_get_pdata(filep);
-
-	atomic_dec(&ir->open_count);
-
-	put_ir_device(ir, false);
 	return 0;
 }
 
-static int ir_remove(struct i2c_client *client);
 static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id);
 
-#define ID_FLAG_TX	0x01
-#define ID_FLAG_HDPVR	0x02
+#define ID_FLAG_HDPVR	0x01
 
 static const struct i2c_device_id ir_transceiver_id[] = {
-	{ "ir_tx_z8f0811_haup",  ID_FLAG_TX                 },
-	{ "ir_rx_z8f0811_haup",  0                          },
-	{ "ir_tx_z8f0811_hdpvr", ID_FLAG_HDPVR | ID_FLAG_TX },
-	{ "ir_rx_z8f0811_hdpvr", ID_FLAG_HDPVR              },
+	{ "ir_tx_z8f0811_haup",  0 },
+	{ "ir_tx_z8f0811_hdpvr", ID_FLAG_HDPVR },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ir_transceiver_id);
@@ -1329,16 +778,13 @@ static struct i2c_driver driver = {
 		.name	= "Zilog/Hauppauge i2c IR",
 	},
 	.probe		= ir_probe,
-	.remove		= ir_remove,
 	.id_table	= ir_transceiver_id,
 };
 
 static const struct file_operations lirc_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
-	.read		= read,
 	.write		= write,
-	.poll		= poll,
 	.unlocked_ioctl	= ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= ioctl,
@@ -1347,55 +793,11 @@ static const struct file_operations lirc_fops = {
 	.release	= close
 };
 
-static int ir_remove(struct i2c_client *client)
-{
-	if (strncmp("ir_tx_z8", client->name, 8) == 0) {
-		struct IR_tx *tx = i2c_get_clientdata(client);
-
-		if (tx) {
-			mutex_lock(&tx->client_lock);
-			tx->c = NULL;
-			mutex_unlock(&tx->client_lock);
-			put_ir_tx(tx, false);
-		}
-	} else if (strncmp("ir_rx_z8", client->name, 8) == 0) {
-		struct IR_rx *rx = i2c_get_clientdata(client);
-
-		if (rx) {
-			mutex_lock(&rx->client_lock);
-			rx->c = NULL;
-			mutex_unlock(&rx->client_lock);
-			put_ir_rx(rx, false);
-		}
-	}
-	return 0;
-}
-
-/* ir_devices_lock must be held */
-static struct IR *get_ir_device_by_adapter(struct i2c_adapter *adapter)
-{
-	struct IR *ir;
-
-	if (list_empty(&ir_devices_list))
-		return NULL;
-
-	list_for_each_entry(ir, &ir_devices_list, list)
-		if (ir->adapter == adapter) {
-			get_ir_device(ir, true);
-			return ir;
-		}
-
-	return NULL;
-}
-
 static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-	struct IR *ir;
 	struct IR_tx *tx;
-	struct IR_rx *rx;
 	struct i2c_adapter *adap = client->adapter;
 	int ret;
-	bool tx_probe = false;
 
 	dev_dbg(&client->dev, "%s: %s on i2c-%d (%s), client addr=0x%02x\n",
 		__func__, id->name, adap->nr, adap->name, client->addr);
@@ -1405,209 +807,61 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	 * The IR transmitter is at i2c address 0x70.
 	 */
 
-	if (id->driver_data & ID_FLAG_TX)
-		tx_probe = true;
-	else if (tx_only) /* module option */
-		return -ENXIO;
-
-	pr_info("probing IR %s on %s (i2c-%d)\n",
-		tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
-
-	mutex_lock(&ir_devices_lock);
-
-	/* Use a single struct IR instance for both the Rx and Tx functions */
-	ir = get_ir_device_by_adapter(adap);
-	if (!ir) {
-		ir = kzalloc(sizeof(*ir), GFP_KERNEL);
-		if (!ir) {
-			ret = -ENOMEM;
-			goto out_no_ir;
-		}
-		kref_init(&ir->ref);
-
-		/* store for use in ir_probe() again, and open() later on */
-		INIT_LIST_HEAD(&ir->list);
-		list_add_tail(&ir->list, &ir_devices_list);
-
-		ir->adapter = adap;
-		ir->dev = &adap->dev;
-		mutex_init(&ir->ir_lock);
-		atomic_set(&ir->open_count, 0);
-		spin_lock_init(&ir->tx_ref_lock);
-		spin_lock_init(&ir->rx_ref_lock);
-
-		/* set lirc_dev stuff */
-		ir->l = lirc_allocate_device();
-		if (!ir->l) {
-			ret = -ENOMEM;
-			goto out_put_ir;
-		}
-
-		snprintf(ir->l->name, sizeof(ir->l->name), "lirc_zilog");
-		ir->l->code_length = 13;
-		ir->l->fops = &lirc_fops;
-		ir->l->owner = THIS_MODULE;
-		ir->l->dev.parent = &adap->dev;
-
-		/*
-		 * FIXME this is a pointer reference to us, but no refcount.
-		 *
-		 * This OK for now, since lirc_dev currently won't touch this
-		 * buffer as we provide our own lirc_fops.
-		 *
-		 * Currently our own lirc_fops rely on this ir->l->buf pointer
-		 */
-		ir->l->buf = &ir->rbuf;
-		/* This will be returned by lirc_get_pdata() */
-		ir->l->data = ir;
-		ret = lirc_buffer_init(ir->l->buf, 2, BUFLEN / 2);
-		if (ret) {
-			lirc_free_device(ir->l);
-			ir->l = NULL;
-			goto out_put_ir;
-		}
-	}
+	pr_info("probing IR Tx on %s (i2c-%d)\n", adap->name, adap->nr);
 
-	if (tx_probe) {
-		/* Get the IR_rx instance for later, if already allocated */
-		rx = get_ir_rx(ir);
-
-		/* Set up a struct IR_tx instance */
-		tx = kzalloc(sizeof(*tx), GFP_KERNEL);
-		if (!tx) {
-			ret = -ENOMEM;
-			goto out_put_xx;
-		}
-		kref_init(&tx->ref);
-		ir->tx = tx;
-
-		ir->l->features |= LIRC_CAN_SEND_LIRCCODE;
-		mutex_init(&tx->client_lock);
-		tx->c = client;
-		tx->need_boot = 1;
-		tx->post_tx_ready_poll =
-			       (id->driver_data & ID_FLAG_HDPVR) ? false : true;
-
-		/* An ir ref goes to the struct IR_tx instance */
-		tx->ir = get_ir_device(ir, true);
-
-		/* A tx ref goes to the i2c_client */
-		i2c_set_clientdata(client, get_ir_tx(ir));
-
-		/*
-		 * Load the 'firmware'.  We do this before registering with
-		 * lirc_dev, so the first firmware load attempt does not happen
-		 * after a open() or write() call on the device.
-		 *
-		 * Failure here is not deemed catastrophic, so the receiver will
-		 * still be usable.  Firmware load will be retried in write(),
-		 * if it is needed.
-		 */
-		fw_load(tx);
-
-		/* Proceed only if the Rx client is also ready or not needed */
-		if (!rx && !tx_only) {
-			dev_info(tx->ir->dev,
-				 "probe of IR Tx on %s (i2c-%d) done. Waiting on IR Rx.\n",
-				 adap->name, adap->nr);
-			goto out_ok;
-		}
-	} else {
-		/* Get the IR_tx instance for later, if already allocated */
-		tx = get_ir_tx(ir);
-
-		/* Set up a struct IR_rx instance */
-		rx = kzalloc(sizeof(*rx), GFP_KERNEL);
-		if (!rx) {
-			ret = -ENOMEM;
-			goto out_put_xx;
-		}
-		kref_init(&rx->ref);
-		ir->rx = rx;
-
-		ir->l->features |= LIRC_CAN_REC_LIRCCODE;
-		mutex_init(&rx->client_lock);
-		rx->c = client;
-		rx->hdpvr_data_fmt =
-			       (id->driver_data & ID_FLAG_HDPVR) ? true : false;
-
-		/* An ir ref goes to the struct IR_rx instance */
-		rx->ir = get_ir_device(ir, true);
+	/* Set up a struct IR_tx instance */
+	tx = devm_kzalloc(&client->dev, sizeof(*tx), GFP_KERNEL);
+	if (!tx)
+		return -ENOMEM;
 
-		/* An rx ref goes to the i2c_client */
-		i2c_set_clientdata(client, get_ir_rx(ir));
+	mutex_init(&tx->client_lock);
+	tx->c = client;
+	tx->need_boot = 1;
+	tx->post_tx_ready_poll = !(id->driver_data & ID_FLAG_HDPVR);
 
-		/*
-		 * Start the polling thread.
-		 * It will only perform an empty loop around schedule_timeout()
-		 * until we register with lirc_dev and the first user open()
-		 */
-		/* An ir ref goes to the new rx polling kthread */
-		rx->task = kthread_run(lirc_thread, get_ir_device(ir, true),
-				       "zilog-rx-i2c-%d", adap->nr);
-		if (IS_ERR(rx->task)) {
-			ret = PTR_ERR(rx->task);
-			dev_err(tx->ir->dev,
-				"%s: could not start IR Rx polling thread\n",
-				__func__);
-			/* Failed kthread, so put back the ir ref */
-			put_ir_device(ir, true);
-			/* Failure exit, so put back rx ref from i2c_client */
-			i2c_set_clientdata(client, NULL);
-			put_ir_rx(rx, true);
-			ir->l->features &= ~LIRC_CAN_REC_LIRCCODE;
-			goto out_put_tx;
-		}
+	/* set lirc_dev stuff */
+	tx->l = lirc_allocate_device();
+	if (!tx->l)
+		return -ENOMEM;
 
-		/* Proceed only if the Tx client is also ready */
-		if (!tx) {
-			pr_info("probe of IR Rx on %s (i2c-%d) done. Waiting on IR Tx.\n",
-				adap->name, adap->nr);
-			goto out_ok;
-		}
-	}
+	snprintf(tx->l->name, sizeof(tx->l->name), "lirc_zilog");
+	tx->l->features |= LIRC_CAN_SEND_LIRCCODE;
+	tx->l->code_length = 13;
+	tx->l->fops = &lirc_fops;
+	tx->l->owner = THIS_MODULE;
+	tx->l->dev.parent = &client->dev;
 
 	/* register with lirc */
-	ret = lirc_register_device(ir->l);
+	ret = lirc_register_device(tx->l);
 	if (ret < 0) {
-		dev_err(tx->ir->dev,
-			"%s: lirc_register_device() failed: %i\n",
+		dev_err(&tx->l->dev, "%s: lirc_register_device() failed: %i\n",
 			__func__, ret);
-		lirc_free_device(ir->l);
-		ir->l = NULL;
-		goto out_put_xx;
+		lirc_free_device(tx->l);
+		tx->l = NULL;
+		return ret;
 	}
 
-	dev_info(ir->dev,
+	/*
+	 * Load the 'firmware'.  We do this before registering with
+	 * lirc_dev, so the first firmware load attempt does not happen
+	 * after a open() or write() call on the device.
+	 */
+	ret = fw_load(tx);
+	if (ret < 0) {
+		lirc_unregister_device(tx->l);
+		return ret;
+	}
+
+	/* A tx ref goes to the i2c_client */
+	i2c_set_clientdata(client, tx);
+
+	dev_info(&tx->l->dev,
 		 "IR unit on %s (i2c-%d) registered as lirc%d and ready\n",
-		 adap->name, adap->nr, ir->l->minor);
-
-out_ok:
-	if (rx)
-		put_ir_rx(rx, true);
-	if (tx)
-		put_ir_tx(tx, true);
-	put_ir_device(ir, true);
-	dev_info(ir->dev,
-		 "probe of IR %s on %s (i2c-%d) done\n",
-		 tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
-	mutex_unlock(&ir_devices_lock);
-	return 0;
+		 adap->name, adap->nr, tx->l->minor);
 
-out_put_xx:
-	if (rx)
-		put_ir_rx(rx, true);
-out_put_tx:
-	if (tx)
-		put_ir_tx(tx, true);
-out_put_ir:
-	put_ir_device(ir, true);
-out_no_ir:
-	dev_err(&client->dev,
-		"%s: probing IR %s on %s (i2c-%d) failed with %d\n",
-		__func__, tx_probe ? "Tx" : "Rx", adap->name, adap->nr, ret);
-	mutex_unlock(&ir_devices_lock);
-	return ret;
+	dev_info(&tx->l->dev,
+		 "probe of IR Tx on %s (i2c-%d) done\n", adap->name, adap->nr);
+	return 0;
 }
 
 static int __init zilog_init(void)
@@ -1648,6 +902,3 @@ MODULE_ALIAS("lirc_pvr150");
 
 module_param(debug, bool, 0644);
 MODULE_PARM_DESC(debug, "Enable debugging messages");
-
-module_param(tx_only, bool, 0644);
-MODULE_PARM_DESC(tx_only, "Only handle the IR transmit function");
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 05/26] media: lirc_zilog: fix variable types and other ugliness
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (3 preceding siblings ...)
  2017-10-10  7:17 ` [PATCH v3 04/26] media: lirc_zilog: remove receiver Sean Young
@ 2017-10-10  7:17 ` Sean Young
  2017-10-10  7:17 ` [PATCH v3 06/26] media: lirc_zilog: port to rc-core using scancode tx interface Sean Young
                   ` (21 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:17 UTC (permalink / raw)
  To: linux-media, Andy Walls

Cleans up code and makes checkpatch happy.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/staging/media/lirc/lirc_zilog.c | 162 +++++++++++---------------------
 1 file changed, 55 insertions(+), 107 deletions(-)

diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
index 757b3fc247ac..902fade98d57 100644
--- a/drivers/staging/media/lirc/lirc_zilog.c
+++ b/drivers/staging/media/lirc/lirc_zilog.c
@@ -32,32 +32,15 @@
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
  */
 
+#include <asm/unaligned.h>
 #include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/kernel.h>
-#include <linux/sched/signal.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/string.h>
-#include <linux/timer.h>
 #include <linux/delay.h>
-#include <linux/completion.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/firmware.h>
 #include <linux/vmalloc.h>
 
-#include <linux/mutex.h>
-#include <linux/kthread.h>
-
 #include <media/lirc_dev.h>
 #include <media/lirc.h>
 
@@ -70,7 +53,7 @@ struct IR_tx {
 	struct i2c_client *c;
 
 	/* TX additional actions needed */
-	int need_boot;
+	bool need_boot;
 	bool post_tx_ready_poll;
 	struct lirc_dev *l;
 };
@@ -81,45 +64,39 @@ struct IR_tx {
 /* Hauppauge IR transmitter data */
 struct tx_data_struct {
 	/* Boot block */
-	unsigned char *boot_data;
+	u8 *boot_data;
 
 	/* Start of binary data block */
-	unsigned char *datap;
+	u8 *datap;
 
 	/* End of binary data block */
-	unsigned char *endp;
+	u8 *endp;
 
 	/* Number of installed codesets */
-	unsigned int num_code_sets;
+	u32 num_code_sets;
 
 	/* Pointers to codesets */
-	unsigned char **code_sets;
+	u8 **code_sets;
 
 	/* Global fixed data template */
 	int fixed[TX_BLOCK_SIZE];
 };
 
 static struct tx_data_struct *tx_data;
-static struct mutex tx_data_lock;
-
-/* module parameters */
-static bool debug;	/* debug output */
+static DEFINE_MUTEX(tx_data_lock);
 
 /* safe read of a uint32 (always network byte order) */
-static int read_uint32(unsigned char **data,
-		       unsigned char *endp, unsigned int *val)
+static int read_u32(u8 **data, u8 *endp, u32 *val)
 {
 	if (*data + 4 > endp)
 		return 0;
-	*val = ((*data)[0] << 24) | ((*data)[1] << 16) |
-	       ((*data)[2] << 8) | (*data)[3];
+	*val = get_unaligned_be32(*data);
 	*data += 4;
 	return 1;
 }
 
 /* safe read of a uint8 */
-static int read_uint8(unsigned char **data,
-		      unsigned char *endp, unsigned char *val)
+static int read_u8(u8 **data, u8 *endp, u8 *val)
 {
 	if (*data + 1 > endp)
 		return 0;
@@ -128,8 +105,8 @@ static int read_uint8(unsigned char **data,
 }
 
 /* safe skipping of N bytes */
-static int skip(unsigned char **data,
-		unsigned char *endp, unsigned int distance)
+static int skip(u8 **data,
+		u8 *endp, unsigned int distance)
 {
 	if (*data + distance > endp)
 		return 0;
@@ -138,11 +115,11 @@ static int skip(unsigned char **data,
 }
 
 /* decompress key data into the given buffer */
-static int get_key_data(unsigned char *buf,
+static int get_key_data(u8 *buf,
 			unsigned int codeset, unsigned int key)
 {
-	unsigned char *data, *endp, *diffs, *key_block;
-	unsigned char keys, ndiffs, id;
+	u8 *data, *endp, *diffs, *key_block;
+	u8 keys, ndiffs, id;
 	unsigned int base, lim, pos, i;
 
 	/* Binary search for the codeset */
@@ -150,7 +127,7 @@ static int get_key_data(unsigned char *buf,
 		pos = base + (lim >> 1);
 		data = tx_data->code_sets[pos];
 
-		if (!read_uint32(&data, tx_data->endp, &i))
+		if (!read_u32(&data, tx_data->endp, &i))
 			goto corrupt;
 
 		if (i == codeset) {
@@ -169,8 +146,8 @@ static int get_key_data(unsigned char *buf,
 		tx_data->code_sets[pos + 1] : tx_data->endp;
 
 	/* Read the block header */
-	if (!read_uint8(&data, endp, &keys) ||
-	    !read_uint8(&data, endp, &ndiffs) ||
+	if (!read_u8(&data, endp, &keys) ||
+	    !read_u8(&data, endp, &ndiffs) ||
 	    ndiffs > TX_BLOCK_SIZE || keys == 0)
 		goto corrupt;
 
@@ -180,16 +157,16 @@ static int get_key_data(unsigned char *buf,
 		goto corrupt;
 
 	/* Read the id of the first key */
-	if (!read_uint8(&data, endp, &id))
+	if (!read_u8(&data, endp, &id))
 		goto corrupt;
 
 	/* Unpack the first key's data */
 	for (i = 0; i < TX_BLOCK_SIZE; ++i) {
 		if (tx_data->fixed[i] == -1) {
-			if (!read_uint8(&data, endp, &buf[i]))
+			if (!read_u8(&data, endp, &buf[i]))
 				goto corrupt;
 		} else {
-			buf[i] = (unsigned char)tx_data->fixed[i];
+			buf[i] = tx_data->fixed[i];
 		}
 	}
 
@@ -207,7 +184,7 @@ static int get_key_data(unsigned char *buf,
 	/* Binary search for the key */
 	for (base = 0, lim = keys - 1; lim; lim >>= 1) {
 		/* Seek to block */
-		unsigned char *key_data;
+		u8 *key_data;
 
 		pos = base + (lim >> 1);
 		key_data = key_block + (ndiffs + 1) * pos;
@@ -218,9 +195,9 @@ static int get_key_data(unsigned char *buf,
 
 			/* found, so unpack the diffs */
 			for (i = 0; i < ndiffs; ++i) {
-				unsigned char val;
+				u8 val;
 
-				if (!read_uint8(&key_data, endp, &val) ||
+				if (!read_u8(&key_data, endp, &val) ||
 				    diffs[i] >= TX_BLOCK_SIZE)
 					goto corrupt;
 				buf[diffs[i]] = val;
@@ -241,17 +218,17 @@ static int get_key_data(unsigned char *buf,
 }
 
 /* send a block of data to the IR TX device */
-static int send_data_block(struct IR_tx *tx, unsigned char *data_block)
+static int send_data_block(struct IR_tx *tx, u8 *data_block)
 {
 	int i, j, ret;
-	unsigned char buf[5];
+	u8 buf[5];
 
 	for (i = 0; i < TX_BLOCK_SIZE;) {
 		int tosend = TX_BLOCK_SIZE - i;
 
 		if (tosend > 4)
 			tosend = 4;
-		buf[0] = (unsigned char)(i + 1);
+		buf[0] = i + 1;
 		for (j = 0; j < tosend; ++j)
 			buf[1 + j] = data_block[i + j];
 		dev_dbg(&tx->l->dev, "%*ph", 5, buf);
@@ -270,7 +247,7 @@ static int send_data_block(struct IR_tx *tx, unsigned char *data_block)
 static int send_boot_data(struct IR_tx *tx)
 {
 	int ret, i;
-	unsigned char buf[4];
+	u8 buf[4];
 
 	/* send the boot block */
 	ret = send_data_block(tx, tx_data->boot_data);
@@ -295,7 +272,7 @@ static int send_boot_data(struct IR_tx *tx)
 		ret = i2c_master_send(tx->c, buf, 1);
 		if (ret == 1)
 			break;
-		udelay(100);
+		usleep_range(100, 110);
 	}
 
 	if (ret != 1) {
@@ -348,7 +325,7 @@ static int fw_load(struct IR_tx *tx)
 {
 	int ret;
 	unsigned int i;
-	unsigned char *data, version, num_global_fixed;
+	u8 *data, version, num_global_fixed;
 	const struct firmware *fw_entry;
 
 	/* Already loaded? */
@@ -392,7 +369,7 @@ static int fw_load(struct IR_tx *tx)
 
 	/* Check version */
 	data = tx_data->datap;
-	if (!read_uint8(&data, tx_data->endp, &version))
+	if (!read_u8(&data, tx_data->endp, &version))
 		goto corrupt;
 	if (version != 1) {
 		dev_err(&tx->l->dev,
@@ -408,8 +385,8 @@ static int fw_load(struct IR_tx *tx)
 	if (!skip(&data, tx_data->endp, TX_BLOCK_SIZE))
 		goto corrupt;
 
-	if (!read_uint32(&data, tx_data->endp,
-			 &tx_data->num_code_sets))
+	if (!read_u32(&data, tx_data->endp,
+		      &tx_data->num_code_sets))
 		goto corrupt;
 
 	dev_dbg(&tx->l->dev, "%u IR blaster codesets loaded\n",
@@ -427,14 +404,14 @@ static int fw_load(struct IR_tx *tx)
 		tx_data->fixed[i] = -1;
 
 	/* Read global fixed data template */
-	if (!read_uint8(&data, tx_data->endp, &num_global_fixed) ||
+	if (!read_u8(&data, tx_data->endp, &num_global_fixed) ||
 	    num_global_fixed > TX_BLOCK_SIZE)
 		goto corrupt;
 	for (i = 0; i < num_global_fixed; ++i) {
-		unsigned char pos, val;
+		u8 pos, val;
 
-		if (!read_uint8(&data, tx_data->endp, &pos) ||
-		    !read_uint8(&data, tx_data->endp, &val) ||
+		if (!read_u8(&data, tx_data->endp, &pos) ||
+		    !read_u8(&data, tx_data->endp, &val) ||
 		    pos >= TX_BLOCK_SIZE)
 			goto corrupt;
 		tx_data->fixed[pos] = (int)val;
@@ -442,17 +419,17 @@ static int fw_load(struct IR_tx *tx)
 
 	/* Filch out the position of each code set */
 	for (i = 0; i < tx_data->num_code_sets; ++i) {
-		unsigned int id;
-		unsigned char keys;
-		unsigned char ndiffs;
+		u32 id;
+		u8 keys;
+		u8 ndiffs;
 
 		/* Save the codeset position */
 		tx_data->code_sets[i] = data;
 
 		/* Read header */
-		if (!read_uint32(&data, tx_data->endp, &id) ||
-		    !read_uint8(&data, tx_data->endp, &keys) ||
-		    !read_uint8(&data, tx_data->endp, &ndiffs) ||
+		if (!read_u32(&data, tx_data->endp, &id) ||
+		    !read_u8(&data, tx_data->endp, &keys) ||
+		    !read_u8(&data, tx_data->endp, &ndiffs) ||
 		    ndiffs > TX_BLOCK_SIZE || keys == 0)
 			goto corrupt;
 
@@ -489,8 +466,8 @@ static int fw_load(struct IR_tx *tx)
 /* send a keypress to the IR TX device */
 static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 {
-	unsigned char data_block[TX_BLOCK_SIZE];
-	unsigned char buf[2];
+	u8 data_block[TX_BLOCK_SIZE];
+	u8 buf[2];
 	int i, ret;
 
 	/* Get data for the codeset/key */
@@ -524,7 +501,7 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 		ret = i2c_master_send(tx->c, buf, 1);
 		if (ret == 1)
 			break;
-		udelay(100);
+		usleep_range(100, 110);
 	}
 
 	if (ret != 1) {
@@ -638,7 +615,7 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n,
 		}
 
 		/* Send boot data first if required */
-		if (tx->need_boot == 1) {
+		if (tx->need_boot) {
 			/* Make sure we have the 'firmware' loaded, first */
 			ret = fw_load(tx);
 			if (ret != 0) {
@@ -650,13 +627,13 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n,
 			/* Prep the chip for transmitting codes */
 			ret = send_boot_data(tx);
 			if (ret == 0)
-				tx->need_boot = 0;
+				tx->need_boot = false;
 		}
 
 		/* Send the code */
 		if (ret == 0) {
 			ret = send_code(tx, (unsigned int)command >> 16,
-					    (unsigned int)command & 0xFFFF);
+					(unsigned int)command & 0xFFFF);
 			if (ret == -EPROTO) {
 				mutex_unlock(&tx->client_lock);
 				return ret;
@@ -680,7 +657,7 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n,
 			}
 			set_current_state(TASK_UNINTERRUPTIBLE);
 			schedule_timeout((100 * HZ + 999) / 1000);
-			tx->need_boot = 1;
+			tx->need_boot = true;
 			++failures;
 		} else {
 			i += sizeof(int);
@@ -693,7 +670,6 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n,
 	return n;
 }
 
-
 static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 {
 	struct IR_tx *tx = lirc_get_pdata(filep);
@@ -773,7 +749,7 @@ static const struct i2c_device_id ir_transceiver_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ir_transceiver_id);
 
-static struct i2c_driver driver = {
+static struct i2c_driver zilog_driver = {
 	.driver = {
 		.name	= "Zilog/Hauppauge i2c IR",
 	},
@@ -806,17 +782,13 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	 * The IR receiver    is at i2c address 0x71.
 	 * The IR transmitter is at i2c address 0x70.
 	 */
-
-	pr_info("probing IR Tx on %s (i2c-%d)\n", adap->name, adap->nr);
-
-	/* Set up a struct IR_tx instance */
 	tx = devm_kzalloc(&client->dev, sizeof(*tx), GFP_KERNEL);
 	if (!tx)
 		return -ENOMEM;
 
 	mutex_init(&tx->client_lock);
 	tx->c = client;
-	tx->need_boot = 1;
+	tx->need_boot = true;
 	tx->post_tx_ready_poll = !(id->driver_data & ID_FLAG_HDPVR);
 
 	/* set lirc_dev stuff */
@@ -855,40 +827,21 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	/* A tx ref goes to the i2c_client */
 	i2c_set_clientdata(client, tx);
 
-	dev_info(&tx->l->dev,
-		 "IR unit on %s (i2c-%d) registered as lirc%d and ready\n",
-		 adap->name, adap->nr, tx->l->minor);
-
-	dev_info(&tx->l->dev,
-		 "probe of IR Tx on %s (i2c-%d) done\n", adap->name, adap->nr);
 	return 0;
 }
 
 static int __init zilog_init(void)
 {
-	int ret;
-
-	pr_notice("Zilog/Hauppauge IR driver initializing\n");
-
-	mutex_init(&tx_data_lock);
-
 	request_module("firmware_class");
 
-	ret = i2c_add_driver(&driver);
-	if (ret)
-		pr_err("initialization failed\n");
-	else
-		pr_notice("initialization complete\n");
-
-	return ret;
+	return i2c_add_driver(&zilog_driver);
 }
 
 static void __exit zilog_exit(void)
 {
-	i2c_del_driver(&driver);
+	i2c_del_driver(&zilog_driver);
 	/* if loaded */
 	fw_unload();
-	pr_notice("Zilog/Hauppauge IR driver unloaded\n");
 }
 
 module_init(zilog_init);
@@ -897,8 +850,3 @@ module_exit(zilog_exit);
 MODULE_DESCRIPTION("Zilog/Hauppauge infrared transmitter driver (i2c stack)");
 MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller, Stefan Jahn, Jerome Brock, Mark Weaver, Andy Walls");
 MODULE_LICENSE("GPL");
-/* for compat with old name, which isn't all that accurate anymore */
-MODULE_ALIAS("lirc_pvr150");
-
-module_param(debug, bool, 0644);
-MODULE_PARM_DESC(debug, "Enable debugging messages");
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 06/26] media: lirc_zilog: port to rc-core using scancode tx interface
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (4 preceding siblings ...)
  2017-10-10  7:17 ` [PATCH v3 05/26] media: lirc_zilog: fix variable types and other ugliness Sean Young
@ 2017-10-10  7:17 ` Sean Young
  2017-10-10  7:17 ` [PATCH v3 07/26] media: promote lirc_zilog out of staging Sean Young
                   ` (20 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:17 UTC (permalink / raw)
  To: linux-media, Andy Walls

Now that rc-core can send a scancode by rc protocol and scancode, port
the lirc_zilog to this interface. The firmware file needs updating
to contain the protocol and scancode, so we have haup-ir-blaster-v2.bin
for this.

The LIRC_MODE_LIRCCODE is no longer supported, and transmit can only
be done using the new LIRC_MODE_SCANCODE interface.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/ir-lirc-codec.c        |  30 ++-
 drivers/staging/media/lirc/lirc_zilog.c | 446 ++++++++++++--------------------
 include/media/rc-core.h                 |   2 +
 3 files changed, 191 insertions(+), 287 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index a5369978e56f..41259b1ce3c2 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -122,6 +122,10 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 	if (!lirc)
 		return -EFAULT;
 
+	dev = lirc->dev;
+	if (!dev)
+		return -EFAULT;
+
 	if (lirc->send_mode == LIRC_MODE_SCANCODE) {
 		struct lirc_scancode scan;
 
@@ -134,6 +138,11 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 		if (scan.flags || scan.keycode || scan.timestamp)
 			return -EINVAL;
 
+		if (dev->tx_scancode) {
+			ret = dev->tx_scancode(dev, &scan);
+			return ret < 0 ? ret : n;
+		}
+
 		raw = kmalloc_array(LIRCBUF_SIZE, sizeof(*raw), GFP_KERNEL);
 		if (!raw)
 			return -ENOMEM;
@@ -174,12 +183,6 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 			return PTR_ERR(txbuf);
 	}
 
-	dev = lirc->dev;
-	if (!dev) {
-		ret = -EFAULT;
-		goto out;
-	}
-
 	if (!dev->tx_ir) {
 		ret = -EINVAL;
 		goto out;
@@ -252,16 +255,19 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 
 	/* mode support */
 	case LIRC_GET_SEND_MODE:
-		if (!dev->tx_ir)
+		if (!dev->tx_ir && !dev->tx_scancode)
 			return -ENOTTY;
 
 		val = lirc->send_mode;
 		break;
 
 	case LIRC_SET_SEND_MODE:
-		if (!dev->tx_ir)
+		if (!dev->tx_ir && !dev->tx_scancode)
 			return -ENOTTY;
 
+		if (!dev->tx_ir && val == LIRC_MODE_PULSE)
+			return -EINVAL;
+
 		if (!(val == LIRC_MODE_PULSE || val == LIRC_MODE_SCANCODE))
 			return -EINVAL;
 
@@ -410,6 +416,9 @@ static int ir_lirc_register(struct rc_dev *dev)
 			features |= LIRC_CAN_GET_REC_RESOLUTION;
 	}
 
+	if (dev->tx_scancode)
+		features |= LIRC_CAN_SEND_SCANCODE;
+
 	if (dev->tx_ir) {
 		features |= LIRC_CAN_SEND_PULSE | LIRC_CAN_SEND_SCANCODE;
 		if (dev->s_tx_mask)
@@ -450,7 +459,10 @@ static int ir_lirc_register(struct rc_dev *dev)
 	if (rc < 0)
 		goto out;
 
-	dev->raw->lirc.send_mode = LIRC_MODE_PULSE;
+	if (dev->tx_scancode)
+		dev->raw->lirc.send_mode = LIRC_MODE_SCANCODE;
+	else
+		dev->raw->lirc.send_mode = LIRC_MODE_PULSE;
 
 	dev->raw->lirc.ldev = ldev;
 	dev->raw->lirc.dev = dev;
diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
index 902fade98d57..62614e7265eb 100644
--- a/drivers/staging/media/lirc/lirc_zilog.c
+++ b/drivers/staging/media/lirc/lirc_zilog.c
@@ -41,11 +41,11 @@
 #include <linux/firmware.h>
 #include <linux/vmalloc.h>
 
-#include <media/lirc_dev.h>
-#include <media/lirc.h>
+#include <media/rc-core.h>
 
+#define DEVICE_NAME	"Zilog/Hauppauge i2c IR TX"
 /* Max transfer size done by I2C transfer functions */
-#define MAX_XFER_SIZE  64
+#define MAX_XFER_SIZE	64
 
 struct IR_tx {
 	/* TX device */
@@ -55,7 +55,8 @@ struct IR_tx {
 	/* TX additional actions needed */
 	bool need_boot;
 	bool post_tx_ready_poll;
-	struct lirc_dev *l;
+	struct rc_dev *rc;
+	char phys[32];
 };
 
 /* Block size for IR transmitter */
@@ -115,102 +116,103 @@ static int skip(u8 **data,
 }
 
 /* decompress key data into the given buffer */
-static int get_key_data(u8 *buf,
-			unsigned int codeset, unsigned int key)
+static int get_key_data(u8 *buf, enum rc_proto proto, u32 scancode)
 {
 	u8 *data, *endp, *diffs, *key_block;
-	u8 keys, ndiffs, id;
-	unsigned int base, lim, pos, i;
+	unsigned int lim, i, base, codeset, pos;
+	u8 keys, ndiffs, p;
+	u32 protocols, s;
 
 	/* Binary search for the codeset */
-	for (base = 0, lim = tx_data->num_code_sets; lim; lim >>= 1) {
-		pos = base + (lim >> 1);
-		data = tx_data->code_sets[pos];
+	for (codeset = 0; codeset < tx_data->num_code_sets; codeset++) {
+		data = tx_data->code_sets[codeset];
 
-		if (!read_u32(&data, tx_data->endp, &i))
+		/* bitset protocols contained in this codeset */
+		if (!read_u32(&data, tx_data->endp, &protocols))
 			goto corrupt;
 
-		if (i == codeset) {
-			break;
-		} else if (codeset > i) {
-			base = pos + 1;
-			--lim;
-		}
-	}
-	/* Not found? */
-	if (!lim)
-		return -EPROTO;
-
-	/* Set end of data block */
-	endp = pos < tx_data->num_code_sets - 1 ?
-		tx_data->code_sets[pos + 1] : tx_data->endp;
-
-	/* Read the block header */
-	if (!read_u8(&data, endp, &keys) ||
-	    !read_u8(&data, endp, &ndiffs) ||
-	    ndiffs > TX_BLOCK_SIZE || keys == 0)
-		goto corrupt;
+		if (!(BIT(proto) & protocols))
+			continue;
 
-	/* Save diffs & skip */
-	diffs = data;
-	if (!skip(&data, endp, ndiffs))
-		goto corrupt;
+		/* Set end of data block */
+		endp = codeset < tx_data->num_code_sets - 1 ?
+			tx_data->code_sets[codeset + 1] : tx_data->endp;
 
-	/* Read the id of the first key */
-	if (!read_u8(&data, endp, &id))
-		goto corrupt;
+		/* Read the block header */
+		if (!read_u8(&data, endp, &keys) ||
+		    !read_u8(&data, endp, &ndiffs) ||
+		    ndiffs > TX_BLOCK_SIZE || keys == 0)
+			goto corrupt;
 
-	/* Unpack the first key's data */
-	for (i = 0; i < TX_BLOCK_SIZE; ++i) {
-		if (tx_data->fixed[i] == -1) {
-			if (!read_u8(&data, endp, &buf[i]))
-				goto corrupt;
-		} else {
-			buf[i] = tx_data->fixed[i];
+		/* Save diffs & skip */
+		diffs = data;
+		if (!skip(&data, endp, ndiffs))
+			goto corrupt;
+
+		/* Read the protocol/scancode of the first key */
+		if (!read_u8(&data, endp, &p))
+			goto corrupt;
+
+		if (!read_u32(&data, endp, &s))
+			goto corrupt;
+
+		/* Unpack the first key's data */
+		for (i = 0; i < TX_BLOCK_SIZE; ++i) {
+			if (tx_data->fixed[i] == -1) {
+				if (!read_u8(&data, endp, &buf[i]))
+					goto corrupt;
+			} else {
+				buf[i] = tx_data->fixed[i];
+			}
 		}
-	}
 
-	/* Early out key found/not found */
-	if (key == id)
-		return 0;
-	if (keys == 1)
-		return -EPROTO;
+		/* Early out key found/not found */
+		if (p == proto && s == scancode)
+			return 0;
+		if (keys == 1)
+			continue;
 
-	/* Sanity check */
-	key_block = data;
-	if (!skip(&data, endp, (keys - 1) * (ndiffs + 1)))
-		goto corrupt;
+		/* Sanity check */
+		key_block = data;
+		if (!skip(&data, endp, (keys - 1) * (ndiffs + 1)))
+			goto corrupt;
 
-	/* Binary search for the key */
-	for (base = 0, lim = keys - 1; lim; lim >>= 1) {
-		/* Seek to block */
-		u8 *key_data;
+		/* Binary search for the key */
+		for (base = 0, lim = keys - 1; lim; lim >>= 1) {
+			/* Seek to block */
+			u8 *key_data;
 
-		pos = base + (lim >> 1);
-		key_data = key_block + (ndiffs + 1) * pos;
+			pos = base + (lim >> 1);
+			key_data = key_block + (ndiffs + 5) * pos;
 
-		if (*key_data == key) {
-			/* skip key id */
-			++key_data;
+			/* Read the protocol/scancode of the first key */
+			if (!read_u8(&key_data, endp, &p))
+				goto corrupt;
 
-			/* found, so unpack the diffs */
-			for (i = 0; i < ndiffs; ++i) {
-				u8 val;
+			if (!read_u32(&key_data, endp, &s))
+				goto corrupt;
 
-				if (!read_u8(&key_data, endp, &val) ||
-				    diffs[i] >= TX_BLOCK_SIZE)
-					goto corrupt;
-				buf[diffs[i]] = val;
+			if (p == proto && s == scancode) {
+				/* found, so unpack the diffs */
+				for (i = 0; i < ndiffs; ++i) {
+					u8 val;
+
+					if (!read_u8(&key_data, endp, &val) ||
+					    diffs[i] >= TX_BLOCK_SIZE)
+						goto corrupt;
+					buf[diffs[i]] = val;
+				}
+
+				return 0;
+			} else if (p > proto || (p == proto && s > scancode)) {
+				base = pos + 1;
+				--lim;
 			}
-
-			return 0;
-		} else if (key > *key_data) {
-			base = pos + 1;
-			--lim;
 		}
 	}
+
 	/* Key not found */
-	return -EPROTO;
+	return -EINVAL;
 
 corrupt:
 	pr_err("firmware is corrupt\n");
@@ -231,10 +233,10 @@ static int send_data_block(struct IR_tx *tx, u8 *data_block)
 		buf[0] = i + 1;
 		for (j = 0; j < tosend; ++j)
 			buf[1 + j] = data_block[i + j];
-		dev_dbg(&tx->l->dev, "%*ph", 5, buf);
+		dev_dbg(&tx->rc->dev, "%*ph", 5, buf);
 		ret = i2c_master_send(tx->c, buf, tosend + 1);
 		if (ret != tosend + 1) {
-			dev_err(&tx->l->dev,
+			dev_err(&tx->rc->dev,
 				"i2c_master_send failed with %d\n", ret);
 			return ret < 0 ? ret : -EFAULT;
 		}
@@ -259,7 +261,7 @@ static int send_boot_data(struct IR_tx *tx)
 	buf[1] = 0x20;
 	ret = i2c_master_send(tx->c, buf, 2);
 	if (ret != 2) {
-		dev_err(&tx->l->dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->rc->dev, "i2c_master_send failed with %d\n", ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
@@ -276,22 +278,22 @@ static int send_boot_data(struct IR_tx *tx)
 	}
 
 	if (ret != 1) {
-		dev_err(&tx->l->dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->rc->dev, "i2c_master_send failed with %d\n", ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
 	/* Here comes the firmware version... (hopefully) */
 	ret = i2c_master_recv(tx->c, buf, 4);
 	if (ret != 4) {
-		dev_err(&tx->l->dev, "i2c_master_recv failed with %d\n", ret);
+		dev_err(&tx->rc->dev, "i2c_master_recv failed with %d\n", ret);
 		return 0;
 	}
 	if ((buf[0] != 0x80) && (buf[0] != 0xa0)) {
-		dev_err(&tx->l->dev, "unexpected IR TX init response: %02x\n",
+		dev_err(&tx->rc->dev, "unexpected IR TX init response: %02x\n",
 			buf[0]);
 		return 0;
 	}
-	dev_notice(&tx->l->dev,
+	dev_notice(&tx->rc->dev,
 		   "Zilog/Hauppauge IR blaster firmware version %d.%d.%d loaded\n",
 		   buf[1], buf[2], buf[3]);
 
@@ -336,15 +338,16 @@ static int fw_load(struct IR_tx *tx)
 	}
 
 	/* Request codeset data file */
-	ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", &tx->l->dev);
+	ret = request_firmware(&fw_entry, "haup-ir-blaster-v2.bin",
+			       &tx->rc->dev);
 	if (ret != 0) {
-		dev_err(&tx->l->dev,
+		dev_err(&tx->rc->dev,
 			"firmware haup-ir-blaster.bin not available (%d)\n",
 			ret);
 		ret = ret < 0 ? ret : -EFAULT;
 		goto out;
 	}
-	dev_dbg(&tx->l->dev, "firmware of size %zu loaded\n", fw_entry->size);
+	dev_dbg(&tx->rc->dev, "firmware of size %zu loaded\n", fw_entry->size);
 
 	/* Parse the file */
 	tx_data = vmalloc(sizeof(*tx_data));
@@ -371,9 +374,9 @@ static int fw_load(struct IR_tx *tx)
 	data = tx_data->datap;
 	if (!read_u8(&data, tx_data->endp, &version))
 		goto corrupt;
-	if (version != 1) {
-		dev_err(&tx->l->dev,
-			"unsupported code set file version (%u, expected 1) -- please upgrade to a newer driver\n",
+	if (version != 2) {
+		dev_err(&tx->rc->dev,
+			"unsupported code set file version (%u, expected 2)\n",
 			version);
 		fw_unload_locked();
 		ret = -EFAULT;
@@ -389,7 +392,7 @@ static int fw_load(struct IR_tx *tx)
 		      &tx_data->num_code_sets))
 		goto corrupt;
 
-	dev_dbg(&tx->l->dev, "%u IR blaster codesets loaded\n",
+	dev_dbg(&tx->rc->dev, "%u IR blaster codesets loaded\n",
 		tx_data->num_code_sets);
 
 	tx_data->code_sets = vmalloc(
@@ -419,7 +422,7 @@ static int fw_load(struct IR_tx *tx)
 
 	/* Filch out the position of each code set */
 	for (i = 0; i < tx_data->num_code_sets; ++i) {
-		u32 id;
+		u32 protocols;
 		u8 keys;
 		u8 ndiffs;
 
@@ -427,7 +430,7 @@ static int fw_load(struct IR_tx *tx)
 		tx_data->code_sets[i] = data;
 
 		/* Read header */
-		if (!read_u32(&data, tx_data->endp, &id) ||
+		if (!read_u32(&data, tx_data->endp, &protocols) ||
 		    !read_u8(&data, tx_data->endp, &keys) ||
 		    !read_u8(&data, tx_data->endp, &ndiffs) ||
 		    ndiffs > TX_BLOCK_SIZE || keys == 0)
@@ -438,23 +441,23 @@ static int fw_load(struct IR_tx *tx)
 			goto corrupt;
 
 		/*
-		 * After the diffs we have the first key id + data -
-		 * global fixed
+		 * After the diffs we have the first key protocol, scancode,
+		 * data, global fixed
 		 */
 		if (!skip(&data, tx_data->endp,
-			  1 + TX_BLOCK_SIZE - num_global_fixed))
+			  5 + TX_BLOCK_SIZE - num_global_fixed))
 			goto corrupt;
 
 		/* Then we have keys-1 blocks of key id+diffs */
 		if (!skip(&data, tx_data->endp,
-			  (ndiffs + 1) * (keys - 1)))
+			  (ndiffs + 5) * (keys - 1)))
 			goto corrupt;
 	}
 	ret = 0;
 	goto out;
 
 corrupt:
-	dev_err(&tx->l->dev, "firmware is corrupt\n");
+	dev_err(&tx->rc->dev, "firmware is corrupt\n");
 	fw_unload_locked();
 	ret = -EFAULT;
 
@@ -464,19 +467,19 @@ static int fw_load(struct IR_tx *tx)
 }
 
 /* send a keypress to the IR TX device */
-static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
+static int send_code(struct IR_tx *tx, enum rc_proto proto, u32 scancode)
 {
 	u8 data_block[TX_BLOCK_SIZE];
 	u8 buf[2];
 	int i, ret;
 
 	/* Get data for the codeset/key */
-	ret = get_key_data(data_block, code, key);
+	ret = get_key_data(data_block, proto, scancode);
 
-	if (ret == -EPROTO) {
-		dev_err(&tx->l->dev,
-			"failed to get data for code %u, key %u -- check lircd.conf entries\n",
-			code, key);
+	if (ret == -EINVAL) {
+		dev_err(&tx->rc->dev,
+			"failed to get data for protocol %u, scancode %u",
+			proto, scancode);
 		return ret;
 	} else if (ret != 0) {
 		return ret;
@@ -492,7 +495,7 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	buf[1] = 0x40;
 	ret = i2c_master_send(tx->c, buf, 2);
 	if (ret != 2) {
-		dev_err(&tx->l->dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->rc->dev, "i2c_master_send failed with %d\n", ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
@@ -505,18 +508,18 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	}
 
 	if (ret != 1) {
-		dev_err(&tx->l->dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->rc->dev, "i2c_master_send failed with %d\n", ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
 	/* Send finished download? */
 	ret = i2c_master_recv(tx->c, buf, 1);
 	if (ret != 1) {
-		dev_err(&tx->l->dev, "i2c_master_recv failed with %d\n", ret);
+		dev_err(&tx->rc->dev, "i2c_master_recv failed with %d\n", ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 	if (buf[0] != 0xA0) {
-		dev_err(&tx->l->dev, "unexpected IR TX response #1: %02x\n",
+		dev_err(&tx->rc->dev, "unexpected IR TX response #1: %02x\n",
 			buf[0]);
 		return -EFAULT;
 	}
@@ -526,7 +529,7 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	buf[1] = 0x80;
 	ret = i2c_master_send(tx->c, buf, 2);
 	if (ret != 2) {
-		dev_err(&tx->l->dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->rc->dev, "i2c_master_send failed with %d\n", ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
@@ -536,7 +539,8 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	 * going to skip this whole mess and say we're done on the HD PVR
 	 */
 	if (!tx->post_tx_ready_poll) {
-		dev_dbg(&tx->l->dev, "sent code %u, key %u\n", code, key);
+		dev_dbg(&tx->rc->dev, "sent proto %u, scancode %u\n", proto,
+			scancode);
 		return 0;
 	}
 
@@ -552,12 +556,12 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 		ret = i2c_master_send(tx->c, buf, 1);
 		if (ret == 1)
 			break;
-		dev_dbg(&tx->l->dev,
+		dev_dbg(&tx->rc->dev,
 			"NAK expected: i2c_master_send failed with %d (try %d)\n",
 			ret, i + 1);
 	}
 	if (ret != 1) {
-		dev_err(&tx->l->dev,
+		dev_err(&tx->rc->dev,
 			"IR TX chip never got ready: last i2c_master_send failed with %d\n",
 			ret);
 		return ret < 0 ? ret : -EFAULT;
@@ -566,78 +570,47 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	/* Seems to be an 'ok' response */
 	i = i2c_master_recv(tx->c, buf, 1);
 	if (i != 1) {
-		dev_err(&tx->l->dev, "i2c_master_recv failed with %d\n", ret);
+		dev_err(&tx->rc->dev, "i2c_master_recv failed with %d\n", ret);
 		return -EFAULT;
 	}
 	if (buf[0] != 0x80) {
-		dev_err(&tx->l->dev, "unexpected IR TX response #2: %02x\n",
+		dev_err(&tx->rc->dev, "unexpected IR TX response #2: %02x\n",
 			buf[0]);
 		return -EFAULT;
 	}
 
 	/* Oh good, it worked */
-	dev_dbg(&tx->l->dev, "sent code %u, key %u\n", code, key);
+	dev_dbg(&tx->rc->dev, "sent proto %u, scancode %u\n", proto, scancode);
 	return 0;
 }
 
-/*
- * Write a code to the device.  We take in a 32-bit number (an int) and then
- * decode this to a codeset/key index.  The key data is then decompressed and
- * sent to the device.  We have a spin lock as per i2c documentation to prevent
- * multiple concurrent sends which would probably cause the device to explode.
- */
-static ssize_t write(struct file *filep, const char __user *buf, size_t n,
-		     loff_t *ppos)
+static int tx_scancode(struct rc_dev *rcdev, struct lirc_scancode *lsc)
 {
-	struct IR_tx *tx = lirc_get_pdata(filep);
-	size_t i;
+	struct IR_tx *tx = rcdev->priv;
 	int failures = 0;
+	int ret;
 
-	/* Validate user parameters */
-	if (n % sizeof(int))
-		return -EINVAL;
-
-	/* Ensure our tx->c i2c_client remains valid for the duration */
 	mutex_lock(&tx->client_lock);
-	if (!tx->c) {
-		mutex_unlock(&tx->client_lock);
-		return -ENXIO;
-	}
 
-	/* Send each keypress */
-	for (i = 0; i < n;) {
-		int ret = 0;
-		int command;
-
-		if (copy_from_user(&command, buf + i, sizeof(command))) {
+	/* Send boot data first if required */
+	if (tx->need_boot) {
+		/* Make sure we have the 'firmware' loaded, first */
+		ret = fw_load(tx);
+		if (ret != 0) {
 			mutex_unlock(&tx->client_lock);
-			return -EFAULT;
-		}
-
-		/* Send boot data first if required */
-		if (tx->need_boot) {
-			/* Make sure we have the 'firmware' loaded, first */
-			ret = fw_load(tx);
-			if (ret != 0) {
-				mutex_unlock(&tx->client_lock);
-				if (ret != -ENOMEM)
-					ret = -EIO;
-				return ret;
-			}
-			/* Prep the chip for transmitting codes */
-			ret = send_boot_data(tx);
-			if (ret == 0)
-				tx->need_boot = false;
+			return ret;
 		}
+		/* Prep the chip for transmitting codes */
+		ret = send_boot_data(tx);
+		if (ret == 0)
+			tx->need_boot = false;
+	}
 
-		/* Send the code */
-		if (ret == 0) {
-			ret = send_code(tx, (unsigned int)command >> 16,
-					(unsigned int)command & 0xFFFF);
-			if (ret == -EPROTO) {
-				mutex_unlock(&tx->client_lock);
-				return ret;
-			}
+	do {
+		ret = send_code(tx, lsc->rc_proto, lsc->scancode);
+		if (ret == -EINVAL) {
+			mutex_unlock(&tx->client_lock);
+			return ret;
 		}
 
 		/*
@@ -646,11 +619,11 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n,
 		 */
 		if (ret != 0) {
 			/* Looks like the chip crashed, reset it */
-			dev_err(&tx->l->dev,
+			dev_err(&rcdev->dev,
 				"sending to the IR transmitter chip failed, trying reset\n");
 
 			if (failures >= 3) {
-				dev_err(&tx->l->dev,
+				dev_err(&rcdev->dev,
 					"unable to send to the IR chip after 3 resets, giving up\n");
 				mutex_unlock(&tx->client_lock);
 				return ret;
@@ -659,83 +632,12 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n,
 			schedule_timeout((100 * HZ + 999) / 1000);
 			tx->need_boot = true;
 			++failures;
-		} else {
-			i += sizeof(int);
 		}
-	}
+	} while (ret != 0);
 
 	mutex_unlock(&tx->client_lock);
 
-	/* All looks good */
-	return n;
-}
-
-static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
-{
-	struct IR_tx *tx = lirc_get_pdata(filep);
-	unsigned long __user *uptr = (unsigned long __user *)arg;
-	int result;
-	unsigned long mode, features;
-
-	features = tx->l->features;
-
-	switch (cmd) {
-	case LIRC_GET_LENGTH:
-		result = put_user(13UL, uptr);
-		break;
-	case LIRC_GET_FEATURES:
-		result = put_user(features, uptr);
-		break;
-	case LIRC_GET_REC_MODE:
-		if (!(features & LIRC_CAN_REC_MASK))
-			return -ENOTTY;
-
-		result = put_user(LIRC_REC2MODE
-				  (features & LIRC_CAN_REC_MASK),
-				  uptr);
-		break;
-	case LIRC_SET_REC_MODE:
-		if (!(features & LIRC_CAN_REC_MASK))
-			return -ENOTTY;
-
-		result = get_user(mode, uptr);
-		if (!result && !(LIRC_MODE2REC(mode) & features))
-			result = -ENOTTY;
-		break;
-	case LIRC_GET_SEND_MODE:
-		if (!(features & LIRC_CAN_SEND_MASK))
-			return -ENOTTY;
-
-		result = put_user(LIRC_MODE_LIRCCODE, uptr);
-		break;
-	case LIRC_SET_SEND_MODE:
-		if (!(features & LIRC_CAN_SEND_MASK))
-			return -ENOTTY;
-
-		result = get_user(mode, uptr);
-		if (!result && mode != LIRC_MODE_LIRCCODE)
-			return -EINVAL;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return result;
-}
-
-/*
- * Open the IR device.
- */
-static int open(struct inode *node, struct file *filep)
-{
-	lirc_init_pdata(node, filep);
-	nonseekable_open(node, filep);
-	return 0;
-}
-
-/* Close the IR device */
-static int close(struct inode *node, struct file *filep)
-{
-	return 0;
+	return ret;
 }
 
 static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id);
@@ -751,28 +653,17 @@ MODULE_DEVICE_TABLE(i2c, ir_transceiver_id);
 
 static struct i2c_driver zilog_driver = {
 	.driver = {
-		.name	= "Zilog/Hauppauge i2c IR",
+		.name	= DEVICE_NAME,
 	},
 	.probe		= ir_probe,
 	.id_table	= ir_transceiver_id,
 };
 
-static const struct file_operations lirc_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.write		= write,
-	.unlocked_ioctl	= ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl	= ioctl,
-#endif
-	.open		= open,
-	.release	= close
-};
-
 static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct IR_tx *tx;
 	struct i2c_adapter *adap = client->adapter;
+	struct rc_dev *rcdev;
 	int ret;
 
 	dev_dbg(&client->dev, "%s: %s on i2c-%d (%s), client addr=0x%02x\n",
@@ -786,43 +677,42 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	if (!tx)
 		return -ENOMEM;
 
+	rcdev = devm_rc_allocate_device(&client->dev, RC_DRIVER_IR_RAW_TX);
+	if (!rcdev)
+		return -ENOMEM;
+
+	snprintf(tx->phys, sizeof(tx->phys), "%s/%s/tx0", dev_name(&adap->dev),
+		 dev_name(&client->dev));
+
+	rcdev->driver_name = KBUILD_MODNAME;
+	rcdev->device_name = DEVICE_NAME;
+	rcdev->input_id.bustype = BUS_I2C;
+	rcdev->input_phys = tx->phys;
+	rcdev->tx_scancode = tx_scancode;
+	rcdev->priv = tx;
+
+	tx->rc = rcdev;
+
+	printk(KBUILD_MODNAME ": " DEVICE_NAME " detected at %s [%s]\n",
+	       tx->phys, adap->name);
+
 	mutex_init(&tx->client_lock);
 	tx->c = client;
 	tx->need_boot = true;
 	tx->post_tx_ready_poll = !(id->driver_data & ID_FLAG_HDPVR);
 
-	/* set lirc_dev stuff */
-	tx->l = lirc_allocate_device();
-	if (!tx->l)
-		return -ENOMEM;
-
-	snprintf(tx->l->name, sizeof(tx->l->name), "lirc_zilog");
-	tx->l->features |= LIRC_CAN_SEND_LIRCCODE;
-	tx->l->code_length = 13;
-	tx->l->fops = &lirc_fops;
-	tx->l->owner = THIS_MODULE;
-	tx->l->dev.parent = &client->dev;
-
-	/* register with lirc */
-	ret = lirc_register_device(tx->l);
-	if (ret < 0) {
-		dev_err(&tx->l->dev, "%s: lirc_register_device() failed: %i\n",
-			__func__, ret);
-		lirc_free_device(tx->l);
-		tx->l = NULL;
+	ret = devm_rc_register_device(&client->dev, rcdev);
+	if (ret)
 		return ret;
-	}
 
 	/*
 	 * Load the 'firmware'.  We do this before registering with
-	 * lirc_dev, so the first firmware load attempt does not happen
+	 * rc_dev, so the first firmware load attempt does not happen
 	 * after a open() or write() call on the device.
 	 */
 	ret = fw_load(tx);
-	if (ret < 0) {
-		lirc_unregister_device(tx->l);
+	if (ret < 0)
 		return ret;
-	}
 
 	/* A tx ref goes to the i2c_client */
 	i2c_set_clientdata(client, tx);
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index ca48632ec8e2..b74b3165dc78 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -125,6 +125,7 @@ enum rc_filter_type {
  * @s_tx_duty_cycle: set transmit duty cycle (0% - 100%)
  * @s_rx_carrier_range: inform driver about carrier it is expected to handle
  * @tx_ir: transmit IR
+ * @tx_scancode: transmit scancode
  * @s_idle: enable/disable hardware idle mode, upon which,
  *	device doesn't interrupt host until it sees IR pulses
  * @s_learning_mode: enable wide band receiver used for learning
@@ -182,6 +183,7 @@ struct rc_dev {
 	int				(*s_tx_duty_cycle)(struct rc_dev *dev, u32 duty_cycle);
 	int				(*s_rx_carrier_range)(struct rc_dev *dev, u32 min, u32 max);
 	int				(*tx_ir)(struct rc_dev *dev, unsigned *txbuf, unsigned n);
+	int				(*tx_scancode)(struct rc_dev *dev, struct lirc_scancode *scancode);
 	void				(*s_idle)(struct rc_dev *dev, bool enable);
 	int				(*s_learning_mode)(struct rc_dev *dev, int enable);
 	int				(*s_carrier_report) (struct rc_dev *dev, int enable);
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 07/26] media: promote lirc_zilog out of staging
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (5 preceding siblings ...)
  2017-10-10  7:17 ` [PATCH v3 06/26] media: lirc_zilog: port to rc-core using scancode tx interface Sean Young
@ 2017-10-10  7:17 ` Sean Young
  2017-10-10  7:17 ` [PATCH v3 08/26] media: lirc: remove LIRCCODE and LIRC_GET_LENGTH Sean Young
                   ` (19 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:17 UTC (permalink / raw)
  To: linux-media, Andy Walls

Rename to zilog_ir in the process.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/Kconfig                           | 12 ++++++++
 drivers/media/rc/Makefile                          |  1 +
 .../lirc/lirc_zilog.c => media/rc/zilog_ir.c}      |  0
 drivers/staging/media/Kconfig                      |  3 --
 drivers/staging/media/Makefile                     |  1 -
 drivers/staging/media/lirc/Kconfig                 | 21 -------------
 drivers/staging/media/lirc/Makefile                |  6 ----
 drivers/staging/media/lirc/TODO                    | 36 ----------------------
 8 files changed, 13 insertions(+), 67 deletions(-)
 rename drivers/{staging/media/lirc/lirc_zilog.c => media/rc/zilog_ir.c} (100%)
 delete mode 100644 drivers/staging/media/lirc/Kconfig
 delete mode 100644 drivers/staging/media/lirc/Makefile
 delete mode 100644 drivers/staging/media/lirc/TODO

diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index afb3456d4e20..2a47139e5811 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -483,6 +483,18 @@ config IR_TANGO
 	   The HW decoder supports NEC, RC-5, RC-6 IR protocols.
 	   When compiled as a module, look for tango-ir.
 
+config IR_ZILOG
+	tristate "Zilog/Hauppauge IR Transmitter"
+	depends on RC_CORE
+	depends on LIRC
+	depends on I2C
+	---help---
+	   Driver for the Zilog/Hauppauge IR Transmitter, found on
+	   PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards
+
+	   To compile this driver as a module, choose M here: the
+	   module will be called zilog_ir.
+
 config IR_ZX
 	tristate "ZTE ZX IR remote control"
 	depends on RC_CORE
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 643797dc971b..a6bf6827b1ed 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -43,5 +43,6 @@ obj-$(CONFIG_IR_IMG) += img-ir/
 obj-$(CONFIG_IR_SERIAL) += serial_ir.o
 obj-$(CONFIG_IR_SIR) += sir_ir.o
 obj-$(CONFIG_IR_MTK) += mtk-cir.o
+obj-$(CONFIG_IR_ZILOG) += zilog_ir.o
 obj-$(CONFIG_IR_ZX) += zx-irdec.o
 obj-$(CONFIG_IR_TANGO) += tango-ir.o
diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/media/rc/zilog_ir.c
similarity index 100%
rename from drivers/staging/media/lirc/lirc_zilog.c
rename to drivers/media/rc/zilog_ir.c
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index f8c25ee082ef..3a09140700e6 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -31,7 +31,4 @@ source "drivers/staging/media/imx/Kconfig"
 
 source "drivers/staging/media/omap4iss/Kconfig"
 
-# Keep LIRC at the end, as it has sub-menus
-source "drivers/staging/media/lirc/Kconfig"
-
 endif
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index ac090c5fce30..9c057126d61f 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -1,7 +1,6 @@
 obj-$(CONFIG_I2C_BCM2048)	+= bcm2048/
 obj-$(CONFIG_DVB_CXD2099)	+= cxd2099/
 obj-$(CONFIG_VIDEO_IMX_MEDIA)	+= imx/
-obj-$(CONFIG_LIRC_STAGING)	+= lirc/
 obj-$(CONFIG_VIDEO_DM365_VPFE)	+= davinci_vpfe/
 obj-$(CONFIG_VIDEO_OMAP4)	+= omap4iss/
 obj-$(CONFIG_INTEL_ATOMISP)     += atomisp/
diff --git a/drivers/staging/media/lirc/Kconfig b/drivers/staging/media/lirc/Kconfig
deleted file mode 100644
index 3e350a9922de..000000000000
--- a/drivers/staging/media/lirc/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# LIRC driver(s) configuration
-#
-menuconfig LIRC_STAGING
-	bool "Linux Infrared Remote Control IR receiver/transmitter drivers"
-	depends on LIRC
-	help
-	  Say Y here, and all supported Linux Infrared Remote Control IR and
-	  RF receiver and transmitter drivers will be displayed. When paired
-	  with a remote control and the lirc daemon, the receiver drivers
-	  allow control of your Linux system via remote control.
-
-if LIRC_STAGING
-
-config LIRC_ZILOG
-	tristate "Zilog/Hauppauge IR Transmitter"
-	depends on LIRC && I2C
-	help
-	  Driver for the Zilog/Hauppauge IR Transmitter, found on
-	  PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards
-endif
diff --git a/drivers/staging/media/lirc/Makefile b/drivers/staging/media/lirc/Makefile
deleted file mode 100644
index 665562436e30..000000000000
--- a/drivers/staging/media/lirc/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# Makefile for the lirc drivers.
-#
-
-# Each configuration option enables a list of files.
-
-obj-$(CONFIG_LIRC_ZILOG)	+= lirc_zilog.o
diff --git a/drivers/staging/media/lirc/TODO b/drivers/staging/media/lirc/TODO
deleted file mode 100644
index a97800a8e127..000000000000
--- a/drivers/staging/media/lirc/TODO
+++ /dev/null
@@ -1,36 +0,0 @@
-1. Both ir-kbd-i2c and lirc_zilog provide support for RX events for
-the chips supported by lirc_zilog.  Before moving lirc_zilog out of staging:
-
-a. ir-kbd-i2c needs a module parameter added to allow the user to tell
-   ir-kbd-i2c to ignore Z8 IR units.
-
-b. lirc_zilog should provide Rx key presses to the rc core like ir-kbd-i2c
-   does.
-
-
-2. lirc_zilog module ref-counting need examination.  It has not been
-verified that cdev and lirc_dev will take the proper module references on
-lirc_zilog to prevent removal of lirc_zilog when the /dev/lircN device node
-is open.
-
-(The good news is ref-counting of lirc_zilog internal structures appears to be
-complete.  Testing has shown the cx18 module can be unloaded out from under
-irw + lircd + lirc_dev, with the /dev/lirc0 device node open, with no adverse
-effects.  The cx18 module could then be reloaded and irw properly began
-receiving button presses again and ir_send worked without error.)
-
-
-3. Bridge drivers, if able, should provide a chip reset() callback
-to lirc_zilog via struct IR_i2c_init_data.  cx18 and ivtv already have routines
-to perform Z8 chip resets via GPIO manipulations.  This would allow lirc_zilog
-to bring the chip back to normal when it hangs, in the same places the
-original lirc_pvr150 driver code does.  This is not strictly needed, so it
-is not required to move lirc_zilog out of staging.
-
-Note: Both lirc_zilog and ir-kbd-i2c support the Zilog Z8 for IR, as programmed
-and installed on Hauppauge products.  When working on either module, developers
-must consider at least the following bridge drivers which mention an IR Rx unit
-at address 0x71 (indicative of a Z8):
-
-	ivtv cx18 hdpvr pvrusb2 bt8xx cx88 saa7134
-
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 08/26] media: lirc: remove LIRCCODE and LIRC_GET_LENGTH
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (6 preceding siblings ...)
  2017-10-10  7:17 ` [PATCH v3 07/26] media: promote lirc_zilog out of staging Sean Young
@ 2017-10-10  7:17 ` Sean Young
  2017-10-10  7:17 ` [PATCH v3 09/26] media: lirc: lirc interface should not be a raw decoder Sean Young
                   ` (18 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:17 UTC (permalink / raw)
  To: linux-media

LIRCCODE is a lirc mode where a driver produces driver-dependent
codes for receive and transmit. No driver uses this any more. The
LIRC_GET_LENGTH ioctl was used for this mode only.

Signed-off-by: Sean Young <sean@mess.org>
---
 Documentation/media/lirc.h.rst.exceptions          |  5 +++
 Documentation/media/uapi/rc/lirc-dev-intro.rst     | 15 --------
 Documentation/media/uapi/rc/lirc-func.rst          |  1 -
 Documentation/media/uapi/rc/lirc-get-features.rst  |  7 +---
 Documentation/media/uapi/rc/lirc-get-length.rst    | 44 ----------------------
 Documentation/media/uapi/rc/lirc-get-rec-mode.rst  |  4 +-
 Documentation/media/uapi/rc/lirc-get-send-mode.rst |  3 +-
 drivers/media/rc/ir-lirc-codec.c                   |  1 -
 drivers/media/rc/lirc_dev.c                        | 12 ------
 include/media/lirc_dev.h                           |  4 --
 10 files changed, 9 insertions(+), 87 deletions(-)
 delete mode 100644 Documentation/media/uapi/rc/lirc-get-length.rst

diff --git a/Documentation/media/lirc.h.rst.exceptions b/Documentation/media/lirc.h.rst.exceptions
index c130617a9986..63ba1d341905 100644
--- a/Documentation/media/lirc.h.rst.exceptions
+++ b/Documentation/media/lirc.h.rst.exceptions
@@ -28,6 +28,10 @@ ignore define LIRC_CAN_SEND_MASK
 ignore define LIRC_CAN_REC_MASK
 ignore define LIRC_CAN_SET_REC_DUTY_CYCLE
 
+# Obsolete ioctls
+
+ignore ioctl LIRC_GET_LENGTH
+
 # Undocumented macros
 
 ignore define PULSE_BIT
@@ -40,3 +44,4 @@ ignore define LIRC_VALUE_MASK
 ignore define LIRC_MODE2_MASK
 
 ignore define LIRC_MODE_RAW
+ignore define LIRC_MODE_LIRCCODE
diff --git a/Documentation/media/uapi/rc/lirc-dev-intro.rst b/Documentation/media/uapi/rc/lirc-dev-intro.rst
index d1936eeb9ce0..3cacf9aeac40 100644
--- a/Documentation/media/uapi/rc/lirc-dev-intro.rst
+++ b/Documentation/media/uapi/rc/lirc-dev-intro.rst
@@ -72,21 +72,6 @@ on the following table.
         this packet will be sent, with the number of microseconds with
         no IR.
 
-.. _lirc-mode-lirccode:
-
-``LIRC_MODE_LIRCCODE``
-
-    This mode can be used for IR receive and send.
-
-    The IR signal is decoded internally by the receiver, or encoded by the
-    transmitter. The LIRC interface represents the scancode as byte string,
-    which might not be a u32, it can be any length. The value is entirely
-    driver dependent. This mode is used by some older lirc drivers.
-
-    The length of each code depends on the driver, which can be retrieved
-    with :ref:`lirc_get_length`. This length is used both
-    for transmitting and receiving IR.
-
 .. _lirc-mode-pulse:
 
 ``LIRC_MODE_PULSE``
diff --git a/Documentation/media/uapi/rc/lirc-func.rst b/Documentation/media/uapi/rc/lirc-func.rst
index 9b5a772ec96c..ddb4620de294 100644
--- a/Documentation/media/uapi/rc/lirc-func.rst
+++ b/Documentation/media/uapi/rc/lirc-func.rst
@@ -18,7 +18,6 @@ LIRC Function Reference
     lirc-set-send-duty-cycle
     lirc-get-timeout
     lirc-set-rec-timeout
-    lirc-get-length
     lirc-set-rec-carrier
     lirc-set-rec-carrier-range
     lirc-set-send-carrier
diff --git a/Documentation/media/uapi/rc/lirc-get-features.rst b/Documentation/media/uapi/rc/lirc-get-features.rst
index 64f89a4f9d9c..50c2c26d8e89 100644
--- a/Documentation/media/uapi/rc/lirc-get-features.rst
+++ b/Documentation/media/uapi/rc/lirc-get-features.rst
@@ -62,8 +62,7 @@ LIRC features
 
 ``LIRC_CAN_REC_LIRCCODE``
 
-    The driver is capable of receiving using
-    :ref:`LIRC_MODE_LIRCCODE <lirc-mode-LIRCCODE>`.
+    Unused. Kept just to avoid breaking uAPI.
 
 .. _LIRC-CAN-SET-SEND-CARRIER:
 
@@ -170,9 +169,7 @@ LIRC features
 
 ``LIRC_CAN_SEND_LIRCCODE``
 
-    The driver supports sending (also called as IR blasting or IR TX) using
-    :ref:`LIRC_MODE_LIRCCODE <lirc-mode-LIRCCODE>`.
-
+    Unused. Kept just to avoid breaking uAPI.
 
 Return Value
 ============
diff --git a/Documentation/media/uapi/rc/lirc-get-length.rst b/Documentation/media/uapi/rc/lirc-get-length.rst
deleted file mode 100644
index 3990af5de0e9..000000000000
--- a/Documentation/media/uapi/rc/lirc-get-length.rst
+++ /dev/null
@@ -1,44 +0,0 @@
-.. -*- coding: utf-8; mode: rst -*-
-
-.. _lirc_get_length:
-
-*********************
-ioctl LIRC_GET_LENGTH
-*********************
-
-Name
-====
-
-LIRC_GET_LENGTH - Retrieves the code length in bits.
-
-Synopsis
-========
-
-.. c:function:: int ioctl( int fd, LIRC_GET_LENGTH, __u32 *length )
-    :name: LIRC_GET_LENGTH
-
-Arguments
-=========
-
-``fd``
-    File descriptor returned by open().
-
-``length``
-    length, in bits
-
-
-Description
-===========
-
-Retrieves the code length in bits (only for
-:ref:`LIRC_MODE_LIRCCODE <lirc-mode-lirccode>`).
-Reads on the device must be done in blocks matching the bit count.
-The bit could should be rounded up so that it matches full bytes.
-
-
-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/Documentation/media/uapi/rc/lirc-get-rec-mode.rst b/Documentation/media/uapi/rc/lirc-get-rec-mode.rst
index a4eb6c0a26e9..b89de9add921 100644
--- a/Documentation/media/uapi/rc/lirc-get-rec-mode.rst
+++ b/Documentation/media/uapi/rc/lirc-get-rec-mode.rst
@@ -34,9 +34,7 @@ Description
 ===========
 
 Get/set supported receive modes. Only :ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>`
-and :ref:`LIRC_MODE_LIRCCODE <lirc-mode-lirccode>` are supported for IR
-receive. Use :ref:`lirc_get_features` to find out which modes the driver
-supports.
+is supported for IR receive.
 
 Return Value
 ============
diff --git a/Documentation/media/uapi/rc/lirc-get-send-mode.rst b/Documentation/media/uapi/rc/lirc-get-send-mode.rst
index a169b234290e..e686b21689a0 100644
--- a/Documentation/media/uapi/rc/lirc-get-send-mode.rst
+++ b/Documentation/media/uapi/rc/lirc-get-send-mode.rst
@@ -36,8 +36,7 @@ Description
 
 Get/set current transmit mode.
 
-Only :ref:`LIRC_MODE_PULSE <lirc-mode-pulse>` and
-:ref:`LIRC_MODE_LIRCCODE <lirc-mode-lirccode>` is supported by for IR send,
+Only :ref:`LIRC_MODE_PULSE <lirc-mode-pulse>` is supported by for IR send,
 depending on the driver. Use :ref:`lirc_get_features` to find out which
 modes the driver supports.
 
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 41259b1ce3c2..4355fbc10158 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -447,7 +447,6 @@ static int ir_lirc_register(struct rc_dev *dev)
 	ldev->features = features;
 	ldev->data = &dev->raw->lirc;
 	ldev->buf = NULL;
-	ldev->code_length = sizeof(struct ir_raw_event) * 8;
 	ldev->chunk_size = sizeof(int);
 	ldev->buffer_size = LIRCBUF_SIZE;
 	ldev->fops = &lirc_fops;
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index e16d1138ca48..ef7e915dc9a2 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -137,12 +137,6 @@ int lirc_register_device(struct lirc_dev *d)
 		return -EINVAL;
 	}
 
-	if (d->code_length < 1 || d->code_length > (BUFLEN * 8)) {
-		dev_err(&d->dev, "code length must be less than %d bits\n",
-			BUFLEN * 8);
-		return -EBADRQC;
-	}
-
 	if (!d->buf && !(d->fops && d->fops->read &&
 			 d->fops->poll && d->fops->unlocked_ioctl)) {
 		dev_err(&d->dev, "undefined read, poll, ioctl\n");
@@ -152,9 +146,6 @@ int lirc_register_device(struct lirc_dev *d)
 	/* some safety check 8-) */
 	d->name[sizeof(d->name) - 1] = '\0';
 
-	if (d->features == 0)
-		d->features = LIRC_CAN_REC_LIRCCODE;
-
 	if (LIRC_CAN_REC(d->features)) {
 		err = lirc_allocate_buffer(d);
 		if (err)
@@ -343,9 +334,6 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		 * for now, lirc_serial doesn't support mode changing either
 		 */
 		break;
-	case LIRC_GET_LENGTH:
-		result = put_user(d->code_length, (__u32 __user *)arg);
-		break;
 	default:
 		result = -ENOTTY;
 	}
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index 857da67bd931..0a03dd9e5a68 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -9,8 +9,6 @@
 #ifndef _LINUX_LIRC_DEV_H
 #define _LINUX_LIRC_DEV_H
 
-#define BUFLEN            16
-
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
@@ -117,7 +115,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
  *
  * @name:		used for logging
  * @minor:		the minor device (/dev/lircX) number for the device
- * @code_length:	length of a remote control key code expressed in bits
  * @features:		lirc compatible hardware features, like LIRC_MODE_RAW,
  *			LIRC_CAN\_\*, as defined at include/media/lirc.h.
  * @buffer_size:	Number of FIFO buffers with @chunk_size size.
@@ -142,7 +139,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
 struct lirc_dev {
 	char name[40];
 	unsigned int minor;
-	__u32 code_length;
 	__u32 features;
 
 	unsigned int buffer_size; /* in chunks holding one code each */
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 09/26] media: lirc: lirc interface should not be a raw decoder
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (7 preceding siblings ...)
  2017-10-10  7:17 ` [PATCH v3 08/26] media: lirc: remove LIRCCODE and LIRC_GET_LENGTH Sean Young
@ 2017-10-10  7:17 ` Sean Young
  2017-10-10  7:17 ` [PATCH v3 10/26] media: lirc: validate scancode for transmit Sean Young
                   ` (17 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:17 UTC (permalink / raw)
  To: linux-media

The lirc user interface exists as a raw decoder, which does not make
much sense for transmit-only devices.

In addition, we want to have lirc char devices for devices which do not
use raw IR, i.e. scancode only devices.

Note that rc-code, lirc_dev, ir-lirc-codec are now calling functions of
each other, so they've been merged into one module rc-core to avoid
circular dependencies.

Since ir-lirc-codec no longer exists as separate codec module, there is no
need for RC_DRIVER_IR_RAW_TX type drivers to call ir_raw_event_register().

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/Kconfig              |  29 ++------
 drivers/media/rc/Makefile             |   5 +-
 drivers/media/rc/ir-lirc-codec.c      | 136 ++++++++++------------------------
 drivers/media/rc/ir-mce_kbd-decoder.c |   6 --
 drivers/media/rc/lirc_dev.c           |  47 ++++--------
 drivers/media/rc/rc-core-priv.h       |  45 ++++++++---
 drivers/media/rc/rc-ir-raw.c          |  24 ++----
 drivers/media/rc/rc-main.c            |  52 ++++++-------
 include/media/lirc_dev.h              |  10 ---
 include/media/rc-core.h               |  33 +++++----
 10 files changed, 145 insertions(+), 242 deletions(-)

diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 2a47139e5811..d84c0d3f7494 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -16,34 +16,21 @@ menuconfig RC_CORE
 if RC_CORE
 source "drivers/media/rc/keymaps/Kconfig"
 
-menuconfig RC_DECODERS
-        bool "Remote controller decoders"
-	depends on RC_CORE
-	default y
-
-if RC_DECODERS
 config LIRC
-	tristate "LIRC interface driver"
+	bool "LIRC user interface"
 	depends on RC_CORE
-
 	---help---
-	   Enable this option to build the Linux Infrared Remote
-	   Control (LIRC) core device interface driver. The LIRC
-	   interface passes raw IR to and from userspace, where the
-	   LIRC daemon handles protocol decoding for IR reception and
-	   encoding for IR transmitting (aka "blasting").
+	   Enable this option to enable the Linux Infrared Remote
+	   Control user interface (e.g. /dev/lirc*). This interface
+	   passes raw IR to and from userspace, which is needed for
+	   IR transmitting (aka "blasting") and for the lirc daemon.
 
-config IR_LIRC_CODEC
-	tristate "Enable IR to LIRC bridge"
+menuconfig RC_DECODERS
+        bool "Remote controller decoders"
 	depends on RC_CORE
-	depends on LIRC
 	default y
 
-	---help---
-	   Enable this option to pass raw IR to and from userspace via
-	   the LIRC interface.
-
-
+if RC_DECODERS
 config IR_NEC_DECODER
 	tristate "Enable IR raw decoder for the NEC protocol"
 	depends on RC_CORE
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index a6bf6827b1ed..d2c7ea328c10 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -1,9 +1,9 @@
-rc-core-objs	:= rc-main.o rc-ir-raw.o
 
 obj-y += keymaps/
 
 obj-$(CONFIG_RC_CORE) += rc-core.o
-obj-$(CONFIG_LIRC) += lirc_dev.o
+rc-core-y := rc-main.o rc-ir-raw.o
+rc-core-$(CONFIG_LIRC) += lirc_dev.o ir-lirc-codec.o
 obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
 obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
 obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
@@ -12,7 +12,6 @@ obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
 obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o
 obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-decoder.o
 obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
-obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
 obj-$(CONFIG_IR_XMP_DECODER) += ir-xmp-decoder.o
 
 # stand-alone IR receivers/transmitters
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 4355fbc10158..f2feca17c3a0 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -14,7 +14,6 @@
 
 #include <linux/sched.h>
 #include <linux/wait.h>
-#include <linux/module.h>
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
 #include <media/rc-core.h>
@@ -23,21 +22,15 @@
 #define LIRCBUF_SIZE 256
 
 /**
- * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the
- *		      lircd userspace daemon for decoding.
- * @input_dev:	the struct rc_dev descriptor of the device
- * @duration:	the struct ir_raw_event descriptor of the pulse/space
+ * ir_lirc_raw_event() - Send raw IR data to lirc to be relayed to userspace
  *
- * This function returns -EINVAL if the lirc interfaces aren't wired up.
+ * @dev:	the struct rc_dev descriptor of the device
+ * @ev:		the struct ir_raw_event descriptor of the pulse/space
  */
-static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
+void ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev)
 {
-	struct lirc_codec *lirc = &dev->raw->lirc;
 	int sample;
 
-	if (!dev->raw->lirc.ldev || !dev->raw->lirc.ldev->buf)
-		return -EINVAL;
-
 	/* Packet start */
 	if (ev.reset) {
 		/* Userspace expects a long space event before the start of
@@ -56,15 +49,15 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	/* Packet end */
 	} else if (ev.timeout) {
 
-		if (lirc->gap)
-			return 0;
+		if (dev->gap)
+			return;
 
-		lirc->gap_start = ktime_get();
-		lirc->gap = true;
-		lirc->gap_duration = ev.duration;
+		dev->gap_start = ktime_get();
+		dev->gap = true;
+		dev->gap_duration = ev.duration;
 
-		if (!lirc->send_timeout_reports)
-			return 0;
+		if (!dev->send_timeout_reports)
+			return;
 
 		sample = LIRC_TIMEOUT(ev.duration / 1000);
 		IR_dprintk(2, "timeout report (duration: %d)\n", sample);
@@ -72,21 +65,21 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	/* Normal sample */
 	} else {
 
-		if (lirc->gap) {
+		if (dev->gap) {
 			int gap_sample;
 
-			lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
-				lirc->gap_start));
+			dev->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
+							 dev->gap_start));
 
 			/* Convert to ms and cap by LIRC_VALUE_MASK */
-			do_div(lirc->gap_duration, 1000);
-			lirc->gap_duration = min(lirc->gap_duration,
-							(u64)LIRC_VALUE_MASK);
+			do_div(dev->gap_duration, 1000);
+			dev->gap_duration = min_t(u64, dev->gap_duration,
+						  LIRC_VALUE_MASK);
 
-			gap_sample = LIRC_SPACE(lirc->gap_duration);
-			lirc_buffer_write(dev->raw->lirc.ldev->buf,
+			gap_sample = LIRC_SPACE(dev->gap_duration);
+			lirc_buffer_write(dev->lirc_dev->buf,
 					  (unsigned char *)&gap_sample);
-			lirc->gap = false;
+			dev->gap = false;
 		}
 
 		sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) :
@@ -95,18 +88,16 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
 			   TO_US(ev.duration), TO_STR(ev.pulse));
 	}
 
-	lirc_buffer_write(dev->raw->lirc.ldev->buf,
+	lirc_buffer_write(dev->lirc_dev->buf,
 			  (unsigned char *) &sample);
-	wake_up(&dev->raw->lirc.ldev->buf->wait_poll);
 
-	return 0;
+	wake_up(&dev->lirc_dev->buf->wait_poll);
 }
 
 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 = file->private_data;
 	unsigned int *txbuf = NULL;
 	struct ir_raw_event *raw = NULL;
 	ssize_t ret = -EINVAL;
@@ -118,15 +109,7 @@ 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 (lirc->send_mode == LIRC_MODE_SCANCODE) {
+	if (dev->send_mode == LIRC_MODE_SCANCODE) {
 		struct lirc_scancode scan;
 
 		if (n != sizeof(scan))
@@ -201,7 +184,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 	if (ret < 0)
 		goto out;
 
-	if (lirc->send_mode == LIRC_MODE_SCANCODE) {
+	if (dev->send_mode == LIRC_MODE_SCANCODE) {
 		ret = n;
 	} else {
 		for (duration = i = 0; i < ret; i++)
@@ -231,20 +214,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 = filep->private_data;
 	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)
@@ -258,7 +232,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		if (!dev->tx_ir && !dev->tx_scancode)
 			return -ENOTTY;
 
-		val = lirc->send_mode;
+		val = dev->send_mode;
 		break;
 
 	case LIRC_SET_SEND_MODE:
@@ -271,7 +245,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 */
@@ -305,7 +279,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 			return -EINVAL;
 
 		return dev->s_rx_carrier_range(dev,
-					       dev->raw->lirc.carrier_low,
+					       dev->carrier_low,
 					       val);
 
 	case LIRC_SET_REC_CARRIER_RANGE:
@@ -315,7 +289,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		if (val <= 0)
 			return -EINVAL;
 
-		dev->raw->lirc.carrier_low = val;
+		dev->carrier_low = val;
 		return 0;
 
 	case LIRC_GET_REC_RESOLUTION:
@@ -373,7 +347,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		if (!dev->timeout)
 			return -ENOTTY;
 
-		lirc->send_timeout_reports = !!val;
+		dev->send_timeout_reports = !!val;
 		break;
 
 	default:
@@ -400,7 +374,7 @@ static const struct file_operations lirc_fops = {
 	.llseek		= no_llseek,
 };
 
-static int ir_lirc_register(struct rc_dev *dev)
+int ir_lirc_register(struct rc_dev *dev)
 {
 	struct lirc_dev *ldev;
 	int rc = -ENOMEM;
@@ -445,7 +419,6 @@ static int ir_lirc_register(struct rc_dev *dev)
 	snprintf(ldev->name, sizeof(ldev->name), "ir-lirc-codec (%s)",
 		 dev->driver_name);
 	ldev->features = features;
-	ldev->data = &dev->raw->lirc;
 	ldev->buf = NULL;
 	ldev->chunk_size = sizeof(int);
 	ldev->buffer_size = LIRCBUF_SIZE;
@@ -459,12 +432,11 @@ static int ir_lirc_register(struct rc_dev *dev)
 		goto out;
 
 	if (dev->tx_scancode)
-		dev->raw->lirc.send_mode = LIRC_MODE_SCANCODE;
+		dev->send_mode = LIRC_MODE_SCANCODE;
 	else
-		dev->raw->lirc.send_mode = LIRC_MODE_PULSE;
+		dev->send_mode = LIRC_MODE_PULSE;
 
-	dev->raw->lirc.ldev = ldev;
-	dev->raw->lirc.dev = dev;
+	dev->lirc_dev = ldev;
 	return 0;
 
 out:
@@ -472,40 +444,8 @@ static int ir_lirc_register(struct rc_dev *dev)
 	return rc;
 }
 
-static int ir_lirc_unregister(struct rc_dev *dev)
+void ir_lirc_unregister(struct rc_dev *dev)
 {
-	struct lirc_codec *lirc = &dev->raw->lirc;
-
-	lirc_unregister_device(lirc->ldev);
-	lirc->ldev = NULL;
-
-	return 0;
+	lirc_unregister_device(dev->lirc_dev);
+	dev->lirc_dev = NULL;
 }
-
-static struct ir_raw_handler lirc_handler = {
-	.protocols	= 0,
-	.decode		= ir_lirc_decode,
-	.raw_register	= ir_lirc_register,
-	.raw_unregister	= ir_lirc_unregister,
-};
-
-static int __init ir_lirc_codec_init(void)
-{
-	ir_raw_handler_register(&lirc_handler);
-
-	printk(KERN_INFO "IR LIRC bridge handler initialized\n");
-	return 0;
-}
-
-static void __exit ir_lirc_codec_exit(void)
-{
-	ir_raw_handler_unregister(&lirc_handler);
-}
-
-module_init(ir_lirc_codec_init);
-module_exit(ir_lirc_codec_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
-MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("LIRC IR handler bridge");
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index efa3b735dcc4..48eef43b0530 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -358,9 +358,6 @@ static int ir_mce_kbd_register(struct rc_dev *dev)
 	struct input_dev *idev;
 	int i, ret;
 
-	if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
-		return 0;
-
 	idev = input_allocate_device();
 	if (!idev)
 		return -ENOMEM;
@@ -416,9 +413,6 @@ static int ir_mce_kbd_unregister(struct rc_dev *dev)
 	struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd;
 	struct input_dev *idev = mce_kbd->idev;
 
-	if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
-		return 0;
-
 	del_timer_sync(&mce_kbd->rx_timeout);
 	input_unregister_device(idev);
 
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index ef7e915dc9a2..3cc95deaa84e 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -26,7 +26,7 @@
 #include <linux/cdev.h>
 #include <linux/idr.h>
 
-#include <media/rc-core.h>
+#include "rc-core-priv.h"
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
 
@@ -236,7 +236,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
 
 	d->open++;
 
-	lirc_init_pdata(inode, file);
+	file->private_data = d->rdev;
 	nonseekable_open(inode, file);
 	mutex_unlock(&d->mutex);
 
@@ -250,11 +250,12 @@ EXPORT_SYMBOL(lirc_dev_fop_open);
 
 int lirc_dev_fop_close(struct inode *inode, struct file *file)
 {
-	struct lirc_dev *d = file->private_data;
+	struct rc_dev *rcdev = file->private_data;
+	struct lirc_dev *d = rcdev->lirc_dev;
 
 	mutex_lock(&d->mutex);
 
-	rc_close(d->rdev);
+	rc_close(rcdev);
 	d->open--;
 
 	mutex_unlock(&d->mutex);
@@ -265,7 +266,8 @@ EXPORT_SYMBOL(lirc_dev_fop_close);
 
 unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
 {
-	struct lirc_dev *d = file->private_data;
+	struct rc_dev *rcdev = file->private_data;
+	struct lirc_dev *d = rcdev->lirc_dev;
 	unsigned int ret;
 
 	if (!d->attached)
@@ -290,7 +292,8 @@ EXPORT_SYMBOL(lirc_dev_fop_poll);
 
 long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct lirc_dev *d = file->private_data;
+	struct rc_dev *rcdev = file->private_data;
+	struct lirc_dev *d = rcdev->lirc_dev;
 	__u32 mode;
 	int result;
 
@@ -349,7 +352,8 @@ ssize_t lirc_dev_fop_read(struct file *file,
 			  size_t length,
 			  loff_t *ppos)
 {
-	struct lirc_dev *d = file->private_data;
+	struct rc_dev *rcdev = file->private_data;
+	struct lirc_dev *d = rcdev->lirc_dev;
 	unsigned char *buf;
 	int ret, written = 0;
 	DECLARE_WAITQUEUE(wait, current);
@@ -448,24 +452,7 @@ ssize_t lirc_dev_fop_read(struct file *file,
 }
 EXPORT_SYMBOL(lirc_dev_fop_read);
 
-void lirc_init_pdata(struct inode *inode, struct file *file)
-{
-	struct lirc_dev *d = container_of(inode->i_cdev, struct lirc_dev, cdev);
-
-	file->private_data = d;
-}
-EXPORT_SYMBOL(lirc_init_pdata);
-
-void *lirc_get_pdata(struct file *file)
-{
-	struct lirc_dev *d = file->private_data;
-
-	return d->data;
-}
-EXPORT_SYMBOL(lirc_get_pdata);
-
-
-static int __init lirc_dev_init(void)
+int __init lirc_dev_init(void)
 {
 	int retval;
 
@@ -489,16 +476,8 @@ static int __init lirc_dev_init(void)
 	return 0;
 }
 
-static void __exit lirc_dev_exit(void)
+void __exit lirc_dev_exit(void)
 {
 	class_destroy(lirc_class);
 	unregister_chrdev_region(lirc_base_dev, LIRC_MAX_DEVICES);
-	pr_info("module unloaded\n");
 }
-
-module_init(lirc_dev_init);
-module_exit(lirc_dev_exit);
-
-MODULE_DESCRIPTION("LIRC base driver module");
-MODULE_AUTHOR("Artur Lipowski");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index d29b1b1ef4b7..21e515d34f64 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -22,6 +22,20 @@
 #include <linux/slab.h>
 #include <media/rc-core.h>
 
+/**
+ * rc_open - Opens a RC device
+ *
+ * @rdev: pointer to struct rc_dev.
+ */
+int rc_open(struct rc_dev *rdev);
+
+/**
+ * rc_close - Closes a RC device
+ *
+ * @rdev: pointer to struct rc_dev.
+ */
+void rc_close(struct rc_dev *rdev);
+
 struct ir_raw_handler {
 	struct list_head list;
 
@@ -31,7 +45,7 @@ struct ir_raw_handler {
 		      struct ir_raw_event *events, unsigned int max);
 	u32 carrier;
 
-	/* These two should only be used by the lirc decoder */
+	/* These two should only be used by the mce kbd decoder */
 	int (*raw_register)(struct rc_dev *dev);
 	int (*raw_unregister)(struct rc_dev *dev);
 };
@@ -105,17 +119,6 @@ struct ir_raw_event_ctrl {
 		unsigned count;
 		unsigned wanted_bits;
 	} mce_kbd;
-	struct lirc_codec {
-		struct rc_dev *dev;
-		struct lirc_dev *ldev;
-		int carrier_low;
-
-		ktime_t gap_start;
-		u64 gap_duration;
-		bool gap;
-		bool send_timeout_reports;
-		u8 send_mode;
-	} lirc;
 	struct xmp_dec {
 		int state;
 		unsigned count;
@@ -275,6 +278,24 @@ void ir_raw_load_modules(u64 *protocols);
 void ir_raw_init(void);
 
 /*
+ * lirc interface
+ */
+#ifdef CONFIG_LIRC
+int lirc_dev_init(void);
+void lirc_dev_exit(void);
+void ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev);
+int ir_lirc_register(struct rc_dev *dev);
+void ir_lirc_unregister(struct rc_dev *dev);
+#else
+static inline int lirc_dev_init(void) { return 0; }
+static inline void lirc_dev_exit(void) {}
+static inline void ir_lirc_raw_event(struct rc_dev *dev,
+				     struct ir_raw_event ev) { }
+static inline int ir_lirc_register(struct rc_dev *dev) { return 0; }
+static inline void ir_lirc_unregister(struct rc_dev *dev) { }
+#endif
+
+/*
  * Decoder initialization code
  *
  * Those load logic are called during ir-core init, and automatically
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index b84201cb012a..8d7fce5dd6ff 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -40,6 +40,7 @@ static int ir_raw_event_thread(void *data)
 				if (raw->dev->enabled_protocols &
 				    handler->protocols || !handler->protocols)
 					handler->decode(raw->dev, ev);
+			ir_lirc_raw_event(raw->dev, ev);
 			raw->prev_ev = ev;
 		}
 		mutex_unlock(&ir_raw_handler_lock);
@@ -529,16 +530,9 @@ EXPORT_SYMBOL(ir_raw_encode_carrier);
  */
 int ir_raw_event_prepare(struct rc_dev *dev)
 {
-	static bool raw_init; /* 'false' default value, raw decoders loaded? */
-
 	if (!dev)
 		return -EINVAL;
 
-	if (!raw_init) {
-		request_module("ir-lirc-codec");
-		raw_init = true;
-	}
-
 	dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL);
 	if (!dev->raw)
 		return -ENOMEM;
@@ -557,19 +551,11 @@ int ir_raw_event_register(struct rc_dev *dev)
 	struct ir_raw_handler *handler;
 	struct task_struct *thread;
 
-	/*
-	 * raw transmitters do not need any event registration
-	 * because the event is coming from userspace
-	 */
-	if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
-		thread = kthread_run(ir_raw_event_thread, dev->raw, "rc%u",
-				     dev->minor);
+	thread = kthread_run(ir_raw_event_thread, dev->raw, "rc%u", dev->minor);
+	if (IS_ERR(thread))
+		return PTR_ERR(thread);
 
-		if (IS_ERR(thread))
-			return PTR_ERR(thread);
-
-		dev->raw->thread = thread;
-	}
+	dev->raw->thread = thread;
 
 	mutex_lock(&ir_raw_handler_lock);
 	list_add_tail(&dev->raw->list, &ir_raw_client_list);
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 62102b3ef5aa..758c14b90a87 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -845,7 +845,6 @@ int rc_open(struct rc_dev *rdev)
 
 	return rval;
 }
-EXPORT_SYMBOL_GPL(rc_open);
 
 static int ir_open(struct input_dev *idev)
 {
@@ -865,7 +864,6 @@ void rc_close(struct rc_dev *rdev)
 		mutex_unlock(&rdev->lock);
 	}
 }
-EXPORT_SYMBOL_GPL(rc_close);
 
 static void ir_close(struct input_dev *idev)
 {
@@ -940,23 +938,6 @@ struct rc_filter_attribute {
 		.mask = (_mask),					\
 	}
 
-static bool lirc_is_present(void)
-{
-#if defined(CONFIG_LIRC_MODULE)
-	struct module *lirc;
-
-	mutex_lock(&module_mutex);
-	lirc = find_module("lirc_dev");
-	mutex_unlock(&module_mutex);
-
-	return lirc ? true : false;
-#elif defined(CONFIG_LIRC)
-	return true;
-#else
-	return false;
-#endif
-}
-
 /**
  * show_protocols() - shows the current IR protocol(s)
  * @device:	the device descriptor
@@ -1001,8 +982,10 @@ static ssize_t show_protocols(struct device *device,
 			allowed &= ~proto_names[i].type;
 	}
 
-	if (dev->driver_type == RC_DRIVER_IR_RAW && lirc_is_present())
+#ifdef CONFIG_LIRC
+	if (dev->driver_type == RC_DRIVER_IR_RAW)
 		tmp += sprintf(tmp, "[lirc] ");
+#endif
 
 	if (tmp != buf)
 		tmp--;
@@ -1759,8 +1742,7 @@ int rc_register_device(struct rc_dev *dev)
 		dev->sysfs_groups[attr++] = &rc_dev_wakeup_filter_attr_grp;
 	dev->sysfs_groups[attr++] = NULL;
 
-	if (dev->driver_type == RC_DRIVER_IR_RAW ||
-	    dev->driver_type == RC_DRIVER_IR_RAW_TX) {
+	if (dev->driver_type == RC_DRIVER_IR_RAW) {
 		rc = ir_raw_event_prepare(dev);
 		if (rc < 0)
 			goto out_minor;
@@ -1787,19 +1769,28 @@ int rc_register_device(struct rc_dev *dev)
 			goto out_dev;
 	}
 
-	if (dev->driver_type == RC_DRIVER_IR_RAW ||
-	    dev->driver_type == RC_DRIVER_IR_RAW_TX) {
-		rc = ir_raw_event_register(dev);
+	/* Ensure that the lirc kfifo is setup before we start the thread */
+	if (dev->driver_type != RC_DRIVER_SCANCODE) {
+		rc = ir_lirc_register(dev);
 		if (rc < 0)
 			goto out_rx;
 	}
 
+	if (dev->driver_type == RC_DRIVER_IR_RAW) {
+		rc = ir_raw_event_register(dev);
+		if (rc < 0)
+			goto out_lirc;
+	}
+
 	IR_dprintk(1, "Registered rc%u (driver: %s)\n",
 		   dev->minor,
 		   dev->driver_name ? dev->driver_name : "unknown");
 
 	return 0;
 
+out_lirc:
+	if (dev->driver_type != RC_DRIVER_SCANCODE)
+		ir_lirc_unregister(dev);
 out_rx:
 	rc_free_rx_device(dev);
 out_dev:
@@ -1853,6 +1844,9 @@ void rc_unregister_device(struct rc_dev *dev)
 
 	rc_free_rx_device(dev);
 
+	if (dev->driver_type != RC_DRIVER_SCANCODE)
+		ir_lirc_unregister(dev);
+
 	device_del(&dev->dev);
 
 	ida_simple_remove(&rc_ida, dev->minor);
@@ -1875,6 +1869,13 @@ static int __init rc_core_init(void)
 		return rc;
 	}
 
+	rc = lirc_dev_init();
+	if (rc) {
+		pr_err("rc_core: unable to init lirc\n");
+		class_unregister(&rc_class);
+		return 0;
+	}
+
 	led_trigger_register_simple("rc-feedback", &led_feedback);
 	rc_map_register(&empty_map);
 
@@ -1883,6 +1884,7 @@ static int __init rc_core_init(void)
 
 static void __exit rc_core_exit(void)
 {
+	lirc_dev_exit();
 	class_unregister(&rc_class);
 	led_trigger_unregister_simple(led_feedback);
 	rc_map_unregister(&empty_map);
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index 0a03dd9e5a68..dd0c078796e8 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -121,7 +121,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
  *			Only used if @rbuf is NULL.
  * @chunk_size:		Size of each FIFO buffer.
  *			Only used if @rbuf is NULL.
- * @data:		private per-driver data
  * @buf:		if %NULL, lirc_dev will allocate and manage the buffer,
  *			otherwise allocated by the caller which will
  *			have to write to the buffer by other means, like irq's
@@ -146,7 +145,6 @@ struct lirc_dev {
 	struct lirc_buffer *buf;
 	bool buf_internal;
 
-	void *data;
 	struct rc_dev *rdev;
 	const struct file_operations *fops;
 	struct module *owner;
@@ -168,14 +166,6 @@ int lirc_register_device(struct lirc_dev *d);
 
 void lirc_unregister_device(struct lirc_dev *d);
 
-/* Must be called in the open fop before lirc_get_pdata() can be used */
-void lirc_init_pdata(struct inode *inode, struct file *file);
-
-/* Returns the private data stored in the lirc_dev
- * associated with the given device file pointer.
- */
-void *lirc_get_pdata(struct file *file);
-
 /* default file operations
  * used by drivers if they override only some operations
  */
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index b74b3165dc78..83aa5e423a13 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -20,6 +20,7 @@
 #include <linux/kfifo.h>
 #include <linux/time.h>
 #include <linux/timer.h>
+#include <media/lirc_dev.h>
 #include <media/rc-map.h>
 
 extern int rc_core_debug;
@@ -115,6 +116,15 @@ enum rc_filter_type {
  * @max_timeout: maximum timeout supported by device
  * @rx_resolution : resolution (in ns) of input sampler
  * @tx_resolution: resolution (in ns) of output sampler
+ * @lirc_dev: lirc char device
+ * @carrier_low: when setting the carrier range, first the low end must be
+ *	set with an ioctl and then the high end with another ioctl
+ * @gap_start: time when gap starts
+ * @gap_duration: duration of initial gap
+ * @gap: true if we're in a gap
+ * @send_timeout_reports: report timeouts in lirc raw IR.
+ * @send_mode: lirc mode for sending, either LIRC_MODE_SCANCODE or
+ *	LIRC_MODE_PULSE
  * @change_protocol: allow changing the protocol used on hardware decoders
  * @open: callback to allow drivers to enable polling/irq when IR input device
  *	is opened.
@@ -175,6 +185,15 @@ struct rc_dev {
 	u32				max_timeout;
 	u32				rx_resolution;
 	u32				tx_resolution;
+#ifdef CONFIG_LIRC
+	struct lirc_dev			*lirc_dev;
+	int				carrier_low;
+	ktime_t				gap_start;
+	u64				gap_duration;
+	bool				gap;
+	bool				send_timeout_reports;
+	u8				send_mode;
+#endif
 	int				(*change_protocol)(struct rc_dev *dev, u64 *rc_proto);
 	int				(*open)(struct rc_dev *dev);
 	void				(*close)(struct rc_dev *dev);
@@ -250,20 +269,6 @@ int devm_rc_register_device(struct device *parent, struct rc_dev *dev);
  */
 void rc_unregister_device(struct rc_dev *dev);
 
-/**
- * rc_open - Opens a RC device
- *
- * @rdev: pointer to struct rc_dev.
- */
-int rc_open(struct rc_dev *rdev);
-
-/**
- * rc_close - Closes a RC device
- *
- * @rdev: pointer to struct rc_dev.
- */
-void rc_close(struct rc_dev *rdev);
-
 void rc_repeat(struct rc_dev *dev);
 void rc_keydown(struct rc_dev *dev, enum rc_proto protocol, u32 scancode,
 		u8 toggle);
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 10/26] media: lirc: validate scancode for transmit
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (8 preceding siblings ...)
  2017-10-10  7:17 ` [PATCH v3 09/26] media: lirc: lirc interface should not be a raw decoder Sean Young
@ 2017-10-10  7:17 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 11/26] media: rc: document and fix rc_validate_scancode() Sean Young
                   ` (16 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:17 UTC (permalink / raw)
  To: linux-media

Ensure we reject an attempt to transmit invalid scancodes.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/ir-lirc-codec.c | 10 ++++++++
 drivers/media/rc/rc-core-priv.h  |  1 +
 drivers/media/rc/rc-main.c       | 53 +++++++++++++++++++++++++---------------
 3 files changed, 44 insertions(+), 20 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index f2feca17c3a0..d9406fdbc9a3 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -121,6 +121,16 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 		if (scan.flags || scan.keycode || scan.timestamp)
 			return -EINVAL;
 
+		/*
+		 * The scancode field in lirc_scancode is 64-bit simply
+		 * to future-proof it, since there are IR protocols encode
+		 * use more than 32 bits. For now only 32-bit protocols
+		 * are supported.
+		 */
+		if (scan.scancode > U32_MAX ||
+		    !rc_validate_scancode(scan.rc_proto, scan.scancode))
+			return -EINVAL;
+
 		if (dev->tx_scancode) {
 			ret = dev->tx_scancode(dev, &scan);
 			return ret < 0 ? ret : n;
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 21e515d34f64..a064c401fa38 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -160,6 +160,7 @@ static inline bool is_timing_event(struct ir_raw_event ev)
 #define TO_STR(is_pulse)		((is_pulse) ? "pulse" : "space")
 
 /* functions for IR encoders */
+bool rc_validate_scancode(enum rc_proto proto, u32 scancode);
 
 static inline void init_ir_raw_event_duration(struct ir_raw_event *ev,
 					      unsigned int pulse,
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 758c14b90a87..38393f13822f 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -776,6 +776,37 @@ void rc_keydown_notimeout(struct rc_dev *dev, enum rc_proto protocol,
 EXPORT_SYMBOL_GPL(rc_keydown_notimeout);
 
 /**
+ * rc_validate_scancode() - checks that a scancode is valid for a protocol
+ * @proto:	protocol
+ * @scancode:	scancode
+ */
+bool rc_validate_scancode(enum rc_proto proto, u32 scancode)
+{
+	switch (proto) {
+	case RC_PROTO_NECX:
+		if ((((scancode >> 16) ^ ~(scancode >> 8)) & 0xff) == 0)
+			return false;
+		break;
+	case RC_PROTO_NEC32:
+		if ((((scancode >> 24) ^ ~(scancode >> 16)) & 0xff) == 0)
+			return false;
+		break;
+	case RC_PROTO_RC6_MCE:
+		if ((scancode & 0xffff0000) != 0x800f0000)
+			return false;
+		break;
+	case RC_PROTO_RC6_6A_32:
+		if ((scancode & 0xffff0000) == 0x800f0000)
+			return false;
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
+/**
  * rc_validate_filter() - checks that the scancode and mask are valid and
  *			  provides sensible defaults
  * @dev:	the struct rc_dev descriptor of the device
@@ -793,26 +824,8 @@ static int rc_validate_filter(struct rc_dev *dev,
 
 	mask = protocols[protocol].scancode_bits;
 
-	switch (protocol) {
-	case RC_PROTO_NECX:
-		if ((((s >> 16) ^ ~(s >> 8)) & 0xff) == 0)
-			return -EINVAL;
-		break;
-	case RC_PROTO_NEC32:
-		if ((((s >> 24) ^ ~(s >> 16)) & 0xff) == 0)
-			return -EINVAL;
-		break;
-	case RC_PROTO_RC6_MCE:
-		if ((s & 0xffff0000) != 0x800f0000)
-			return -EINVAL;
-		break;
-	case RC_PROTO_RC6_6A_32:
-		if ((s & 0xffff0000) == 0x800f0000)
-			return -EINVAL;
-		break;
-	default:
-		break;
-	}
+	if (!rc_validate_scancode(protocol, s))
+		return -EINVAL;
 
 	filter->data &= mask;
 	filter->mask &= mask;
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 11/26] media: rc: document and fix rc_validate_scancode()
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (9 preceding siblings ...)
  2017-10-10  7:17 ` [PATCH v3 10/26] media: lirc: validate scancode for transmit Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 12/26] media: lirc: merge lirc_dev_fop_ioctl and ir_lirc_ioctl Sean Young
                   ` (15 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

For some IR protocols, some scancode values not valid, i.e. they're part
of a different protocol variant.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/rc-main.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 38393f13822f..ae1df089c96f 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -776,21 +776,35 @@ void rc_keydown_notimeout(struct rc_dev *dev, enum rc_proto protocol,
 EXPORT_SYMBOL_GPL(rc_keydown_notimeout);
 
 /**
- * rc_validate_scancode() - checks that a scancode is valid for a protocol
+ * rc_validate_scancode() - checks that a scancode is valid for a protocol.
+ *	For nec, it should do the opposite of ir_nec_bytes_to_scancode()
  * @proto:	protocol
  * @scancode:	scancode
  */
 bool rc_validate_scancode(enum rc_proto proto, u32 scancode)
 {
 	switch (proto) {
+	/*
+	 * NECX has a 16-bit address; if the lower 8 bits match the upper
+	 * 8 bits inverted, then the address would match regular nec.
+	 */
 	case RC_PROTO_NECX:
 		if ((((scancode >> 16) ^ ~(scancode >> 8)) & 0xff) == 0)
 			return false;
 		break;
+	/*
+	 * NEC32 has a 16 bit address and 16 bit command. If the lower 8 bits
+	 * of the command match the upper 8 bits inverted, then it would
+	 * be either NEC or NECX.
+	 */
 	case RC_PROTO_NEC32:
-		if ((((scancode >> 24) ^ ~(scancode >> 16)) & 0xff) == 0)
+		if ((((scancode >> 8) ^ ~scancode) & 0xff) == 0)
 			return false;
 		break;
+	/*
+	 * If the customer code (top 32-bit) is 0x800f, it is MCE else it
+	 * is regular mode-6a 32 bit
+	 */
 	case RC_PROTO_RC6_MCE:
 		if ((scancode & 0xffff0000) != 0x800f0000)
 			return false;
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 12/26] media: lirc: merge lirc_dev_fop_ioctl and ir_lirc_ioctl
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (10 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 11/26] media: rc: document and fix rc_validate_scancode() Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 13/26] media: lirc: use kfifo rather than lirc_buffer for raw IR Sean Young
                   ` (14 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

Calculate lirc features when necessary, and add LIRC_{S,G}ET_REC_MODE
cases to ir_lirc_ioctl.

This makes lirc_dev_fop_ioctl() unnecessary since all cases are
already handled by ir_lirc_ioctl().

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/ir-lirc-codec.c | 85 +++++++++++++++++++++++-----------------
 drivers/media/rc/lirc_dev.c      | 62 ++---------------------------
 include/media/lirc_dev.h         |  4 --
 3 files changed, 53 insertions(+), 98 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index d9406fdbc9a3..05b2c1d5c0e6 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -236,8 +236,57 @@ 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;
+			if (dev->rx_resolution)
+				val |= LIRC_CAN_GET_REC_RESOLUTION;
+		}
+
+		if (dev->tx_scancode)
+			val |= LIRC_CAN_SEND_SCANCODE;
+
+		if (dev->tx_ir) {
+			val |= LIRC_CAN_SEND_PULSE | LIRC_CAN_SEND_SCANCODE;
+			if (dev->s_tx_mask)
+				val |= LIRC_CAN_SET_TRANSMITTER_MASK;
+			if (dev->s_tx_carrier)
+				val |= LIRC_CAN_SET_SEND_CARRIER;
+			if (dev->s_tx_duty_cycle)
+				val |= LIRC_CAN_SET_SEND_DUTY_CYCLE;
+		}
+
+		if (dev->s_rx_carrier_range)
+			val |= LIRC_CAN_SET_REC_CARRIER |
+				LIRC_CAN_SET_REC_CARRIER_RANGE;
+
+		if (dev->s_learning_mode)
+			val |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
+
+		if (dev->s_carrier_report)
+			val |= LIRC_CAN_MEASURE_CARRIER;
+
+		if (dev->max_timeout)
+			val |= LIRC_CAN_SET_REC_TIMEOUT;
+
+		break;
 
 	/* mode support */
+	case LIRC_GET_REC_MODE:
+		if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
+			return -ENOTTY;
+
+		val = LIRC_MODE_MODE2;
+		break;
+
+	case LIRC_SET_REC_MODE:
+		if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
+			return -ENOTTY;
+
+		if (val != LIRC_MODE_MODE2)
+			return -EINVAL;
+		return 0;
+
 	case LIRC_GET_SEND_MODE:
 		if (!dev->tx_ir && !dev->tx_scancode)
 			return -ENOTTY;
@@ -361,7 +410,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		break;
 
 	default:
-		return lirc_dev_fop_ioctl(filep, cmd, arg);
+		return -ENOTTY;
 	}
 
 	if (_IOC_DIR(cmd) & _IOC_READ)
@@ -388,47 +437,13 @@ int ir_lirc_register(struct rc_dev *dev)
 {
 	struct lirc_dev *ldev;
 	int rc = -ENOMEM;
-	unsigned long features = 0;
 
 	ldev = lirc_allocate_device();
 	if (!ldev)
 		return rc;
 
-	if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
-		features |= LIRC_CAN_REC_MODE2;
-		if (dev->rx_resolution)
-			features |= LIRC_CAN_GET_REC_RESOLUTION;
-	}
-
-	if (dev->tx_scancode)
-		features |= LIRC_CAN_SEND_SCANCODE;
-
-	if (dev->tx_ir) {
-		features |= LIRC_CAN_SEND_PULSE | LIRC_CAN_SEND_SCANCODE;
-		if (dev->s_tx_mask)
-			features |= LIRC_CAN_SET_TRANSMITTER_MASK;
-		if (dev->s_tx_carrier)
-			features |= LIRC_CAN_SET_SEND_CARRIER;
-		if (dev->s_tx_duty_cycle)
-			features |= LIRC_CAN_SET_SEND_DUTY_CYCLE;
-	}
-
-	if (dev->s_rx_carrier_range)
-		features |= LIRC_CAN_SET_REC_CARRIER |
-			LIRC_CAN_SET_REC_CARRIER_RANGE;
-
-	if (dev->s_learning_mode)
-		features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
-
-	if (dev->s_carrier_report)
-		features |= LIRC_CAN_MEASURE_CARRIER;
-
-	if (dev->max_timeout)
-		features |= LIRC_CAN_SET_REC_TIMEOUT;
-
 	snprintf(ldev->name, sizeof(ldev->name), "ir-lirc-codec (%s)",
 		 dev->driver_name);
-	ldev->features = features;
 	ldev->buf = NULL;
 	ldev->chunk_size = sizeof(int);
 	ldev->buffer_size = LIRCBUF_SIZE;
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 3cc95deaa84e..95058ea01e62 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -109,6 +109,7 @@ EXPORT_SYMBOL(lirc_free_device);
 
 int lirc_register_device(struct lirc_dev *d)
 {
+	struct rc_dev *rcdev = d->rdev;
 	int minor;
 	int err;
 
@@ -146,7 +147,7 @@ int lirc_register_device(struct lirc_dev *d)
 	/* some safety check 8-) */
 	d->name[sizeof(d->name) - 1] = '\0';
 
-	if (LIRC_CAN_REC(d->features)) {
+	if (rcdev->driver_type == RC_DRIVER_IR_RAW) {
 		err = lirc_allocate_buffer(d);
 		if (err)
 			return err;
@@ -290,63 +291,6 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
 }
 EXPORT_SYMBOL(lirc_dev_fop_poll);
 
-long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct rc_dev *rcdev = file->private_data;
-	struct lirc_dev *d = rcdev->lirc_dev;
-	__u32 mode;
-	int result;
-
-	dev_dbg(&d->dev, LOGHEAD "ioctl called (0x%x)\n",
-		d->name, d->minor, cmd);
-
-	result = mutex_lock_interruptible(&d->mutex);
-	if (result)
-		return result;
-
-	if (!d->attached) {
-		result = -ENODEV;
-		goto out;
-	}
-
-	switch (cmd) {
-	case LIRC_GET_FEATURES:
-		result = put_user(d->features, (__u32 __user *)arg);
-		break;
-	case LIRC_GET_REC_MODE:
-		if (!LIRC_CAN_REC(d->features)) {
-			result = -ENOTTY;
-			break;
-		}
-
-		result = put_user(LIRC_REC2MODE
-				  (d->features & LIRC_CAN_REC_MASK),
-				  (__u32 __user *)arg);
-		break;
-	case LIRC_SET_REC_MODE:
-		if (!LIRC_CAN_REC(d->features)) {
-			result = -ENOTTY;
-			break;
-		}
-
-		result = get_user(mode, (__u32 __user *)arg);
-		if (!result && !(LIRC_MODE2REC(mode) & d->features))
-			result = -EINVAL;
-		/*
-		 * FIXME: We should actually set the mode somehow but
-		 * for now, lirc_serial doesn't support mode changing either
-		 */
-		break;
-	default:
-		result = -ENOTTY;
-	}
-
-out:
-	mutex_unlock(&d->mutex);
-	return result;
-}
-EXPORT_SYMBOL(lirc_dev_fop_ioctl);
-
 ssize_t lirc_dev_fop_read(struct file *file,
 			  char __user *buffer,
 			  size_t length,
@@ -375,7 +319,7 @@ ssize_t lirc_dev_fop_read(struct file *file,
 		goto out_locked;
 	}
 
-	if (!LIRC_CAN_REC(d->features)) {
+	if (rcdev->driver_type != RC_DRIVER_IR_RAW) {
 		ret = -EINVAL;
 		goto out_locked;
 	}
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index dd0c078796e8..86a3cf798775 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -115,8 +115,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
  *
  * @name:		used for logging
  * @minor:		the minor device (/dev/lircX) number for the device
- * @features:		lirc compatible hardware features, like LIRC_MODE_RAW,
- *			LIRC_CAN\_\*, as defined at include/media/lirc.h.
  * @buffer_size:	Number of FIFO buffers with @chunk_size size.
  *			Only used if @rbuf is NULL.
  * @chunk_size:		Size of each FIFO buffer.
@@ -138,7 +136,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
 struct lirc_dev {
 	char name[40];
 	unsigned int minor;
-	__u32 features;
 
 	unsigned int buffer_size; /* in chunks holding one code each */
 	unsigned int chunk_size;
@@ -172,7 +169,6 @@ void lirc_unregister_device(struct lirc_dev *d);
 int lirc_dev_fop_open(struct inode *inode, struct file *file);
 int lirc_dev_fop_close(struct inode *inode, struct file *file);
 unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait);
-long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 ssize_t lirc_dev_fop_read(struct file *file, char __user *buffer, size_t length,
 			  loff_t *ppos);
 #endif
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 13/26] media: lirc: use kfifo rather than lirc_buffer for raw IR
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (11 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 12/26] media: lirc: merge lirc_dev_fop_ioctl and ir_lirc_ioctl Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 14/26] media: lirc: move lirc_dev->attached to rc_dev->registered Sean Young
                   ` (13 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

Since the only mode lirc devices can handle is raw IR, handle this
in a plain kfifo.

Remove lirc_buffer since this is no longer needed.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/ir-lirc-codec.c |  79 +++++++++++++---
 drivers/media/rc/lirc_dev.c      | 199 ++++-----------------------------------
 include/media/lirc_dev.h         | 109 ---------------------
 include/media/rc-core.h          |   4 +
 4 files changed, 85 insertions(+), 306 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 05b2c1d5c0e6..7dc3fe8a5a96 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -66,8 +66,6 @@ void ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev)
 	} else {
 
 		if (dev->gap) {
-			int gap_sample;
-
 			dev->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
 							 dev->gap_start));
 
@@ -76,9 +74,7 @@ void ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev)
 			dev->gap_duration = min_t(u64, dev->gap_duration,
 						  LIRC_VALUE_MASK);
 
-			gap_sample = LIRC_SPACE(dev->gap_duration);
-			lirc_buffer_write(dev->lirc_dev->buf,
-					  (unsigned char *)&gap_sample);
+			kfifo_put(&dev->rawir, LIRC_SPACE(dev->gap_duration));
 			dev->gap = false;
 		}
 
@@ -88,10 +84,8 @@ void ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev)
 			   TO_US(ev.duration), TO_STR(ev.pulse));
 	}
 
-	lirc_buffer_write(dev->lirc_dev->buf,
-			  (unsigned char *) &sample);
-
-	wake_up(&dev->lirc_dev->buf->wait_poll);
+	kfifo_put(&dev->rawir, sample);
+	wake_up_poll(&dev->wait_poll, POLLIN | POLLRDNORM);
 }
 
 static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
@@ -419,6 +413,66 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 	return ret;
 }
 
+static unsigned int ir_lirc_poll(struct file *file,
+				 struct poll_table_struct *wait)
+{
+	struct rc_dev *rcdev = file->private_data;
+	struct lirc_dev *d = rcdev->lirc_dev;
+	unsigned int events = 0;
+
+	poll_wait(file, &rcdev->wait_poll, wait);
+
+	if (!d->attached)
+		events = POLLHUP | POLLERR;
+	else if (rcdev->driver_type == RC_DRIVER_IR_RAW &&
+		 !kfifo_is_empty(&rcdev->rawir))
+		events = POLLIN | POLLRDNORM;
+
+	return events;
+}
+
+static ssize_t ir_lirc_read(struct file *file, char __user *buffer,
+			    size_t length, loff_t *ppos)
+{
+	struct rc_dev *rcdev = file->private_data;
+	struct lirc_dev *d = rcdev->lirc_dev;
+	unsigned int copied;
+	int ret;
+
+	if (rcdev->driver_type == RC_DRIVER_IR_RAW_TX)
+		return -EINVAL;
+
+	if (length < sizeof(unsigned int) || length % sizeof(unsigned int))
+		return -EINVAL;
+
+	if (!d->attached)
+		return -ENODEV;
+
+	do {
+		if (kfifo_is_empty(&rcdev->rawir)) {
+			if (file->f_flags & O_NONBLOCK)
+				return -EAGAIN;
+
+			ret = wait_event_interruptible(rcdev->wait_poll,
+					!kfifo_is_empty(&rcdev->rawir) ||
+					!d->attached);
+			if (ret)
+				return ret;
+		}
+
+		if (!d->attached)
+			return -ENODEV;
+
+		mutex_lock(&rcdev->lock);
+		ret = kfifo_to_user(&rcdev->rawir, buffer, length, &copied);
+		mutex_unlock(&rcdev->lock);
+		if (ret)
+			return ret;
+	} while (copied == 0);
+
+	return copied;
+}
+
 static const struct file_operations lirc_fops = {
 	.owner		= THIS_MODULE,
 	.write		= ir_lirc_transmit_ir,
@@ -426,8 +480,8 @@ static const struct file_operations lirc_fops = {
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= ir_lirc_ioctl,
 #endif
-	.read		= lirc_dev_fop_read,
-	.poll		= lirc_dev_fop_poll,
+	.read		= ir_lirc_read,
+	.poll		= ir_lirc_poll,
 	.open		= lirc_dev_fop_open,
 	.release	= lirc_dev_fop_close,
 	.llseek		= no_llseek,
@@ -444,9 +498,6 @@ int ir_lirc_register(struct rc_dev *dev)
 
 	snprintf(ldev->name, sizeof(ldev->name), "ir-lirc-codec (%s)",
 		 dev->driver_name);
-	ldev->buf = NULL;
-	ldev->chunk_size = sizeof(int);
-	ldev->buffer_size = LIRCBUF_SIZE;
 	ldev->fops = &lirc_fops;
 	ldev->dev.parent = &dev->dev;
 	ldev->rdev = dev;
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 95058ea01e62..9a0ad8d9a0cb 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -44,40 +44,14 @@ static struct class *lirc_class;
 static void lirc_release_device(struct device *ld)
 {
 	struct lirc_dev *d = container_of(ld, struct lirc_dev, dev);
+	struct rc_dev *rcdev = d->rdev;
 
-	put_device(d->dev.parent);
+	if (rcdev->driver_type == RC_DRIVER_IR_RAW)
+		kfifo_free(&rcdev->rawir);
 
-	if (d->buf_internal) {
-		lirc_buffer_free(d->buf);
-		kfree(d->buf);
-		d->buf = NULL;
-	}
 	kfree(d);
 	module_put(THIS_MODULE);
-}
-
-static int lirc_allocate_buffer(struct lirc_dev *d)
-{
-	int err;
-
-	if (d->buf) {
-		d->buf_internal = false;
-		return 0;
-	}
-
-	d->buf = kmalloc(sizeof(*d->buf), GFP_KERNEL);
-	if (!d->buf)
-		return -ENOMEM;
-
-	err = lirc_buffer_init(d->buf, d->chunk_size, d->buffer_size);
-	if (err) {
-		kfree(d->buf);
-		d->buf = NULL;
-		return err;
-	}
-
-	d->buf_internal = true;
-	return 0;
+	put_device(d->dev.parent);
 }
 
 struct lirc_dev *
@@ -128,31 +102,16 @@ int lirc_register_device(struct lirc_dev *d)
 		return -EINVAL;
 	}
 
-	if (!d->buf && d->chunk_size < 1) {
-		pr_err("chunk_size must be set!\n");
-		return -EINVAL;
-	}
-
-	if (!d->buf && d->buffer_size < 1) {
-		pr_err("buffer_size must be set!\n");
-		return -EINVAL;
-	}
-
-	if (!d->buf && !(d->fops && d->fops->read &&
-			 d->fops->poll && d->fops->unlocked_ioctl)) {
-		dev_err(&d->dev, "undefined read, poll, ioctl\n");
-		return -EBADRQC;
-	}
-
 	/* some safety check 8-) */
 	d->name[sizeof(d->name) - 1] = '\0';
 
 	if (rcdev->driver_type == RC_DRIVER_IR_RAW) {
-		err = lirc_allocate_buffer(d);
-		if (err)
-			return err;
+		if (kfifo_alloc(&rcdev->rawir, MAX_IR_EVENT_SIZE, GFP_KERNEL))
+			return -ENOMEM;
 	}
 
+	init_waitqueue_head(&rcdev->wait_poll);
+
 	minor = ida_simple_get(&lirc_ida, 0, LIRC_MAX_DEVICES, GFP_KERNEL);
 	if (minor < 0)
 		return minor;
@@ -182,9 +141,13 @@ EXPORT_SYMBOL(lirc_register_device);
 
 void lirc_unregister_device(struct lirc_dev *d)
 {
+	struct rc_dev *rcdev;
+
 	if (!d)
 		return;
 
+	rcdev = d->rdev;
+
 	dev_dbg(&d->dev, "lirc_dev: driver %s unregistered from minor = %d\n",
 		d->name, d->minor);
 
@@ -194,7 +157,7 @@ void lirc_unregister_device(struct lirc_dev *d)
 	if (d->open) {
 		dev_dbg(&d->dev, LOGHEAD "releasing opened driver\n",
 			d->name, d->minor);
-		wake_up_interruptible(&d->buf->wait_poll);
+		wake_up_poll(&rcdev->wait_poll, POLLHUP);
 	}
 
 	mutex_unlock(&d->mutex);
@@ -208,6 +171,7 @@ EXPORT_SYMBOL(lirc_unregister_device);
 int lirc_dev_fop_open(struct inode *inode, struct file *file)
 {
 	struct lirc_dev *d = container_of(inode->i_cdev, struct lirc_dev, cdev);
+	struct rc_dev *rcdev = d->rdev;
 	int retval;
 
 	dev_dbg(&d->dev, LOGHEAD "open called\n", d->name, d->minor);
@@ -232,8 +196,8 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
 			goto out;
 	}
 
-	if (d->buf)
-		lirc_buffer_clear(d->buf);
+	if (rcdev->driver_type == RC_DRIVER_IR_RAW)
+		kfifo_reset_out(&rcdev->rawir);
 
 	d->open++;
 
@@ -265,137 +229,6 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file)
 }
 EXPORT_SYMBOL(lirc_dev_fop_close);
 
-unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
-{
-	struct rc_dev *rcdev = file->private_data;
-	struct lirc_dev *d = rcdev->lirc_dev;
-	unsigned int ret;
-
-	if (!d->attached)
-		return POLLHUP | POLLERR;
-
-	if (d->buf) {
-		poll_wait(file, &d->buf->wait_poll, wait);
-
-		if (lirc_buffer_empty(d->buf))
-			ret = 0;
-		else
-			ret = POLLIN | POLLRDNORM;
-	} else {
-		ret = POLLERR;
-	}
-
-	dev_dbg(&d->dev, LOGHEAD "poll result = %d\n", d->name, d->minor, ret);
-
-	return ret;
-}
-EXPORT_SYMBOL(lirc_dev_fop_poll);
-
-ssize_t lirc_dev_fop_read(struct file *file,
-			  char __user *buffer,
-			  size_t length,
-			  loff_t *ppos)
-{
-	struct rc_dev *rcdev = file->private_data;
-	struct lirc_dev *d = rcdev->lirc_dev;
-	unsigned char *buf;
-	int ret, written = 0;
-	DECLARE_WAITQUEUE(wait, current);
-
-	buf = kzalloc(d->buf->chunk_size, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	dev_dbg(&d->dev, LOGHEAD "read called\n", d->name, d->minor);
-
-	ret = mutex_lock_interruptible(&d->mutex);
-	if (ret) {
-		kfree(buf);
-		return ret;
-	}
-
-	if (!d->attached) {
-		ret = -ENODEV;
-		goto out_locked;
-	}
-
-	if (rcdev->driver_type != RC_DRIVER_IR_RAW) {
-		ret = -EINVAL;
-		goto out_locked;
-	}
-
-	if (length % d->buf->chunk_size) {
-		ret = -EINVAL;
-		goto out_locked;
-	}
-
-	/*
-	 * we add ourselves to the task queue before buffer check
-	 * to avoid losing scan code (in case when queue is awaken somewhere
-	 * between while condition checking and scheduling)
-	 */
-	add_wait_queue(&d->buf->wait_poll, &wait);
-
-	/*
-	 * while we didn't provide 'length' bytes, device is opened in blocking
-	 * mode and 'copy_to_user' is happy, wait for data.
-	 */
-	while (written < length && ret == 0) {
-		if (lirc_buffer_empty(d->buf)) {
-			/* According to the read(2) man page, 'written' can be
-			 * returned as less than 'length', instead of blocking
-			 * again, returning -EWOULDBLOCK, or returning
-			 * -ERESTARTSYS
-			 */
-			if (written)
-				break;
-			if (file->f_flags & O_NONBLOCK) {
-				ret = -EWOULDBLOCK;
-				break;
-			}
-			if (signal_pending(current)) {
-				ret = -ERESTARTSYS;
-				break;
-			}
-
-			mutex_unlock(&d->mutex);
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule();
-			set_current_state(TASK_RUNNING);
-
-			ret = mutex_lock_interruptible(&d->mutex);
-			if (ret) {
-				remove_wait_queue(&d->buf->wait_poll, &wait);
-				goto out_unlocked;
-			}
-
-			if (!d->attached) {
-				ret = -ENODEV;
-				goto out_locked;
-			}
-		} else {
-			lirc_buffer_read(d->buf, buf);
-			ret = copy_to_user((void __user *)buffer+written, buf,
-					   d->buf->chunk_size);
-			if (!ret)
-				written += d->buf->chunk_size;
-			else
-				ret = -EFAULT;
-		}
-	}
-
-	remove_wait_queue(&d->buf->wait_poll, &wait);
-
-out_locked:
-	mutex_unlock(&d->mutex);
-
-out_unlocked:
-	kfree(buf);
-
-	return ret ? ret : written;
-}
-EXPORT_SYMBOL(lirc_dev_fop_read);
-
 int __init lirc_dev_init(void)
 {
 	int retval;
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index 86a3cf798775..14d3eb36672e 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -18,112 +18,11 @@
 #include <linux/device.h>
 #include <linux/cdev.h>
 
-struct lirc_buffer {
-	wait_queue_head_t wait_poll;
-	spinlock_t fifo_lock;
-	unsigned int chunk_size;
-	unsigned int size; /* in chunks */
-	/* Using chunks instead of bytes pretends to simplify boundary checking
-	 * And should allow for some performance fine tunning later */
-	struct kfifo fifo;
-};
-
-static inline void lirc_buffer_clear(struct lirc_buffer *buf)
-{
-	unsigned long flags;
-
-	if (kfifo_initialized(&buf->fifo)) {
-		spin_lock_irqsave(&buf->fifo_lock, flags);
-		kfifo_reset(&buf->fifo);
-		spin_unlock_irqrestore(&buf->fifo_lock, flags);
-	} else
-		WARN(1, "calling %s on an uninitialized lirc_buffer\n",
-		     __func__);
-}
-
-static inline int lirc_buffer_init(struct lirc_buffer *buf,
-				    unsigned int chunk_size,
-				    unsigned int size)
-{
-	int ret;
-
-	init_waitqueue_head(&buf->wait_poll);
-	spin_lock_init(&buf->fifo_lock);
-	buf->chunk_size = chunk_size;
-	buf->size = size;
-	ret = kfifo_alloc(&buf->fifo, size * chunk_size, GFP_KERNEL);
-
-	return ret;
-}
-
-static inline void lirc_buffer_free(struct lirc_buffer *buf)
-{
-	if (kfifo_initialized(&buf->fifo)) {
-		kfifo_free(&buf->fifo);
-	} else
-		WARN(1, "calling %s on an uninitialized lirc_buffer\n",
-		     __func__);
-}
-
-static inline int lirc_buffer_len(struct lirc_buffer *buf)
-{
-	int len;
-	unsigned long flags;
-
-	spin_lock_irqsave(&buf->fifo_lock, flags);
-	len = kfifo_len(&buf->fifo);
-	spin_unlock_irqrestore(&buf->fifo_lock, flags);
-
-	return len;
-}
-
-static inline int lirc_buffer_full(struct lirc_buffer *buf)
-{
-	return lirc_buffer_len(buf) == buf->size * buf->chunk_size;
-}
-
-static inline int lirc_buffer_empty(struct lirc_buffer *buf)
-{
-	return !lirc_buffer_len(buf);
-}
-
-static inline unsigned int lirc_buffer_read(struct lirc_buffer *buf,
-					    unsigned char *dest)
-{
-	unsigned int ret = 0;
-
-	if (lirc_buffer_len(buf) >= buf->chunk_size)
-		ret = kfifo_out_locked(&buf->fifo, dest, buf->chunk_size,
-				       &buf->fifo_lock);
-	return ret;
-
-}
-
-static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
-					     unsigned char *orig)
-{
-	unsigned int ret;
-
-	ret = kfifo_in_locked(&buf->fifo, orig, buf->chunk_size,
-			      &buf->fifo_lock);
-
-	return ret;
-}
-
 /**
  * struct lirc_dev - represents a LIRC device
  *
  * @name:		used for logging
  * @minor:		the minor device (/dev/lircX) number for the device
- * @buffer_size:	Number of FIFO buffers with @chunk_size size.
- *			Only used if @rbuf is NULL.
- * @chunk_size:		Size of each FIFO buffer.
- *			Only used if @rbuf is NULL.
- * @buf:		if %NULL, lirc_dev will allocate and manage the buffer,
- *			otherwise allocated by the caller which will
- *			have to write to the buffer by other means, like irq's
- *			(see also lirc_serial.c).
- * @buf_internal:	whether lirc_dev has allocated the read buffer or not
  * @rdev:		&struct rc_dev associated with the device
  * @fops:		&struct file_operations for the device
  * @owner:		the module owning this struct
@@ -137,11 +36,6 @@ struct lirc_dev {
 	char name[40];
 	unsigned int minor;
 
-	unsigned int buffer_size; /* in chunks holding one code each */
-	unsigned int chunk_size;
-	struct lirc_buffer *buf;
-	bool buf_internal;
-
 	struct rc_dev *rdev;
 	const struct file_operations *fops;
 	struct module *owner;
@@ -168,7 +62,4 @@ void lirc_unregister_device(struct lirc_dev *d);
  */
 int lirc_dev_fop_open(struct inode *inode, struct file *file);
 int lirc_dev_fop_close(struct inode *inode, struct file *file);
-unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait);
-ssize_t lirc_dev_fop_read(struct file *file, char __user *buffer, size_t length,
-			  loff_t *ppos);
 #endif
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 83aa5e423a13..d886ac56015b 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -123,6 +123,8 @@ enum rc_filter_type {
  * @gap_duration: duration of initial gap
  * @gap: true if we're in a gap
  * @send_timeout_reports: report timeouts in lirc raw IR.
+ * @rawir: queue for incoming raw IR
+ * @wait_poll: poll struct for lirc device
  * @send_mode: lirc mode for sending, either LIRC_MODE_SCANCODE or
  *	LIRC_MODE_PULSE
  * @change_protocol: allow changing the protocol used on hardware decoders
@@ -192,6 +194,8 @@ struct rc_dev {
 	u64				gap_duration;
 	bool				gap;
 	bool				send_timeout_reports;
+	DECLARE_KFIFO_PTR(rawir, unsigned int);
+	wait_queue_head_t		wait_poll;
 	u8				send_mode;
 #endif
 	int				(*change_protocol)(struct rc_dev *dev, u64 *rc_proto);
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 14/26] media: lirc: move lirc_dev->attached to rc_dev->registered
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (12 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 13/26] media: lirc: use kfifo rather than lirc_buffer for raw IR Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 15/26] media: lirc: do not call rc_close() on unregistered devices Sean Young
                   ` (12 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

This is done to further remove the lirc kernel api. Ensure that every
fops checks for this.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/ir-lirc-codec.c | 16 ++++++++++------
 drivers/media/rc/lirc_dev.c      |  4 +---
 drivers/media/rc/rc-main.c       |  8 ++++++++
 include/media/lirc_dev.h         |  2 --
 include/media/rc-core.h          |  3 +++
 5 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 7dc3fe8a5a96..60ff8f188e6f 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -101,6 +101,9 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 	unsigned int duration = 0; /* signal duration in us */
 	int i;
 
+	if (!dev->registered)
+		return -ENODEV;
+
 	start = ktime_get();
 
 	if (dev->send_mode == LIRC_MODE_SCANCODE) {
@@ -229,6 +232,9 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 			return ret;
 	}
 
+	if (!dev->registered)
+		return -ENODEV;
+
 	switch (cmd) {
 	case LIRC_GET_FEATURES:
 		if (dev->driver_type == RC_DRIVER_IR_RAW) {
@@ -417,12 +423,11 @@ static unsigned int ir_lirc_poll(struct file *file,
 				 struct poll_table_struct *wait)
 {
 	struct rc_dev *rcdev = file->private_data;
-	struct lirc_dev *d = rcdev->lirc_dev;
 	unsigned int events = 0;
 
 	poll_wait(file, &rcdev->wait_poll, wait);
 
-	if (!d->attached)
+	if (!rcdev->registered)
 		events = POLLHUP | POLLERR;
 	else if (rcdev->driver_type == RC_DRIVER_IR_RAW &&
 		 !kfifo_is_empty(&rcdev->rawir))
@@ -435,7 +440,6 @@ static ssize_t ir_lirc_read(struct file *file, char __user *buffer,
 			    size_t length, loff_t *ppos)
 {
 	struct rc_dev *rcdev = file->private_data;
-	struct lirc_dev *d = rcdev->lirc_dev;
 	unsigned int copied;
 	int ret;
 
@@ -445,7 +449,7 @@ static ssize_t ir_lirc_read(struct file *file, char __user *buffer,
 	if (length < sizeof(unsigned int) || length % sizeof(unsigned int))
 		return -EINVAL;
 
-	if (!d->attached)
+	if (!rcdev->registered)
 		return -ENODEV;
 
 	do {
@@ -455,12 +459,12 @@ static ssize_t ir_lirc_read(struct file *file, char __user *buffer,
 
 			ret = wait_event_interruptible(rcdev->wait_poll,
 					!kfifo_is_empty(&rcdev->rawir) ||
-					!d->attached);
+					!rcdev->registered);
 			if (ret)
 				return ret;
 		}
 
-		if (!d->attached)
+		if (!rcdev->registered)
 			return -ENODEV;
 
 		mutex_lock(&rcdev->lock);
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 9a0ad8d9a0cb..22171267aa90 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -122,7 +122,6 @@ int lirc_register_device(struct lirc_dev *d)
 
 	cdev_init(&d->cdev, d->fops);
 	d->cdev.owner = d->owner;
-	d->attached = true;
 
 	err = cdev_device_add(&d->cdev, &d->dev);
 	if (err) {
@@ -153,7 +152,6 @@ void lirc_unregister_device(struct lirc_dev *d)
 
 	mutex_lock(&d->mutex);
 
-	d->attached = false;
 	if (d->open) {
 		dev_dbg(&d->dev, LOGHEAD "releasing opened driver\n",
 			d->name, d->minor);
@@ -180,7 +178,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
 	if (retval)
 		return retval;
 
-	if (!d->attached) {
+	if (!rcdev->registered) {
 		retval = -ENODEV;
 		goto out;
 	}
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index ae1df089c96f..9e73899b5994 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1809,6 +1809,8 @@ int rc_register_device(struct rc_dev *dev)
 			goto out_lirc;
 	}
 
+	dev->registered = true;
+
 	IR_dprintk(1, "Registered rc%u (driver: %s)\n",
 		   dev->minor,
 		   dev->driver_name ? dev->driver_name : "unknown");
@@ -1871,6 +1873,12 @@ void rc_unregister_device(struct rc_dev *dev)
 
 	rc_free_rx_device(dev);
 
+	dev->registered = false;
+
+	/*
+	 * lirc device should be freed with dev->registered = false, so
+	 * that userspace polling will get notified.
+	 */
 	if (dev->driver_type != RC_DRIVER_SCANCODE)
 		ir_lirc_unregister(dev);
 
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index 14d3eb36672e..5782add67edd 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -26,7 +26,6 @@
  * @rdev:		&struct rc_dev associated with the device
  * @fops:		&struct file_operations for the device
  * @owner:		the module owning this struct
- * @attached:		if the device is still live
  * @open:		open count for the device's chardev
  * @mutex:		serialises file_operations calls
  * @dev:		&struct device assigned to the device
@@ -40,7 +39,6 @@ struct lirc_dev {
 	const struct file_operations *fops;
 	struct module *owner;
 
-	bool attached;
 	int open;
 
 	struct mutex mutex; /* protect from simultaneous accesses */
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index d886ac56015b..17131762fb75 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -127,6 +127,8 @@ enum rc_filter_type {
  * @wait_poll: poll struct for lirc device
  * @send_mode: lirc mode for sending, either LIRC_MODE_SCANCODE or
  *	LIRC_MODE_PULSE
+ * @registered: set to true by rc_register_device(), false by
+ *	rc_unregister_device
  * @change_protocol: allow changing the protocol used on hardware decoders
  * @open: callback to allow drivers to enable polling/irq when IR input device
  *	is opened.
@@ -198,6 +200,7 @@ struct rc_dev {
 	wait_queue_head_t		wait_poll;
 	u8				send_mode;
 #endif
+	bool				registered;
 	int				(*change_protocol)(struct rc_dev *dev, u64 *rc_proto);
 	int				(*open)(struct rc_dev *dev);
 	void				(*close)(struct rc_dev *dev);
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 15/26] media: lirc: do not call rc_close() on unregistered devices
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (13 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 14/26] media: lirc: move lirc_dev->attached to rc_dev->registered Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 16/26] media: lirc: create rc-core open and close lirc functions Sean Young
                   ` (11 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

If a lirc chardev is held open after a device is unplugged, rc_close()
will be called after rc_unregister_device(). The driver is not expecting
any calls at this point, and the iguanair driver causes an oops in
this scenario.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/rc-main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 9e73899b5994..9a8fc86b0835 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -885,7 +885,7 @@ void rc_close(struct rc_dev *rdev)
 	if (rdev) {
 		mutex_lock(&rdev->lock);
 
-		if (!--rdev->users && rdev->close != NULL)
+		if (!--rdev->users && rdev->close && rdev->registered)
 			rdev->close(rdev);
 
 		mutex_unlock(&rdev->lock);
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 16/26] media: lirc: create rc-core open and close lirc functions
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (14 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 15/26] media: lirc: do not call rc_close() on unregistered devices Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 17/26] media: lirc: remove name from lirc_dev Sean Young
                   ` (10 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

Replace the generic kernel lirc api with ones which use rc-core, further
reducing the lirc_dev members.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/ir-lirc-codec.c | 59 ++++++++++++++++++++++++++++++++--
 drivers/media/rc/lirc_dev.c      | 68 ++--------------------------------------
 include/media/lirc_dev.h         | 11 -------
 include/media/rc-core.h          |  2 ++
 4 files changed, 62 insertions(+), 78 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 60ff8f188e6f..f852ec231f4e 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -88,6 +88,61 @@ void ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev)
 	wake_up_poll(&dev->wait_poll, POLLIN | POLLRDNORM);
 }
 
+static int ir_lirc_open(struct inode *inode, struct file *file)
+{
+	struct lirc_dev *d = container_of(inode->i_cdev, struct lirc_dev, cdev);
+	struct rc_dev *dev = d->rdev;
+	int retval;
+
+	retval = rc_open(dev);
+	if (retval)
+		return retval;
+
+	retval = mutex_lock_interruptible(&dev->lock);
+	if (retval)
+		goto out_rc;
+
+	if (!dev->registered) {
+		retval = -ENODEV;
+		goto out_unlock;
+	}
+
+	if (dev->lirc_open) {
+		retval = -EBUSY;
+		goto out_unlock;
+	}
+
+	if (dev->driver_type == RC_DRIVER_IR_RAW)
+		kfifo_reset_out(&dev->rawir);
+
+	dev->lirc_open++;
+	file->private_data = dev;
+
+	nonseekable_open(inode, file);
+	mutex_unlock(&dev->lock);
+
+	return 0;
+
+out_unlock:
+	mutex_unlock(&dev->lock);
+out_rc:
+	rc_close(dev);
+	return retval;
+}
+
+static int ir_lirc_close(struct inode *inode, struct file *file)
+{
+	struct rc_dev *dev = file->private_data;
+
+	mutex_lock(&dev->lock);
+	dev->lirc_open--;
+	mutex_unlock(&dev->lock);
+
+	rc_close(dev);
+
+	return 0;
+}
+
 static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 				   size_t n, loff_t *ppos)
 {
@@ -486,8 +541,8 @@ static const struct file_operations lirc_fops = {
 #endif
 	.read		= ir_lirc_read,
 	.poll		= ir_lirc_poll,
-	.open		= lirc_dev_fop_open,
-	.release	= lirc_dev_fop_close,
+	.open		= ir_lirc_open,
+	.release	= ir_lirc_close,
 	.llseek		= no_llseek,
 };
 
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 22171267aa90..32124fb5c88e 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -61,7 +61,6 @@ lirc_allocate_device(void)
 
 	d = kzalloc(sizeof(*d), GFP_KERNEL);
 	if (d) {
-		mutex_init(&d->mutex);
 		device_initialize(&d->dev);
 		d->dev.class = lirc_class;
 		d->dev.release = lirc_release_device;
@@ -150,15 +149,15 @@ void lirc_unregister_device(struct lirc_dev *d)
 	dev_dbg(&d->dev, "lirc_dev: driver %s unregistered from minor = %d\n",
 		d->name, d->minor);
 
-	mutex_lock(&d->mutex);
+	mutex_lock(&rcdev->lock);
 
-	if (d->open) {
+	if (rcdev->lirc_open) {
 		dev_dbg(&d->dev, LOGHEAD "releasing opened driver\n",
 			d->name, d->minor);
 		wake_up_poll(&rcdev->wait_poll, POLLHUP);
 	}
 
-	mutex_unlock(&d->mutex);
+	mutex_unlock(&rcdev->lock);
 
 	cdev_device_del(&d->cdev, &d->dev);
 	ida_simple_remove(&lirc_ida, d->minor);
@@ -166,67 +165,6 @@ void lirc_unregister_device(struct lirc_dev *d)
 }
 EXPORT_SYMBOL(lirc_unregister_device);
 
-int lirc_dev_fop_open(struct inode *inode, struct file *file)
-{
-	struct lirc_dev *d = container_of(inode->i_cdev, struct lirc_dev, cdev);
-	struct rc_dev *rcdev = d->rdev;
-	int retval;
-
-	dev_dbg(&d->dev, LOGHEAD "open called\n", d->name, d->minor);
-
-	retval = mutex_lock_interruptible(&d->mutex);
-	if (retval)
-		return retval;
-
-	if (!rcdev->registered) {
-		retval = -ENODEV;
-		goto out;
-	}
-
-	if (d->open) {
-		retval = -EBUSY;
-		goto out;
-	}
-
-	if (d->rdev) {
-		retval = rc_open(d->rdev);
-		if (retval)
-			goto out;
-	}
-
-	if (rcdev->driver_type == RC_DRIVER_IR_RAW)
-		kfifo_reset_out(&rcdev->rawir);
-
-	d->open++;
-
-	file->private_data = d->rdev;
-	nonseekable_open(inode, file);
-	mutex_unlock(&d->mutex);
-
-	return 0;
-
-out:
-	mutex_unlock(&d->mutex);
-	return retval;
-}
-EXPORT_SYMBOL(lirc_dev_fop_open);
-
-int lirc_dev_fop_close(struct inode *inode, struct file *file)
-{
-	struct rc_dev *rcdev = file->private_data;
-	struct lirc_dev *d = rcdev->lirc_dev;
-
-	mutex_lock(&d->mutex);
-
-	rc_close(rcdev);
-	d->open--;
-
-	mutex_unlock(&d->mutex);
-
-	return 0;
-}
-EXPORT_SYMBOL(lirc_dev_fop_close);
-
 int __init lirc_dev_init(void)
 {
 	int retval;
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index 5782add67edd..b45af81b4633 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -26,8 +26,6 @@
  * @rdev:		&struct rc_dev associated with the device
  * @fops:		&struct file_operations for the device
  * @owner:		the module owning this struct
- * @open:		open count for the device's chardev
- * @mutex:		serialises file_operations calls
  * @dev:		&struct device assigned to the device
  * @cdev:		&struct cdev assigned to the device
  */
@@ -39,10 +37,6 @@ struct lirc_dev {
 	const struct file_operations *fops;
 	struct module *owner;
 
-	int open;
-
-	struct mutex mutex; /* protect from simultaneous accesses */
-
 	struct device dev;
 	struct cdev cdev;
 };
@@ -55,9 +49,4 @@ int lirc_register_device(struct lirc_dev *d);
 
 void lirc_unregister_device(struct lirc_dev *d);
 
-/* default file operations
- * used by drivers if they override only some operations
- */
-int lirc_dev_fop_open(struct inode *inode, struct file *file);
-int lirc_dev_fop_close(struct inode *inode, struct file *file);
 #endif
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 17131762fb75..f0ee1ba01a47 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -117,6 +117,7 @@ enum rc_filter_type {
  * @rx_resolution : resolution (in ns) of input sampler
  * @tx_resolution: resolution (in ns) of output sampler
  * @lirc_dev: lirc char device
+ * @lirc_open: count of the number of times the device has been opened
  * @carrier_low: when setting the carrier range, first the low end must be
  *	set with an ioctl and then the high end with another ioctl
  * @gap_start: time when gap starts
@@ -191,6 +192,7 @@ struct rc_dev {
 	u32				tx_resolution;
 #ifdef CONFIG_LIRC
 	struct lirc_dev			*lirc_dev;
+	int				lirc_open;
 	int				carrier_low;
 	ktime_t				gap_start;
 	u64				gap_duration;
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 17/26] media: lirc: remove name from lirc_dev
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (15 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 16/26] media: lirc: create rc-core open and close lirc functions Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 18/26] media: lirc: remove last remnants of lirc kapi Sean Young
                   ` (9 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

This is a duplicate of rcdev->driver_name.

Signed-off-by: Sean Young <sean@mess.org>
---
 Documentation/media/uapi/rc/lirc-dev-intro.rst | 2 +-
 drivers/media/rc/ir-lirc-codec.c               | 2 --
 drivers/media/rc/lirc_dev.c                    | 9 +++------
 include/media/lirc_dev.h                       | 2 --
 4 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/Documentation/media/uapi/rc/lirc-dev-intro.rst b/Documentation/media/uapi/rc/lirc-dev-intro.rst
index 3cacf9aeac40..a3fa3c1ef169 100644
--- a/Documentation/media/uapi/rc/lirc-dev-intro.rst
+++ b/Documentation/media/uapi/rc/lirc-dev-intro.rst
@@ -18,7 +18,7 @@ Example dmesg output upon a driver registering w/LIRC:
 
     $ dmesg |grep lirc_dev
     lirc_dev: IR Remote Control driver registered, major 248
-    rc rc0: lirc_dev: driver ir-lirc-codec (mceusb) registered at minor = 0
+    rc rc0: lirc_dev: driver mceusb registered at minor = 0
 
 What you should see for a chardev:
 
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index f852ec231f4e..4411a3d0a778 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -555,8 +555,6 @@ int ir_lirc_register(struct rc_dev *dev)
 	if (!ldev)
 		return rc;
 
-	snprintf(ldev->name, sizeof(ldev->name), "ir-lirc-codec (%s)",
-		 dev->driver_name);
 	ldev->fops = &lirc_fops;
 	ldev->dev.parent = &dev->dev;
 	ldev->rdev = dev;
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 32124fb5c88e..4ac74fd86fd4 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -101,9 +101,6 @@ int lirc_register_device(struct lirc_dev *d)
 		return -EINVAL;
 	}
 
-	/* some safety check 8-) */
-	d->name[sizeof(d->name) - 1] = '\0';
-
 	if (rcdev->driver_type == RC_DRIVER_IR_RAW) {
 		if (kfifo_alloc(&rcdev->rawir, MAX_IR_EVENT_SIZE, GFP_KERNEL))
 			return -ENOMEM;
@@ -131,7 +128,7 @@ int lirc_register_device(struct lirc_dev *d)
 	get_device(d->dev.parent);
 
 	dev_info(&d->dev, "lirc_dev: driver %s registered at minor = %d\n",
-		 d->name, d->minor);
+		 rcdev->driver_name, d->minor);
 
 	return 0;
 }
@@ -147,13 +144,13 @@ void lirc_unregister_device(struct lirc_dev *d)
 	rcdev = d->rdev;
 
 	dev_dbg(&d->dev, "lirc_dev: driver %s unregistered from minor = %d\n",
-		d->name, d->minor);
+		rcdev->driver_name, d->minor);
 
 	mutex_lock(&rcdev->lock);
 
 	if (rcdev->lirc_open) {
 		dev_dbg(&d->dev, LOGHEAD "releasing opened driver\n",
-			d->name, d->minor);
+			rcdev->driver_name, d->minor);
 		wake_up_poll(&rcdev->wait_poll, POLLHUP);
 	}
 
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index b45af81b4633..d12e1d1c3d67 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -21,7 +21,6 @@
 /**
  * struct lirc_dev - represents a LIRC device
  *
- * @name:		used for logging
  * @minor:		the minor device (/dev/lircX) number for the device
  * @rdev:		&struct rc_dev associated with the device
  * @fops:		&struct file_operations for the device
@@ -30,7 +29,6 @@
  * @cdev:		&struct cdev assigned to the device
  */
 struct lirc_dev {
-	char name[40];
 	unsigned int minor;
 
 	struct rc_dev *rdev;
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 18/26] media: lirc: remove last remnants of lirc kapi
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (16 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 17/26] media: lirc: remove name from lirc_dev Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 19/26] media: lirc: implement reading scancode Sean Young
                   ` (8 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

rc-core has replaced the lirc kapi many years ago, and now with the last
driver ported to rc-core, we can finally remove it.

Note this has no effect on userspace.

All future IR drivers should use the rc-core api.

Signed-off-by: Sean Young <sean@mess.org>
---
 Documentation/media/kapi/rc-core.rst |   5 --
 drivers/media/rc/ir-lirc-codec.c     |  45 +----------
 drivers/media/rc/lirc_dev.c          | 147 ++++++++++++-----------------------
 drivers/media/rc/rc-core-priv.h      |   3 +
 drivers/media/rc/rc-main.c           |   1 -
 include/media/lirc_dev.h             |  50 ------------
 include/media/rc-core.h              |   8 +-
 7 files changed, 63 insertions(+), 196 deletions(-)
 delete mode 100644 include/media/lirc_dev.h

diff --git a/Documentation/media/kapi/rc-core.rst b/Documentation/media/kapi/rc-core.rst
index a45895886257..41c2256dbf6a 100644
--- a/Documentation/media/kapi/rc-core.rst
+++ b/Documentation/media/kapi/rc-core.rst
@@ -7,8 +7,3 @@ Remote Controller core
 .. kernel-doc:: include/media/rc-core.h
 
 .. kernel-doc:: include/media/rc-map.h
-
-LIRC
-~~~~
-
-.. kernel-doc:: include/media/lirc_dev.h
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 4411a3d0a778..9127544883ed 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -12,10 +12,10 @@
  *  GNU General Public License for more details.
  */
 
+#include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <media/lirc.h>
-#include <media/lirc_dev.h>
 #include <media/rc-core.h>
 #include "rc-core-priv.h"
 
@@ -90,8 +90,8 @@ void ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev)
 
 static int ir_lirc_open(struct inode *inode, struct file *file)
 {
-	struct lirc_dev *d = container_of(inode->i_cdev, struct lirc_dev, cdev);
-	struct rc_dev *dev = d->rdev;
+	struct rc_dev *dev = container_of(inode->i_cdev, struct rc_dev,
+					  lirc_cdev);
 	int retval;
 
 	retval = rc_open(dev);
@@ -532,7 +532,7 @@ static ssize_t ir_lirc_read(struct file *file, char __user *buffer,
 	return copied;
 }
 
-static const struct file_operations lirc_fops = {
+const struct file_operations lirc_fops = {
 	.owner		= THIS_MODULE,
 	.write		= ir_lirc_transmit_ir,
 	.unlocked_ioctl	= ir_lirc_ioctl,
@@ -545,40 +545,3 @@ static const struct file_operations lirc_fops = {
 	.release	= ir_lirc_close,
 	.llseek		= no_llseek,
 };
-
-int ir_lirc_register(struct rc_dev *dev)
-{
-	struct lirc_dev *ldev;
-	int rc = -ENOMEM;
-
-	ldev = lirc_allocate_device();
-	if (!ldev)
-		return rc;
-
-	ldev->fops = &lirc_fops;
-	ldev->dev.parent = &dev->dev;
-	ldev->rdev = dev;
-	ldev->owner = THIS_MODULE;
-
-	rc = lirc_register_device(ldev);
-	if (rc < 0)
-		goto out;
-
-	if (dev->tx_scancode)
-		dev->send_mode = LIRC_MODE_SCANCODE;
-	else
-		dev->send_mode = LIRC_MODE_PULSE;
-
-	dev->lirc_dev = ldev;
-	return 0;
-
-out:
-	lirc_free_device(ldev);
-	return rc;
-}
-
-void ir_lirc_unregister(struct rc_dev *dev)
-{
-	lirc_unregister_device(dev->lirc_dev);
-	dev->lirc_dev = NULL;
-}
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 4ac74fd86fd4..217c1203c87b 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -18,24 +18,19 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
-#include <linux/sched/signal.h>
-#include <linux/ioctl.h>
-#include <linux/poll.h>
 #include <linux/mutex.h>
 #include <linux/device.h>
-#include <linux/cdev.h>
 #include <linux/idr.h>
+#include <linux/poll.h>
 
 #include "rc-core-priv.h"
 #include <media/lirc.h>
-#include <media/lirc_dev.h>
 
 #define LOGHEAD		"lirc_dev (%s[%d]): "
 
 static dev_t lirc_base_dev;
 
 /* Used to keep track of allocated lirc devices */
-#define LIRC_MAX_DEVICES 256
 static DEFINE_IDA(lirc_ida);
 
 /* Only used for sysfs but defined to void otherwise */
@@ -43,124 +38,84 @@ static struct class *lirc_class;
 
 static void lirc_release_device(struct device *ld)
 {
-	struct lirc_dev *d = container_of(ld, struct lirc_dev, dev);
-	struct rc_dev *rcdev = d->rdev;
+	struct rc_dev *rcdev = container_of(ld, struct rc_dev, lirc_dev);
 
 	if (rcdev->driver_type == RC_DRIVER_IR_RAW)
 		kfifo_free(&rcdev->rawir);
 
-	kfree(d);
-	module_put(THIS_MODULE);
-	put_device(d->dev.parent);
+	put_device(&rcdev->dev);
 }
 
-struct lirc_dev *
-lirc_allocate_device(void)
+int ir_lirc_register(struct rc_dev *dev)
 {
-	struct lirc_dev *d;
-
-	d = kzalloc(sizeof(*d), GFP_KERNEL);
-	if (d) {
-		device_initialize(&d->dev);
-		d->dev.class = lirc_class;
-		d->dev.release = lirc_release_device;
-		__module_get(THIS_MODULE);
-	}
+	int err, minor;
 
-	return d;
-}
-EXPORT_SYMBOL(lirc_allocate_device);
-
-void lirc_free_device(struct lirc_dev *d)
-{
-	if (!d)
-		return;
+	device_initialize(&dev->lirc_dev);
+	dev->lirc_dev.class = lirc_class;
+	dev->lirc_dev.release = lirc_release_device;
 
-	put_device(&d->dev);
-}
-EXPORT_SYMBOL(lirc_free_device);
-
-int lirc_register_device(struct lirc_dev *d)
-{
-	struct rc_dev *rcdev = d->rdev;
-	int minor;
-	int err;
-
-	if (!d) {
-		pr_err("driver pointer must be not NULL!\n");
-		return -EBADRQC;
-	}
+	if (dev->tx_scancode)
+		dev->send_mode = LIRC_MODE_SCANCODE;
+	else
+		dev->send_mode = LIRC_MODE_PULSE;
 
-	if (!d->dev.parent) {
-		pr_err("dev parent pointer not filled in!\n");
-		return -EINVAL;
-	}
-
-	if (!d->fops) {
-		pr_err("fops pointer not filled in!\n");
-		return -EINVAL;
-	}
-
-	if (rcdev->driver_type == RC_DRIVER_IR_RAW) {
-		if (kfifo_alloc(&rcdev->rawir, MAX_IR_EVENT_SIZE, GFP_KERNEL))
+	if (dev->driver_type == RC_DRIVER_IR_RAW) {
+		if (kfifo_alloc(&dev->rawir, MAX_IR_EVENT_SIZE, GFP_KERNEL))
 			return -ENOMEM;
 	}
 
-	init_waitqueue_head(&rcdev->wait_poll);
+	init_waitqueue_head(&dev->wait_poll);
 
-	minor = ida_simple_get(&lirc_ida, 0, LIRC_MAX_DEVICES, GFP_KERNEL);
-	if (minor < 0)
-		return minor;
+	minor = ida_simple_get(&lirc_ida, 0, RC_DEV_MAX, GFP_KERNEL);
+	if (minor < 0) {
+		err = minor;
+		goto out_kfifo;
+	}
 
-	d->minor = minor;
-	d->dev.devt = MKDEV(MAJOR(lirc_base_dev), d->minor);
-	dev_set_name(&d->dev, "lirc%d", d->minor);
+	dev->lirc_dev.parent = &dev->dev;
+	dev->lirc_dev.devt = MKDEV(MAJOR(lirc_base_dev), minor);
+	dev_set_name(&dev->lirc_dev, "lirc%d", minor);
 
-	cdev_init(&d->cdev, d->fops);
-	d->cdev.owner = d->owner;
+	cdev_init(&dev->lirc_cdev, &lirc_fops);
 
-	err = cdev_device_add(&d->cdev, &d->dev);
-	if (err) {
-		ida_simple_remove(&lirc_ida, minor);
-		return err;
-	}
+	err = cdev_device_add(&dev->lirc_cdev, &dev->lirc_dev);
+	if (err)
+		goto out_ida;
 
-	get_device(d->dev.parent);
+	get_device(&dev->dev);
 
-	dev_info(&d->dev, "lirc_dev: driver %s registered at minor = %d\n",
-		 rcdev->driver_name, d->minor);
+	dev_info(&dev->dev, "lirc_dev: driver %s registered at minor = %d",
+		 dev->driver_name, minor);
 
 	return 0;
+
+out_ida:
+	ida_simple_remove(&lirc_ida, minor);
+out_kfifo:
+	if (dev->driver_type == RC_DRIVER_IR_RAW)
+		kfifo_free(&dev->rawir);
+	return err;
 }
-EXPORT_SYMBOL(lirc_register_device);
 
-void lirc_unregister_device(struct lirc_dev *d)
+void ir_lirc_unregister(struct rc_dev *dev)
 {
-	struct rc_dev *rcdev;
-
-	if (!d)
-		return;
-
-	rcdev = d->rdev;
-
-	dev_dbg(&d->dev, "lirc_dev: driver %s unregistered from minor = %d\n",
-		rcdev->driver_name, d->minor);
+	dev_dbg(&dev->dev, "lirc_dev: driver %s unregistered from minor = %d\n",
+		dev->driver_name, MINOR(dev->lirc_dev.devt));
 
-	mutex_lock(&rcdev->lock);
+	mutex_lock(&dev->lock);
 
-	if (rcdev->lirc_open) {
-		dev_dbg(&d->dev, LOGHEAD "releasing opened driver\n",
-			rcdev->driver_name, d->minor);
-		wake_up_poll(&rcdev->wait_poll, POLLHUP);
+	if (dev->lirc_open) {
+		dev_dbg(&dev->dev, LOGHEAD "releasing opened driver\n",
+			dev->driver_name, MINOR(dev->lirc_dev.devt));
+		wake_up_poll(&dev->wait_poll, POLLHUP);
 	}
 
-	mutex_unlock(&rcdev->lock);
+	mutex_unlock(&dev->lock);
 
-	cdev_device_del(&d->cdev, &d->dev);
-	ida_simple_remove(&lirc_ida, d->minor);
-	put_device(&d->dev);
+	cdev_device_del(&dev->lirc_cdev, &dev->lirc_dev);
+	ida_simple_remove(&lirc_ida, MINOR(dev->lirc_dev.devt));
+	put_device(&dev->lirc_dev);
 }
-EXPORT_SYMBOL(lirc_unregister_device);
 
 int __init lirc_dev_init(void)
 {
@@ -172,7 +127,7 @@ int __init lirc_dev_init(void)
 		return PTR_ERR(lirc_class);
 	}
 
-	retval = alloc_chrdev_region(&lirc_base_dev, 0, LIRC_MAX_DEVICES,
+	retval = alloc_chrdev_region(&lirc_base_dev, 0, RC_DEV_MAX,
 				     "BaseRemoteCtl");
 	if (retval) {
 		class_destroy(lirc_class);
@@ -189,5 +144,5 @@ int __init lirc_dev_init(void)
 void __exit lirc_dev_exit(void)
 {
 	class_destroy(lirc_class);
-	unregister_chrdev_region(lirc_base_dev, LIRC_MAX_DEVICES);
+	unregister_chrdev_region(lirc_base_dev, RC_DEV_MAX);
 }
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index a064c401fa38..a8ca6d7ff551 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -16,6 +16,7 @@
 #ifndef _RC_CORE_PRIV
 #define _RC_CORE_PRIV
 
+#define	RC_DEV_MAX		256
 /* Define the max number of pulse/space transitions to buffer */
 #define	MAX_IR_EVENT_SIZE	512
 
@@ -287,6 +288,8 @@ void lirc_dev_exit(void);
 void ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev);
 int ir_lirc_register(struct rc_dev *dev);
 void ir_lirc_unregister(struct rc_dev *dev);
+
+extern const struct file_operations lirc_fops;
 #else
 static inline int lirc_dev_init(void) { return 0; }
 static inline void lirc_dev_exit(void) {}
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 9a8fc86b0835..e5027ac3c8fb 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -29,7 +29,6 @@
 /* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */
 #define IR_TAB_MIN_SIZE	256
 #define IR_TAB_MAX_SIZE	8192
-#define RC_DEV_MAX	256
 
 static const struct {
 	const char *name;
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
deleted file mode 100644
index d12e1d1c3d67..000000000000
--- a/include/media/lirc_dev.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * LIRC base driver
- *
- * by Artur Lipowski <alipowski@interia.pl>
- *        This code is licensed under GNU GPL
- *
- */
-
-#ifndef _LINUX_LIRC_DEV_H
-#define _LINUX_LIRC_DEV_H
-
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/ioctl.h>
-#include <linux/poll.h>
-#include <linux/kfifo.h>
-#include <media/lirc.h>
-#include <linux/device.h>
-#include <linux/cdev.h>
-
-/**
- * struct lirc_dev - represents a LIRC device
- *
- * @minor:		the minor device (/dev/lircX) number for the device
- * @rdev:		&struct rc_dev associated with the device
- * @fops:		&struct file_operations for the device
- * @owner:		the module owning this struct
- * @dev:		&struct device assigned to the device
- * @cdev:		&struct cdev assigned to the device
- */
-struct lirc_dev {
-	unsigned int minor;
-
-	struct rc_dev *rdev;
-	const struct file_operations *fops;
-	struct module *owner;
-
-	struct device dev;
-	struct cdev cdev;
-};
-
-struct lirc_dev *lirc_allocate_device(void);
-
-void lirc_free_device(struct lirc_dev *d);
-
-int lirc_register_device(struct lirc_dev *d);
-
-void lirc_unregister_device(struct lirc_dev *d);
-
-#endif
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index f0ee1ba01a47..e3db561a9bd7 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -17,10 +17,10 @@
 #define _RC_CORE
 
 #include <linux/spinlock.h>
+#include <linux/cdev.h>
 #include <linux/kfifo.h>
 #include <linux/time.h>
 #include <linux/timer.h>
-#include <media/lirc_dev.h>
 #include <media/rc-map.h>
 
 extern int rc_core_debug;
@@ -116,7 +116,8 @@ enum rc_filter_type {
  * @max_timeout: maximum timeout supported by device
  * @rx_resolution : resolution (in ns) of input sampler
  * @tx_resolution: resolution (in ns) of output sampler
- * @lirc_dev: lirc char device
+ * @lirc_dev: lirc device
+ * @lirc_cdev: lirc char cdev
  * @lirc_open: count of the number of times the device has been opened
  * @carrier_low: when setting the carrier range, first the low end must be
  *	set with an ioctl and then the high end with another ioctl
@@ -191,7 +192,8 @@ struct rc_dev {
 	u32				rx_resolution;
 	u32				tx_resolution;
 #ifdef CONFIG_LIRC
-	struct lirc_dev			*lirc_dev;
+	struct device			lirc_dev;
+	struct cdev			lirc_cdev;
 	int				lirc_open;
 	int				carrier_low;
 	ktime_t				gap_start;
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 19/26] media: lirc: implement reading scancode
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (17 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 18/26] media: lirc: remove last remnants of lirc kapi Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 20/26] media: rc: ensure lirc device receives nec repeats Sean Young
                   ` (7 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

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, keycode, toggle and repeat status in addition
to 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, &mode)) {
		// kernel too old or lirc does not support transmit
	}
	struct lirc_scancode scancode;
	while (read(fd, &scancode, 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);
}

Signed-off-by: Sean Young <sean@mess.org>
---
 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            |   7 +++
 include/media/rc-core.h               |   5 ++
 6 files changed, 120 insertions(+), 15 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 9127544883ed..92674bca8225 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(&dev->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
+ * @lsc		the 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(&dev->scancodes, *lsc))
+		wake_up_poll(&dev->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(&dev->rawir);
+	if (dev->driver_type != RC_DRIVER_IR_RAW_TX)
+		kfifo_reset_out(&dev->scancodes);
 
 	dev->lirc_open++;
 	file->private_data = dev;
@@ -293,7 +310,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;
 		}
@@ -331,15 +348,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:
@@ -482,31 +501,31 @@ static unsigned int ir_lirc_poll(struct file *file,
 
 	poll_wait(file, &rcdev->wait_poll, wait);
 
-	if (!rcdev->registered)
+	if (!rcdev->registered) {
 		events = POLLHUP | POLLERR;
-	else if (rcdev->driver_type == RC_DRIVER_IR_RAW &&
-		 !kfifo_is_empty(&rcdev->rawir))
-		events = POLLIN | POLLRDNORM;
+	} else if (rcdev->driver_type != RC_DRIVER_IR_RAW_TX) {
+		if (rcdev->rec_mode == LIRC_MODE_SCANCODE &&
+		    !kfifo_is_empty(&rcdev->scancodes))
+			events = POLLIN | POLLRDNORM;
+
+		if (rcdev->rec_mode == LIRC_MODE_MODE2 &&
+		    !kfifo_is_empty(&rcdev->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 = file->private_data;
 	unsigned int copied;
 	int ret;
 
-	if (rcdev->driver_type == RC_DRIVER_IR_RAW_TX)
-		return -EINVAL;
-
 	if (length < sizeof(unsigned int) || length % sizeof(unsigned int))
 		return -EINVAL;
 
-	if (!rcdev->registered)
-		return -ENODEV;
-
 	do {
 		if (kfifo_is_empty(&rcdev->rawir)) {
 			if (file->f_flags & O_NONBLOCK)
@@ -532,6 +551,59 @@ static ssize_t ir_lirc_read(struct file *file, char __user *buffer,
 	return copied;
 }
 
+static ssize_t ir_lirc_read_scancode(struct file *file, char __user *buffer,
+				     size_t length)
+{
+	struct rc_dev *rcdev = file->private_data;
+	unsigned int copied;
+	int ret;
+
+	if (length < sizeof(struct lirc_scancode) ||
+	    length % sizeof(struct lirc_scancode))
+		return -EINVAL;
+
+	do {
+		if (kfifo_is_empty(&rcdev->scancodes)) {
+			if (file->f_flags & O_NONBLOCK)
+				return -EAGAIN;
+
+			ret = wait_event_interruptible(rcdev->wait_poll,
+					!kfifo_is_empty(&rcdev->scancodes) ||
+					!rcdev->registered);
+			if (ret)
+				return ret;
+		}
+
+		if (!rcdev->registered)
+			return -ENODEV;
+
+		mutex_lock(&rcdev->lock);
+		ret = kfifo_to_user(&rcdev->scancodes, buffer, length, &copied);
+		mutex_unlock(&rcdev->lock);
+		if (ret)
+			return ret;
+	} while (copied == 0);
+
+	return copied;
+}
+
+static ssize_t ir_lirc_read(struct file *file, char __user *buffer,
+			    size_t length, loff_t *ppos)
+{
+	struct rc_dev *rcdev = file->private_data;
+
+	if (rcdev->driver_type == RC_DRIVER_IR_RAW_TX)
+		return -EINVAL;
+
+	if (!rcdev->registered)
+		return -ENODEV;
+
+	if (rcdev->rec_mode == LIRC_MODE_MODE2)
+		return ir_lirc_read_mode2(file, buffer, length);
+	else /* LIRC_MODE_SCANCODE */
+		return ir_lirc_read_scancode(file, buffer, length);
+}
+
 const struct file_operations lirc_fops = {
 	.owner		= THIS_MODULE,
 	.write		= ir_lirc_transmit_ir,
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 48eef43b0530..ba3e42d67893 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -215,6 +215,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	struct mce_kbd_dec *data = &dev->raw->mce_kbd;
 	u32 scancode;
 	unsigned long delay;
+	struct lirc_scancode lsc = {};
 
 	if (!is_timing_event(ev)) {
 		if (ev.reset)
@@ -326,18 +327,22 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
 			mod_timer(&data->rx_timeout, jiffies + delay);
 			/* Pass data to keyboard buffer parser */
 			ir_mce_kbd_process_keyboard_data(data->idev, scancode);
+			lsc.rc_proto = RC_PROTO_MCIR2_KBD;
 			break;
 		case MCIR2_MOUSE_NBITS:
 			scancode = data->body & 0x1fffff;
 			IR_dprintk(1, "mouse data 0x%06x\n", scancode);
 			/* Pass data to mouse buffer parser */
 			ir_mce_kbd_process_mouse_data(data->idev, scancode);
+			lsc.rc_proto = RC_PROTO_MCIR2_MSE;
 			break;
 		default:
 			IR_dprintk(1, "not keyboard or mouse data\n");
 			goto out;
 		}
 
+		lsc.scancode = scancode;
+		ir_lirc_scancode_event(dev, &lsc);
 		data->state = STATE_INACTIVE;
 		input_event(data->idev, EV_MSC, MSC_SCAN, scancode);
 		input_sync(data->idev);
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 217c1203c87b..35d6072b12b2 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -42,6 +42,8 @@ static void lirc_release_device(struct device *ld)
 
 	if (rcdev->driver_type == RC_DRIVER_IR_RAW)
 		kfifo_free(&rcdev->rawir);
+	if (rcdev->driver_type != RC_DRIVER_IR_RAW_TX)
+		kfifo_free(&rcdev->scancodes);
 
 	put_device(&rcdev->dev);
 }
@@ -59,11 +61,20 @@ int ir_lirc_register(struct rc_dev *dev)
 	else
 		dev->send_mode = LIRC_MODE_PULSE;
 
+	dev->rec_mode = LIRC_MODE_MODE2;
+
 	if (dev->driver_type == RC_DRIVER_IR_RAW) {
 		if (kfifo_alloc(&dev->rawir, MAX_IR_EVENT_SIZE, GFP_KERNEL))
 			return -ENOMEM;
 	}
 
+	if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
+		if (kfifo_alloc(&dev->scancodes, 32, GFP_KERNEL)) {
+			kfifo_free(&dev->rawir);
+			return -ENOMEM;
+		}
+	}
+
 	init_waitqueue_head(&dev->wait_poll);
 
 	minor = ida_simple_get(&lirc_ida, 0, RC_DEV_MAX, GFP_KERNEL);
@@ -94,6 +105,8 @@ int ir_lirc_register(struct rc_dev *dev)
 out_kfifo:
 	if (dev->driver_type == RC_DRIVER_IR_RAW)
 		kfifo_free(&dev->rawir);
+	if (dev->driver_type != RC_DRIVER_IR_RAW_TX)
+		kfifo_free(&dev->scancodes);
 	return err;
 }
 
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index a8ca6d7ff551..950de264666f 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -286,6 +286,7 @@ void ir_raw_init(void);
 int lirc_dev_init(void);
 void lirc_dev_exit(void);
 void ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev);
+void ir_lirc_scancode_event(struct rc_dev *dev, struct lirc_scancode *lsc);
 int ir_lirc_register(struct rc_dev *dev);
 void ir_lirc_unregister(struct rc_dev *dev);
 
@@ -295,6 +296,8 @@ static inline int lirc_dev_init(void) { return 0; }
 static inline void lirc_dev_exit(void) {}
 static inline void ir_lirc_raw_event(struct rc_dev *dev,
 				     struct ir_raw_event ev) { }
+static inline void ir_lirc_scancode_event(struct rc_dev *dev,
+					  struct lirc_scancode *lsc) { }
 static inline int ir_lirc_register(struct rc_dev *dev) { return 0; }
 static inline void ir_lirc_unregister(struct rc_dev *dev) { }
 #endif
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index e5027ac3c8fb..e9d6ce024cd2 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -697,6 +697,13 @@ static void ir_do_keydown(struct rc_dev *dev, enum rc_proto protocol,
 			  dev->last_protocol != protocol ||
 			  dev->last_scancode != scancode ||
 			  dev->last_toggle   != toggle);
+	struct lirc_scancode sc = {
+		.scancode = scancode, .rc_proto = protocol,
+		.flags = toggle ? LIRC_SCANCODE_FLAG_TOGGLE : 0,
+		.keycode = keycode
+	};
+
+	ir_lirc_scancode_event(dev, &sc);
 
 	if (new_event && dev->keypressed)
 		ir_do_keyup(dev, false);
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index e3db561a9bd7..82e5a8ffd5b9 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -126,9 +126,12 @@ enum rc_filter_type {
  * @gap: true if we're in a gap
  * @send_timeout_reports: report timeouts in lirc raw IR.
  * @rawir: queue for incoming raw IR
+ * @scancodes: queue for incoming decoded scancodes
  * @wait_poll: poll struct for lirc device
  * @send_mode: lirc mode for sending, either LIRC_MODE_SCANCODE or
  *	LIRC_MODE_PULSE
+ * @rec_mode: lirc mode for receiving, either LIRC_MODE_SCANCODE or
+ *	LIRC_MODE_MODE2
  * @registered: set to true by rc_register_device(), false by
  *	rc_unregister_device
  * @change_protocol: allow changing the protocol used on hardware decoders
@@ -201,8 +204,10 @@ struct rc_dev {
 	bool				gap;
 	bool				send_timeout_reports;
 	DECLARE_KFIFO_PTR(rawir, unsigned int);
+	DECLARE_KFIFO_PTR(scancodes, struct lirc_scancode);
 	wait_queue_head_t		wait_poll;
 	u8				send_mode;
+	u8				rec_mode;
 #endif
 	bool				registered;
 	int				(*change_protocol)(struct rc_dev *dev, u64 *rc_proto);
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 20/26] media: rc: ensure lirc device receives nec repeats
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (18 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 19/26] media: lirc: implement reading scancode Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 21/26] media: lirc: document LIRC_MODE_SCANCODE Sean Young
                   ` (6 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

The lirc device should get lirc repeats whether there is a keymap
match or not.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/rc-main.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index e9d6ce024cd2..dae427e25d71 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -662,19 +662,25 @@ void rc_repeat(struct rc_dev *dev)
 {
 	unsigned long flags;
 	unsigned int timeout = protocols[dev->last_protocol].repeat_period;
+	struct lirc_scancode sc = {
+		.scancode = dev->last_scancode, .rc_proto = dev->last_protocol,
+		.keycode = dev->keypressed ? dev->last_keycode : KEY_RESERVED,
+		.flags = LIRC_SCANCODE_FLAG_REPEAT |
+			 (dev->last_toggle ? LIRC_SCANCODE_FLAG_TOGGLE : 0)
+	};
 
-	spin_lock_irqsave(&dev->keylock, flags);
+	ir_lirc_scancode_event(dev, &sc);
 
-	if (!dev->keypressed)
-		goto out;
+	spin_lock_irqsave(&dev->keylock, flags);
 
 	input_event(dev->input_dev, EV_MSC, MSC_SCAN, dev->last_scancode);
 	input_sync(dev->input_dev);
 
-	dev->keyup_jiffies = jiffies + msecs_to_jiffies(timeout);
-	mod_timer(&dev->timer_keyup, dev->keyup_jiffies);
+	if (dev->keypressed) {
+		dev->keyup_jiffies = jiffies + msecs_to_jiffies(timeout);
+		mod_timer(&dev->timer_keyup, dev->keyup_jiffies);
+	}
 
-out:
 	spin_unlock_irqrestore(&dev->keylock, flags);
 }
 EXPORT_SYMBOL_GPL(rc_repeat);
@@ -710,13 +716,14 @@ static void ir_do_keydown(struct rc_dev *dev, enum rc_proto protocol,
 
 	input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode);
 
+	dev->last_protocol = protocol;
+	dev->last_scancode = scancode;
+	dev->last_toggle = toggle;
+	dev->last_keycode = keycode;
+
 	if (new_event && keycode != KEY_RESERVED) {
 		/* Register a keypress */
 		dev->keypressed = true;
-		dev->last_protocol = protocol;
-		dev->last_scancode = scancode;
-		dev->last_toggle = toggle;
-		dev->last_keycode = keycode;
 
 		IR_dprintk(1, "%s: key down event, key 0x%04x, protocol 0x%04x, scancode 0x%08x\n",
 			   dev->device_name, keycode, protocol, scancode);
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 21/26] media: lirc: document LIRC_MODE_SCANCODE
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (19 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 20/26] media: rc: ensure lirc device receives nec repeats Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 22/26] media: lirc: introduce LIRC_SET_POLL_MODES Sean Young
                   ` (5 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

Lirc supports a new mode which requires documentation.

Signed-off-by: Sean Young <sean@mess.org>
---
 Documentation/media/lirc.h.rst.exceptions          | 26 +++++++++++
 Documentation/media/uapi/rc/lirc-dev-intro.rst     | 51 +++++++++++++++++++---
 Documentation/media/uapi/rc/lirc-get-features.rst  | 16 +++++++
 Documentation/media/uapi/rc/lirc-get-rec-mode.rst  |  3 +-
 Documentation/media/uapi/rc/lirc-get-send-mode.rst |  3 +-
 Documentation/media/uapi/rc/lirc-read.rst          | 15 +++++--
 Documentation/media/uapi/rc/lirc-write.rst         | 19 ++++++--
 7 files changed, 118 insertions(+), 15 deletions(-)

diff --git a/Documentation/media/lirc.h.rst.exceptions b/Documentation/media/lirc.h.rst.exceptions
index 63ba1d341905..c6e3a35d2c4e 100644
--- a/Documentation/media/lirc.h.rst.exceptions
+++ b/Documentation/media/lirc.h.rst.exceptions
@@ -32,6 +32,32 @@ ignore define LIRC_CAN_SET_REC_DUTY_CYCLE
 
 ignore ioctl LIRC_GET_LENGTH
 
+# rc protocols
+
+ignore symbol RC_PROTO_UNKNOWN
+ignore symbol RC_PROTO_OTHER
+ignore symbol RC_PROTO_RC5
+ignore symbol RC_PROTO_RC5X_20
+ignore symbol RC_PROTO_RC5_SZ
+ignore symbol RC_PROTO_JVC
+ignore symbol RC_PROTO_SONY12
+ignore symbol RC_PROTO_SONY15
+ignore symbol RC_PROTO_SONY20
+ignore symbol RC_PROTO_NEC
+ignore symbol RC_PROTO_NECX
+ignore symbol RC_PROTO_NEC32
+ignore symbol RC_PROTO_SANYO
+ignore symbol RC_PROTO_MCIR2_KBD
+ignore symbol RC_PROTO_MCIR2_MSE
+ignore symbol RC_PROTO_RC6_0
+ignore symbol RC_PROTO_RC6_6A_20
+ignore symbol RC_PROTO_RC6_6A_24
+ignore symbol RC_PROTO_RC6_6A_32
+ignore symbol RC_PROTO_RC6_MCE
+ignore symbol RC_PROTO_SHARP
+ignore symbol RC_PROTO_XMP
+ignore symbol RC_PROTO_CEC
+
 # Undocumented macros
 
 ignore define PULSE_BIT
diff --git a/Documentation/media/uapi/rc/lirc-dev-intro.rst b/Documentation/media/uapi/rc/lirc-dev-intro.rst
index a3fa3c1ef169..47c6c218e72a 100644
--- a/Documentation/media/uapi/rc/lirc-dev-intro.rst
+++ b/Documentation/media/uapi/rc/lirc-dev-intro.rst
@@ -6,11 +6,12 @@
 Introduction
 ************
 
-The LIRC device interface is a bi-directional interface for transporting
-raw IR data between userspace and kernelspace. Fundamentally, it is just
-a chardev (/dev/lircX, for X = 0, 1, 2, ...), with a number of standard
-struct file_operations defined on it. With respect to transporting raw
-IR data to and fro, the essential fops are read, write and ioctl.
+LIRC stands for Linux Infrared Remote Control. The LIRC device interface is
+a bi-directional interface for transporting raw IR and decoded scancodes
+data between userspace and kernelspace. Fundamentally, it is just a chardev
+(/dev/lircX, for X = 0, 1, 2, ...), with a number of standard struct
+file_operations defined on it. With respect to transporting raw IR and
+decoded scancodes to and fro, the essential fops are read, write and ioctl.
 
 Example dmesg output upon a driver registering w/LIRC:
 
@@ -36,6 +37,46 @@ LIRC modes
 LIRC supports some modes of receiving and sending IR codes, as shown
 on the following table.
 
+.. _lirc-mode-scancode:
+.. _lirc-scancode-flag-toggle:
+.. _lirc-scancode-flag-repeat:
+
+``LIRC_MODE_SCANCODE``
+
+    This mode is for both sending and receiving IR.
+
+    For transmitting (aka sending), create a ``struct lirc_scancode`` with
+    the desired scancode set in the ``scancode`` member, ``rc_proto`` set
+    the IR protocol, and all other members set to 0. Write this struct to
+    the lirc device.
+
+    For receiving, you read ``struct lirc_scancode`` from the lirc device,
+    with ``scancode`` set to the received scancode and the IR protocol
+    ``rc_proto``. If the scancode maps to a valid key code, this is set
+    in the ``keycode`` field, else it is set to ``KEY_RESERVED``.
+
+    The ``flags`` can have ``LIRC_SCANCODE_FLAG_TOGGLE`` set if the toggle
+    bit is set in protocols that support it (e.g. rc-5 and rc-6), or
+    ``LIRC_SCANCODE_FLAG_REPEAT`` for when a repeat is received for protocols
+    that support it (e.g. nec).
+
+    In the Sanyo and NEC protocol, if you hold a button on remote, rather than
+    repeating the entire scancode, the remote sends a shorter message with
+    no scancode, which just means button is held, a "repeat". When this is
+    received, the ``LIRC_SCANCODE_FLAG_REPEAT`` is set and the scancode and
+    keycode is repeated.
+
+    With nec, there is no way to distinguish "button hold" from "repeatedly
+    pressing the same button". The rc-5 and rc-6 protocols have a toggle bit.
+    When a button is released and pressed again, the toggle bit is inverted.
+    If the toggle bit is set, the ``LIRC_SCANCODE_FLAG_TOGGLE`` is set.
+
+    The ``timestamp`` field is filled with the time nanoseconds
+    (in ``CLOCK_MONOTONIC``) when the scancode was decoded.
+
+    An ``enum rc_proto`` in the :ref:`lirc_header` lists all the supported
+    IR protocols.
+
 .. _lirc-mode-mode2:
 
 ``LIRC_MODE_MODE2``
diff --git a/Documentation/media/uapi/rc/lirc-get-features.rst b/Documentation/media/uapi/rc/lirc-get-features.rst
index 50c2c26d8e89..3ee44067de63 100644
--- a/Documentation/media/uapi/rc/lirc-get-features.rst
+++ b/Documentation/media/uapi/rc/lirc-get-features.rst
@@ -64,6 +64,14 @@ LIRC features
 
     Unused. Kept just to avoid breaking uAPI.
 
+.. _LIRC-CAN-REC-SCANCODE:
+
+``LIRC_CAN_REC_SCANCODE``
+
+    The driver is capable of receiving using
+    :ref:`LIRC_MODE_SCANCODE <lirc-mode-SCANCODE>`.
+
+
 .. _LIRC-CAN-SET-SEND-CARRIER:
 
 ``LIRC_CAN_SET_SEND_CARRIER``
@@ -171,6 +179,14 @@ LIRC features
 
     Unused. Kept just to avoid breaking uAPI.
 
+.. _LIRC-CAN-SEND-SCANCODE:
+
+``LIRC_CAN_SEND_SCANCODE``
+
+    The driver supports sending (also called as IR blasting or IR TX) using
+    :ref:`LIRC_MODE_SCANCODE <lirc-mode-SCANCODE>`.
+
+
 Return Value
 ============
 
diff --git a/Documentation/media/uapi/rc/lirc-get-rec-mode.rst b/Documentation/media/uapi/rc/lirc-get-rec-mode.rst
index b89de9add921..34919feaf392 100644
--- a/Documentation/media/uapi/rc/lirc-get-rec-mode.rst
+++ b/Documentation/media/uapi/rc/lirc-get-rec-mode.rst
@@ -34,7 +34,8 @@ Description
 ===========
 
 Get/set supported receive modes. Only :ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>`
-is supported for IR receive.
+and :ref:`LIRC_MODE_SCANCODE <lirc-mode-scancode>` are supported.
+Use :ref:`lirc_get_features` to find out which modes the driver supports.
 
 Return Value
 ============
diff --git a/Documentation/media/uapi/rc/lirc-get-send-mode.rst b/Documentation/media/uapi/rc/lirc-get-send-mode.rst
index e686b21689a0..e39383f08e21 100644
--- a/Documentation/media/uapi/rc/lirc-get-send-mode.rst
+++ b/Documentation/media/uapi/rc/lirc-get-send-mode.rst
@@ -36,7 +36,8 @@ Description
 
 Get/set current transmit mode.
 
-Only :ref:`LIRC_MODE_PULSE <lirc-mode-pulse>` is supported by for IR send,
+Only :ref:`LIRC_MODE_PULSE <lirc-mode-pulse>` and
+:ref:`LIRC_MODE_SCANCODE <lirc-mode-scancode>` are supported by for IR send,
 depending on the driver. Use :ref:`lirc_get_features` to find out which
 modes the driver supports.
 
diff --git a/Documentation/media/uapi/rc/lirc-read.rst b/Documentation/media/uapi/rc/lirc-read.rst
index ff14a69104e5..51d37ed10194 100644
--- a/Documentation/media/uapi/rc/lirc-read.rst
+++ b/Documentation/media/uapi/rc/lirc-read.rst
@@ -45,13 +45,20 @@ descriptor ``fd`` into the buffer starting at ``buf``.  If ``count`` is zero,
 is greater than ``SSIZE_MAX``, the result is unspecified.
 
 The exact format of the data depends on what :ref:`lirc_modes` a driver
-uses. Use :ref:`lirc_get_features` to get the supported mode.
+uses. Use :ref:`lirc_get_features` to get the supported mode, and use
+:ref:`lirc_set_rec_mode` set the current active mode.
 
-The generally preferred mode for receive is
-:ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>`,
-in which packets containing an int value describing an IR signal are
+The mode :ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>` is for raw IR,
+in which packets containing an unsigned int value describing an IR signal are
 read from the chardev.
 
+Alternatively, :ref:`LIRC_MODE_SCANCODE <lirc-mode-scancode>` can be available,
+in this mode scancodes which are either decoded by software decoders, or
+by hardware decoders. The ``rc_proto`` member is set to the
+protocol used for transmission, and ``scancode`` to the decoded scancode,
+and the ``keycode`` set to the keycode or ``KEY_RESERVED``.
+
+
 Return Value
 ============
 
diff --git a/Documentation/media/uapi/rc/lirc-write.rst b/Documentation/media/uapi/rc/lirc-write.rst
index 2aad0fef4a5b..3d7541bad8b9 100644
--- a/Documentation/media/uapi/rc/lirc-write.rst
+++ b/Documentation/media/uapi/rc/lirc-write.rst
@@ -42,21 +42,32 @@ Description
 referenced by the file descriptor ``fd`` from the buffer starting at
 ``buf``.
 
-The exact format of the data depends on what mode a driver uses, use
-:ref:`lirc_get_features` to get the supported mode.
+The exact format of the data depends on what mode a driver is in, use
+:ref:`lirc_get_features` to get the supported modes and use
+:ref:`lirc_set_send_mode` set the mode.
 
 When in :ref:`LIRC_MODE_PULSE <lirc-mode-PULSE>` mode, the data written to
 the chardev is a pulse/space sequence of integer values. Pulses and spaces
 are only marked implicitly by their position. The data must start and end
 with a pulse, therefore, the data must always include an uneven number of
-samples. The write function must block until the data has been transmitted
+samples. The write function blocks until the data has been transmitted
 by the hardware. If more data is provided than the hardware can send, the
 driver returns ``EINVAL``.
 
+When in :ref:`LIRC_MODE_SCANCODE <lirc-mode-scancode>` mode, one
+``struct lirc_scancode`` must be written to the chardev at a time, else
+``EINVAL`` is returned. Set the desired scancode in the ``scancode`` member,
+and the protocol in the ``rc_proto`` member. All other members must be set
+to 0, else ``EINVAL`` is returned. If there is no protocol encoder
+for the protocol or the scancode is not valid for the specified protocol,
+``EINVAL`` is returned. The write function may not wait until the scancode
+is transmitted.
+
+
 Return Value
 ============
 
-On success, the number of bytes read is returned. It is not an error if
+On success, the number of bytes written is returned. It is not an error if
 this number is smaller than the number of bytes requested, or the amount
 of data required for one frame.  On error, -1 is returned, and the ``errno``
 variable is set appropriately. The generic error codes are described at the
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 22/26] media: lirc: introduce LIRC_SET_POLL_MODES
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (20 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 21/26] media: lirc: document LIRC_MODE_SCANCODE Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 23/26] media: lirc: scancode rc devices should have a lirc device too Sean Young
                   ` (4 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

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_MODES, &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_proto, 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 +
 .../media/uapi/rc/lirc-set-poll-modes.rst          | 52 ++++++++++++++++++++++
 drivers/media/rc/ir-lirc-codec.c                   | 19 ++++++--
 drivers/media/rc/lirc_dev.c                        |  1 +
 include/media/rc-core.h                            |  3 ++
 include/uapi/linux/lirc.h                          |  9 ++++
 6 files changed, 81 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/media/uapi/rc/lirc-set-poll-modes.rst

diff --git a/Documentation/media/uapi/rc/lirc-func.rst b/Documentation/media/uapi/rc/lirc-func.rst
index ddb4620de294..6493430aabef 100644
--- a/Documentation/media/uapi/rc/lirc-func.rst
+++ b/Documentation/media/uapi/rc/lirc-func.rst
@@ -25,3 +25,4 @@ LIRC Function Reference
     lirc-set-rec-timeout-reports
     lirc-set-measure-carrier-mode
     lirc-set-wideband-receiver
+    lirc-set-poll-modes
diff --git a/Documentation/media/uapi/rc/lirc-set-poll-modes.rst b/Documentation/media/uapi/rc/lirc-set-poll-modes.rst
new file mode 100644
index 000000000000..2ae08dcd86ea
--- /dev/null
+++ b/Documentation/media/uapi/rc/lirc-set-poll-modes.rst
@@ -0,0 +1,52 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _lirc_set_poll_modes:
+
+**********************************************
+ioctls LIRC_SET_POLL_MODES
+**********************************************
+
+Name
+====
+
+LIRC_SET_POLL_MODES - Set LIRC modes to use for poll
+
+Synopsis
+========
+
+.. c:function:: int ioctl( int fd, LIRC_SET_POLL_MODES, __u32 modes)
+	:name: LIRC_SET_POLL_MODES
+
+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. Poll
+can report read readiness for both modes if you bitwise or them together.
+Use :ref:`lirc_get_features` to find out which modes the driver supports.
+
+This ioctl is useful when you want to read both raw IR and decoded
+scancodes. You can set :ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>` and
+poll for raw IR for some time, and then set
+:ref:`LIRC_MODE_SCANCODE <lirc-mode-scancode>` and poll for decoded
+scancodes, and repeat both modes again. Using this ioctl, you can poll
+for both without having to wait for a limited period in each mode.
+
+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 92674bca8225..559a4049151e 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -359,6 +359,17 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 			return -EINVAL;
 
 		dev->rec_mode = val;
+		dev->poll_mode = val;
+		return 0;
+
+	case LIRC_SET_POLL_MODES:
+		if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
+			return -ENOTTY;
+
+		if (val & ~(LIRC_MODE_MODE2 | LIRC_MODE_SCANCODE))
+			return -EINVAL;
+
+		dev->poll_mode = val;
 		return 0;
 
 	case LIRC_GET_SEND_MODE:
@@ -504,13 +515,13 @@ static unsigned int ir_lirc_poll(struct file *file,
 	if (!rcdev->registered) {
 		events = POLLHUP | POLLERR;
 	} else if (rcdev->driver_type != RC_DRIVER_IR_RAW_TX) {
-		if (rcdev->rec_mode == LIRC_MODE_SCANCODE &&
+		if ((rcdev->poll_mode & LIRC_MODE_SCANCODE) &&
 		    !kfifo_is_empty(&rcdev->scancodes))
-			events = POLLIN | POLLRDNORM;
+			events |= POLLIN | POLLRDNORM;
 
-		if (rcdev->rec_mode == LIRC_MODE_MODE2 &&
+		if ((rcdev->poll_mode & LIRC_MODE_MODE2) &&
 		    !kfifo_is_empty(&rcdev->rawir))
-			events = POLLIN | POLLRDNORM;
+			events |= POLLIN | POLLRDNORM;
 	}
 
 	return events;
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 35d6072b12b2..aee7cbb04439 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -62,6 +62,7 @@ int ir_lirc_register(struct rc_dev *dev)
 		dev->send_mode = LIRC_MODE_PULSE;
 
 	dev->rec_mode = LIRC_MODE_MODE2;
+	dev->poll_mode = LIRC_MODE_MODE2;
 
 	if (dev->driver_type == RC_DRIVER_IR_RAW) {
 		if (kfifo_alloc(&dev->rawir, MAX_IR_EVENT_SIZE, GFP_KERNEL))
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 82e5a8ffd5b9..3c9126e401c5 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -132,6 +132,8 @@ enum rc_filter_type {
  *	LIRC_MODE_PULSE
  * @rec_mode: lirc mode for receiving, either LIRC_MODE_SCANCODE or
  *	LIRC_MODE_MODE2
+ * @poll_mode: lirc mode used for polling, can poll for both LIRC_MODE_SCANCODE
+ *	and LIRC_MODE_MODE2
  * @registered: set to true by rc_register_device(), false by
  *	rc_unregister_device
  * @change_protocol: allow changing the protocol used on hardware decoders
@@ -208,6 +210,7 @@ struct rc_dev {
 	wait_queue_head_t		wait_poll;
 	u8				send_mode;
 	u8				rec_mode;
+	u8				poll_mode;
 #endif
 	bool				registered;
 	int				(*change_protocol)(struct rc_dev *dev, u64 *rc_proto);
diff --git a/include/uapi/linux/lirc.h b/include/uapi/linux/lirc.h
index fed779546017..5297e96d5469 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_MODES	       _IOW('i', 0x00000024, __u32)
+
+/*
  * struct lirc_scancode - decoded scancode with protocol for use with
  *	LIRC_MODE_SCANCODE
  *
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 23/26] media: lirc: scancode rc devices should have a lirc device too
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (21 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 22/26] media: lirc: introduce LIRC_SET_POLL_MODES Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 24/26] media: MAINTAINERS: remove lirc staging area Sean Young
                   ` (3 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

Now that the lirc interface supports scancodes, RC scancode devices
can also have a lirc device. The only feature they will have
enabled is LIRC_CAN_REC_SCANCODE.

Note that CEC devices have no lirc device, since they can be controlled
from their /dev/cecN chardev.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/ir-lirc-codec.c | 34 ++++++++++++++++++++++++++--------
 drivers/media/rc/lirc_dev.c      |  9 +++++++--
 drivers/media/rc/rc-main.c       |  6 +++---
 3 files changed, 36 insertions(+), 13 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 559a4049151e..6f1d9dd766d5 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -309,6 +309,9 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 
 	switch (cmd) {
 	case LIRC_GET_FEATURES:
+		if (dev->driver_type == RC_DRIVER_SCANCODE)
+			val |= LIRC_CAN_REC_SCANCODE;
+
 		if (dev->driver_type == RC_DRIVER_IR_RAW) {
 			val |= LIRC_CAN_REC_MODE2 | LIRC_CAN_REC_SCANCODE;
 			if (dev->rx_resolution)
@@ -352,22 +355,37 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		break;
 
 	case LIRC_SET_REC_MODE:
-		if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
+		switch (dev->driver_type) {
+		case RC_DRIVER_IR_RAW_TX:
 			return -ENOTTY;
-
-		if (!(val == LIRC_MODE_MODE2 || val == LIRC_MODE_SCANCODE))
-			return -EINVAL;
+		case RC_DRIVER_SCANCODE:
+			if (val != LIRC_MODE_SCANCODE)
+				return -EINVAL;
+			break;
+		case RC_DRIVER_IR_RAW:
+			if (!(val == LIRC_MODE_MODE2 ||
+			      val == LIRC_MODE_SCANCODE))
+				return -EINVAL;
+			break;
+		}
 
 		dev->rec_mode = val;
 		dev->poll_mode = val;
 		return 0;
 
 	case LIRC_SET_POLL_MODES:
-		if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
+		switch (dev->driver_type) {
+		case RC_DRIVER_IR_RAW_TX:
 			return -ENOTTY;
-
-		if (val & ~(LIRC_MODE_MODE2 | LIRC_MODE_SCANCODE))
-			return -EINVAL;
+		case RC_DRIVER_SCANCODE:
+			if (val != LIRC_MODE_SCANCODE)
+				return -EINVAL;
+			break;
+		case RC_DRIVER_IR_RAW:
+			if (val & ~(LIRC_MODE_MODE2 | LIRC_MODE_SCANCODE))
+				return -EINVAL;
+			break;
+		}
 
 		dev->poll_mode = val;
 		return 0;
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index aee7cbb04439..6fc1ec257153 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -61,8 +61,13 @@ int ir_lirc_register(struct rc_dev *dev)
 	else
 		dev->send_mode = LIRC_MODE_PULSE;
 
-	dev->rec_mode = LIRC_MODE_MODE2;
-	dev->poll_mode = LIRC_MODE_MODE2;
+	if (dev->driver_type == RC_DRIVER_SCANCODE) {
+		dev->rec_mode = LIRC_MODE_SCANCODE;
+		dev->poll_mode = LIRC_MODE_SCANCODE;
+	} else {
+		dev->rec_mode = LIRC_MODE_MODE2;
+		dev->poll_mode = LIRC_MODE_MODE2;
+	}
 
 	if (dev->driver_type == RC_DRIVER_IR_RAW) {
 		if (kfifo_alloc(&dev->rawir, MAX_IR_EVENT_SIZE, GFP_KERNEL))
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index dae427e25d71..9f39bc074837 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1810,7 +1810,7 @@ int rc_register_device(struct rc_dev *dev)
 	}
 
 	/* Ensure that the lirc kfifo is setup before we start the thread */
-	if (dev->driver_type != RC_DRIVER_SCANCODE) {
+	if (dev->allowed_protocols != RC_PROTO_BIT_CEC) {
 		rc = ir_lirc_register(dev);
 		if (rc < 0)
 			goto out_rx;
@@ -1831,7 +1831,7 @@ int rc_register_device(struct rc_dev *dev)
 	return 0;
 
 out_lirc:
-	if (dev->driver_type != RC_DRIVER_SCANCODE)
+	if (dev->allowed_protocols != RC_PROTO_BIT_CEC)
 		ir_lirc_unregister(dev);
 out_rx:
 	rc_free_rx_device(dev);
@@ -1892,7 +1892,7 @@ void rc_unregister_device(struct rc_dev *dev)
 	 * lirc device should be freed with dev->registered = false, so
 	 * that userspace polling will get notified.
 	 */
-	if (dev->driver_type != RC_DRIVER_SCANCODE)
+	if (dev->allowed_protocols != RC_PROTO_BIT_CEC)
 		ir_lirc_unregister(dev);
 
 	device_del(&dev->dev);
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 24/26] media: MAINTAINERS: remove lirc staging area
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (22 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 23/26] media: lirc: scancode rc devices should have a lirc device too Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 25/26] media: MAINTAINERS: add entry for zilog_ir Sean Young
                   ` (2 subsequent siblings)
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

Now that lirc is no longer in the staging area, remove the entry.

Signed-off-by: Sean Young <sean@mess.org>
---
 MAINTAINERS | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index a8126830829b..fb5f548a568e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12677,12 +12677,6 @@ S:	Odd Fixes
 F:	Documentation/devicetree/bindings/staging/iio/
 F:	drivers/staging/iio/
 
-STAGING - LIRC (LINUX INFRARED REMOTE CONTROL) DRIVERS
-M:	Jarod Wilson <jarod@wilsonet.com>
-W:	http://www.lirc.org/
-S:	Odd Fixes
-F:	drivers/staging/media/lirc/
-
 STAGING - LUSTRE PARALLEL FILESYSTEM
 M:	Oleg Drokin <oleg.drokin@intel.com>
 M:	Andreas Dilger <andreas.dilger@intel.com>
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 25/26] media: MAINTAINERS: add entry for zilog_ir
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (23 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 24/26] media: MAINTAINERS: remove lirc staging area Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:18 ` [PATCH v3 26/26] kfifo: DECLARE_KIFO_PTR(fifo, u64) does not work on arm 32 bit Sean Young
  2017-10-10  7:59 ` Sean Young
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media

Add MAINTAINER's entry for this new driver ported from staging.

Signed-off-by: Sean Young <sean@mess.org>
---
 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index fb5f548a568e..15d32348e902 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14876,6 +14876,12 @@ Q:	https://patchwork.linuxtv.org/project/linux-media/list/
 S:	Maintained
 F:	drivers/media/dvb-frontends/zd1301_demod*
 
+ZILOG/HAUPPAUGE IR TRANSMITTER
+M:	Sean Young <sean@mess.org>
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	drivers/media/rc/zilog_ir.c
+
 ZPOOL COMPRESSED PAGE STORAGE API
 M:	Dan Streetman <ddstreet@ieee.org>
 L:	linux-mm@kvack.org
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 26/26] kfifo: DECLARE_KIFO_PTR(fifo, u64) does not work on arm 32 bit
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (24 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 25/26] media: MAINTAINERS: add entry for zilog_ir Sean Young
@ 2017-10-10  7:18 ` Sean Young
  2017-10-10  7:59 ` Sean Young
  26 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:18 UTC (permalink / raw)
  To: linux-media, linux-kernel, Stefani Seibold, Randy Dunlap; +Cc: Andrew Morton

If you try to store u64 in a kfifo (or a struct with u64 members),
then the buf member of __STRUCT_KFIFO_PTR will cause 4 bytes
padding due to alignment (note that struct __kfifo is 20 bytes
on 32 bit).

That in turn causes the __is_kfifo_ptr() to fail, which is caught
by kfifo_alloc(), which now returns EINVAL.

So, ensure that __is_kfifo_ptr() compares to the right structure.

Signed-off-by: Sean Young <sean@mess.org>
---
 include/linux/kfifo.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
index 41eb6fdf87a8..86b5fb08e96c 100644
--- a/include/linux/kfifo.h
+++ b/include/linux/kfifo.h
@@ -113,7 +113,8 @@ struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PTR(unsigned char, 2, void);
  * array is a part of the structure and the fifo type where the array is
  * outside of the fifo structure.
  */
-#define	__is_kfifo_ptr(fifo)	(sizeof(*fifo) == sizeof(struct __kfifo))
+#define	__is_kfifo_ptr(fifo) \
+	(sizeof(*fifo) == sizeof(STRUCT_KFIFO_PTR(typeof(*(fifo)->type))))
 
 /**
  * DECLARE_KFIFO_PTR - macro to declare a fifo pointer object
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 26/26] kfifo: DECLARE_KIFO_PTR(fifo, u64) does not work on arm 32 bit
  2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
                   ` (25 preceding siblings ...)
  2017-10-10  7:18 ` [PATCH v3 26/26] kfifo: DECLARE_KIFO_PTR(fifo, u64) does not work on arm 32 bit Sean Young
@ 2017-10-10  7:59 ` Sean Young
  2017-11-30 12:29   ` Mauro Carvalho Chehab
  26 siblings, 1 reply; 39+ messages in thread
From: Sean Young @ 2017-10-10  7:59 UTC (permalink / raw)
  To: linux-media, linux-kernel, Stefani Seibold, Randy Dunlap; +Cc: Andrew Morton

If you try to store u64 in a kfifo (or a struct with u64 members),
then the buf member of __STRUCT_KFIFO_PTR will cause 4 bytes
padding due to alignment (note that struct __kfifo is 20 bytes
on 32 bit).

That in turn causes the __is_kfifo_ptr() to fail, which is caught
by kfifo_alloc(), which now returns EINVAL.

So, ensure that __is_kfifo_ptr() compares to the right structure.

Signed-off-by: Sean Young <sean@mess.org>
Acked-by: Stefani Seibold <stefani@seibold.net>

---
 include/linux/kfifo.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
index 41eb6fdf87a8..86b5fb08e96c 100644
--- a/include/linux/kfifo.h
+++ b/include/linux/kfifo.h
@@ -113,7 +113,8 @@ struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PTR(unsigned char, 2, void);
  * array is a part of the structure and the fifo type where the array is
  * outside of the fifo structure.
  */
-#define	__is_kfifo_ptr(fifo)	(sizeof(*fifo) == sizeof(struct __kfifo))
+#define	__is_kfifo_ptr(fifo) \
+	(sizeof(*fifo) == sizeof(STRUCT_KFIFO_PTR(typeof(*(fifo)->type))))
 
 /**
  * DECLARE_KFIFO_PTR - macro to declare a fifo pointer object

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 04/26] media: lirc_zilog: remove receiver
  2017-10-10  7:17 ` [PATCH v3 04/26] media: lirc_zilog: remove receiver Sean Young
@ 2017-10-11 19:43   ` Andy Walls
  2017-10-11 21:02     ` Sean Young
  0 siblings, 1 reply; 39+ messages in thread
From: Andy Walls @ 2017-10-11 19:43 UTC (permalink / raw)
  To: Sean Young, linux-media

On Tue, 2017-10-10 at 08:17 +0100, Sean Young wrote:
> The ir-kbd-i2c module already handles this very well.

Hi Sean:

It's been years, but my recollection is that although ir-kdb-i2c might
handle receive well, but since the 4 i2c addresses (1 Rx, 1 Tx, 1 IR Tx
code learning, 1 custom Tx code) are all handled by the same Zilog
microcontroller internally, that splitting the Rx and Tx functionality
between two modules became problematic.

Believe me, if i could have leveraged ir-kdb-i2c back when I ported
this, I would have.  I think it's a very bad idea to remove the
receiver from lirc_zilog.

The cx18 and ivtv drivers both use lirc_zilog IIRC.  Have you looked at
the changes required to have the first I2C address used by one i2c
module, and the next one (or three) I2C addresses used by another i2c
module?

-Andy


> 
> Signed-off-by: Sean Young <sean@mess.org>
> ---
>  drivers/staging/media/lirc/lirc_zilog.c | 901 +++-------------------
> ----------
>  1 file changed, 76 insertions(+), 825 deletions(-)
> 
> diff --git a/drivers/staging/media/lirc/lirc_zilog.c
> b/drivers/staging/media/lirc/lirc_zilog.c
> index 6bd0717bf76e..757b3fc247ac 100644
> --- a/drivers/staging/media/lirc/lirc_zilog.c
> +++ b/drivers/staging/media/lirc/lirc_zilog.c
> @@ -64,28 +64,7 @@
>  /* Max transfer size done by I2C transfer functions */
>  #define MAX_XFER_SIZE  64
>  
> -struct IR;
> -
> -struct IR_rx {
> -	struct kref ref;
> -	struct IR *ir;
> -
> -	/* RX device */
> -	struct mutex client_lock;
> -	struct i2c_client *c;
> -
> -	/* RX polling thread data */
> -	struct task_struct *task;
> -
> -	/* RX read data */
> -	unsigned char b[3];
> -	bool hdpvr_data_fmt;
> -};
> -
>  struct IR_tx {
> -	struct kref ref;
> -	struct IR *ir;
> -
>  	/* TX device */
>  	struct mutex client_lock;
>  	struct i2c_client *c;
> @@ -93,39 +72,9 @@ struct IR_tx {
>  	/* TX additional actions needed */
>  	int need_boot;
>  	bool post_tx_ready_poll;
> -};
> -
> -struct IR {
> -	struct kref ref;
> -	struct list_head list;
> -
> -	/* FIXME spinlock access to l->features */
>  	struct lirc_dev *l;
> -	struct lirc_buffer rbuf;
> -
> -	struct mutex ir_lock;
> -	atomic_t open_count;
> -
> -	struct device *dev;
> -	struct i2c_adapter *adapter;
> -
> -	spinlock_t rx_ref_lock; /* struct IR_rx kref get()/put() */
> -	struct IR_rx *rx;
> -
> -	spinlock_t tx_ref_lock; /* struct IR_tx kref get()/put() */
> -	struct IR_tx *tx;
>  };
>  
> -/* IR transceiver instance object list */
> -/*
> - * This lock is used for the following:
> - * a. ir_devices_list access, insertions, deletions
> - * b. struct IR kref get()s and put()s
> - * c. serialization of ir_probe() for the two i2c_clients for a Z8
> - */
> -static DEFINE_MUTEX(ir_devices_lock);
> -static LIST_HEAD(ir_devices_list);
> -
>  /* Block size for IR transmitter */
>  #define TX_BLOCK_SIZE	99
>  
> @@ -153,348 +102,8 @@ struct tx_data_struct {
>  static struct tx_data_struct *tx_data;
>  static struct mutex tx_data_lock;
>  
> -
>  /* module parameters */
>  static bool debug;	/* debug output */
> -static bool tx_only;	/* only handle the IR Tx function */
> -
> -
> -/* struct IR reference counting */
> -static struct IR *get_ir_device(struct IR *ir, bool
> ir_devices_lock_held)
> -{
> -	if (ir_devices_lock_held) {
> -		kref_get(&ir->ref);
> -	} else {
> -		mutex_lock(&ir_devices_lock);
> -		kref_get(&ir->ref);
> -		mutex_unlock(&ir_devices_lock);
> -	}
> -	return ir;
> -}
> -
> -static void release_ir_device(struct kref *ref)
> -{
> -	struct IR *ir = container_of(ref, struct IR, ref);
> -
> -	/*
> -	 * Things should be in this state by now:
> -	 * ir->rx set to NULL and deallocated - happens before ir-
> >rx->ir put()
> -	 * ir->rx->task kthread stopped - happens before ir->rx->ir
> put()
> -	 * ir->tx set to NULL and deallocated - happens before ir-
> >tx->ir put()
> -	 * ir->open_count ==  0 - happens on final close()
> -	 * ir_lock, tx_ref_lock, rx_ref_lock, all released
> -	 */
> -	if (ir->l)
> -		lirc_unregister_device(ir->l);
> -
> -	if (kfifo_initialized(&ir->rbuf.fifo))
> -		lirc_buffer_free(&ir->rbuf);
> -	list_del(&ir->list);
> -	kfree(ir);
> -}
> -
> -static int put_ir_device(struct IR *ir, bool ir_devices_lock_held)
> -{
> -	int released;
> -
> -	if (ir_devices_lock_held)
> -		return kref_put(&ir->ref, release_ir_device);
> -
> -	mutex_lock(&ir_devices_lock);
> -	released = kref_put(&ir->ref, release_ir_device);
> -	mutex_unlock(&ir_devices_lock);
> -
> -	return released;
> -}
> -
> -/* struct IR_rx reference counting */
> -static struct IR_rx *get_ir_rx(struct IR *ir)
> -{
> -	struct IR_rx *rx;
> -
> -	spin_lock(&ir->rx_ref_lock);
> -	rx = ir->rx;
> -	if (rx)
> -		kref_get(&rx->ref);
> -	spin_unlock(&ir->rx_ref_lock);
> -	return rx;
> -}
> -
> -static void destroy_rx_kthread(struct IR_rx *rx, bool
> ir_devices_lock_held)
> -{
> -	/* end up polling thread */
> -	if (!IS_ERR_OR_NULL(rx->task)) {
> -		kthread_stop(rx->task);
> -		rx->task = NULL;
> -		/* Put the ir ptr that ir_probe() gave to the rx
> poll thread */
> -		put_ir_device(rx->ir, ir_devices_lock_held);
> -	}
> -}
> -
> -static void release_ir_rx(struct kref *ref)
> -{
> -	struct IR_rx *rx = container_of(ref, struct IR_rx, ref);
> -	struct IR *ir = rx->ir;
> -
> -	/*
> -	 * This release function can't do all the work, as we want
> -	 * to keep the rx_ref_lock a spinlock, and killing the poll
> thread
> -	 * and releasing the ir reference can cause a sleep.  That
> work is
> -	 * performed by put_ir_rx()
> -	 */
> -	ir->l->features &= ~LIRC_CAN_REC_LIRCCODE;
> -	/* Don't put_ir_device(rx->ir) here; lock can't be freed yet
> */
> -	ir->rx = NULL;
> -	/* Don't do the kfree(rx) here; we still need to kill the
> poll thread */
> -}
> -
> -static int put_ir_rx(struct IR_rx *rx, bool ir_devices_lock_held)
> -{
> -	int released;
> -	struct IR *ir = rx->ir;
> -
> -	spin_lock(&ir->rx_ref_lock);
> -	released = kref_put(&rx->ref, release_ir_rx);
> -	spin_unlock(&ir->rx_ref_lock);
> -	/* Destroy the rx kthread while not holding the spinlock */
> -	if (released) {
> -		destroy_rx_kthread(rx, ir_devices_lock_held);
> -		kfree(rx);
> -		/* Make sure we're not still in a poll_table
> somewhere */
> -		wake_up_interruptible(&ir->rbuf.wait_poll);
> -	}
> -	/* Do a reference put() for the rx->ir reference, if we
> released rx */
> -	if (released)
> -		put_ir_device(ir, ir_devices_lock_held);
> -	return released;
> -}
> -
> -/* struct IR_tx reference counting */
> -static struct IR_tx *get_ir_tx(struct IR *ir)
> -{
> -	struct IR_tx *tx;
> -
> -	spin_lock(&ir->tx_ref_lock);
> -	tx = ir->tx;
> -	if (tx)
> -		kref_get(&tx->ref);
> -	spin_unlock(&ir->tx_ref_lock);
> -	return tx;
> -}
> -
> -static void release_ir_tx(struct kref *ref)
> -{
> -	struct IR_tx *tx = container_of(ref, struct IR_tx, ref);
> -	struct IR *ir = tx->ir;
> -
> -	ir->l->features &= ~LIRC_CAN_SEND_LIRCCODE;
> -	/* Don't put_ir_device(tx->ir) here, so our lock doesn't get
> freed */
> -	ir->tx = NULL;
> -	kfree(tx);
> -}
> -
> -static int put_ir_tx(struct IR_tx *tx, bool ir_devices_lock_held)
> -{
> -	int released;
> -	struct IR *ir = tx->ir;
> -
> -	spin_lock(&ir->tx_ref_lock);
> -	released = kref_put(&tx->ref, release_ir_tx);
> -	spin_unlock(&ir->tx_ref_lock);
> -	/* Do a reference put() for the tx->ir reference, if we
> released tx */
> -	if (released)
> -		put_ir_device(ir, ir_devices_lock_held);
> -	return released;
> -}
> -
> -static int add_to_buf(struct IR *ir)
> -{
> -	__u16 code;
> -	unsigned char codes[2];
> -	unsigned char keybuf[6];
> -	int got_data = 0;
> -	int ret;
> -	int failures = 0;
> -	unsigned char sendbuf[1] = { 0 };
> -	struct lirc_buffer *rbuf = ir->l->buf;
> -	struct IR_rx *rx;
> -	struct IR_tx *tx;
> -
> -	if (lirc_buffer_full(rbuf)) {
> -		dev_dbg(ir->dev, "buffer overflow\n");
> -		return -EOVERFLOW;
> -	}
> -
> -	rx = get_ir_rx(ir);
> -	if (!rx)
> -		return -ENXIO;
> -
> -	/* Ensure our rx->c i2c_client remains valid for the
> duration */
> -	mutex_lock(&rx->client_lock);
> -	if (!rx->c) {
> -		mutex_unlock(&rx->client_lock);
> -		put_ir_rx(rx, false);
> -		return -ENXIO;
> -	}
> -
> -	tx = get_ir_tx(ir);
> -
> -	/*
> -	 * service the device as long as it is returning
> -	 * data and we have space
> -	 */
> -	do {
> -		if (kthread_should_stop()) {
> -			ret = -ENODATA;
> -			break;
> -		}
> -
> -		/*
> -		 * Lock i2c bus for the duration.  RX/TX chips
> interfere so
> -		 * this is worth it
> -		 */
> -		mutex_lock(&ir->ir_lock);
> -
> -		if (kthread_should_stop()) {
> -			mutex_unlock(&ir->ir_lock);
> -			ret = -ENODATA;
> -			break;
> -		}
> -
> -		/*
> -		 * Send random "poll command" (?)  Windows driver
> does this
> -		 * and it is a good point to detect chip failure.
> -		 */
> -		ret = i2c_master_send(rx->c, sendbuf, 1);
> -		if (ret != 1) {
> -			dev_err(ir->dev, "i2c_master_send failed
> with %d\n",
> -				ret);
> -			if (failures >= 3) {
> -				mutex_unlock(&ir->ir_lock);
> -				dev_err(ir->dev,
> -					"unable to read from the IR
> chip after 3 resets, giving up\n");
> -				break;
> -			}
> -
> -			/* Looks like the chip crashed, reset it */
> -			dev_err(ir->dev,
> -				"polling the IR receiver chip
> failed, trying reset\n");
> -
> -			set_current_state(TASK_UNINTERRUPTIBLE);
> -			if (kthread_should_stop()) {
> -				mutex_unlock(&ir->ir_lock);
> -				ret = -ENODATA;
> -				break;
> -			}
> -			schedule_timeout((100 * HZ + 999) / 1000);
> -			if (tx)
> -				tx->need_boot = 1;
> -
> -			++failures;
> -			mutex_unlock(&ir->ir_lock);
> -			ret = 0;
> -			continue;
> -		}
> -
> -		if (kthread_should_stop()) {
> -			mutex_unlock(&ir->ir_lock);
> -			ret = -ENODATA;
> -			break;
> -		}
> -		ret = i2c_master_recv(rx->c, keybuf,
> sizeof(keybuf));
> -		mutex_unlock(&ir->ir_lock);
> -		if (ret != sizeof(keybuf)) {
> -			dev_err(ir->dev,
> -				"i2c_master_recv failed with %d --
> keeping last read buffer\n",
> -				ret);
> -		} else {
> -			rx->b[0] = keybuf[3];
> -			rx->b[1] = keybuf[4];
> -			rx->b[2] = keybuf[5];
> -			dev_dbg(ir->dev,
> -				"key (0x%02x/0x%02x)\n",
> -				rx->b[0], rx->b[1]);
> -		}
> -
> -		/* key pressed ? */
> -		if (rx->hdpvr_data_fmt) {
> -			if (got_data && (keybuf[0] == 0x80)) {
> -				ret = 0;
> -				break;
> -			} else if (got_data && (keybuf[0] == 0x00))
> {
> -				ret = -ENODATA;
> -				break;
> -			}
> -		} else if ((rx->b[0] & 0x80) == 0) {
> -			ret = got_data ? 0 : -ENODATA;
> -			break;
> -		}
> -
> -		/* look what we have */
> -		code = (((__u16)rx->b[0] & 0x7f) << 6) | (rx->b[1]
> >> 2);
> -
> -		codes[0] = (code >> 8) & 0xff;
> -		codes[1] = code & 0xff;
> -
> -		/* return it */
> -		lirc_buffer_write(rbuf, codes);
> -		++got_data;
> -		ret = 0;
> -	} while (!lirc_buffer_full(rbuf));
> -
> -	mutex_unlock(&rx->client_lock);
> -	if (tx)
> -		put_ir_tx(tx, false);
> -	put_ir_rx(rx, false);
> -	return ret;
> -}
> -
> -/*
> - * Main function of the polling thread -- from lirc_dev.
> - * We don't fit the LIRC model at all anymore.  This is horrible,
> but
> - * basically we have a single RX/TX device with a nasty failure mode
> - * that needs to be accounted for across the pair.  lirc lets us
> provide
> - * fops, but prevents us from using the internal polling, etc. if we
> do
> - * so.  Hence the replication.  Might be neater to extend the LIRC
> model
> - * to account for this but I'd think it's a very special case of
> seriously
> - * messed up hardware.
> - */
> -static int lirc_thread(void *arg)
> -{
> -	struct IR *ir = arg;
> -	struct lirc_buffer *rbuf = ir->l->buf;
> -
> -	dev_dbg(ir->dev, "poll thread started\n");
> -
> -	while (!kthread_should_stop()) {
> -		set_current_state(TASK_INTERRUPTIBLE);
> -
> -		/* if device not opened, we can sleep half a second
> */
> -		if (atomic_read(&ir->open_count) == 0) {
> -			schedule_timeout(HZ / 2);
> -			continue;
> -		}
> -
> -		/*
> -		 * This is ~113*2 + 24 + jitter (2*repeat gap + code
> length).
> -		 * We use this interval as the chip resets every
> time you poll
> -		 * it (bad!).  This is therefore just sufficient to
> catch all
> -		 * of the button presses.  It makes the remote much
> more
> -		 * responsive.  You can see the difference by
> running irw and
> -		 * holding down a button.  With 100ms, the old
> polling
> -		 * interval, you'll notice breaks in the repeat
> sequence
> -		 * corresponding to lost keypresses.
> -		 */
> -		schedule_timeout((260 * HZ) / 1000);
> -		if (kthread_should_stop())
> -			break;
> -		if (!add_to_buf(ir))
> -			wake_up_interruptible(&rbuf->wait_poll);
> -	}
> -
> -	dev_dbg(ir->dev, "poll thread ended\n");
> -	return 0;
> -}
>  
>  /* safe read of a uint32 (always network byte order) */
>  static int read_uint32(unsigned char **data,
> @@ -645,10 +254,10 @@ static int send_data_block(struct IR_tx *tx,
> unsigned char *data_block)
>  		buf[0] = (unsigned char)(i + 1);
>  		for (j = 0; j < tosend; ++j)
>  			buf[1 + j] = data_block[i + j];
> -		dev_dbg(tx->ir->dev, "%*ph", 5, buf);
> +		dev_dbg(&tx->l->dev, "%*ph", 5, buf);
>  		ret = i2c_master_send(tx->c, buf, tosend + 1);
>  		if (ret != tosend + 1) {
> -			dev_err(tx->ir->dev,
> +			dev_err(&tx->l->dev,
>  				"i2c_master_send failed with %d\n",
> ret);
>  			return ret < 0 ? ret : -EFAULT;
>  		}
> @@ -673,7 +282,7 @@ static int send_boot_data(struct IR_tx *tx)
>  	buf[1] = 0x20;
>  	ret = i2c_master_send(tx->c, buf, 2);
>  	if (ret != 2) {
> -		dev_err(tx->ir->dev, "i2c_master_send failed with
> %d\n", ret);
> +		dev_err(&tx->l->dev, "i2c_master_send failed with
> %d\n", ret);
>  		return ret < 0 ? ret : -EFAULT;
>  	}
>  
> @@ -690,22 +299,22 @@ static int send_boot_data(struct IR_tx *tx)
>  	}
>  
>  	if (ret != 1) {
> -		dev_err(tx->ir->dev, "i2c_master_send failed with
> %d\n", ret);
> +		dev_err(&tx->l->dev, "i2c_master_send failed with
> %d\n", ret);
>  		return ret < 0 ? ret : -EFAULT;
>  	}
>  
>  	/* Here comes the firmware version... (hopefully) */
>  	ret = i2c_master_recv(tx->c, buf, 4);
>  	if (ret != 4) {
> -		dev_err(tx->ir->dev, "i2c_master_recv failed with
> %d\n", ret);
> +		dev_err(&tx->l->dev, "i2c_master_recv failed with
> %d\n", ret);
>  		return 0;
>  	}
>  	if ((buf[0] != 0x80) && (buf[0] != 0xa0)) {
> -		dev_err(tx->ir->dev, "unexpected IR TX init
> response: %02x\n",
> +		dev_err(&tx->l->dev, "unexpected IR TX init
> response: %02x\n",
>  			buf[0]);
>  		return 0;
>  	}
> -	dev_notice(tx->ir->dev,
> +	dev_notice(&tx->l->dev,
>  		   "Zilog/Hauppauge IR blaster firmware version
> %d.%d.%d loaded\n",
>  		   buf[1], buf[2], buf[3]);
>  
> @@ -750,15 +359,15 @@ static int fw_load(struct IR_tx *tx)
>  	}
>  
>  	/* Request codeset data file */
> -	ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx-
> >ir->dev);
> +	ret = request_firmware(&fw_entry, "haup-ir-blaster.bin",
> &tx->l->dev);
>  	if (ret != 0) {
> -		dev_err(tx->ir->dev,
> +		dev_err(&tx->l->dev,
>  			"firmware haup-ir-blaster.bin not available
> (%d)\n",
>  			ret);
>  		ret = ret < 0 ? ret : -EFAULT;
>  		goto out;
>  	}
> -	dev_dbg(tx->ir->dev, "firmware of size %zu loaded\n",
> fw_entry->size);
> +	dev_dbg(&tx->l->dev, "firmware of size %zu loaded\n",
> fw_entry->size);
>  
>  	/* Parse the file */
>  	tx_data = vmalloc(sizeof(*tx_data));
> @@ -786,7 +395,7 @@ static int fw_load(struct IR_tx *tx)
>  	if (!read_uint8(&data, tx_data->endp, &version))
>  		goto corrupt;
>  	if (version != 1) {
> -		dev_err(tx->ir->dev,
> +		dev_err(&tx->l->dev,
>  			"unsupported code set file version (%u,
> expected 1) -- please upgrade to a newer driver\n",
>  			version);
>  		fw_unload_locked();
> @@ -803,7 +412,7 @@ static int fw_load(struct IR_tx *tx)
>  			 &tx_data->num_code_sets))
>  		goto corrupt;
>  
> -	dev_dbg(tx->ir->dev, "%u IR blaster codesets loaded\n",
> +	dev_dbg(&tx->l->dev, "%u IR blaster codesets loaded\n",
>  		tx_data->num_code_sets);
>  
>  	tx_data->code_sets = vmalloc(
> @@ -868,7 +477,7 @@ static int fw_load(struct IR_tx *tx)
>  	goto out;
>  
>  corrupt:
> -	dev_err(tx->ir->dev, "firmware is corrupt\n");
> +	dev_err(&tx->l->dev, "firmware is corrupt\n");
>  	fw_unload_locked();
>  	ret = -EFAULT;
>  
> @@ -877,94 +486,6 @@ static int fw_load(struct IR_tx *tx)
>  	return ret;
>  }
>  
> -/* copied from lirc_dev */
> -static ssize_t read(struct file *filep, char __user *outbuf, size_t
> n,
> -		    loff_t *ppos)
> -{
> -	struct IR *ir = lirc_get_pdata(filep);
> -	struct IR_rx *rx;
> -	struct lirc_buffer *rbuf = ir->l->buf;
> -	int ret = 0, written = 0, retries = 0;
> -	unsigned int m;
> -	DECLARE_WAITQUEUE(wait, current);
> -
> -	dev_dbg(ir->dev, "read called\n");
> -	if (n % rbuf->chunk_size) {
> -		dev_dbg(ir->dev, "read result = -EINVAL\n");
> -		return -EINVAL;
> -	}
> -
> -	rx = get_ir_rx(ir);
> -	if (!rx)
> -		return -ENXIO;
> -
> -	/*
> -	 * we add ourselves to the task queue before buffer check
> -	 * to avoid losing scan code (in case when queue is awaken
> somewhere
> -	 * between while condition checking and scheduling)
> -	 */
> -	add_wait_queue(&rbuf->wait_poll, &wait);
> -	set_current_state(TASK_INTERRUPTIBLE);
> -
> -	/*
> -	 * while we didn't provide 'length' bytes, device is opened
> in blocking
> -	 * mode and 'copy_to_user' is happy, wait for data.
> -	 */
> -	while (written < n && ret == 0) {
> -		if (lirc_buffer_empty(rbuf)) {
> -			/*
> -			 * According to the read(2) man page,
> 'written' can be
> -			 * returned as less than 'n', instead of
> blocking
> -			 * again, returning -EWOULDBLOCK, or
> returning
> -			 * -ERESTARTSYS
> -			 */
> -			if (written)
> -				break;
> -			if (filep->f_flags & O_NONBLOCK) {
> -				ret = -EWOULDBLOCK;
> -				break;
> -			}
> -			if (signal_pending(current)) {
> -				ret = -ERESTARTSYS;
> -				break;
> -			}
> -			schedule();
> -			set_current_state(TASK_INTERRUPTIBLE);
> -		} else {
> -			unsigned char buf[MAX_XFER_SIZE];
> -
> -			if (rbuf->chunk_size > sizeof(buf)) {
> -				dev_err(ir->dev,
> -					"chunk_size is too big
> (%d)!\n",
> -					rbuf->chunk_size);
> -				ret = -EINVAL;
> -				break;
> -			}
> -			m = lirc_buffer_read(rbuf, buf);
> -			if (m == rbuf->chunk_size) {
> -				ret = copy_to_user(outbuf + written,
> buf,
> -						   rbuf-
> >chunk_size);
> -				written += rbuf->chunk_size;
> -			} else {
> -				retries++;
> -			}
> -			if (retries >= 5) {
> -				dev_err(ir->dev, "Buffer read
> failed!\n");
> -				ret = -EIO;
> -			}
> -		}
> -	}
> -
> -	remove_wait_queue(&rbuf->wait_poll, &wait);
> -	put_ir_rx(rx, false);
> -	set_current_state(TASK_RUNNING);
> -
> -	dev_dbg(ir->dev, "read result = %d (%s)\n", ret,
> -		ret ? "Error" : "OK");
> -
> -	return ret ? ret : written;
> -}
> -
>  /* send a keypress to the IR TX device */
>  static int send_code(struct IR_tx *tx, unsigned int code, unsigned
> int key)
>  {
> @@ -976,7 +497,7 @@ static int send_code(struct IR_tx *tx, unsigned
> int code, unsigned int key)
>  	ret = get_key_data(data_block, code, key);
>  
>  	if (ret == -EPROTO) {
> -		dev_err(tx->ir->dev,
> +		dev_err(&tx->l->dev,
>  			"failed to get data for code %u, key %u --
> check lircd.conf entries\n",
>  			code, key);
>  		return ret;
> @@ -994,7 +515,7 @@ static int send_code(struct IR_tx *tx, unsigned
> int code, unsigned int key)
>  	buf[1] = 0x40;
>  	ret = i2c_master_send(tx->c, buf, 2);
>  	if (ret != 2) {
> -		dev_err(tx->ir->dev, "i2c_master_send failed with
> %d\n", ret);
> +		dev_err(&tx->l->dev, "i2c_master_send failed with
> %d\n", ret);
>  		return ret < 0 ? ret : -EFAULT;
>  	}
>  
> @@ -1007,18 +528,18 @@ static int send_code(struct IR_tx *tx,
> unsigned int code, unsigned int key)
>  	}
>  
>  	if (ret != 1) {
> -		dev_err(tx->ir->dev, "i2c_master_send failed with
> %d\n", ret);
> +		dev_err(&tx->l->dev, "i2c_master_send failed with
> %d\n", ret);
>  		return ret < 0 ? ret : -EFAULT;
>  	}
>  
>  	/* Send finished download? */
>  	ret = i2c_master_recv(tx->c, buf, 1);
>  	if (ret != 1) {
> -		dev_err(tx->ir->dev, "i2c_master_recv failed with
> %d\n", ret);
> +		dev_err(&tx->l->dev, "i2c_master_recv failed with
> %d\n", ret);
>  		return ret < 0 ? ret : -EFAULT;
>  	}
>  	if (buf[0] != 0xA0) {
> -		dev_err(tx->ir->dev, "unexpected IR TX response #1:
> %02x\n",
> +		dev_err(&tx->l->dev, "unexpected IR TX response #1:
> %02x\n",
>  			buf[0]);
>  		return -EFAULT;
>  	}
> @@ -1028,7 +549,7 @@ static int send_code(struct IR_tx *tx, unsigned
> int code, unsigned int key)
>  	buf[1] = 0x80;
>  	ret = i2c_master_send(tx->c, buf, 2);
>  	if (ret != 2) {
> -		dev_err(tx->ir->dev, "i2c_master_send failed with
> %d\n", ret);
> +		dev_err(&tx->l->dev, "i2c_master_send failed with
> %d\n", ret);
>  		return ret < 0 ? ret : -EFAULT;
>  	}
>  
> @@ -1038,7 +559,7 @@ static int send_code(struct IR_tx *tx, unsigned
> int code, unsigned int key)
>  	 * going to skip this whole mess and say we're done on the
> HD PVR
>  	 */
>  	if (!tx->post_tx_ready_poll) {
> -		dev_dbg(tx->ir->dev, "sent code %u, key %u\n", code,
> key);
> +		dev_dbg(&tx->l->dev, "sent code %u, key %u\n", code,
> key);
>  		return 0;
>  	}
>  
> @@ -1054,12 +575,12 @@ static int send_code(struct IR_tx *tx,
> unsigned int code, unsigned int key)
>  		ret = i2c_master_send(tx->c, buf, 1);
>  		if (ret == 1)
>  			break;
> -		dev_dbg(tx->ir->dev,
> +		dev_dbg(&tx->l->dev,
>  			"NAK expected: i2c_master_send failed with
> %d (try %d)\n",
>  			ret, i + 1);
>  	}
>  	if (ret != 1) {
> -		dev_err(tx->ir->dev,
> +		dev_err(&tx->l->dev,
>  			"IR TX chip never got ready: last
> i2c_master_send failed with %d\n",
>  			ret);
>  		return ret < 0 ? ret : -EFAULT;
> @@ -1068,17 +589,17 @@ static int send_code(struct IR_tx *tx,
> unsigned int code, unsigned int key)
>  	/* Seems to be an 'ok' response */
>  	i = i2c_master_recv(tx->c, buf, 1);
>  	if (i != 1) {
> -		dev_err(tx->ir->dev, "i2c_master_recv failed with
> %d\n", ret);
> +		dev_err(&tx->l->dev, "i2c_master_recv failed with
> %d\n", ret);
>  		return -EFAULT;
>  	}
>  	if (buf[0] != 0x80) {
> -		dev_err(tx->ir->dev, "unexpected IR TX response #2:
> %02x\n",
> +		dev_err(&tx->l->dev, "unexpected IR TX response #2:
> %02x\n",
>  			buf[0]);
>  		return -EFAULT;
>  	}
>  
>  	/* Oh good, it worked */
> -	dev_dbg(tx->ir->dev, "sent code %u, key %u\n", code, key);
> +	dev_dbg(&tx->l->dev, "sent code %u, key %u\n", code, key);
>  	return 0;
>  }
>  
> @@ -1091,8 +612,7 @@ static int send_code(struct IR_tx *tx, unsigned
> int code, unsigned int key)
>  static ssize_t write(struct file *filep, const char __user *buf,
> size_t n,
>  		     loff_t *ppos)
>  {
> -	struct IR *ir = lirc_get_pdata(filep);
> -	struct IR_tx *tx;
> +	struct IR_tx *tx = lirc_get_pdata(filep);
>  	size_t i;
>  	int failures = 0;
>  
> @@ -1100,31 +620,20 @@ static ssize_t write(struct file *filep, const
> char __user *buf, size_t n,
>  	if (n % sizeof(int))
>  		return -EINVAL;
>  
> -	/* Get a struct IR_tx reference */
> -	tx = get_ir_tx(ir);
> -	if (!tx)
> -		return -ENXIO;
> -
>  	/* Ensure our tx->c i2c_client remains valid for the
> duration */
>  	mutex_lock(&tx->client_lock);
>  	if (!tx->c) {
>  		mutex_unlock(&tx->client_lock);
> -		put_ir_tx(tx, false);
>  		return -ENXIO;
>  	}
>  
> -	/* Lock i2c bus for the duration */
> -	mutex_lock(&ir->ir_lock);
> -
>  	/* Send each keypress */
>  	for (i = 0; i < n;) {
>  		int ret = 0;
>  		int command;
>  
>  		if (copy_from_user(&command, buf + i,
> sizeof(command))) {
> -			mutex_unlock(&ir->ir_lock);
>  			mutex_unlock(&tx->client_lock);
> -			put_ir_tx(tx, false);
>  			return -EFAULT;
>  		}
>  
> @@ -1133,9 +642,7 @@ static ssize_t write(struct file *filep, const
> char __user *buf, size_t n,
>  			/* Make sure we have the 'firmware' loaded,
> first */
>  			ret = fw_load(tx);
>  			if (ret != 0) {
> -				mutex_unlock(&ir->ir_lock);
>  				mutex_unlock(&tx->client_lock);
> -				put_ir_tx(tx, false);
>  				if (ret != -ENOMEM)
>  					ret = -EIO;
>  				return ret;
> @@ -1151,9 +658,7 @@ static ssize_t write(struct file *filep, const
> char __user *buf, size_t n,
>  			ret = send_code(tx, (unsigned int)command >>
> 16,
>  					    (unsigned int)command &
> 0xFFFF);
>  			if (ret == -EPROTO) {
> -				mutex_unlock(&ir->ir_lock);
>  				mutex_unlock(&tx->client_lock);
> -				put_ir_tx(tx, false);
>  				return ret;
>  			}
>  		}
> @@ -1164,15 +669,13 @@ static ssize_t write(struct file *filep, const
> char __user *buf, size_t n,
>  		 */
>  		if (ret != 0) {
>  			/* Looks like the chip crashed, reset it */
> -			dev_err(tx->ir->dev,
> +			dev_err(&tx->l->dev,
>  				"sending to the IR transmitter chip
> failed, trying reset\n");
>  
>  			if (failures >= 3) {
> -				dev_err(tx->ir->dev,
> +				dev_err(&tx->l->dev,
>  					"unable to send to the IR
> chip after 3 resets, giving up\n");
> -				mutex_unlock(&ir->ir_lock);
>  				mutex_unlock(&tx->client_lock);
> -				put_ir_tx(tx, false);
>  				return ret;
>  			}
>  			set_current_state(TASK_UNINTERRUPTIBLE);
> @@ -1184,60 +687,21 @@ static ssize_t write(struct file *filep, const
> char __user *buf, size_t n,
>  		}
>  	}
>  
> -	/* Release i2c bus */
> -	mutex_unlock(&ir->ir_lock);
> -
>  	mutex_unlock(&tx->client_lock);
>  
> -	/* Give back our struct IR_tx reference */
> -	put_ir_tx(tx, false);
> -
>  	/* All looks good */
>  	return n;
>  }
>  
> -/* copied from lirc_dev */
> -static unsigned int poll(struct file *filep, poll_table *wait)
> -{
> -	struct IR *ir = lirc_get_pdata(filep);
> -	struct IR_rx *rx;
> -	struct lirc_buffer *rbuf = ir->l->buf;
> -	unsigned int ret;
> -
> -	dev_dbg(ir->dev, "%s called\n", __func__);
> -
> -	rx = get_ir_rx(ir);
> -	if (!rx) {
> -		/*
> -		 * Revisit this, if our poll function ever reports
> writeable
> -		 * status for Tx
> -		 */
> -		dev_dbg(ir->dev, "%s result = POLLERR\n", __func__);
> -		return POLLERR;
> -	}
> -
> -	/*
> -	 * Add our lirc_buffer's wait_queue to the poll_table. A
> wake up on
> -	 * that buffer's wait queue indicates we may have a new poll
> status.
> -	 */
> -	poll_wait(filep, &rbuf->wait_poll, wait);
> -
> -	/* Indicate what ops could happen immediately without
> blocking */
> -	ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN | POLLRDNORM);
> -
> -	dev_dbg(ir->dev, "%s result = %s\n", __func__,
> -		ret ? "POLLIN|POLLRDNORM" : "none");
> -	return ret;
> -}
>  
>  static long ioctl(struct file *filep, unsigned int cmd, unsigned
> long arg)
>  {
> -	struct IR *ir = lirc_get_pdata(filep);
> +	struct IR_tx *tx = lirc_get_pdata(filep);
>  	unsigned long __user *uptr = (unsigned long __user *)arg;
>  	int result;
>  	unsigned long mode, features;
>  
> -	features = ir->l->features;
> +	features = tx->l->features;
>  
>  	switch (cmd) {
>  	case LIRC_GET_LENGTH:
> @@ -1287,13 +751,7 @@ static long ioctl(struct file *filep, unsigned
> int cmd, unsigned long arg)
>   */
>  static int open(struct inode *node, struct file *filep)
>  {
> -	struct IR *ir;
> -
>  	lirc_init_pdata(node, filep);
> -	ir = lirc_get_pdata(filep);
> -
> -	atomic_inc(&ir->open_count);
> -
>  	nonseekable_open(node, filep);
>  	return 0;
>  }
> @@ -1301,25 +759,16 @@ static int open(struct inode *node, struct
> file *filep)
>  /* Close the IR device */
>  static int close(struct inode *node, struct file *filep)
>  {
> -	struct IR *ir = lirc_get_pdata(filep);
> -
> -	atomic_dec(&ir->open_count);
> -
> -	put_ir_device(ir, false);
>  	return 0;
>  }
>  
> -static int ir_remove(struct i2c_client *client);
>  static int ir_probe(struct i2c_client *client, const struct
> i2c_device_id *id);
>  
> -#define ID_FLAG_TX	0x01
> -#define ID_FLAG_HDPVR	0x02
> +#define ID_FLAG_HDPVR	0x01
>  
>  static const struct i2c_device_id ir_transceiver_id[] = {
> -	{ "ir_tx_z8f0811_haup",  ID_FLAG_TX                 },
> -	{ "ir_rx_z8f0811_haup",  0                          },
> -	{ "ir_tx_z8f0811_hdpvr", ID_FLAG_HDPVR | ID_FLAG_TX },
> -	{ "ir_rx_z8f0811_hdpvr", ID_FLAG_HDPVR              },
> +	{ "ir_tx_z8f0811_haup",  0 },
> +	{ "ir_tx_z8f0811_hdpvr", ID_FLAG_HDPVR },
>  	{ }
>  };
>  MODULE_DEVICE_TABLE(i2c, ir_transceiver_id);
> @@ -1329,16 +778,13 @@ static struct i2c_driver driver = {
>  		.name	= "Zilog/Hauppauge i2c IR",
>  	},
>  	.probe		= ir_probe,
> -	.remove		= ir_remove,
>  	.id_table	= ir_transceiver_id,
>  };
>  
>  static const struct file_operations lirc_fops = {
>  	.owner		= THIS_MODULE,
>  	.llseek		= no_llseek,
> -	.read		= read,
>  	.write		= write,
> -	.poll		= poll,
>  	.unlocked_ioctl	= ioctl,
>  #ifdef CONFIG_COMPAT
>  	.compat_ioctl	= ioctl,
> @@ -1347,55 +793,11 @@ static const struct file_operations lirc_fops
> = {
>  	.release	= close
>  };
>  
> -static int ir_remove(struct i2c_client *client)
> -{
> -	if (strncmp("ir_tx_z8", client->name, 8) == 0) {
> -		struct IR_tx *tx = i2c_get_clientdata(client);
> -
> -		if (tx) {
> -			mutex_lock(&tx->client_lock);
> -			tx->c = NULL;
> -			mutex_unlock(&tx->client_lock);
> -			put_ir_tx(tx, false);
> -		}
> -	} else if (strncmp("ir_rx_z8", client->name, 8) == 0) {
> -		struct IR_rx *rx = i2c_get_clientdata(client);
> -
> -		if (rx) {
> -			mutex_lock(&rx->client_lock);
> -			rx->c = NULL;
> -			mutex_unlock(&rx->client_lock);
> -			put_ir_rx(rx, false);
> -		}
> -	}
> -	return 0;
> -}
> -
> -/* ir_devices_lock must be held */
> -static struct IR *get_ir_device_by_adapter(struct i2c_adapter
> *adapter)
> -{
> -	struct IR *ir;
> -
> -	if (list_empty(&ir_devices_list))
> -		return NULL;
> -
> -	list_for_each_entry(ir, &ir_devices_list, list)
> -		if (ir->adapter == adapter) {
> -			get_ir_device(ir, true);
> -			return ir;
> -		}
> -
> -	return NULL;
> -}
> -
>  static int ir_probe(struct i2c_client *client, const struct
> i2c_device_id *id)
>  {
> -	struct IR *ir;
>  	struct IR_tx *tx;
> -	struct IR_rx *rx;
>  	struct i2c_adapter *adap = client->adapter;
>  	int ret;
> -	bool tx_probe = false;
>  
>  	dev_dbg(&client->dev, "%s: %s on i2c-%d (%s), client
> addr=0x%02x\n",
>  		__func__, id->name, adap->nr, adap->name, client-
> >addr);
> @@ -1405,209 +807,61 @@ static int ir_probe(struct i2c_client
> *client, const struct i2c_device_id *id)
>  	 * The IR transmitter is at i2c address 0x70.
>  	 */
>  
> -	if (id->driver_data & ID_FLAG_TX)
> -		tx_probe = true;
> -	else if (tx_only) /* module option */
> -		return -ENXIO;
> -
> -	pr_info("probing IR %s on %s (i2c-%d)\n",
> -		tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
> -
> -	mutex_lock(&ir_devices_lock);
> -
> -	/* Use a single struct IR instance for both the Rx and Tx
> functions */
> -	ir = get_ir_device_by_adapter(adap);
> -	if (!ir) {
> -		ir = kzalloc(sizeof(*ir), GFP_KERNEL);
> -		if (!ir) {
> -			ret = -ENOMEM;
> -			goto out_no_ir;
> -		}
> -		kref_init(&ir->ref);
> -
> -		/* store for use in ir_probe() again, and open()
> later on */
> -		INIT_LIST_HEAD(&ir->list);
> -		list_add_tail(&ir->list, &ir_devices_list);
> -
> -		ir->adapter = adap;
> -		ir->dev = &adap->dev;
> -		mutex_init(&ir->ir_lock);
> -		atomic_set(&ir->open_count, 0);
> -		spin_lock_init(&ir->tx_ref_lock);
> -		spin_lock_init(&ir->rx_ref_lock);
> -
> -		/* set lirc_dev stuff */
> -		ir->l = lirc_allocate_device();
> -		if (!ir->l) {
> -			ret = -ENOMEM;
> -			goto out_put_ir;
> -		}
> -
> -		snprintf(ir->l->name, sizeof(ir->l->name),
> "lirc_zilog");
> -		ir->l->code_length = 13;
> -		ir->l->fops = &lirc_fops;
> -		ir->l->owner = THIS_MODULE;
> -		ir->l->dev.parent = &adap->dev;
> -
> -		/*
> -		 * FIXME this is a pointer reference to us, but no
> refcount.
> -		 *
> -		 * This OK for now, since lirc_dev currently won't
> touch this
> -		 * buffer as we provide our own lirc_fops.
> -		 *
> -		 * Currently our own lirc_fops rely on this ir->l-
> >buf pointer
> -		 */
> -		ir->l->buf = &ir->rbuf;
> -		/* This will be returned by lirc_get_pdata() */
> -		ir->l->data = ir;
> -		ret = lirc_buffer_init(ir->l->buf, 2, BUFLEN / 2);
> -		if (ret) {
> -			lirc_free_device(ir->l);
> -			ir->l = NULL;
> -			goto out_put_ir;
> -		}
> -	}
> +	pr_info("probing IR Tx on %s (i2c-%d)\n", adap->name, adap-
> >nr);
>  
> -	if (tx_probe) {
> -		/* Get the IR_rx instance for later, if already
> allocated */
> -		rx = get_ir_rx(ir);
> -
> -		/* Set up a struct IR_tx instance */
> -		tx = kzalloc(sizeof(*tx), GFP_KERNEL);
> -		if (!tx) {
> -			ret = -ENOMEM;
> -			goto out_put_xx;
> -		}
> -		kref_init(&tx->ref);
> -		ir->tx = tx;
> -
> -		ir->l->features |= LIRC_CAN_SEND_LIRCCODE;
> -		mutex_init(&tx->client_lock);
> -		tx->c = client;
> -		tx->need_boot = 1;
> -		tx->post_tx_ready_poll =
> -			       (id->driver_data & ID_FLAG_HDPVR) ?
> false : true;
> -
> -		/* An ir ref goes to the struct IR_tx instance */
> -		tx->ir = get_ir_device(ir, true);
> -
> -		/* A tx ref goes to the i2c_client */
> -		i2c_set_clientdata(client, get_ir_tx(ir));
> -
> -		/*
> -		 * Load the 'firmware'.  We do this before
> registering with
> -		 * lirc_dev, so the first firmware load attempt does
> not happen
> -		 * after a open() or write() call on the device.
> -		 *
> -		 * Failure here is not deemed catastrophic, so the
> receiver will
> -		 * still be usable.  Firmware load will be retried
> in write(),
> -		 * if it is needed.
> -		 */
> -		fw_load(tx);
> -
> -		/* Proceed only if the Rx client is also ready or
> not needed */
> -		if (!rx && !tx_only) {
> -			dev_info(tx->ir->dev,
> -				 "probe of IR Tx on %s (i2c-%d)
> done. Waiting on IR Rx.\n",
> -				 adap->name, adap->nr);
> -			goto out_ok;
> -		}
> -	} else {
> -		/* Get the IR_tx instance for later, if already
> allocated */
> -		tx = get_ir_tx(ir);
> -
> -		/* Set up a struct IR_rx instance */
> -		rx = kzalloc(sizeof(*rx), GFP_KERNEL);
> -		if (!rx) {
> -			ret = -ENOMEM;
> -			goto out_put_xx;
> -		}
> -		kref_init(&rx->ref);
> -		ir->rx = rx;
> -
> -		ir->l->features |= LIRC_CAN_REC_LIRCCODE;
> -		mutex_init(&rx->client_lock);
> -		rx->c = client;
> -		rx->hdpvr_data_fmt =
> -			       (id->driver_data & ID_FLAG_HDPVR) ?
> true : false;
> -
> -		/* An ir ref goes to the struct IR_rx instance */
> -		rx->ir = get_ir_device(ir, true);
> +	/* Set up a struct IR_tx instance */
> +	tx = devm_kzalloc(&client->dev, sizeof(*tx), GFP_KERNEL);
> +	if (!tx)
> +		return -ENOMEM;
>  
> -		/* An rx ref goes to the i2c_client */
> -		i2c_set_clientdata(client, get_ir_rx(ir));
> +	mutex_init(&tx->client_lock);
> +	tx->c = client;
> +	tx->need_boot = 1;
> +	tx->post_tx_ready_poll = !(id->driver_data & ID_FLAG_HDPVR);
>  
> -		/*
> -		 * Start the polling thread.
> -		 * It will only perform an empty loop around
> schedule_timeout()
> -		 * until we register with lirc_dev and the first
> user open()
> -		 */
> -		/* An ir ref goes to the new rx polling kthread */
> -		rx->task = kthread_run(lirc_thread,
> get_ir_device(ir, true),
> -				       "zilog-rx-i2c-%d", adap->nr);
> -		if (IS_ERR(rx->task)) {
> -			ret = PTR_ERR(rx->task);
> -			dev_err(tx->ir->dev,
> -				"%s: could not start IR Rx polling
> thread\n",
> -				__func__);
> -			/* Failed kthread, so put back the ir ref */
> -			put_ir_device(ir, true);
> -			/* Failure exit, so put back rx ref from
> i2c_client */
> -			i2c_set_clientdata(client, NULL);
> -			put_ir_rx(rx, true);
> -			ir->l->features &= ~LIRC_CAN_REC_LIRCCODE;
> -			goto out_put_tx;
> -		}
> +	/* set lirc_dev stuff */
> +	tx->l = lirc_allocate_device();
> +	if (!tx->l)
> +		return -ENOMEM;
>  
> -		/* Proceed only if the Tx client is also ready */
> -		if (!tx) {
> -			pr_info("probe of IR Rx on %s (i2c-%d) done.
> Waiting on IR Tx.\n",
> -				adap->name, adap->nr);
> -			goto out_ok;
> -		}
> -	}
> +	snprintf(tx->l->name, sizeof(tx->l->name), "lirc_zilog");
> +	tx->l->features |= LIRC_CAN_SEND_LIRCCODE;
> +	tx->l->code_length = 13;
> +	tx->l->fops = &lirc_fops;
> +	tx->l->owner = THIS_MODULE;
> +	tx->l->dev.parent = &client->dev;
>  
>  	/* register with lirc */
> -	ret = lirc_register_device(ir->l);
> +	ret = lirc_register_device(tx->l);
>  	if (ret < 0) {
> -		dev_err(tx->ir->dev,
> -			"%s: lirc_register_device() failed: %i\n",
> +		dev_err(&tx->l->dev, "%s: lirc_register_device()
> failed: %i\n",
>  			__func__, ret);
> -		lirc_free_device(ir->l);
> -		ir->l = NULL;
> -		goto out_put_xx;
> +		lirc_free_device(tx->l);
> +		tx->l = NULL;
> +		return ret;
>  	}
>  
> -	dev_info(ir->dev,
> +	/*
> +	 * Load the 'firmware'.  We do this before registering with
> +	 * lirc_dev, so the first firmware load attempt does not
> happen
> +	 * after a open() or write() call on the device.
> +	 */
> +	ret = fw_load(tx);
> +	if (ret < 0) {
> +		lirc_unregister_device(tx->l);
> +		return ret;
> +	}
> +
> +	/* A tx ref goes to the i2c_client */
> +	i2c_set_clientdata(client, tx);
> +
> +	dev_info(&tx->l->dev,
>  		 "IR unit on %s (i2c-%d) registered as lirc%d and
> ready\n",
> -		 adap->name, adap->nr, ir->l->minor);
> -
> -out_ok:
> -	if (rx)
> -		put_ir_rx(rx, true);
> -	if (tx)
> -		put_ir_tx(tx, true);
> -	put_ir_device(ir, true);
> -	dev_info(ir->dev,
> -		 "probe of IR %s on %s (i2c-%d) done\n",
> -		 tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
> -	mutex_unlock(&ir_devices_lock);
> -	return 0;
> +		 adap->name, adap->nr, tx->l->minor);
>  
> -out_put_xx:
> -	if (rx)
> -		put_ir_rx(rx, true);
> -out_put_tx:
> -	if (tx)
> -		put_ir_tx(tx, true);
> -out_put_ir:
> -	put_ir_device(ir, true);
> -out_no_ir:
> -	dev_err(&client->dev,
> -		"%s: probing IR %s on %s (i2c-%d) failed with %d\n",
> -		__func__, tx_probe ? "Tx" : "Rx", adap->name, adap-
> >nr, ret);
> -	mutex_unlock(&ir_devices_lock);
> -	return ret;
> +	dev_info(&tx->l->dev,
> +		 "probe of IR Tx on %s (i2c-%d) done\n", adap->name, 
> adap->nr);
> +	return 0;
>  }
>  
>  static int __init zilog_init(void)
> @@ -1648,6 +902,3 @@ MODULE_ALIAS("lirc_pvr150");
>  
>  module_param(debug, bool, 0644);
>  MODULE_PARM_DESC(debug, "Enable debugging messages");
> -
> -module_param(tx_only, bool, 0644);
> -MODULE_PARM_DESC(tx_only, "Only handle the IR transmit function");

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 04/26] media: lirc_zilog: remove receiver
  2017-10-11 19:43   ` Andy Walls
@ 2017-10-11 21:02     ` Sean Young
  2017-10-11 23:24       ` Andy Walls
  0 siblings, 1 reply; 39+ messages in thread
From: Sean Young @ 2017-10-11 21:02 UTC (permalink / raw)
  To: Andy Walls; +Cc: linux-media

On Wed, Oct 11, 2017 at 03:43:16PM -0400, Andy Walls wrote:
> On Tue, 2017-10-10 at 08:17 +0100, Sean Young wrote:
> > The ir-kbd-i2c module already handles this very well.
> 
> Hi Sean:
> 
> It's been years, but my recollection is that although ir-kdb-i2c might
> handle receive well, but since the 4 i2c addresses (1 Rx, 1 Tx, 1 IR Tx
> code learning, 1 custom Tx code) are all handled by the same Zilog
> microcontroller internally, that splitting the Rx and Tx functionality
> between two modules became problematic.
> 
> Believe me, if i could have leveraged ir-kdb-i2c back when I ported
> this, I would have.  I think it's a very bad idea to remove the
> receiver from lirc_zilog.
> 
> The cx18 and ivtv drivers both use lirc_zilog IIRC.  Have you looked at
> the changes required to have the first I2C address used by one i2c
> module, and the next one (or three) I2C addresses used by another i2c
> module?

This is already the case.

In current kernels you can use ir-kbd-i2c for Rx and lirc_zilog for Tx,
this works fine. In fact, the lirc_zilog Rx code produces lirccodes,
(not mode2) and ir-kbd-i2c produces keycodes through rc-core, so ir-kbd-i2c
(also mainline, not staging) is much more likely to be used for Rx. For Tx
you have to use lirc_zilog.

I haven't heard of any reports of problems (or observed this myself) when
using these two modules together.

As you point out, both drivers sending i2c commands to the same z8f0811 
with its z8 encore hand-coded i2c implementation. But they're using different
addresses.

So removing the lirc_zilog Rx doesn't make things worse, in fact, it just
removes some code which is unlikely to be used.

It's the hdpvr, ivtv, cx18 and pvrusb2 drivers which have a Tx interface. I
have hdpvr and ivtv hardware to test.


Sean

> 
> -Andy
> 
> 
> > 
> > Signed-off-by: Sean Young <sean@mess.org>
> > ---
> >  drivers/staging/media/lirc/lirc_zilog.c | 901 +++-------------------
> > ----------
> >  1 file changed, 76 insertions(+), 825 deletions(-)
> > 
> > diff --git a/drivers/staging/media/lirc/lirc_zilog.c
> > b/drivers/staging/media/lirc/lirc_zilog.c
> > index 6bd0717bf76e..757b3fc247ac 100644
> > --- a/drivers/staging/media/lirc/lirc_zilog.c
> > +++ b/drivers/staging/media/lirc/lirc_zilog.c
> > @@ -64,28 +64,7 @@
> >  /* Max transfer size done by I2C transfer functions */
> >  #define MAX_XFER_SIZE  64
> >  
> > -struct IR;
> > -
> > -struct IR_rx {
> > -	struct kref ref;
> > -	struct IR *ir;
> > -
> > -	/* RX device */
> > -	struct mutex client_lock;
> > -	struct i2c_client *c;
> > -
> > -	/* RX polling thread data */
> > -	struct task_struct *task;
> > -
> > -	/* RX read data */
> > -	unsigned char b[3];
> > -	bool hdpvr_data_fmt;
> > -};
> > -
> >  struct IR_tx {
> > -	struct kref ref;
> > -	struct IR *ir;
> > -
> >  	/* TX device */
> >  	struct mutex client_lock;
> >  	struct i2c_client *c;
> > @@ -93,39 +72,9 @@ struct IR_tx {
> >  	/* TX additional actions needed */
> >  	int need_boot;
> >  	bool post_tx_ready_poll;
> > -};
> > -
> > -struct IR {
> > -	struct kref ref;
> > -	struct list_head list;
> > -
> > -	/* FIXME spinlock access to l->features */
> >  	struct lirc_dev *l;
> > -	struct lirc_buffer rbuf;
> > -
> > -	struct mutex ir_lock;
> > -	atomic_t open_count;
> > -
> > -	struct device *dev;
> > -	struct i2c_adapter *adapter;
> > -
> > -	spinlock_t rx_ref_lock; /* struct IR_rx kref get()/put() */
> > -	struct IR_rx *rx;
> > -
> > -	spinlock_t tx_ref_lock; /* struct IR_tx kref get()/put() */
> > -	struct IR_tx *tx;
> >  };
> >  
> > -/* IR transceiver instance object list */
> > -/*
> > - * This lock is used for the following:
> > - * a. ir_devices_list access, insertions, deletions
> > - * b. struct IR kref get()s and put()s
> > - * c. serialization of ir_probe() for the two i2c_clients for a Z8
> > - */
> > -static DEFINE_MUTEX(ir_devices_lock);
> > -static LIST_HEAD(ir_devices_list);
> > -
> >  /* Block size for IR transmitter */
> >  #define TX_BLOCK_SIZE	99
> >  
> > @@ -153,348 +102,8 @@ struct tx_data_struct {
> >  static struct tx_data_struct *tx_data;
> >  static struct mutex tx_data_lock;
> >  
> > -
> >  /* module parameters */
> >  static bool debug;	/* debug output */
> > -static bool tx_only;	/* only handle the IR Tx function */
> > -
> > -
> > -/* struct IR reference counting */
> > -static struct IR *get_ir_device(struct IR *ir, bool
> > ir_devices_lock_held)
> > -{
> > -	if (ir_devices_lock_held) {
> > -		kref_get(&ir->ref);
> > -	} else {
> > -		mutex_lock(&ir_devices_lock);
> > -		kref_get(&ir->ref);
> > -		mutex_unlock(&ir_devices_lock);
> > -	}
> > -	return ir;
> > -}
> > -
> > -static void release_ir_device(struct kref *ref)
> > -{
> > -	struct IR *ir = container_of(ref, struct IR, ref);
> > -
> > -	/*
> > -	 * Things should be in this state by now:
> > -	 * ir->rx set to NULL and deallocated - happens before ir-
> > >rx->ir put()
> > -	 * ir->rx->task kthread stopped - happens before ir->rx->ir
> > put()
> > -	 * ir->tx set to NULL and deallocated - happens before ir-
> > >tx->ir put()
> > -	 * ir->open_count ==  0 - happens on final close()
> > -	 * ir_lock, tx_ref_lock, rx_ref_lock, all released
> > -	 */
> > -	if (ir->l)
> > -		lirc_unregister_device(ir->l);
> > -
> > -	if (kfifo_initialized(&ir->rbuf.fifo))
> > -		lirc_buffer_free(&ir->rbuf);
> > -	list_del(&ir->list);
> > -	kfree(ir);
> > -}
> > -
> > -static int put_ir_device(struct IR *ir, bool ir_devices_lock_held)
> > -{
> > -	int released;
> > -
> > -	if (ir_devices_lock_held)
> > -		return kref_put(&ir->ref, release_ir_device);
> > -
> > -	mutex_lock(&ir_devices_lock);
> > -	released = kref_put(&ir->ref, release_ir_device);
> > -	mutex_unlock(&ir_devices_lock);
> > -
> > -	return released;
> > -}
> > -
> > -/* struct IR_rx reference counting */
> > -static struct IR_rx *get_ir_rx(struct IR *ir)
> > -{
> > -	struct IR_rx *rx;
> > -
> > -	spin_lock(&ir->rx_ref_lock);
> > -	rx = ir->rx;
> > -	if (rx)
> > -		kref_get(&rx->ref);
> > -	spin_unlock(&ir->rx_ref_lock);
> > -	return rx;
> > -}
> > -
> > -static void destroy_rx_kthread(struct IR_rx *rx, bool
> > ir_devices_lock_held)
> > -{
> > -	/* end up polling thread */
> > -	if (!IS_ERR_OR_NULL(rx->task)) {
> > -		kthread_stop(rx->task);
> > -		rx->task = NULL;
> > -		/* Put the ir ptr that ir_probe() gave to the rx
> > poll thread */
> > -		put_ir_device(rx->ir, ir_devices_lock_held);
> > -	}
> > -}
> > -
> > -static void release_ir_rx(struct kref *ref)
> > -{
> > -	struct IR_rx *rx = container_of(ref, struct IR_rx, ref);
> > -	struct IR *ir = rx->ir;
> > -
> > -	/*
> > -	 * This release function can't do all the work, as we want
> > -	 * to keep the rx_ref_lock a spinlock, and killing the poll
> > thread
> > -	 * and releasing the ir reference can cause a sleep.  That
> > work is
> > -	 * performed by put_ir_rx()
> > -	 */
> > -	ir->l->features &= ~LIRC_CAN_REC_LIRCCODE;
> > -	/* Don't put_ir_device(rx->ir) here; lock can't be freed yet
> > */
> > -	ir->rx = NULL;
> > -	/* Don't do the kfree(rx) here; we still need to kill the
> > poll thread */
> > -}
> > -
> > -static int put_ir_rx(struct IR_rx *rx, bool ir_devices_lock_held)
> > -{
> > -	int released;
> > -	struct IR *ir = rx->ir;
> > -
> > -	spin_lock(&ir->rx_ref_lock);
> > -	released = kref_put(&rx->ref, release_ir_rx);
> > -	spin_unlock(&ir->rx_ref_lock);
> > -	/* Destroy the rx kthread while not holding the spinlock */
> > -	if (released) {
> > -		destroy_rx_kthread(rx, ir_devices_lock_held);
> > -		kfree(rx);
> > -		/* Make sure we're not still in a poll_table
> > somewhere */
> > -		wake_up_interruptible(&ir->rbuf.wait_poll);
> > -	}
> > -	/* Do a reference put() for the rx->ir reference, if we
> > released rx */
> > -	if (released)
> > -		put_ir_device(ir, ir_devices_lock_held);
> > -	return released;
> > -}
> > -
> > -/* struct IR_tx reference counting */
> > -static struct IR_tx *get_ir_tx(struct IR *ir)
> > -{
> > -	struct IR_tx *tx;
> > -
> > -	spin_lock(&ir->tx_ref_lock);
> > -	tx = ir->tx;
> > -	if (tx)
> > -		kref_get(&tx->ref);
> > -	spin_unlock(&ir->tx_ref_lock);
> > -	return tx;
> > -}
> > -
> > -static void release_ir_tx(struct kref *ref)
> > -{
> > -	struct IR_tx *tx = container_of(ref, struct IR_tx, ref);
> > -	struct IR *ir = tx->ir;
> > -
> > -	ir->l->features &= ~LIRC_CAN_SEND_LIRCCODE;
> > -	/* Don't put_ir_device(tx->ir) here, so our lock doesn't get
> > freed */
> > -	ir->tx = NULL;
> > -	kfree(tx);
> > -}
> > -
> > -static int put_ir_tx(struct IR_tx *tx, bool ir_devices_lock_held)
> > -{
> > -	int released;
> > -	struct IR *ir = tx->ir;
> > -
> > -	spin_lock(&ir->tx_ref_lock);
> > -	released = kref_put(&tx->ref, release_ir_tx);
> > -	spin_unlock(&ir->tx_ref_lock);
> > -	/* Do a reference put() for the tx->ir reference, if we
> > released tx */
> > -	if (released)
> > -		put_ir_device(ir, ir_devices_lock_held);
> > -	return released;
> > -}
> > -
> > -static int add_to_buf(struct IR *ir)
> > -{
> > -	__u16 code;
> > -	unsigned char codes[2];
> > -	unsigned char keybuf[6];
> > -	int got_data = 0;
> > -	int ret;
> > -	int failures = 0;
> > -	unsigned char sendbuf[1] = { 0 };
> > -	struct lirc_buffer *rbuf = ir->l->buf;
> > -	struct IR_rx *rx;
> > -	struct IR_tx *tx;
> > -
> > -	if (lirc_buffer_full(rbuf)) {
> > -		dev_dbg(ir->dev, "buffer overflow\n");
> > -		return -EOVERFLOW;
> > -	}
> > -
> > -	rx = get_ir_rx(ir);
> > -	if (!rx)
> > -		return -ENXIO;
> > -
> > -	/* Ensure our rx->c i2c_client remains valid for the
> > duration */
> > -	mutex_lock(&rx->client_lock);
> > -	if (!rx->c) {
> > -		mutex_unlock(&rx->client_lock);
> > -		put_ir_rx(rx, false);
> > -		return -ENXIO;
> > -	}
> > -
> > -	tx = get_ir_tx(ir);
> > -
> > -	/*
> > -	 * service the device as long as it is returning
> > -	 * data and we have space
> > -	 */
> > -	do {
> > -		if (kthread_should_stop()) {
> > -			ret = -ENODATA;
> > -			break;
> > -		}
> > -
> > -		/*
> > -		 * Lock i2c bus for the duration.  RX/TX chips
> > interfere so
> > -		 * this is worth it
> > -		 */
> > -		mutex_lock(&ir->ir_lock);
> > -
> > -		if (kthread_should_stop()) {
> > -			mutex_unlock(&ir->ir_lock);
> > -			ret = -ENODATA;
> > -			break;
> > -		}
> > -
> > -		/*
> > -		 * Send random "poll command" (?)  Windows driver
> > does this
> > -		 * and it is a good point to detect chip failure.
> > -		 */
> > -		ret = i2c_master_send(rx->c, sendbuf, 1);
> > -		if (ret != 1) {
> > -			dev_err(ir->dev, "i2c_master_send failed
> > with %d\n",
> > -				ret);
> > -			if (failures >= 3) {
> > -				mutex_unlock(&ir->ir_lock);
> > -				dev_err(ir->dev,
> > -					"unable to read from the IR
> > chip after 3 resets, giving up\n");
> > -				break;
> > -			}
> > -
> > -			/* Looks like the chip crashed, reset it */
> > -			dev_err(ir->dev,
> > -				"polling the IR receiver chip
> > failed, trying reset\n");
> > -
> > -			set_current_state(TASK_UNINTERRUPTIBLE);
> > -			if (kthread_should_stop()) {
> > -				mutex_unlock(&ir->ir_lock);
> > -				ret = -ENODATA;
> > -				break;
> > -			}
> > -			schedule_timeout((100 * HZ + 999) / 1000);
> > -			if (tx)
> > -				tx->need_boot = 1;
> > -
> > -			++failures;
> > -			mutex_unlock(&ir->ir_lock);
> > -			ret = 0;
> > -			continue;
> > -		}
> > -
> > -		if (kthread_should_stop()) {
> > -			mutex_unlock(&ir->ir_lock);
> > -			ret = -ENODATA;
> > -			break;
> > -		}
> > -		ret = i2c_master_recv(rx->c, keybuf,
> > sizeof(keybuf));
> > -		mutex_unlock(&ir->ir_lock);
> > -		if (ret != sizeof(keybuf)) {
> > -			dev_err(ir->dev,
> > -				"i2c_master_recv failed with %d --
> > keeping last read buffer\n",
> > -				ret);
> > -		} else {
> > -			rx->b[0] = keybuf[3];
> > -			rx->b[1] = keybuf[4];
> > -			rx->b[2] = keybuf[5];
> > -			dev_dbg(ir->dev,
> > -				"key (0x%02x/0x%02x)\n",
> > -				rx->b[0], rx->b[1]);
> > -		}
> > -
> > -		/* key pressed ? */
> > -		if (rx->hdpvr_data_fmt) {
> > -			if (got_data && (keybuf[0] == 0x80)) {
> > -				ret = 0;
> > -				break;
> > -			} else if (got_data && (keybuf[0] == 0x00))
> > {
> > -				ret = -ENODATA;
> > -				break;
> > -			}
> > -		} else if ((rx->b[0] & 0x80) == 0) {
> > -			ret = got_data ? 0 : -ENODATA;
> > -			break;
> > -		}
> > -
> > -		/* look what we have */
> > -		code = (((__u16)rx->b[0] & 0x7f) << 6) | (rx->b[1]
> > >> 2);
> > -
> > -		codes[0] = (code >> 8) & 0xff;
> > -		codes[1] = code & 0xff;
> > -
> > -		/* return it */
> > -		lirc_buffer_write(rbuf, codes);
> > -		++got_data;
> > -		ret = 0;
> > -	} while (!lirc_buffer_full(rbuf));
> > -
> > -	mutex_unlock(&rx->client_lock);
> > -	if (tx)
> > -		put_ir_tx(tx, false);
> > -	put_ir_rx(rx, false);
> > -	return ret;
> > -}
> > -
> > -/*
> > - * Main function of the polling thread -- from lirc_dev.
> > - * We don't fit the LIRC model at all anymore.  This is horrible,
> > but
> > - * basically we have a single RX/TX device with a nasty failure mode
> > - * that needs to be accounted for across the pair.  lirc lets us
> > provide
> > - * fops, but prevents us from using the internal polling, etc. if we
> > do
> > - * so.  Hence the replication.  Might be neater to extend the LIRC
> > model
> > - * to account for this but I'd think it's a very special case of
> > seriously
> > - * messed up hardware.
> > - */
> > -static int lirc_thread(void *arg)
> > -{
> > -	struct IR *ir = arg;
> > -	struct lirc_buffer *rbuf = ir->l->buf;
> > -
> > -	dev_dbg(ir->dev, "poll thread started\n");
> > -
> > -	while (!kthread_should_stop()) {
> > -		set_current_state(TASK_INTERRUPTIBLE);
> > -
> > -		/* if device not opened, we can sleep half a second
> > */
> > -		if (atomic_read(&ir->open_count) == 0) {
> > -			schedule_timeout(HZ / 2);
> > -			continue;
> > -		}
> > -
> > -		/*
> > -		 * This is ~113*2 + 24 + jitter (2*repeat gap + code
> > length).
> > -		 * We use this interval as the chip resets every
> > time you poll
> > -		 * it (bad!).  This is therefore just sufficient to
> > catch all
> > -		 * of the button presses.  It makes the remote much
> > more
> > -		 * responsive.  You can see the difference by
> > running irw and
> > -		 * holding down a button.  With 100ms, the old
> > polling
> > -		 * interval, you'll notice breaks in the repeat
> > sequence
> > -		 * corresponding to lost keypresses.
> > -		 */
> > -		schedule_timeout((260 * HZ) / 1000);
> > -		if (kthread_should_stop())
> > -			break;
> > -		if (!add_to_buf(ir))
> > -			wake_up_interruptible(&rbuf->wait_poll);
> > -	}
> > -
> > -	dev_dbg(ir->dev, "poll thread ended\n");
> > -	return 0;
> > -}
> >  
> >  /* safe read of a uint32 (always network byte order) */
> >  static int read_uint32(unsigned char **data,
> > @@ -645,10 +254,10 @@ static int send_data_block(struct IR_tx *tx,
> > unsigned char *data_block)
> >  		buf[0] = (unsigned char)(i + 1);
> >  		for (j = 0; j < tosend; ++j)
> >  			buf[1 + j] = data_block[i + j];
> > -		dev_dbg(tx->ir->dev, "%*ph", 5, buf);
> > +		dev_dbg(&tx->l->dev, "%*ph", 5, buf);
> >  		ret = i2c_master_send(tx->c, buf, tosend + 1);
> >  		if (ret != tosend + 1) {
> > -			dev_err(tx->ir->dev,
> > +			dev_err(&tx->l->dev,
> >  				"i2c_master_send failed with %d\n",
> > ret);
> >  			return ret < 0 ? ret : -EFAULT;
> >  		}
> > @@ -673,7 +282,7 @@ static int send_boot_data(struct IR_tx *tx)
> >  	buf[1] = 0x20;
> >  	ret = i2c_master_send(tx->c, buf, 2);
> >  	if (ret != 2) {
> > -		dev_err(tx->ir->dev, "i2c_master_send failed with
> > %d\n", ret);
> > +		dev_err(&tx->l->dev, "i2c_master_send failed with
> > %d\n", ret);
> >  		return ret < 0 ? ret : -EFAULT;
> >  	}
> >  
> > @@ -690,22 +299,22 @@ static int send_boot_data(struct IR_tx *tx)
> >  	}
> >  
> >  	if (ret != 1) {
> > -		dev_err(tx->ir->dev, "i2c_master_send failed with
> > %d\n", ret);
> > +		dev_err(&tx->l->dev, "i2c_master_send failed with
> > %d\n", ret);
> >  		return ret < 0 ? ret : -EFAULT;
> >  	}
> >  
> >  	/* Here comes the firmware version... (hopefully) */
> >  	ret = i2c_master_recv(tx->c, buf, 4);
> >  	if (ret != 4) {
> > -		dev_err(tx->ir->dev, "i2c_master_recv failed with
> > %d\n", ret);
> > +		dev_err(&tx->l->dev, "i2c_master_recv failed with
> > %d\n", ret);
> >  		return 0;
> >  	}
> >  	if ((buf[0] != 0x80) && (buf[0] != 0xa0)) {
> > -		dev_err(tx->ir->dev, "unexpected IR TX init
> > response: %02x\n",
> > +		dev_err(&tx->l->dev, "unexpected IR TX init
> > response: %02x\n",
> >  			buf[0]);
> >  		return 0;
> >  	}
> > -	dev_notice(tx->ir->dev,
> > +	dev_notice(&tx->l->dev,
> >  		   "Zilog/Hauppauge IR blaster firmware version
> > %d.%d.%d loaded\n",
> >  		   buf[1], buf[2], buf[3]);
> >  
> > @@ -750,15 +359,15 @@ static int fw_load(struct IR_tx *tx)
> >  	}
> >  
> >  	/* Request codeset data file */
> > -	ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx-
> > >ir->dev);
> > +	ret = request_firmware(&fw_entry, "haup-ir-blaster.bin",
> > &tx->l->dev);
> >  	if (ret != 0) {
> > -		dev_err(tx->ir->dev,
> > +		dev_err(&tx->l->dev,
> >  			"firmware haup-ir-blaster.bin not available
> > (%d)\n",
> >  			ret);
> >  		ret = ret < 0 ? ret : -EFAULT;
> >  		goto out;
> >  	}
> > -	dev_dbg(tx->ir->dev, "firmware of size %zu loaded\n",
> > fw_entry->size);
> > +	dev_dbg(&tx->l->dev, "firmware of size %zu loaded\n",
> > fw_entry->size);
> >  
> >  	/* Parse the file */
> >  	tx_data = vmalloc(sizeof(*tx_data));
> > @@ -786,7 +395,7 @@ static int fw_load(struct IR_tx *tx)
> >  	if (!read_uint8(&data, tx_data->endp, &version))
> >  		goto corrupt;
> >  	if (version != 1) {
> > -		dev_err(tx->ir->dev,
> > +		dev_err(&tx->l->dev,
> >  			"unsupported code set file version (%u,
> > expected 1) -- please upgrade to a newer driver\n",
> >  			version);
> >  		fw_unload_locked();
> > @@ -803,7 +412,7 @@ static int fw_load(struct IR_tx *tx)
> >  			 &tx_data->num_code_sets))
> >  		goto corrupt;
> >  
> > -	dev_dbg(tx->ir->dev, "%u IR blaster codesets loaded\n",
> > +	dev_dbg(&tx->l->dev, "%u IR blaster codesets loaded\n",
> >  		tx_data->num_code_sets);
> >  
> >  	tx_data->code_sets = vmalloc(
> > @@ -868,7 +477,7 @@ static int fw_load(struct IR_tx *tx)
> >  	goto out;
> >  
> >  corrupt:
> > -	dev_err(tx->ir->dev, "firmware is corrupt\n");
> > +	dev_err(&tx->l->dev, "firmware is corrupt\n");
> >  	fw_unload_locked();
> >  	ret = -EFAULT;
> >  
> > @@ -877,94 +486,6 @@ static int fw_load(struct IR_tx *tx)
> >  	return ret;
> >  }
> >  
> > -/* copied from lirc_dev */
> > -static ssize_t read(struct file *filep, char __user *outbuf, size_t
> > n,
> > -		    loff_t *ppos)
> > -{
> > -	struct IR *ir = lirc_get_pdata(filep);
> > -	struct IR_rx *rx;
> > -	struct lirc_buffer *rbuf = ir->l->buf;
> > -	int ret = 0, written = 0, retries = 0;
> > -	unsigned int m;
> > -	DECLARE_WAITQUEUE(wait, current);
> > -
> > -	dev_dbg(ir->dev, "read called\n");
> > -	if (n % rbuf->chunk_size) {
> > -		dev_dbg(ir->dev, "read result = -EINVAL\n");
> > -		return -EINVAL;
> > -	}
> > -
> > -	rx = get_ir_rx(ir);
> > -	if (!rx)
> > -		return -ENXIO;
> > -
> > -	/*
> > -	 * we add ourselves to the task queue before buffer check
> > -	 * to avoid losing scan code (in case when queue is awaken
> > somewhere
> > -	 * between while condition checking and scheduling)
> > -	 */
> > -	add_wait_queue(&rbuf->wait_poll, &wait);
> > -	set_current_state(TASK_INTERRUPTIBLE);
> > -
> > -	/*
> > -	 * while we didn't provide 'length' bytes, device is opened
> > in blocking
> > -	 * mode and 'copy_to_user' is happy, wait for data.
> > -	 */
> > -	while (written < n && ret == 0) {
> > -		if (lirc_buffer_empty(rbuf)) {
> > -			/*
> > -			 * According to the read(2) man page,
> > 'written' can be
> > -			 * returned as less than 'n', instead of
> > blocking
> > -			 * again, returning -EWOULDBLOCK, or
> > returning
> > -			 * -ERESTARTSYS
> > -			 */
> > -			if (written)
> > -				break;
> > -			if (filep->f_flags & O_NONBLOCK) {
> > -				ret = -EWOULDBLOCK;
> > -				break;
> > -			}
> > -			if (signal_pending(current)) {
> > -				ret = -ERESTARTSYS;
> > -				break;
> > -			}
> > -			schedule();
> > -			set_current_state(TASK_INTERRUPTIBLE);
> > -		} else {
> > -			unsigned char buf[MAX_XFER_SIZE];
> > -
> > -			if (rbuf->chunk_size > sizeof(buf)) {
> > -				dev_err(ir->dev,
> > -					"chunk_size is too big
> > (%d)!\n",
> > -					rbuf->chunk_size);
> > -				ret = -EINVAL;
> > -				break;
> > -			}
> > -			m = lirc_buffer_read(rbuf, buf);
> > -			if (m == rbuf->chunk_size) {
> > -				ret = copy_to_user(outbuf + written,
> > buf,
> > -						   rbuf-
> > >chunk_size);
> > -				written += rbuf->chunk_size;
> > -			} else {
> > -				retries++;
> > -			}
> > -			if (retries >= 5) {
> > -				dev_err(ir->dev, "Buffer read
> > failed!\n");
> > -				ret = -EIO;
> > -			}
> > -		}
> > -	}
> > -
> > -	remove_wait_queue(&rbuf->wait_poll, &wait);
> > -	put_ir_rx(rx, false);
> > -	set_current_state(TASK_RUNNING);
> > -
> > -	dev_dbg(ir->dev, "read result = %d (%s)\n", ret,
> > -		ret ? "Error" : "OK");
> > -
> > -	return ret ? ret : written;
> > -}
> > -
> >  /* send a keypress to the IR TX device */
> >  static int send_code(struct IR_tx *tx, unsigned int code, unsigned
> > int key)
> >  {
> > @@ -976,7 +497,7 @@ static int send_code(struct IR_tx *tx, unsigned
> > int code, unsigned int key)
> >  	ret = get_key_data(data_block, code, key);
> >  
> >  	if (ret == -EPROTO) {
> > -		dev_err(tx->ir->dev,
> > +		dev_err(&tx->l->dev,
> >  			"failed to get data for code %u, key %u --
> > check lircd.conf entries\n",
> >  			code, key);
> >  		return ret;
> > @@ -994,7 +515,7 @@ static int send_code(struct IR_tx *tx, unsigned
> > int code, unsigned int key)
> >  	buf[1] = 0x40;
> >  	ret = i2c_master_send(tx->c, buf, 2);
> >  	if (ret != 2) {
> > -		dev_err(tx->ir->dev, "i2c_master_send failed with
> > %d\n", ret);
> > +		dev_err(&tx->l->dev, "i2c_master_send failed with
> > %d\n", ret);
> >  		return ret < 0 ? ret : -EFAULT;
> >  	}
> >  
> > @@ -1007,18 +528,18 @@ static int send_code(struct IR_tx *tx,
> > unsigned int code, unsigned int key)
> >  	}
> >  
> >  	if (ret != 1) {
> > -		dev_err(tx->ir->dev, "i2c_master_send failed with
> > %d\n", ret);
> > +		dev_err(&tx->l->dev, "i2c_master_send failed with
> > %d\n", ret);
> >  		return ret < 0 ? ret : -EFAULT;
> >  	}
> >  
> >  	/* Send finished download? */
> >  	ret = i2c_master_recv(tx->c, buf, 1);
> >  	if (ret != 1) {
> > -		dev_err(tx->ir->dev, "i2c_master_recv failed with
> > %d\n", ret);
> > +		dev_err(&tx->l->dev, "i2c_master_recv failed with
> > %d\n", ret);
> >  		return ret < 0 ? ret : -EFAULT;
> >  	}
> >  	if (buf[0] != 0xA0) {
> > -		dev_err(tx->ir->dev, "unexpected IR TX response #1:
> > %02x\n",
> > +		dev_err(&tx->l->dev, "unexpected IR TX response #1:
> > %02x\n",
> >  			buf[0]);
> >  		return -EFAULT;
> >  	}
> > @@ -1028,7 +549,7 @@ static int send_code(struct IR_tx *tx, unsigned
> > int code, unsigned int key)
> >  	buf[1] = 0x80;
> >  	ret = i2c_master_send(tx->c, buf, 2);
> >  	if (ret != 2) {
> > -		dev_err(tx->ir->dev, "i2c_master_send failed with
> > %d\n", ret);
> > +		dev_err(&tx->l->dev, "i2c_master_send failed with
> > %d\n", ret);
> >  		return ret < 0 ? ret : -EFAULT;
> >  	}
> >  
> > @@ -1038,7 +559,7 @@ static int send_code(struct IR_tx *tx, unsigned
> > int code, unsigned int key)
> >  	 * going to skip this whole mess and say we're done on the
> > HD PVR
> >  	 */
> >  	if (!tx->post_tx_ready_poll) {
> > -		dev_dbg(tx->ir->dev, "sent code %u, key %u\n", code,
> > key);
> > +		dev_dbg(&tx->l->dev, "sent code %u, key %u\n", code,
> > key);
> >  		return 0;
> >  	}
> >  
> > @@ -1054,12 +575,12 @@ static int send_code(struct IR_tx *tx,
> > unsigned int code, unsigned int key)
> >  		ret = i2c_master_send(tx->c, buf, 1);
> >  		if (ret == 1)
> >  			break;
> > -		dev_dbg(tx->ir->dev,
> > +		dev_dbg(&tx->l->dev,
> >  			"NAK expected: i2c_master_send failed with
> > %d (try %d)\n",
> >  			ret, i + 1);
> >  	}
> >  	if (ret != 1) {
> > -		dev_err(tx->ir->dev,
> > +		dev_err(&tx->l->dev,
> >  			"IR TX chip never got ready: last
> > i2c_master_send failed with %d\n",
> >  			ret);
> >  		return ret < 0 ? ret : -EFAULT;
> > @@ -1068,17 +589,17 @@ static int send_code(struct IR_tx *tx,
> > unsigned int code, unsigned int key)
> >  	/* Seems to be an 'ok' response */
> >  	i = i2c_master_recv(tx->c, buf, 1);
> >  	if (i != 1) {
> > -		dev_err(tx->ir->dev, "i2c_master_recv failed with
> > %d\n", ret);
> > +		dev_err(&tx->l->dev, "i2c_master_recv failed with
> > %d\n", ret);
> >  		return -EFAULT;
> >  	}
> >  	if (buf[0] != 0x80) {
> > -		dev_err(tx->ir->dev, "unexpected IR TX response #2:
> > %02x\n",
> > +		dev_err(&tx->l->dev, "unexpected IR TX response #2:
> > %02x\n",
> >  			buf[0]);
> >  		return -EFAULT;
> >  	}
> >  
> >  	/* Oh good, it worked */
> > -	dev_dbg(tx->ir->dev, "sent code %u, key %u\n", code, key);
> > +	dev_dbg(&tx->l->dev, "sent code %u, key %u\n", code, key);
> >  	return 0;
> >  }
> >  
> > @@ -1091,8 +612,7 @@ static int send_code(struct IR_tx *tx, unsigned
> > int code, unsigned int key)
> >  static ssize_t write(struct file *filep, const char __user *buf,
> > size_t n,
> >  		     loff_t *ppos)
> >  {
> > -	struct IR *ir = lirc_get_pdata(filep);
> > -	struct IR_tx *tx;
> > +	struct IR_tx *tx = lirc_get_pdata(filep);
> >  	size_t i;
> >  	int failures = 0;
> >  
> > @@ -1100,31 +620,20 @@ static ssize_t write(struct file *filep, const
> > char __user *buf, size_t n,
> >  	if (n % sizeof(int))
> >  		return -EINVAL;
> >  
> > -	/* Get a struct IR_tx reference */
> > -	tx = get_ir_tx(ir);
> > -	if (!tx)
> > -		return -ENXIO;
> > -
> >  	/* Ensure our tx->c i2c_client remains valid for the
> > duration */
> >  	mutex_lock(&tx->client_lock);
> >  	if (!tx->c) {
> >  		mutex_unlock(&tx->client_lock);
> > -		put_ir_tx(tx, false);
> >  		return -ENXIO;
> >  	}
> >  
> > -	/* Lock i2c bus for the duration */
> > -	mutex_lock(&ir->ir_lock);
> > -
> >  	/* Send each keypress */
> >  	for (i = 0; i < n;) {
> >  		int ret = 0;
> >  		int command;
> >  
> >  		if (copy_from_user(&command, buf + i,
> > sizeof(command))) {
> > -			mutex_unlock(&ir->ir_lock);
> >  			mutex_unlock(&tx->client_lock);
> > -			put_ir_tx(tx, false);
> >  			return -EFAULT;
> >  		}
> >  
> > @@ -1133,9 +642,7 @@ static ssize_t write(struct file *filep, const
> > char __user *buf, size_t n,
> >  			/* Make sure we have the 'firmware' loaded,
> > first */
> >  			ret = fw_load(tx);
> >  			if (ret != 0) {
> > -				mutex_unlock(&ir->ir_lock);
> >  				mutex_unlock(&tx->client_lock);
> > -				put_ir_tx(tx, false);
> >  				if (ret != -ENOMEM)
> >  					ret = -EIO;
> >  				return ret;
> > @@ -1151,9 +658,7 @@ static ssize_t write(struct file *filep, const
> > char __user *buf, size_t n,
> >  			ret = send_code(tx, (unsigned int)command >>
> > 16,
> >  					    (unsigned int)command &
> > 0xFFFF);
> >  			if (ret == -EPROTO) {
> > -				mutex_unlock(&ir->ir_lock);
> >  				mutex_unlock(&tx->client_lock);
> > -				put_ir_tx(tx, false);
> >  				return ret;
> >  			}
> >  		}
> > @@ -1164,15 +669,13 @@ static ssize_t write(struct file *filep, const
> > char __user *buf, size_t n,
> >  		 */
> >  		if (ret != 0) {
> >  			/* Looks like the chip crashed, reset it */
> > -			dev_err(tx->ir->dev,
> > +			dev_err(&tx->l->dev,
> >  				"sending to the IR transmitter chip
> > failed, trying reset\n");
> >  
> >  			if (failures >= 3) {
> > -				dev_err(tx->ir->dev,
> > +				dev_err(&tx->l->dev,
> >  					"unable to send to the IR
> > chip after 3 resets, giving up\n");
> > -				mutex_unlock(&ir->ir_lock);
> >  				mutex_unlock(&tx->client_lock);
> > -				put_ir_tx(tx, false);
> >  				return ret;
> >  			}
> >  			set_current_state(TASK_UNINTERRUPTIBLE);
> > @@ -1184,60 +687,21 @@ static ssize_t write(struct file *filep, const
> > char __user *buf, size_t n,
> >  		}
> >  	}
> >  
> > -	/* Release i2c bus */
> > -	mutex_unlock(&ir->ir_lock);
> > -
> >  	mutex_unlock(&tx->client_lock);
> >  
> > -	/* Give back our struct IR_tx reference */
> > -	put_ir_tx(tx, false);
> > -
> >  	/* All looks good */
> >  	return n;
> >  }
> >  
> > -/* copied from lirc_dev */
> > -static unsigned int poll(struct file *filep, poll_table *wait)
> > -{
> > -	struct IR *ir = lirc_get_pdata(filep);
> > -	struct IR_rx *rx;
> > -	struct lirc_buffer *rbuf = ir->l->buf;
> > -	unsigned int ret;
> > -
> > -	dev_dbg(ir->dev, "%s called\n", __func__);
> > -
> > -	rx = get_ir_rx(ir);
> > -	if (!rx) {
> > -		/*
> > -		 * Revisit this, if our poll function ever reports
> > writeable
> > -		 * status for Tx
> > -		 */
> > -		dev_dbg(ir->dev, "%s result = POLLERR\n", __func__);
> > -		return POLLERR;
> > -	}
> > -
> > -	/*
> > -	 * Add our lirc_buffer's wait_queue to the poll_table. A
> > wake up on
> > -	 * that buffer's wait queue indicates we may have a new poll
> > status.
> > -	 */
> > -	poll_wait(filep, &rbuf->wait_poll, wait);
> > -
> > -	/* Indicate what ops could happen immediately without
> > blocking */
> > -	ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN | POLLRDNORM);
> > -
> > -	dev_dbg(ir->dev, "%s result = %s\n", __func__,
> > -		ret ? "POLLIN|POLLRDNORM" : "none");
> > -	return ret;
> > -}
> >  
> >  static long ioctl(struct file *filep, unsigned int cmd, unsigned
> > long arg)
> >  {
> > -	struct IR *ir = lirc_get_pdata(filep);
> > +	struct IR_tx *tx = lirc_get_pdata(filep);
> >  	unsigned long __user *uptr = (unsigned long __user *)arg;
> >  	int result;
> >  	unsigned long mode, features;
> >  
> > -	features = ir->l->features;
> > +	features = tx->l->features;
> >  
> >  	switch (cmd) {
> >  	case LIRC_GET_LENGTH:
> > @@ -1287,13 +751,7 @@ static long ioctl(struct file *filep, unsigned
> > int cmd, unsigned long arg)
> >   */
> >  static int open(struct inode *node, struct file *filep)
> >  {
> > -	struct IR *ir;
> > -
> >  	lirc_init_pdata(node, filep);
> > -	ir = lirc_get_pdata(filep);
> > -
> > -	atomic_inc(&ir->open_count);
> > -
> >  	nonseekable_open(node, filep);
> >  	return 0;
> >  }
> > @@ -1301,25 +759,16 @@ static int open(struct inode *node, struct
> > file *filep)
> >  /* Close the IR device */
> >  static int close(struct inode *node, struct file *filep)
> >  {
> > -	struct IR *ir = lirc_get_pdata(filep);
> > -
> > -	atomic_dec(&ir->open_count);
> > -
> > -	put_ir_device(ir, false);
> >  	return 0;
> >  }
> >  
> > -static int ir_remove(struct i2c_client *client);
> >  static int ir_probe(struct i2c_client *client, const struct
> > i2c_device_id *id);
> >  
> > -#define ID_FLAG_TX	0x01
> > -#define ID_FLAG_HDPVR	0x02
> > +#define ID_FLAG_HDPVR	0x01
> >  
> >  static const struct i2c_device_id ir_transceiver_id[] = {
> > -	{ "ir_tx_z8f0811_haup",  ID_FLAG_TX                 },
> > -	{ "ir_rx_z8f0811_haup",  0                          },
> > -	{ "ir_tx_z8f0811_hdpvr", ID_FLAG_HDPVR | ID_FLAG_TX },
> > -	{ "ir_rx_z8f0811_hdpvr", ID_FLAG_HDPVR              },
> > +	{ "ir_tx_z8f0811_haup",  0 },
> > +	{ "ir_tx_z8f0811_hdpvr", ID_FLAG_HDPVR },
> >  	{ }
> >  };
> >  MODULE_DEVICE_TABLE(i2c, ir_transceiver_id);
> > @@ -1329,16 +778,13 @@ static struct i2c_driver driver = {
> >  		.name	= "Zilog/Hauppauge i2c IR",
> >  	},
> >  	.probe		= ir_probe,
> > -	.remove		= ir_remove,
> >  	.id_table	= ir_transceiver_id,
> >  };
> >  
> >  static const struct file_operations lirc_fops = {
> >  	.owner		= THIS_MODULE,
> >  	.llseek		= no_llseek,
> > -	.read		= read,
> >  	.write		= write,
> > -	.poll		= poll,
> >  	.unlocked_ioctl	= ioctl,
> >  #ifdef CONFIG_COMPAT
> >  	.compat_ioctl	= ioctl,
> > @@ -1347,55 +793,11 @@ static const struct file_operations lirc_fops
> > = {
> >  	.release	= close
> >  };
> >  
> > -static int ir_remove(struct i2c_client *client)
> > -{
> > -	if (strncmp("ir_tx_z8", client->name, 8) == 0) {
> > -		struct IR_tx *tx = i2c_get_clientdata(client);
> > -
> > -		if (tx) {
> > -			mutex_lock(&tx->client_lock);
> > -			tx->c = NULL;
> > -			mutex_unlock(&tx->client_lock);
> > -			put_ir_tx(tx, false);
> > -		}
> > -	} else if (strncmp("ir_rx_z8", client->name, 8) == 0) {
> > -		struct IR_rx *rx = i2c_get_clientdata(client);
> > -
> > -		if (rx) {
> > -			mutex_lock(&rx->client_lock);
> > -			rx->c = NULL;
> > -			mutex_unlock(&rx->client_lock);
> > -			put_ir_rx(rx, false);
> > -		}
> > -	}
> > -	return 0;
> > -}
> > -
> > -/* ir_devices_lock must be held */
> > -static struct IR *get_ir_device_by_adapter(struct i2c_adapter
> > *adapter)
> > -{
> > -	struct IR *ir;
> > -
> > -	if (list_empty(&ir_devices_list))
> > -		return NULL;
> > -
> > -	list_for_each_entry(ir, &ir_devices_list, list)
> > -		if (ir->adapter == adapter) {
> > -			get_ir_device(ir, true);
> > -			return ir;
> > -		}
> > -
> > -	return NULL;
> > -}
> > -
> >  static int ir_probe(struct i2c_client *client, const struct
> > i2c_device_id *id)
> >  {
> > -	struct IR *ir;
> >  	struct IR_tx *tx;
> > -	struct IR_rx *rx;
> >  	struct i2c_adapter *adap = client->adapter;
> >  	int ret;
> > -	bool tx_probe = false;
> >  
> >  	dev_dbg(&client->dev, "%s: %s on i2c-%d (%s), client
> > addr=0x%02x\n",
> >  		__func__, id->name, adap->nr, adap->name, client-
> > >addr);
> > @@ -1405,209 +807,61 @@ static int ir_probe(struct i2c_client
> > *client, const struct i2c_device_id *id)
> >  	 * The IR transmitter is at i2c address 0x70.
> >  	 */
> >  
> > -	if (id->driver_data & ID_FLAG_TX)
> > -		tx_probe = true;
> > -	else if (tx_only) /* module option */
> > -		return -ENXIO;
> > -
> > -	pr_info("probing IR %s on %s (i2c-%d)\n",
> > -		tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
> > -
> > -	mutex_lock(&ir_devices_lock);
> > -
> > -	/* Use a single struct IR instance for both the Rx and Tx
> > functions */
> > -	ir = get_ir_device_by_adapter(adap);
> > -	if (!ir) {
> > -		ir = kzalloc(sizeof(*ir), GFP_KERNEL);
> > -		if (!ir) {
> > -			ret = -ENOMEM;
> > -			goto out_no_ir;
> > -		}
> > -		kref_init(&ir->ref);
> > -
> > -		/* store for use in ir_probe() again, and open()
> > later on */
> > -		INIT_LIST_HEAD(&ir->list);
> > -		list_add_tail(&ir->list, &ir_devices_list);
> > -
> > -		ir->adapter = adap;
> > -		ir->dev = &adap->dev;
> > -		mutex_init(&ir->ir_lock);
> > -		atomic_set(&ir->open_count, 0);
> > -		spin_lock_init(&ir->tx_ref_lock);
> > -		spin_lock_init(&ir->rx_ref_lock);
> > -
> > -		/* set lirc_dev stuff */
> > -		ir->l = lirc_allocate_device();
> > -		if (!ir->l) {
> > -			ret = -ENOMEM;
> > -			goto out_put_ir;
> > -		}
> > -
> > -		snprintf(ir->l->name, sizeof(ir->l->name),
> > "lirc_zilog");
> > -		ir->l->code_length = 13;
> > -		ir->l->fops = &lirc_fops;
> > -		ir->l->owner = THIS_MODULE;
> > -		ir->l->dev.parent = &adap->dev;
> > -
> > -		/*
> > -		 * FIXME this is a pointer reference to us, but no
> > refcount.
> > -		 *
> > -		 * This OK for now, since lirc_dev currently won't
> > touch this
> > -		 * buffer as we provide our own lirc_fops.
> > -		 *
> > -		 * Currently our own lirc_fops rely on this ir->l-
> > >buf pointer
> > -		 */
> > -		ir->l->buf = &ir->rbuf;
> > -		/* This will be returned by lirc_get_pdata() */
> > -		ir->l->data = ir;
> > -		ret = lirc_buffer_init(ir->l->buf, 2, BUFLEN / 2);
> > -		if (ret) {
> > -			lirc_free_device(ir->l);
> > -			ir->l = NULL;
> > -			goto out_put_ir;
> > -		}
> > -	}
> > +	pr_info("probing IR Tx on %s (i2c-%d)\n", adap->name, adap-
> > >nr);
> >  
> > -	if (tx_probe) {
> > -		/* Get the IR_rx instance for later, if already
> > allocated */
> > -		rx = get_ir_rx(ir);
> > -
> > -		/* Set up a struct IR_tx instance */
> > -		tx = kzalloc(sizeof(*tx), GFP_KERNEL);
> > -		if (!tx) {
> > -			ret = -ENOMEM;
> > -			goto out_put_xx;
> > -		}
> > -		kref_init(&tx->ref);
> > -		ir->tx = tx;
> > -
> > -		ir->l->features |= LIRC_CAN_SEND_LIRCCODE;
> > -		mutex_init(&tx->client_lock);
> > -		tx->c = client;
> > -		tx->need_boot = 1;
> > -		tx->post_tx_ready_poll =
> > -			       (id->driver_data & ID_FLAG_HDPVR) ?
> > false : true;
> > -
> > -		/* An ir ref goes to the struct IR_tx instance */
> > -		tx->ir = get_ir_device(ir, true);
> > -
> > -		/* A tx ref goes to the i2c_client */
> > -		i2c_set_clientdata(client, get_ir_tx(ir));
> > -
> > -		/*
> > -		 * Load the 'firmware'.  We do this before
> > registering with
> > -		 * lirc_dev, so the first firmware load attempt does
> > not happen
> > -		 * after a open() or write() call on the device.
> > -		 *
> > -		 * Failure here is not deemed catastrophic, so the
> > receiver will
> > -		 * still be usable.  Firmware load will be retried
> > in write(),
> > -		 * if it is needed.
> > -		 */
> > -		fw_load(tx);
> > -
> > -		/* Proceed only if the Rx client is also ready or
> > not needed */
> > -		if (!rx && !tx_only) {
> > -			dev_info(tx->ir->dev,
> > -				 "probe of IR Tx on %s (i2c-%d)
> > done. Waiting on IR Rx.\n",
> > -				 adap->name, adap->nr);
> > -			goto out_ok;
> > -		}
> > -	} else {
> > -		/* Get the IR_tx instance for later, if already
> > allocated */
> > -		tx = get_ir_tx(ir);
> > -
> > -		/* Set up a struct IR_rx instance */
> > -		rx = kzalloc(sizeof(*rx), GFP_KERNEL);
> > -		if (!rx) {
> > -			ret = -ENOMEM;
> > -			goto out_put_xx;
> > -		}
> > -		kref_init(&rx->ref);
> > -		ir->rx = rx;
> > -
> > -		ir->l->features |= LIRC_CAN_REC_LIRCCODE;
> > -		mutex_init(&rx->client_lock);
> > -		rx->c = client;
> > -		rx->hdpvr_data_fmt =
> > -			       (id->driver_data & ID_FLAG_HDPVR) ?
> > true : false;
> > -
> > -		/* An ir ref goes to the struct IR_rx instance */
> > -		rx->ir = get_ir_device(ir, true);
> > +	/* Set up a struct IR_tx instance */
> > +	tx = devm_kzalloc(&client->dev, sizeof(*tx), GFP_KERNEL);
> > +	if (!tx)
> > +		return -ENOMEM;
> >  
> > -		/* An rx ref goes to the i2c_client */
> > -		i2c_set_clientdata(client, get_ir_rx(ir));
> > +	mutex_init(&tx->client_lock);
> > +	tx->c = client;
> > +	tx->need_boot = 1;
> > +	tx->post_tx_ready_poll = !(id->driver_data & ID_FLAG_HDPVR);
> >  
> > -		/*
> > -		 * Start the polling thread.
> > -		 * It will only perform an empty loop around
> > schedule_timeout()
> > -		 * until we register with lirc_dev and the first
> > user open()
> > -		 */
> > -		/* An ir ref goes to the new rx polling kthread */
> > -		rx->task = kthread_run(lirc_thread,
> > get_ir_device(ir, true),
> > -				       "zilog-rx-i2c-%d", adap->nr);
> > -		if (IS_ERR(rx->task)) {
> > -			ret = PTR_ERR(rx->task);
> > -			dev_err(tx->ir->dev,
> > -				"%s: could not start IR Rx polling
> > thread\n",
> > -				__func__);
> > -			/* Failed kthread, so put back the ir ref */
> > -			put_ir_device(ir, true);
> > -			/* Failure exit, so put back rx ref from
> > i2c_client */
> > -			i2c_set_clientdata(client, NULL);
> > -			put_ir_rx(rx, true);
> > -			ir->l->features &= ~LIRC_CAN_REC_LIRCCODE;
> > -			goto out_put_tx;
> > -		}
> > +	/* set lirc_dev stuff */
> > +	tx->l = lirc_allocate_device();
> > +	if (!tx->l)
> > +		return -ENOMEM;
> >  
> > -		/* Proceed only if the Tx client is also ready */
> > -		if (!tx) {
> > -			pr_info("probe of IR Rx on %s (i2c-%d) done.
> > Waiting on IR Tx.\n",
> > -				adap->name, adap->nr);
> > -			goto out_ok;
> > -		}
> > -	}
> > +	snprintf(tx->l->name, sizeof(tx->l->name), "lirc_zilog");
> > +	tx->l->features |= LIRC_CAN_SEND_LIRCCODE;
> > +	tx->l->code_length = 13;
> > +	tx->l->fops = &lirc_fops;
> > +	tx->l->owner = THIS_MODULE;
> > +	tx->l->dev.parent = &client->dev;
> >  
> >  	/* register with lirc */
> > -	ret = lirc_register_device(ir->l);
> > +	ret = lirc_register_device(tx->l);
> >  	if (ret < 0) {
> > -		dev_err(tx->ir->dev,
> > -			"%s: lirc_register_device() failed: %i\n",
> > +		dev_err(&tx->l->dev, "%s: lirc_register_device()
> > failed: %i\n",
> >  			__func__, ret);
> > -		lirc_free_device(ir->l);
> > -		ir->l = NULL;
> > -		goto out_put_xx;
> > +		lirc_free_device(tx->l);
> > +		tx->l = NULL;
> > +		return ret;
> >  	}
> >  
> > -	dev_info(ir->dev,
> > +	/*
> > +	 * Load the 'firmware'.  We do this before registering with
> > +	 * lirc_dev, so the first firmware load attempt does not
> > happen
> > +	 * after a open() or write() call on the device.
> > +	 */
> > +	ret = fw_load(tx);
> > +	if (ret < 0) {
> > +		lirc_unregister_device(tx->l);
> > +		return ret;
> > +	}
> > +
> > +	/* A tx ref goes to the i2c_client */
> > +	i2c_set_clientdata(client, tx);
> > +
> > +	dev_info(&tx->l->dev,
> >  		 "IR unit on %s (i2c-%d) registered as lirc%d and
> > ready\n",
> > -		 adap->name, adap->nr, ir->l->minor);
> > -
> > -out_ok:
> > -	if (rx)
> > -		put_ir_rx(rx, true);
> > -	if (tx)
> > -		put_ir_tx(tx, true);
> > -	put_ir_device(ir, true);
> > -	dev_info(ir->dev,
> > -		 "probe of IR %s on %s (i2c-%d) done\n",
> > -		 tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
> > -	mutex_unlock(&ir_devices_lock);
> > -	return 0;
> > +		 adap->name, adap->nr, tx->l->minor);
> >  
> > -out_put_xx:
> > -	if (rx)
> > -		put_ir_rx(rx, true);
> > -out_put_tx:
> > -	if (tx)
> > -		put_ir_tx(tx, true);
> > -out_put_ir:
> > -	put_ir_device(ir, true);
> > -out_no_ir:
> > -	dev_err(&client->dev,
> > -		"%s: probing IR %s on %s (i2c-%d) failed with %d\n",
> > -		__func__, tx_probe ? "Tx" : "Rx", adap->name, adap-
> > >nr, ret);
> > -	mutex_unlock(&ir_devices_lock);
> > -	return ret;
> > +	dev_info(&tx->l->dev,
> > +		 "probe of IR Tx on %s (i2c-%d) done\n", adap->name, 
> > adap->nr);
> > +	return 0;
> >  }
> >  
> >  static int __init zilog_init(void)
> > @@ -1648,6 +902,3 @@ MODULE_ALIAS("lirc_pvr150");
> >  
> >  module_param(debug, bool, 0644);
> >  MODULE_PARM_DESC(debug, "Enable debugging messages");
> > -
> > -module_param(tx_only, bool, 0644);
> > -MODULE_PARM_DESC(tx_only, "Only handle the IR transmit function");

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 04/26] media: lirc_zilog: remove receiver
  2017-10-11 21:02     ` Sean Young
@ 2017-10-11 23:24       ` Andy Walls
  2017-10-12  0:25         ` Devin Heitmueller
  0 siblings, 1 reply; 39+ messages in thread
From: Andy Walls @ 2017-10-11 23:24 UTC (permalink / raw)
  To: Sean Young; +Cc: linux-media

On October 11, 2017 5:02:37 PM EDT, Sean Young <sean@mess.org> wrote:
>On Wed, Oct 11, 2017 at 03:43:16PM -0400, Andy Walls wrote:
>> On Tue, 2017-10-10 at 08:17 +0100, Sean Young wrote:
>> > The ir-kbd-i2c module already handles this very well.
>> 
>> Hi Sean:
>> 
>> It's been years, but my recollection is that although ir-kdb-i2c
>might
>> handle receive well, but since the 4 i2c addresses (1 Rx, 1 Tx, 1 IR
>Tx
>> code learning, 1 custom Tx code) are all handled by the same Zilog
>> microcontroller internally, that splitting the Rx and Tx
>functionality
>> between two modules became problematic.
>> 
>> Believe me, if i could have leveraged ir-kdb-i2c back when I ported
>> this, I would have.  I think it's a very bad idea to remove the
>> receiver from lirc_zilog.
>> 
>> The cx18 and ivtv drivers both use lirc_zilog IIRC.  Have you looked
>at
>> the changes required to have the first I2C address used by one i2c
>> module, and the next one (or three) I2C addresses used by another i2c
>> module?
>
>This is already the case.
>
>In current kernels you can use ir-kbd-i2c for Rx and lirc_zilog for Tx,
>this works fine. In fact, the lirc_zilog Rx code produces lirccodes,
>(not mode2) and ir-kbd-i2c produces keycodes through rc-core, so
>ir-kbd-i2c
>(also mainline, not staging) is much more likely to be used for Rx. For
>Tx
>you have to use lirc_zilog.
>
>I haven't heard of any reports of problems (or observed this myself)
>when
>using these two modules together.
>
>As you point out, both drivers sending i2c commands to the same z8f0811
>
>with its z8 encore hand-coded i2c implementation. But they're using
>different
>addresses.
>
>So removing the lirc_zilog Rx doesn't make things worse, in fact, it
>just
>removes some code which is unlikely to be used.
>
>It's the hdpvr, ivtv, cx18 and pvrusb2 drivers which have a Tx
>interface. I
>have hdpvr and ivtv hardware to test.
>
>
>Sean
>
>> 
>> -Andy
>> 
>> 
>> > 
>> > Signed-off-by: Sean Young <sean@mess.org>
>> > ---
>> >  drivers/staging/media/lirc/lirc_zilog.c | 901
>+++-------------------
>> > ----------
>> >  1 file changed, 76 insertions(+), 825 deletions(-)
>> > 
>> > diff --git a/drivers/staging/media/lirc/lirc_zilog.c
>> > b/drivers/staging/media/lirc/lirc_zilog.c
>> > index 6bd0717bf76e..757b3fc247ac 100644
>> > --- a/drivers/staging/media/lirc/lirc_zilog.c
>> > +++ b/drivers/staging/media/lirc/lirc_zilog.c
>> > @@ -64,28 +64,7 @@
>> >  /* Max transfer size done by I2C transfer functions */
>> >  #define MAX_XFER_SIZE  64
>> >  
>> > -struct IR;
>> > -
>> > -struct IR_rx {
>> > -	struct kref ref;
>> > -	struct IR *ir;
>> > -
>> > -	/* RX device */
>> > -	struct mutex client_lock;
>> > -	struct i2c_client *c;
>> > -
>> > -	/* RX polling thread data */
>> > -	struct task_struct *task;
>> > -
>> > -	/* RX read data */
>> > -	unsigned char b[3];
>> > -	bool hdpvr_data_fmt;
>> > -};
>> > -
>> >  struct IR_tx {
>> > -	struct kref ref;
>> > -	struct IR *ir;
>> > -
>> >  	/* TX device */
>> >  	struct mutex client_lock;
>> >  	struct i2c_client *c;
>> > @@ -93,39 +72,9 @@ struct IR_tx {
>> >  	/* TX additional actions needed */
>> >  	int need_boot;
>> >  	bool post_tx_ready_poll;
>> > -};
>> > -
>> > -struct IR {
>> > -	struct kref ref;
>> > -	struct list_head list;
>> > -
>> > -	/* FIXME spinlock access to l->features */
>> >  	struct lirc_dev *l;
>> > -	struct lirc_buffer rbuf;
>> > -
>> > -	struct mutex ir_lock;
>> > -	atomic_t open_count;
>> > -
>> > -	struct device *dev;
>> > -	struct i2c_adapter *adapter;
>> > -
>> > -	spinlock_t rx_ref_lock; /* struct IR_rx kref get()/put() */
>> > -	struct IR_rx *rx;
>> > -
>> > -	spinlock_t tx_ref_lock; /* struct IR_tx kref get()/put() */
>> > -	struct IR_tx *tx;
>> >  };
>> >  
>> > -/* IR transceiver instance object list */
>> > -/*
>> > - * This lock is used for the following:
>> > - * a. ir_devices_list access, insertions, deletions
>> > - * b. struct IR kref get()s and put()s
>> > - * c. serialization of ir_probe() for the two i2c_clients for a Z8
>> > - */
>> > -static DEFINE_MUTEX(ir_devices_lock);
>> > -static LIST_HEAD(ir_devices_list);
>> > -
>> >  /* Block size for IR transmitter */
>> >  #define TX_BLOCK_SIZE	99
>> >  
>> > @@ -153,348 +102,8 @@ struct tx_data_struct {
>> >  static struct tx_data_struct *tx_data;
>> >  static struct mutex tx_data_lock;
>> >  
>> > -
>> >  /* module parameters */
>> >  static bool debug;	/* debug output */
>> > -static bool tx_only;	/* only handle the IR Tx function */
>> > -
>> > -
>> > -/* struct IR reference counting */
>> > -static struct IR *get_ir_device(struct IR *ir, bool
>> > ir_devices_lock_held)
>> > -{
>> > -	if (ir_devices_lock_held) {
>> > -		kref_get(&ir->ref);
>> > -	} else {
>> > -		mutex_lock(&ir_devices_lock);
>> > -		kref_get(&ir->ref);
>> > -		mutex_unlock(&ir_devices_lock);
>> > -	}
>> > -	return ir;
>> > -}
>> > -
>> > -static void release_ir_device(struct kref *ref)
>> > -{
>> > -	struct IR *ir = container_of(ref, struct IR, ref);
>> > -
>> > -	/*
>> > -	 * Things should be in this state by now:
>> > -	 * ir->rx set to NULL and deallocated - happens before ir-
>> > >rx->ir put()
>> > -	 * ir->rx->task kthread stopped - happens before ir->rx->ir
>> > put()
>> > -	 * ir->tx set to NULL and deallocated - happens before ir-
>> > >tx->ir put()
>> > -	 * ir->open_count ==  0 - happens on final close()
>> > -	 * ir_lock, tx_ref_lock, rx_ref_lock, all released
>> > -	 */
>> > -	if (ir->l)
>> > -		lirc_unregister_device(ir->l);
>> > -
>> > -	if (kfifo_initialized(&ir->rbuf.fifo))
>> > -		lirc_buffer_free(&ir->rbuf);
>> > -	list_del(&ir->list);
>> > -	kfree(ir);
>> > -}
>> > -
>> > -static int put_ir_device(struct IR *ir, bool ir_devices_lock_held)
>> > -{
>> > -	int released;
>> > -
>> > -	if (ir_devices_lock_held)
>> > -		return kref_put(&ir->ref, release_ir_device);
>> > -
>> > -	mutex_lock(&ir_devices_lock);
>> > -	released = kref_put(&ir->ref, release_ir_device);
>> > -	mutex_unlock(&ir_devices_lock);
>> > -
>> > -	return released;
>> > -}
>> > -
>> > -/* struct IR_rx reference counting */
>> > -static struct IR_rx *get_ir_rx(struct IR *ir)
>> > -{
>> > -	struct IR_rx *rx;
>> > -
>> > -	spin_lock(&ir->rx_ref_lock);
>> > -	rx = ir->rx;
>> > -	if (rx)
>> > -		kref_get(&rx->ref);
>> > -	spin_unlock(&ir->rx_ref_lock);
>> > -	return rx;
>> > -}
>> > -
>> > -static void destroy_rx_kthread(struct IR_rx *rx, bool
>> > ir_devices_lock_held)
>> > -{
>> > -	/* end up polling thread */
>> > -	if (!IS_ERR_OR_NULL(rx->task)) {
>> > -		kthread_stop(rx->task);
>> > -		rx->task = NULL;
>> > -		/* Put the ir ptr that ir_probe() gave to the rx
>> > poll thread */
>> > -		put_ir_device(rx->ir, ir_devices_lock_held);
>> > -	}
>> > -}
>> > -
>> > -static void release_ir_rx(struct kref *ref)
>> > -{
>> > -	struct IR_rx *rx = container_of(ref, struct IR_rx, ref);
>> > -	struct IR *ir = rx->ir;
>> > -
>> > -	/*
>> > -	 * This release function can't do all the work, as we want
>> > -	 * to keep the rx_ref_lock a spinlock, and killing the poll
>> > thread
>> > -	 * and releasing the ir reference can cause a sleep.  That
>> > work is
>> > -	 * performed by put_ir_rx()
>> > -	 */
>> > -	ir->l->features &= ~LIRC_CAN_REC_LIRCCODE;
>> > -	/* Don't put_ir_device(rx->ir) here; lock can't be freed yet
>> > */
>> > -	ir->rx = NULL;
>> > -	/* Don't do the kfree(rx) here; we still need to kill the
>> > poll thread */
>> > -}
>> > -
>> > -static int put_ir_rx(struct IR_rx *rx, bool ir_devices_lock_held)
>> > -{
>> > -	int released;
>> > -	struct IR *ir = rx->ir;
>> > -
>> > -	spin_lock(&ir->rx_ref_lock);
>> > -	released = kref_put(&rx->ref, release_ir_rx);
>> > -	spin_unlock(&ir->rx_ref_lock);
>> > -	/* Destroy the rx kthread while not holding the spinlock */
>> > -	if (released) {
>> > -		destroy_rx_kthread(rx, ir_devices_lock_held);
>> > -		kfree(rx);
>> > -		/* Make sure we're not still in a poll_table
>> > somewhere */
>> > -		wake_up_interruptible(&ir->rbuf.wait_poll);
>> > -	}
>> > -	/* Do a reference put() for the rx->ir reference, if we
>> > released rx */
>> > -	if (released)
>> > -		put_ir_device(ir, ir_devices_lock_held);
>> > -	return released;
>> > -}
>> > -
>> > -/* struct IR_tx reference counting */
>> > -static struct IR_tx *get_ir_tx(struct IR *ir)
>> > -{
>> > -	struct IR_tx *tx;
>> > -
>> > -	spin_lock(&ir->tx_ref_lock);
>> > -	tx = ir->tx;
>> > -	if (tx)
>> > -		kref_get(&tx->ref);
>> > -	spin_unlock(&ir->tx_ref_lock);
>> > -	return tx;
>> > -}
>> > -
>> > -static void release_ir_tx(struct kref *ref)
>> > -{
>> > -	struct IR_tx *tx = container_of(ref, struct IR_tx, ref);
>> > -	struct IR *ir = tx->ir;
>> > -
>> > -	ir->l->features &= ~LIRC_CAN_SEND_LIRCCODE;
>> > -	/* Don't put_ir_device(tx->ir) here, so our lock doesn't get
>> > freed */
>> > -	ir->tx = NULL;
>> > -	kfree(tx);
>> > -}
>> > -
>> > -static int put_ir_tx(struct IR_tx *tx, bool ir_devices_lock_held)
>> > -{
>> > -	int released;
>> > -	struct IR *ir = tx->ir;
>> > -
>> > -	spin_lock(&ir->tx_ref_lock);
>> > -	released = kref_put(&tx->ref, release_ir_tx);
>> > -	spin_unlock(&ir->tx_ref_lock);
>> > -	/* Do a reference put() for the tx->ir reference, if we
>> > released tx */
>> > -	if (released)
>> > -		put_ir_device(ir, ir_devices_lock_held);
>> > -	return released;
>> > -}
>> > -
>> > -static int add_to_buf(struct IR *ir)
>> > -{
>> > -	__u16 code;
>> > -	unsigned char codes[2];
>> > -	unsigned char keybuf[6];
>> > -	int got_data = 0;
>> > -	int ret;
>> > -	int failures = 0;
>> > -	unsigned char sendbuf[1] = { 0 };
>> > -	struct lirc_buffer *rbuf = ir->l->buf;
>> > -	struct IR_rx *rx;
>> > -	struct IR_tx *tx;
>> > -
>> > -	if (lirc_buffer_full(rbuf)) {
>> > -		dev_dbg(ir->dev, "buffer overflow\n");
>> > -		return -EOVERFLOW;
>> > -	}
>> > -
>> > -	rx = get_ir_rx(ir);
>> > -	if (!rx)
>> > -		return -ENXIO;
>> > -
>> > -	/* Ensure our rx->c i2c_client remains valid for the
>> > duration */
>> > -	mutex_lock(&rx->client_lock);
>> > -	if (!rx->c) {
>> > -		mutex_unlock(&rx->client_lock);
>> > -		put_ir_rx(rx, false);
>> > -		return -ENXIO;
>> > -	}
>> > -
>> > -	tx = get_ir_tx(ir);
>> > -
>> > -	/*
>> > -	 * service the device as long as it is returning
>> > -	 * data and we have space
>> > -	 */
>> > -	do {
>> > -		if (kthread_should_stop()) {
>> > -			ret = -ENODATA;
>> > -			break;
>> > -		}
>> > -
>> > -		/*
>> > -		 * Lock i2c bus for the duration.  RX/TX chips
>> > interfere so
>> > -		 * this is worth it
>> > -		 */
>> > -		mutex_lock(&ir->ir_lock);
>> > -
>> > -		if (kthread_should_stop()) {
>> > -			mutex_unlock(&ir->ir_lock);
>> > -			ret = -ENODATA;
>> > -			break;
>> > -		}
>> > -
>> > -		/*
>> > -		 * Send random "poll command" (?)  Windows driver
>> > does this
>> > -		 * and it is a good point to detect chip failure.
>> > -		 */
>> > -		ret = i2c_master_send(rx->c, sendbuf, 1);
>> > -		if (ret != 1) {
>> > -			dev_err(ir->dev, "i2c_master_send failed
>> > with %d\n",
>> > -				ret);
>> > -			if (failures >= 3) {
>> > -				mutex_unlock(&ir->ir_lock);
>> > -				dev_err(ir->dev,
>> > -					"unable to read from the IR
>> > chip after 3 resets, giving up\n");
>> > -				break;
>> > -			}
>> > -
>> > -			/* Looks like the chip crashed, reset it */
>> > -			dev_err(ir->dev,
>> > -				"polling the IR receiver chip
>> > failed, trying reset\n");
>> > -
>> > -			set_current_state(TASK_UNINTERRUPTIBLE);
>> > -			if (kthread_should_stop()) {
>> > -				mutex_unlock(&ir->ir_lock);
>> > -				ret = -ENODATA;
>> > -				break;
>> > -			}
>> > -			schedule_timeout((100 * HZ + 999) / 1000);
>> > -			if (tx)
>> > -				tx->need_boot = 1;
>> > -
>> > -			++failures;
>> > -			mutex_unlock(&ir->ir_lock);
>> > -			ret = 0;
>> > -			continue;
>> > -		}
>> > -
>> > -		if (kthread_should_stop()) {
>> > -			mutex_unlock(&ir->ir_lock);
>> > -			ret = -ENODATA;
>> > -			break;
>> > -		}
>> > -		ret = i2c_master_recv(rx->c, keybuf,
>> > sizeof(keybuf));
>> > -		mutex_unlock(&ir->ir_lock);
>> > -		if (ret != sizeof(keybuf)) {
>> > -			dev_err(ir->dev,
>> > -				"i2c_master_recv failed with %d --
>> > keeping last read buffer\n",
>> > -				ret);
>> > -		} else {
>> > -			rx->b[0] = keybuf[3];
>> > -			rx->b[1] = keybuf[4];
>> > -			rx->b[2] = keybuf[5];
>> > -			dev_dbg(ir->dev,
>> > -				"key (0x%02x/0x%02x)\n",
>> > -				rx->b[0], rx->b[1]);
>> > -		}
>> > -
>> > -		/* key pressed ? */
>> > -		if (rx->hdpvr_data_fmt) {
>> > -			if (got_data && (keybuf[0] == 0x80)) {
>> > -				ret = 0;
>> > -				break;
>> > -			} else if (got_data && (keybuf[0] == 0x00))
>> > {
>> > -				ret = -ENODATA;
>> > -				break;
>> > -			}
>> > -		} else if ((rx->b[0] & 0x80) == 0) {
>> > -			ret = got_data ? 0 : -ENODATA;
>> > -			break;
>> > -		}
>> > -
>> > -		/* look what we have */
>> > -		code = (((__u16)rx->b[0] & 0x7f) << 6) | (rx->b[1]
>> > >> 2);
>> > -
>> > -		codes[0] = (code >> 8) & 0xff;
>> > -		codes[1] = code & 0xff;
>> > -
>> > -		/* return it */
>> > -		lirc_buffer_write(rbuf, codes);
>> > -		++got_data;
>> > -		ret = 0;
>> > -	} while (!lirc_buffer_full(rbuf));
>> > -
>> > -	mutex_unlock(&rx->client_lock);
>> > -	if (tx)
>> > -		put_ir_tx(tx, false);
>> > -	put_ir_rx(rx, false);
>> > -	return ret;
>> > -}
>> > -
>> > -/*
>> > - * Main function of the polling thread -- from lirc_dev.
>> > - * We don't fit the LIRC model at all anymore.  This is horrible,
>> > but
>> > - * basically we have a single RX/TX device with a nasty failure
>mode
>> > - * that needs to be accounted for across the pair.  lirc lets us
>> > provide
>> > - * fops, but prevents us from using the internal polling, etc. if
>we
>> > do
>> > - * so.  Hence the replication.  Might be neater to extend the LIRC
>> > model
>> > - * to account for this but I'd think it's a very special case of
>> > seriously
>> > - * messed up hardware.
>> > - */
>> > -static int lirc_thread(void *arg)
>> > -{
>> > -	struct IR *ir = arg;
>> > -	struct lirc_buffer *rbuf = ir->l->buf;
>> > -
>> > -	dev_dbg(ir->dev, "poll thread started\n");
>> > -
>> > -	while (!kthread_should_stop()) {
>> > -		set_current_state(TASK_INTERRUPTIBLE);
>> > -
>> > -		/* if device not opened, we can sleep half a second
>> > */
>> > -		if (atomic_read(&ir->open_count) == 0) {
>> > -			schedule_timeout(HZ / 2);
>> > -			continue;
>> > -		}
>> > -
>> > -		/*
>> > -		 * This is ~113*2 + 24 + jitter (2*repeat gap + code
>> > length).
>> > -		 * We use this interval as the chip resets every
>> > time you poll
>> > -		 * it (bad!).  This is therefore just sufficient to
>> > catch all
>> > -		 * of the button presses.  It makes the remote much
>> > more
>> > -		 * responsive.  You can see the difference by
>> > running irw and
>> > -		 * holding down a button.  With 100ms, the old
>> > polling
>> > -		 * interval, you'll notice breaks in the repeat
>> > sequence
>> > -		 * corresponding to lost keypresses.
>> > -		 */
>> > -		schedule_timeout((260 * HZ) / 1000);
>> > -		if (kthread_should_stop())
>> > -			break;
>> > -		if (!add_to_buf(ir))
>> > -			wake_up_interruptible(&rbuf->wait_poll);
>> > -	}
>> > -
>> > -	dev_dbg(ir->dev, "poll thread ended\n");
>> > -	return 0;
>> > -}
>> >  
>> >  /* safe read of a uint32 (always network byte order) */
>> >  static int read_uint32(unsigned char **data,
>> > @@ -645,10 +254,10 @@ static int send_data_block(struct IR_tx *tx,
>> > unsigned char *data_block)
>> >  		buf[0] = (unsigned char)(i + 1);
>> >  		for (j = 0; j < tosend; ++j)
>> >  			buf[1 + j] = data_block[i + j];
>> > -		dev_dbg(tx->ir->dev, "%*ph", 5, buf);
>> > +		dev_dbg(&tx->l->dev, "%*ph", 5, buf);
>> >  		ret = i2c_master_send(tx->c, buf, tosend + 1);
>> >  		if (ret != tosend + 1) {
>> > -			dev_err(tx->ir->dev,
>> > +			dev_err(&tx->l->dev,
>> >  				"i2c_master_send failed with %d\n",
>> > ret);
>> >  			return ret < 0 ? ret : -EFAULT;
>> >  		}
>> > @@ -673,7 +282,7 @@ static int send_boot_data(struct IR_tx *tx)
>> >  	buf[1] = 0x20;
>> >  	ret = i2c_master_send(tx->c, buf, 2);
>> >  	if (ret != 2) {
>> > -		dev_err(tx->ir->dev, "i2c_master_send failed with
>> > %d\n", ret);
>> > +		dev_err(&tx->l->dev, "i2c_master_send failed with
>> > %d\n", ret);
>> >  		return ret < 0 ? ret : -EFAULT;
>> >  	}
>> >  
>> > @@ -690,22 +299,22 @@ static int send_boot_data(struct IR_tx *tx)
>> >  	}
>> >  
>> >  	if (ret != 1) {
>> > -		dev_err(tx->ir->dev, "i2c_master_send failed with
>> > %d\n", ret);
>> > +		dev_err(&tx->l->dev, "i2c_master_send failed with
>> > %d\n", ret);
>> >  		return ret < 0 ? ret : -EFAULT;
>> >  	}
>> >  
>> >  	/* Here comes the firmware version... (hopefully) */
>> >  	ret = i2c_master_recv(tx->c, buf, 4);
>> >  	if (ret != 4) {
>> > -		dev_err(tx->ir->dev, "i2c_master_recv failed with
>> > %d\n", ret);
>> > +		dev_err(&tx->l->dev, "i2c_master_recv failed with
>> > %d\n", ret);
>> >  		return 0;
>> >  	}
>> >  	if ((buf[0] != 0x80) && (buf[0] != 0xa0)) {
>> > -		dev_err(tx->ir->dev, "unexpected IR TX init
>> > response: %02x\n",
>> > +		dev_err(&tx->l->dev, "unexpected IR TX init
>> > response: %02x\n",
>> >  			buf[0]);
>> >  		return 0;
>> >  	}
>> > -	dev_notice(tx->ir->dev,
>> > +	dev_notice(&tx->l->dev,
>> >  		   "Zilog/Hauppauge IR blaster firmware version
>> > %d.%d.%d loaded\n",
>> >  		   buf[1], buf[2], buf[3]);
>> >  
>> > @@ -750,15 +359,15 @@ static int fw_load(struct IR_tx *tx)
>> >  	}
>> >  
>> >  	/* Request codeset data file */
>> > -	ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx-
>> > >ir->dev);
>> > +	ret = request_firmware(&fw_entry, "haup-ir-blaster.bin",
>> > &tx->l->dev);
>> >  	if (ret != 0) {
>> > -		dev_err(tx->ir->dev,
>> > +		dev_err(&tx->l->dev,
>> >  			"firmware haup-ir-blaster.bin not available
>> > (%d)\n",
>> >  			ret);
>> >  		ret = ret < 0 ? ret : -EFAULT;
>> >  		goto out;
>> >  	}
>> > -	dev_dbg(tx->ir->dev, "firmware of size %zu loaded\n",
>> > fw_entry->size);
>> > +	dev_dbg(&tx->l->dev, "firmware of size %zu loaded\n",
>> > fw_entry->size);
>> >  
>> >  	/* Parse the file */
>> >  	tx_data = vmalloc(sizeof(*tx_data));
>> > @@ -786,7 +395,7 @@ static int fw_load(struct IR_tx *tx)
>> >  	if (!read_uint8(&data, tx_data->endp, &version))
>> >  		goto corrupt;
>> >  	if (version != 1) {
>> > -		dev_err(tx->ir->dev,
>> > +		dev_err(&tx->l->dev,
>> >  			"unsupported code set file version (%u,
>> > expected 1) -- please upgrade to a newer driver\n",
>> >  			version);
>> >  		fw_unload_locked();
>> > @@ -803,7 +412,7 @@ static int fw_load(struct IR_tx *tx)
>> >  			 &tx_data->num_code_sets))
>> >  		goto corrupt;
>> >  
>> > -	dev_dbg(tx->ir->dev, "%u IR blaster codesets loaded\n",
>> > +	dev_dbg(&tx->l->dev, "%u IR blaster codesets loaded\n",
>> >  		tx_data->num_code_sets);
>> >  
>> >  	tx_data->code_sets = vmalloc(
>> > @@ -868,7 +477,7 @@ static int fw_load(struct IR_tx *tx)
>> >  	goto out;
>> >  
>> >  corrupt:
>> > -	dev_err(tx->ir->dev, "firmware is corrupt\n");
>> > +	dev_err(&tx->l->dev, "firmware is corrupt\n");
>> >  	fw_unload_locked();
>> >  	ret = -EFAULT;
>> >  
>> > @@ -877,94 +486,6 @@ static int fw_load(struct IR_tx *tx)
>> >  	return ret;
>> >  }
>> >  
>> > -/* copied from lirc_dev */
>> > -static ssize_t read(struct file *filep, char __user *outbuf,
>size_t
>> > n,
>> > -		    loff_t *ppos)
>> > -{
>> > -	struct IR *ir = lirc_get_pdata(filep);
>> > -	struct IR_rx *rx;
>> > -	struct lirc_buffer *rbuf = ir->l->buf;
>> > -	int ret = 0, written = 0, retries = 0;
>> > -	unsigned int m;
>> > -	DECLARE_WAITQUEUE(wait, current);
>> > -
>> > -	dev_dbg(ir->dev, "read called\n");
>> > -	if (n % rbuf->chunk_size) {
>> > -		dev_dbg(ir->dev, "read result = -EINVAL\n");
>> > -		return -EINVAL;
>> > -	}
>> > -
>> > -	rx = get_ir_rx(ir);
>> > -	if (!rx)
>> > -		return -ENXIO;
>> > -
>> > -	/*
>> > -	 * we add ourselves to the task queue before buffer check
>> > -	 * to avoid losing scan code (in case when queue is awaken
>> > somewhere
>> > -	 * between while condition checking and scheduling)
>> > -	 */
>> > -	add_wait_queue(&rbuf->wait_poll, &wait);
>> > -	set_current_state(TASK_INTERRUPTIBLE);
>> > -
>> > -	/*
>> > -	 * while we didn't provide 'length' bytes, device is opened
>> > in blocking
>> > -	 * mode and 'copy_to_user' is happy, wait for data.
>> > -	 */
>> > -	while (written < n && ret == 0) {
>> > -		if (lirc_buffer_empty(rbuf)) {
>> > -			/*
>> > -			 * According to the read(2) man page,
>> > 'written' can be
>> > -			 * returned as less than 'n', instead of
>> > blocking
>> > -			 * again, returning -EWOULDBLOCK, or
>> > returning
>> > -			 * -ERESTARTSYS
>> > -			 */
>> > -			if (written)
>> > -				break;
>> > -			if (filep->f_flags & O_NONBLOCK) {
>> > -				ret = -EWOULDBLOCK;
>> > -				break;
>> > -			}
>> > -			if (signal_pending(current)) {
>> > -				ret = -ERESTARTSYS;
>> > -				break;
>> > -			}
>> > -			schedule();
>> > -			set_current_state(TASK_INTERRUPTIBLE);
>> > -		} else {
>> > -			unsigned char buf[MAX_XFER_SIZE];
>> > -
>> > -			if (rbuf->chunk_size > sizeof(buf)) {
>> > -				dev_err(ir->dev,
>> > -					"chunk_size is too big
>> > (%d)!\n",
>> > -					rbuf->chunk_size);
>> > -				ret = -EINVAL;
>> > -				break;
>> > -			}
>> > -			m = lirc_buffer_read(rbuf, buf);
>> > -			if (m == rbuf->chunk_size) {
>> > -				ret = copy_to_user(outbuf + written,
>> > buf,
>> > -						   rbuf-
>> > >chunk_size);
>> > -				written += rbuf->chunk_size;
>> > -			} else {
>> > -				retries++;
>> > -			}
>> > -			if (retries >= 5) {
>> > -				dev_err(ir->dev, "Buffer read
>> > failed!\n");
>> > -				ret = -EIO;
>> > -			}
>> > -		}
>> > -	}
>> > -
>> > -	remove_wait_queue(&rbuf->wait_poll, &wait);
>> > -	put_ir_rx(rx, false);
>> > -	set_current_state(TASK_RUNNING);
>> > -
>> > -	dev_dbg(ir->dev, "read result = %d (%s)\n", ret,
>> > -		ret ? "Error" : "OK");
>> > -
>> > -	return ret ? ret : written;
>> > -}
>> > -
>> >  /* send a keypress to the IR TX device */
>> >  static int send_code(struct IR_tx *tx, unsigned int code, unsigned
>> > int key)
>> >  {
>> > @@ -976,7 +497,7 @@ static int send_code(struct IR_tx *tx, unsigned
>> > int code, unsigned int key)
>> >  	ret = get_key_data(data_block, code, key);
>> >  
>> >  	if (ret == -EPROTO) {
>> > -		dev_err(tx->ir->dev,
>> > +		dev_err(&tx->l->dev,
>> >  			"failed to get data for code %u, key %u --
>> > check lircd.conf entries\n",
>> >  			code, key);
>> >  		return ret;
>> > @@ -994,7 +515,7 @@ static int send_code(struct IR_tx *tx, unsigned
>> > int code, unsigned int key)
>> >  	buf[1] = 0x40;
>> >  	ret = i2c_master_send(tx->c, buf, 2);
>> >  	if (ret != 2) {
>> > -		dev_err(tx->ir->dev, "i2c_master_send failed with
>> > %d\n", ret);
>> > +		dev_err(&tx->l->dev, "i2c_master_send failed with
>> > %d\n", ret);
>> >  		return ret < 0 ? ret : -EFAULT;
>> >  	}
>> >  
>> > @@ -1007,18 +528,18 @@ static int send_code(struct IR_tx *tx,
>> > unsigned int code, unsigned int key)
>> >  	}
>> >  
>> >  	if (ret != 1) {
>> > -		dev_err(tx->ir->dev, "i2c_master_send failed with
>> > %d\n", ret);
>> > +		dev_err(&tx->l->dev, "i2c_master_send failed with
>> > %d\n", ret);
>> >  		return ret < 0 ? ret : -EFAULT;
>> >  	}
>> >  
>> >  	/* Send finished download? */
>> >  	ret = i2c_master_recv(tx->c, buf, 1);
>> >  	if (ret != 1) {
>> > -		dev_err(tx->ir->dev, "i2c_master_recv failed with
>> > %d\n", ret);
>> > +		dev_err(&tx->l->dev, "i2c_master_recv failed with
>> > %d\n", ret);
>> >  		return ret < 0 ? ret : -EFAULT;
>> >  	}
>> >  	if (buf[0] != 0xA0) {
>> > -		dev_err(tx->ir->dev, "unexpected IR TX response #1:
>> > %02x\n",
>> > +		dev_err(&tx->l->dev, "unexpected IR TX response #1:
>> > %02x\n",
>> >  			buf[0]);
>> >  		return -EFAULT;
>> >  	}
>> > @@ -1028,7 +549,7 @@ static int send_code(struct IR_tx *tx,
>unsigned
>> > int code, unsigned int key)
>> >  	buf[1] = 0x80;
>> >  	ret = i2c_master_send(tx->c, buf, 2);
>> >  	if (ret != 2) {
>> > -		dev_err(tx->ir->dev, "i2c_master_send failed with
>> > %d\n", ret);
>> > +		dev_err(&tx->l->dev, "i2c_master_send failed with
>> > %d\n", ret);
>> >  		return ret < 0 ? ret : -EFAULT;
>> >  	}
>> >  
>> > @@ -1038,7 +559,7 @@ static int send_code(struct IR_tx *tx,
>unsigned
>> > int code, unsigned int key)
>> >  	 * going to skip this whole mess and say we're done on the
>> > HD PVR
>> >  	 */
>> >  	if (!tx->post_tx_ready_poll) {
>> > -		dev_dbg(tx->ir->dev, "sent code %u, key %u\n", code,
>> > key);
>> > +		dev_dbg(&tx->l->dev, "sent code %u, key %u\n", code,
>> > key);
>> >  		return 0;
>> >  	}
>> >  
>> > @@ -1054,12 +575,12 @@ static int send_code(struct IR_tx *tx,
>> > unsigned int code, unsigned int key)
>> >  		ret = i2c_master_send(tx->c, buf, 1);
>> >  		if (ret == 1)
>> >  			break;
>> > -		dev_dbg(tx->ir->dev,
>> > +		dev_dbg(&tx->l->dev,
>> >  			"NAK expected: i2c_master_send failed with
>> > %d (try %d)\n",
>> >  			ret, i + 1);
>> >  	}
>> >  	if (ret != 1) {
>> > -		dev_err(tx->ir->dev,
>> > +		dev_err(&tx->l->dev,
>> >  			"IR TX chip never got ready: last
>> > i2c_master_send failed with %d\n",
>> >  			ret);
>> >  		return ret < 0 ? ret : -EFAULT;
>> > @@ -1068,17 +589,17 @@ static int send_code(struct IR_tx *tx,
>> > unsigned int code, unsigned int key)
>> >  	/* Seems to be an 'ok' response */
>> >  	i = i2c_master_recv(tx->c, buf, 1);
>> >  	if (i != 1) {
>> > -		dev_err(tx->ir->dev, "i2c_master_recv failed with
>> > %d\n", ret);
>> > +		dev_err(&tx->l->dev, "i2c_master_recv failed with
>> > %d\n", ret);
>> >  		return -EFAULT;
>> >  	}
>> >  	if (buf[0] != 0x80) {
>> > -		dev_err(tx->ir->dev, "unexpected IR TX response #2:
>> > %02x\n",
>> > +		dev_err(&tx->l->dev, "unexpected IR TX response #2:
>> > %02x\n",
>> >  			buf[0]);
>> >  		return -EFAULT;
>> >  	}
>> >  
>> >  	/* Oh good, it worked */
>> > -	dev_dbg(tx->ir->dev, "sent code %u, key %u\n", code, key);
>> > +	dev_dbg(&tx->l->dev, "sent code %u, key %u\n", code, key);
>> >  	return 0;
>> >  }
>> >  
>> > @@ -1091,8 +612,7 @@ static int send_code(struct IR_tx *tx,
>unsigned
>> > int code, unsigned int key)
>> >  static ssize_t write(struct file *filep, const char __user *buf,
>> > size_t n,
>> >  		     loff_t *ppos)
>> >  {
>> > -	struct IR *ir = lirc_get_pdata(filep);
>> > -	struct IR_tx *tx;
>> > +	struct IR_tx *tx = lirc_get_pdata(filep);
>> >  	size_t i;
>> >  	int failures = 0;
>> >  
>> > @@ -1100,31 +620,20 @@ static ssize_t write(struct file *filep,
>const
>> > char __user *buf, size_t n,
>> >  	if (n % sizeof(int))
>> >  		return -EINVAL;
>> >  
>> > -	/* Get a struct IR_tx reference */
>> > -	tx = get_ir_tx(ir);
>> > -	if (!tx)
>> > -		return -ENXIO;
>> > -
>> >  	/* Ensure our tx->c i2c_client remains valid for the
>> > duration */
>> >  	mutex_lock(&tx->client_lock);
>> >  	if (!tx->c) {
>> >  		mutex_unlock(&tx->client_lock);
>> > -		put_ir_tx(tx, false);
>> >  		return -ENXIO;
>> >  	}
>> >  
>> > -	/* Lock i2c bus for the duration */
>> > -	mutex_lock(&ir->ir_lock);
>> > -
>> >  	/* Send each keypress */
>> >  	for (i = 0; i < n;) {
>> >  		int ret = 0;
>> >  		int command;
>> >  
>> >  		if (copy_from_user(&command, buf + i,
>> > sizeof(command))) {
>> > -			mutex_unlock(&ir->ir_lock);
>> >  			mutex_unlock(&tx->client_lock);
>> > -			put_ir_tx(tx, false);
>> >  			return -EFAULT;
>> >  		}
>> >  
>> > @@ -1133,9 +642,7 @@ static ssize_t write(struct file *filep, const
>> > char __user *buf, size_t n,
>> >  			/* Make sure we have the 'firmware' loaded,
>> > first */
>> >  			ret = fw_load(tx);
>> >  			if (ret != 0) {
>> > -				mutex_unlock(&ir->ir_lock);
>> >  				mutex_unlock(&tx->client_lock);
>> > -				put_ir_tx(tx, false);
>> >  				if (ret != -ENOMEM)
>> >  					ret = -EIO;
>> >  				return ret;
>> > @@ -1151,9 +658,7 @@ static ssize_t write(struct file *filep, const
>> > char __user *buf, size_t n,
>> >  			ret = send_code(tx, (unsigned int)command >>
>> > 16,
>> >  					    (unsigned int)command &
>> > 0xFFFF);
>> >  			if (ret == -EPROTO) {
>> > -				mutex_unlock(&ir->ir_lock);
>> >  				mutex_unlock(&tx->client_lock);
>> > -				put_ir_tx(tx, false);
>> >  				return ret;
>> >  			}
>> >  		}
>> > @@ -1164,15 +669,13 @@ static ssize_t write(struct file *filep,
>const
>> > char __user *buf, size_t n,
>> >  		 */
>> >  		if (ret != 0) {
>> >  			/* Looks like the chip crashed, reset it */
>> > -			dev_err(tx->ir->dev,
>> > +			dev_err(&tx->l->dev,
>> >  				"sending to the IR transmitter chip
>> > failed, trying reset\n");
>> >  
>> >  			if (failures >= 3) {
>> > -				dev_err(tx->ir->dev,
>> > +				dev_err(&tx->l->dev,
>> >  					"unable to send to the IR
>> > chip after 3 resets, giving up\n");
>> > -				mutex_unlock(&ir->ir_lock);
>> >  				mutex_unlock(&tx->client_lock);
>> > -				put_ir_tx(tx, false);
>> >  				return ret;
>> >  			}
>> >  			set_current_state(TASK_UNINTERRUPTIBLE);
>> > @@ -1184,60 +687,21 @@ static ssize_t write(struct file *filep,
>const
>> > char __user *buf, size_t n,
>> >  		}
>> >  	}
>> >  
>> > -	/* Release i2c bus */
>> > -	mutex_unlock(&ir->ir_lock);
>> > -
>> >  	mutex_unlock(&tx->client_lock);
>> >  
>> > -	/* Give back our struct IR_tx reference */
>> > -	put_ir_tx(tx, false);
>> > -
>> >  	/* All looks good */
>> >  	return n;
>> >  }
>> >  
>> > -/* copied from lirc_dev */
>> > -static unsigned int poll(struct file *filep, poll_table *wait)
>> > -{
>> > -	struct IR *ir = lirc_get_pdata(filep);
>> > -	struct IR_rx *rx;
>> > -	struct lirc_buffer *rbuf = ir->l->buf;
>> > -	unsigned int ret;
>> > -
>> > -	dev_dbg(ir->dev, "%s called\n", __func__);
>> > -
>> > -	rx = get_ir_rx(ir);
>> > -	if (!rx) {
>> > -		/*
>> > -		 * Revisit this, if our poll function ever reports
>> > writeable
>> > -		 * status for Tx
>> > -		 */
>> > -		dev_dbg(ir->dev, "%s result = POLLERR\n", __func__);
>> > -		return POLLERR;
>> > -	}
>> > -
>> > -	/*
>> > -	 * Add our lirc_buffer's wait_queue to the poll_table. A
>> > wake up on
>> > -	 * that buffer's wait queue indicates we may have a new poll
>> > status.
>> > -	 */
>> > -	poll_wait(filep, &rbuf->wait_poll, wait);
>> > -
>> > -	/* Indicate what ops could happen immediately without
>> > blocking */
>> > -	ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN | POLLRDNORM);
>> > -
>> > -	dev_dbg(ir->dev, "%s result = %s\n", __func__,
>> > -		ret ? "POLLIN|POLLRDNORM" : "none");
>> > -	return ret;
>> > -}
>> >  
>> >  static long ioctl(struct file *filep, unsigned int cmd, unsigned
>> > long arg)
>> >  {
>> > -	struct IR *ir = lirc_get_pdata(filep);
>> > +	struct IR_tx *tx = lirc_get_pdata(filep);
>> >  	unsigned long __user *uptr = (unsigned long __user *)arg;
>> >  	int result;
>> >  	unsigned long mode, features;
>> >  
>> > -	features = ir->l->features;
>> > +	features = tx->l->features;
>> >  
>> >  	switch (cmd) {
>> >  	case LIRC_GET_LENGTH:
>> > @@ -1287,13 +751,7 @@ static long ioctl(struct file *filep,
>unsigned
>> > int cmd, unsigned long arg)
>> >   */
>> >  static int open(struct inode *node, struct file *filep)
>> >  {
>> > -	struct IR *ir;
>> > -
>> >  	lirc_init_pdata(node, filep);
>> > -	ir = lirc_get_pdata(filep);
>> > -
>> > -	atomic_inc(&ir->open_count);
>> > -
>> >  	nonseekable_open(node, filep);
>> >  	return 0;
>> >  }
>> > @@ -1301,25 +759,16 @@ static int open(struct inode *node, struct
>> > file *filep)
>> >  /* Close the IR device */
>> >  static int close(struct inode *node, struct file *filep)
>> >  {
>> > -	struct IR *ir = lirc_get_pdata(filep);
>> > -
>> > -	atomic_dec(&ir->open_count);
>> > -
>> > -	put_ir_device(ir, false);
>> >  	return 0;
>> >  }
>> >  
>> > -static int ir_remove(struct i2c_client *client);
>> >  static int ir_probe(struct i2c_client *client, const struct
>> > i2c_device_id *id);
>> >  
>> > -#define ID_FLAG_TX	0x01
>> > -#define ID_FLAG_HDPVR	0x02
>> > +#define ID_FLAG_HDPVR	0x01
>> >  
>> >  static const struct i2c_device_id ir_transceiver_id[] = {
>> > -	{ "ir_tx_z8f0811_haup",  ID_FLAG_TX                 },
>> > -	{ "ir_rx_z8f0811_haup",  0                          },
>> > -	{ "ir_tx_z8f0811_hdpvr", ID_FLAG_HDPVR | ID_FLAG_TX },
>> > -	{ "ir_rx_z8f0811_hdpvr", ID_FLAG_HDPVR              },
>> > +	{ "ir_tx_z8f0811_haup",  0 },
>> > +	{ "ir_tx_z8f0811_hdpvr", ID_FLAG_HDPVR },
>> >  	{ }
>> >  };
>> >  MODULE_DEVICE_TABLE(i2c, ir_transceiver_id);
>> > @@ -1329,16 +778,13 @@ static struct i2c_driver driver = {
>> >  		.name	= "Zilog/Hauppauge i2c IR",
>> >  	},
>> >  	.probe		= ir_probe,
>> > -	.remove		= ir_remove,
>> >  	.id_table	= ir_transceiver_id,
>> >  };
>> >  
>> >  static const struct file_operations lirc_fops = {
>> >  	.owner		= THIS_MODULE,
>> >  	.llseek		= no_llseek,
>> > -	.read		= read,
>> >  	.write		= write,
>> > -	.poll		= poll,
>> >  	.unlocked_ioctl	= ioctl,
>> >  #ifdef CONFIG_COMPAT
>> >  	.compat_ioctl	= ioctl,
>> > @@ -1347,55 +793,11 @@ static const struct file_operations
>lirc_fops
>> > = {
>> >  	.release	= close
>> >  };
>> >  
>> > -static int ir_remove(struct i2c_client *client)
>> > -{
>> > -	if (strncmp("ir_tx_z8", client->name, 8) == 0) {
>> > -		struct IR_tx *tx = i2c_get_clientdata(client);
>> > -
>> > -		if (tx) {
>> > -			mutex_lock(&tx->client_lock);
>> > -			tx->c = NULL;
>> > -			mutex_unlock(&tx->client_lock);
>> > -			put_ir_tx(tx, false);
>> > -		}
>> > -	} else if (strncmp("ir_rx_z8", client->name, 8) == 0) {
>> > -		struct IR_rx *rx = i2c_get_clientdata(client);
>> > -
>> > -		if (rx) {
>> > -			mutex_lock(&rx->client_lock);
>> > -			rx->c = NULL;
>> > -			mutex_unlock(&rx->client_lock);
>> > -			put_ir_rx(rx, false);
>> > -		}
>> > -	}
>> > -	return 0;
>> > -}
>> > -
>> > -/* ir_devices_lock must be held */
>> > -static struct IR *get_ir_device_by_adapter(struct i2c_adapter
>> > *adapter)
>> > -{
>> > -	struct IR *ir;
>> > -
>> > -	if (list_empty(&ir_devices_list))
>> > -		return NULL;
>> > -
>> > -	list_for_each_entry(ir, &ir_devices_list, list)
>> > -		if (ir->adapter == adapter) {
>> > -			get_ir_device(ir, true);
>> > -			return ir;
>> > -		}
>> > -
>> > -	return NULL;
>> > -}
>> > -
>> >  static int ir_probe(struct i2c_client *client, const struct
>> > i2c_device_id *id)
>> >  {
>> > -	struct IR *ir;
>> >  	struct IR_tx *tx;
>> > -	struct IR_rx *rx;
>> >  	struct i2c_adapter *adap = client->adapter;
>> >  	int ret;
>> > -	bool tx_probe = false;
>> >  
>> >  	dev_dbg(&client->dev, "%s: %s on i2c-%d (%s), client
>> > addr=0x%02x\n",
>> >  		__func__, id->name, adap->nr, adap->name, client-
>> > >addr);
>> > @@ -1405,209 +807,61 @@ static int ir_probe(struct i2c_client
>> > *client, const struct i2c_device_id *id)
>> >  	 * The IR transmitter is at i2c address 0x70.
>> >  	 */
>> >  
>> > -	if (id->driver_data & ID_FLAG_TX)
>> > -		tx_probe = true;
>> > -	else if (tx_only) /* module option */
>> > -		return -ENXIO;
>> > -
>> > -	pr_info("probing IR %s on %s (i2c-%d)\n",
>> > -		tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
>> > -
>> > -	mutex_lock(&ir_devices_lock);
>> > -
>> > -	/* Use a single struct IR instance for both the Rx and Tx
>> > functions */
>> > -	ir = get_ir_device_by_adapter(adap);
>> > -	if (!ir) {
>> > -		ir = kzalloc(sizeof(*ir), GFP_KERNEL);
>> > -		if (!ir) {
>> > -			ret = -ENOMEM;
>> > -			goto out_no_ir;
>> > -		}
>> > -		kref_init(&ir->ref);
>> > -
>> > -		/* store for use in ir_probe() again, and open()
>> > later on */
>> > -		INIT_LIST_HEAD(&ir->list);
>> > -		list_add_tail(&ir->list, &ir_devices_list);
>> > -
>> > -		ir->adapter = adap;
>> > -		ir->dev = &adap->dev;
>> > -		mutex_init(&ir->ir_lock);
>> > -		atomic_set(&ir->open_count, 0);
>> > -		spin_lock_init(&ir->tx_ref_lock);
>> > -		spin_lock_init(&ir->rx_ref_lock);
>> > -
>> > -		/* set lirc_dev stuff */
>> > -		ir->l = lirc_allocate_device();
>> > -		if (!ir->l) {
>> > -			ret = -ENOMEM;
>> > -			goto out_put_ir;
>> > -		}
>> > -
>> > -		snprintf(ir->l->name, sizeof(ir->l->name),
>> > "lirc_zilog");
>> > -		ir->l->code_length = 13;
>> > -		ir->l->fops = &lirc_fops;
>> > -		ir->l->owner = THIS_MODULE;
>> > -		ir->l->dev.parent = &adap->dev;
>> > -
>> > -		/*
>> > -		 * FIXME this is a pointer reference to us, but no
>> > refcount.
>> > -		 *
>> > -		 * This OK for now, since lirc_dev currently won't
>> > touch this
>> > -		 * buffer as we provide our own lirc_fops.
>> > -		 *
>> > -		 * Currently our own lirc_fops rely on this ir->l-
>> > >buf pointer
>> > -		 */
>> > -		ir->l->buf = &ir->rbuf;
>> > -		/* This will be returned by lirc_get_pdata() */
>> > -		ir->l->data = ir;
>> > -		ret = lirc_buffer_init(ir->l->buf, 2, BUFLEN / 2);
>> > -		if (ret) {
>> > -			lirc_free_device(ir->l);
>> > -			ir->l = NULL;
>> > -			goto out_put_ir;
>> > -		}
>> > -	}
>> > +	pr_info("probing IR Tx on %s (i2c-%d)\n", adap->name, adap-
>> > >nr);
>> >  
>> > -	if (tx_probe) {
>> > -		/* Get the IR_rx instance for later, if already
>> > allocated */
>> > -		rx = get_ir_rx(ir);
>> > -
>> > -		/* Set up a struct IR_tx instance */
>> > -		tx = kzalloc(sizeof(*tx), GFP_KERNEL);
>> > -		if (!tx) {
>> > -			ret = -ENOMEM;
>> > -			goto out_put_xx;
>> > -		}
>> > -		kref_init(&tx->ref);
>> > -		ir->tx = tx;
>> > -
>> > -		ir->l->features |= LIRC_CAN_SEND_LIRCCODE;
>> > -		mutex_init(&tx->client_lock);
>> > -		tx->c = client;
>> > -		tx->need_boot = 1;
>> > -		tx->post_tx_ready_poll =
>> > -			       (id->driver_data & ID_FLAG_HDPVR) ?
>> > false : true;
>> > -
>> > -		/* An ir ref goes to the struct IR_tx instance */
>> > -		tx->ir = get_ir_device(ir, true);
>> > -
>> > -		/* A tx ref goes to the i2c_client */
>> > -		i2c_set_clientdata(client, get_ir_tx(ir));
>> > -
>> > -		/*
>> > -		 * Load the 'firmware'.  We do this before
>> > registering with
>> > -		 * lirc_dev, so the first firmware load attempt does
>> > not happen
>> > -		 * after a open() or write() call on the device.
>> > -		 *
>> > -		 * Failure here is not deemed catastrophic, so the
>> > receiver will
>> > -		 * still be usable.  Firmware load will be retried
>> > in write(),
>> > -		 * if it is needed.
>> > -		 */
>> > -		fw_load(tx);
>> > -
>> > -		/* Proceed only if the Rx client is also ready or
>> > not needed */
>> > -		if (!rx && !tx_only) {
>> > -			dev_info(tx->ir->dev,
>> > -				 "probe of IR Tx on %s (i2c-%d)
>> > done. Waiting on IR Rx.\n",
>> > -				 adap->name, adap->nr);
>> > -			goto out_ok;
>> > -		}
>> > -	} else {
>> > -		/* Get the IR_tx instance for later, if already
>> > allocated */
>> > -		tx = get_ir_tx(ir);
>> > -
>> > -		/* Set up a struct IR_rx instance */
>> > -		rx = kzalloc(sizeof(*rx), GFP_KERNEL);
>> > -		if (!rx) {
>> > -			ret = -ENOMEM;
>> > -			goto out_put_xx;
>> > -		}
>> > -		kref_init(&rx->ref);
>> > -		ir->rx = rx;
>> > -
>> > -		ir->l->features |= LIRC_CAN_REC_LIRCCODE;
>> > -		mutex_init(&rx->client_lock);
>> > -		rx->c = client;
>> > -		rx->hdpvr_data_fmt =
>> > -			       (id->driver_data & ID_FLAG_HDPVR) ?
>> > true : false;
>> > -
>> > -		/* An ir ref goes to the struct IR_rx instance */
>> > -		rx->ir = get_ir_device(ir, true);
>> > +	/* Set up a struct IR_tx instance */
>> > +	tx = devm_kzalloc(&client->dev, sizeof(*tx), GFP_KERNEL);
>> > +	if (!tx)
>> > +		return -ENOMEM;
>> >  
>> > -		/* An rx ref goes to the i2c_client */
>> > -		i2c_set_clientdata(client, get_ir_rx(ir));
>> > +	mutex_init(&tx->client_lock);
>> > +	tx->c = client;
>> > +	tx->need_boot = 1;
>> > +	tx->post_tx_ready_poll = !(id->driver_data & ID_FLAG_HDPVR);
>> >  
>> > -		/*
>> > -		 * Start the polling thread.
>> > -		 * It will only perform an empty loop around
>> > schedule_timeout()
>> > -		 * until we register with lirc_dev and the first
>> > user open()
>> > -		 */
>> > -		/* An ir ref goes to the new rx polling kthread */
>> > -		rx->task = kthread_run(lirc_thread,
>> > get_ir_device(ir, true),
>> > -				       "zilog-rx-i2c-%d", adap->nr);
>> > -		if (IS_ERR(rx->task)) {
>> > -			ret = PTR_ERR(rx->task);
>> > -			dev_err(tx->ir->dev,
>> > -				"%s: could not start IR Rx polling
>> > thread\n",
>> > -				__func__);
>> > -			/* Failed kthread, so put back the ir ref */
>> > -			put_ir_device(ir, true);
>> > -			/* Failure exit, so put back rx ref from
>> > i2c_client */
>> > -			i2c_set_clientdata(client, NULL);
>> > -			put_ir_rx(rx, true);
>> > -			ir->l->features &= ~LIRC_CAN_REC_LIRCCODE;
>> > -			goto out_put_tx;
>> > -		}
>> > +	/* set lirc_dev stuff */
>> > +	tx->l = lirc_allocate_device();
>> > +	if (!tx->l)
>> > +		return -ENOMEM;
>> >  
>> > -		/* Proceed only if the Tx client is also ready */
>> > -		if (!tx) {
>> > -			pr_info("probe of IR Rx on %s (i2c-%d) done.
>> > Waiting on IR Tx.\n",
>> > -				adap->name, adap->nr);
>> > -			goto out_ok;
>> > -		}
>> > -	}
>> > +	snprintf(tx->l->name, sizeof(tx->l->name), "lirc_zilog");
>> > +	tx->l->features |= LIRC_CAN_SEND_LIRCCODE;
>> > +	tx->l->code_length = 13;
>> > +	tx->l->fops = &lirc_fops;
>> > +	tx->l->owner = THIS_MODULE;
>> > +	tx->l->dev.parent = &client->dev;
>> >  
>> >  	/* register with lirc */
>> > -	ret = lirc_register_device(ir->l);
>> > +	ret = lirc_register_device(tx->l);
>> >  	if (ret < 0) {
>> > -		dev_err(tx->ir->dev,
>> > -			"%s: lirc_register_device() failed: %i\n",
>> > +		dev_err(&tx->l->dev, "%s: lirc_register_device()
>> > failed: %i\n",
>> >  			__func__, ret);
>> > -		lirc_free_device(ir->l);
>> > -		ir->l = NULL;
>> > -		goto out_put_xx;
>> > +		lirc_free_device(tx->l);
>> > +		tx->l = NULL;
>> > +		return ret;
>> >  	}
>> >  
>> > -	dev_info(ir->dev,
>> > +	/*
>> > +	 * Load the 'firmware'.  We do this before registering with
>> > +	 * lirc_dev, so the first firmware load attempt does not
>> > happen
>> > +	 * after a open() or write() call on the device.
>> > +	 */
>> > +	ret = fw_load(tx);
>> > +	if (ret < 0) {
>> > +		lirc_unregister_device(tx->l);
>> > +		return ret;
>> > +	}
>> > +
>> > +	/* A tx ref goes to the i2c_client */
>> > +	i2c_set_clientdata(client, tx);
>> > +
>> > +	dev_info(&tx->l->dev,
>> >  		 "IR unit on %s (i2c-%d) registered as lirc%d and
>> > ready\n",
>> > -		 adap->name, adap->nr, ir->l->minor);
>> > -
>> > -out_ok:
>> > -	if (rx)
>> > -		put_ir_rx(rx, true);
>> > -	if (tx)
>> > -		put_ir_tx(tx, true);
>> > -	put_ir_device(ir, true);
>> > -	dev_info(ir->dev,
>> > -		 "probe of IR %s on %s (i2c-%d) done\n",
>> > -		 tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
>> > -	mutex_unlock(&ir_devices_lock);
>> > -	return 0;
>> > +		 adap->name, adap->nr, tx->l->minor);
>> >  
>> > -out_put_xx:
>> > -	if (rx)
>> > -		put_ir_rx(rx, true);
>> > -out_put_tx:
>> > -	if (tx)
>> > -		put_ir_tx(tx, true);
>> > -out_put_ir:
>> > -	put_ir_device(ir, true);
>> > -out_no_ir:
>> > -	dev_err(&client->dev,
>> > -		"%s: probing IR %s on %s (i2c-%d) failed with %d\n",
>> > -		__func__, tx_probe ? "Tx" : "Rx", adap->name, adap-
>> > >nr, ret);
>> > -	mutex_unlock(&ir_devices_lock);
>> > -	return ret;
>> > +	dev_info(&tx->l->dev,
>> > +		 "probe of IR Tx on %s (i2c-%d) done\n", adap->name, 
>> > adap->nr);
>> > +	return 0;
>> >  }
>> >  
>> >  static int __init zilog_init(void)
>> > @@ -1648,6 +902,3 @@ MODULE_ALIAS("lirc_pvr150");
>> >  
>> >  module_param(debug, bool, 0644);
>> >  MODULE_PARM_DESC(debug, "Enable debugging messages");
>> > -
>> > -module_param(tx_only, bool, 0644);
>> > -MODULE_PARM_DESC(tx_only, "Only handle the IR transmit function");

There's an ir_lock mutex in the driver to prevent simultaneous access to the Rx and Tx functions of the z8.  Accessing Rx and Tx functions of the chip together can cause it to do the wrong thing (sometimes hang?), IIRC.

I'll see if I can dig up my old disassembly of the z8's firmware to see if that interlock is strictly necessary.

Yes I know ir-kbd-i2c is in mainline, but as I said, I had reasons for avoiding it when using Tx operation of the chip.  It's been 7 years, and I'm getting too old to remember the reasons. :P

-Andy

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 04/26] media: lirc_zilog: remove receiver
  2017-10-11 23:24       ` Andy Walls
@ 2017-10-12  0:25         ` Devin Heitmueller
  2017-10-12  0:50           ` Andy Walls
  2017-10-12 11:40           ` Sean Young
  0 siblings, 2 replies; 39+ messages in thread
From: Devin Heitmueller @ 2017-10-12  0:25 UTC (permalink / raw)
  To: Andy Walls; +Cc: Sean Young, Linux Media Mailing List

> There's an ir_lock mutex in the driver to prevent simultaneous access to the Rx and Tx functions of the z8.  Accessing Rx and Tx functions of the chip together can cause it to do the wrong thing (sometimes hang?), IIRC.
>
> I'll see if I can dig up my old disassembly of the z8's firmware to see if that interlock is strictly necessary.
>
> Yes I know ir-kbd-i2c is in mainline, but as I said, I had reasons for avoiding it when using Tx operation of the chip.  It's been 7 years, and I'm getting too old to remember the reasons. :P

Yeah, you definitely don't want to be issuing requests to the Rx and
Tx addresses at the same time.  Very bad things will happen.

Also, what is the polling interval for ir-kbd-i2c?  If it's too high
you can wedge the I2C bus (depending on the hardware design).
Likewise, many people disable IR RX entirely (which is trivial to do
with lirc_zilog through a modprobe optoin).  This is because early
versions of the HDPVR had issues where polling too often can interfere
with traffic that configures the component receiver chip.  This was
improved in later versions of the design, but many people found it was
just easiest to disable RX since they don't use it (i.e. they would
use the blaster for controlling their STB but use a separate IR
receiver).

Are you testing with video capture actively in use?  If you're testing
the IR interface without an active HD capture in progress you're
likely to miss some of these edge cases (in particular those which
would hang the encoder).

I'm not against the removal of duplicate code in general, but you have
to tread carefully because there are plenty of non-obvious edge cases
to consider.

Devin

-- 
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 04/26] media: lirc_zilog: remove receiver
  2017-10-12  0:25         ` Devin Heitmueller
@ 2017-10-12  0:50           ` Andy Walls
  2017-10-12  2:25             ` Devin Heitmueller
  2017-10-12 11:40           ` Sean Young
  1 sibling, 1 reply; 39+ messages in thread
From: Andy Walls @ 2017-10-12  0:50 UTC (permalink / raw)
  To: Devin Heitmueller, Sean Young; +Cc: Linux Media Mailing List

Hi Sean and Devin:

On Wed, 2017-10-11 at 20:25 -0400, Devin Heitmueller wrote:
> > There's an ir_lock mutex in the driver to prevent simultaneous
> > access to the Rx and Tx functions of the z8.  Accessing Rx and Tx
> > functions of the chip together can cause it to do the wrong thing
> > (sometimes hang?), IIRC.
> > 
> > I'll see if I can dig up my old disassembly of the z8's firmware to
> > see if that interlock is strictly necessary.

Following up on this:

1. The I2C bus command and response buffers inside the Z8 appear to be
independent and non-overlapping (ignore the garbage assembly
mnemonics):

; I2C data buffer addresses
01bf srp   #%00   ; 01 00 ; Buffer pointer I2C addr E0 (70w) IR Tx  - 160 bytes
01c1 add   r0,@r0 ; 03 00 ; Buffer pointer I2C addr E1 (70r) IR Tx  -   4 bytes
01c3 add   r1,@r5 ; 03 15 ; Buffer pointer I2C addr E2 (71w) IR Rx  -   5 bytes
01c5 add   r1,@r0 ; 03 10 ; Buffer pointer I2C addr E3 (71r) IR Rx  -   5 bytes
01c7 add   r0,@r10; 03 0a ; Buffer pointer I2C addr E4 (72w) IR PB1 -   4 bytes
01c9 add   r1,@r10; 03 1a ; Buffer pointer I2C addr E5 (72r) IR PB1 -   4 bytes
01cb add   r0,@r5 ; 03 05 ; Buffer pointer I2C addr E6 (73w) IR Lrn -   1 bytes
01cd add   r0,r0  ; 02 00 ; Buffer pointer I2C addr E7 (73r) IR Lrn - 256 bytes

and the I2C handling routines appear to do the right thing in waiting
for "full" buffers before operating on them.

2. Z8 Port B is used by both Tx and Rx functions, but the functions
each only use 1 line of the I/O port and they use different lines.

3. Z8 Port C is unused.

4. Z8 Port A is used by both Tx functions, Rx functions, the I2C
interface.  If something inside the Z8 screws up the I2C bus comms with
the chip, it's likely the errant misconfiguration of Port A during
certain Rx and Tx operations.

5. Rx and IR Learn both use the same external hardware.  Not
coordinating Rx with Learn mode in the same driver, will prevent Learn
operation from working.  That is, if Learn mode is ever implemented. 
(Once upon a time, I was planning on doing that.  But I have no time
for that anymore.)  

> > Yes I know ir-kbd-i2c is in mainline, but as I said, I had reasons
> > for avoiding it when using Tx operation of the chip.  It's been 7
> > years, and I'm getting too old to remember the reasons. :P
> 
> Yeah, you definitely don't want to be issuing requests to the Rx and
> Tx addresses at the same time.  Very bad things will happen.
> 
> Also, what is the polling interval for ir-kbd-i2c?  If it's too high
> you can wedge the I2C bus (depending on the hardware design).
> Likewise, many people disable IR RX entirely (which is trivial to do
> with lirc_zilog through a modprobe optoin).  This is because early
> versions of the HDPVR had issues where polling too often can
> interfere
> with traffic that configures the component receiver chip.  This was
> improved in later versions of the design, but many people found it
> was
> just easiest to disable RX since they don't use it (i.e. they would
> use the blaster for controlling their STB but use a separate IR
> receiver).
> 
> Are you testing with video capture actively in use?  If you're
> testing
> the IR interface without an active HD capture in progress you're
> likely to miss some of these edge cases (in particular those which
> would hang the encoder).

I'm glad someone remembers all this stuff.  I'm assuming you had more
pain with this than I ever did.  I never owned an HD-PVR.

Regards,
Andy

> I'm not against the removal of duplicate code in general, but you
> have
> to tread carefully because there are plenty of non-obvious edge cases
> to consider.
> 
> Devin
> 

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 04/26] media: lirc_zilog: remove receiver
  2017-10-12  0:50           ` Andy Walls
@ 2017-10-12  2:25             ` Devin Heitmueller
  2017-10-12 12:25               ` Sean Young
  0 siblings, 1 reply; 39+ messages in thread
From: Devin Heitmueller @ 2017-10-12  2:25 UTC (permalink / raw)
  To: Andy Walls; +Cc: Sean Young, Linux Media Mailing List

Hi Andy,

> 5. Rx and IR Learn both use the same external hardware.  Not
> coordinating Rx with Learn mode in the same driver, will prevent Learn
> operation from working.  That is, if Learn mode is ever implemented.
> (Once upon a time, I was planning on doing that.  But I have no time
> for that anymore.)

There's not really any infrastructure in Linux that maps to the
Zilog's "learning mode" functionality.  Usually I would just tell
users to do the learning under Windows and send me the resulting .ini
file (which we could then add to the database).

I had planned on getting rid of the database entirely and just
converting an MCE compatible pulse train to the blasting format
required by the Zilog firmware (using the awesome work you sent me
privately), but the fact of the matter is that nobody cares and MCEUSB
devices are $20 online.

> I'm glad someone remembers all this stuff.  I'm assuming you had more
> pain with this than I ever did.

This would be a safe assumption.  I probably put about a month's worth
of engineering into driver work for the Zilog, which seems
extraordinary given how simple something like an IR blaster/receiver
is supposed to be.  I guess that's the fun of proving out a new
hardware design as opposed to just making something work under Linux
that is already known to work under Windows.

> I never owned an HD-PVR.

I'm sure I have a spare or two if you really want one (not that you
have the time to muck with such things nowadays).  :-)

The HD-PVR was a bit of a weird case compared to devices like ivtv and
cx18 because it was technically multi-master (I2C commands came both
from the host and from the onboard SOC).  Hence you could have weird
cases where one would block the other at unexpected times.  I2C
commands to the Zilog would hold the bus which would delay the onboard
firmware from issuing commands to the video decoder (fun timing
issues).  There was also some weird edge case I don't recall the
details of that prompted them to add an I2C gate in later board
revisions.

Devin

-- 
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 04/26] media: lirc_zilog: remove receiver
  2017-10-12  0:25         ` Devin Heitmueller
  2017-10-12  0:50           ` Andy Walls
@ 2017-10-12 11:40           ` Sean Young
  1 sibling, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-12 11:40 UTC (permalink / raw)
  To: Devin Heitmueller; +Cc: Andy Walls, Linux Media Mailing List

On Wed, Oct 11, 2017 at 08:25:12PM -0400, Devin Heitmueller wrote:
> > There's an ir_lock mutex in the driver to prevent simultaneous access to the Rx and Tx functions of the z8.  Accessing Rx and Tx functions of the chip together can cause it to do the wrong thing (sometimes hang?), IIRC.
> >
> > I'll see if I can dig up my old disassembly of the z8's firmware to see if that interlock is strictly necessary.
> >
> > Yes I know ir-kbd-i2c is in mainline, but as I said, I had reasons for avoiding it when using Tx operation of the chip.  It's been 7 years, and I'm getting too old to remember the reasons. :P
> 
> Yeah, you definitely don't want to be issuing requests to the Rx and
> Tx addresses at the same time.  Very bad things will happen.

Right, ok. That's good to know. I'll have to merge the Tx code with 
ir-kbd-i2c or port lirc_zilog Rx to rc-core.

> Also, what is the polling interval for ir-kbd-i2c?

lirc_zilog polls every 260ms and ir-kbd-i2c polls every 100ms.

>  If it's too high
> you can wedge the I2C bus (depending on the hardware design).
> Likewise, many people disable IR RX entirely (which is trivial to do
> with lirc_zilog through a modprobe optoin).

Yes, lirc_zilog has a tx_only option.

>  This is because early
> versions of the HDPVR had issues where polling too often can interfere
> with traffic that configures the component receiver chip.  This was
> improved in later versions of the design, but many people found it was
> just easiest to disable RX since they don't use it (i.e. they would
> use the blaster for controlling their STB but use a separate IR
> receiver).

That's very interesting.

> Are you testing with video capture actively in use?  If you're testing
> the IR interface without an active HD capture in progress you're
> likely to miss some of these edge cases (in particular those which
> would hang the encoder).

I had not, but I'll do that now.

> I'm not against the removal of duplicate code in general, but you have
> to tread carefully because there are plenty of non-obvious edge cases
> to consider.

Absolutely, thank you for your insights. 

Rather than relying on ir-kbd-i2c for receive, I can port lirc_zilog
to rc-core and leave much of it in place.

Thanks

Sean

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 04/26] media: lirc_zilog: remove receiver
  2017-10-12  2:25             ` Devin Heitmueller
@ 2017-10-12 12:25               ` Sean Young
  0 siblings, 0 replies; 39+ messages in thread
From: Sean Young @ 2017-10-12 12:25 UTC (permalink / raw)
  To: Devin Heitmueller; +Cc: Andy Walls, Linux Media Mailing List

Hi Devin, Andy,

On Wed, Oct 11, 2017 at 10:25:34PM -0400, Devin Heitmueller wrote:
> Hi Andy,
> 
> > 5. Rx and IR Learn both use the same external hardware.  Not
> > coordinating Rx with Learn mode in the same driver, will prevent Learn
> > operation from working.  That is, if Learn mode is ever implemented.
> > (Once upon a time, I was planning on doing that.  But I have no time
> > for that anymore.)
> 
> There's not really any infrastructure in Linux that maps to the
> Zilog's "learning mode" functionality.  Usually I would just tell
> users to do the learning under Windows and send me the resulting .ini
> file (which we could then add to the database).
> 
> I had planned on getting rid of the database entirely and just
> converting an MCE compatible pulse train to the blasting format
> required by the Zilog firmware (using the awesome work you sent me
> privately), but the fact of the matter is that nobody cares and MCEUSB
> devices are $20 online.

I wouldn't mind working on that, if I had the blasting format. :)

Note that you can have IR Rx and Tx on a gpio port, so it can get even
cheaper than $20. The hauppauge solution with a z8 microcontroller
with it's non-obvious firmware and i2c format seem a bit ludricous.

> > I'm glad someone remembers all this stuff.  I'm assuming you had more
> > pain with this than I ever did.
> 
> This would be a safe assumption.  I probably put about a month's worth
> of engineering into driver work for the Zilog, which seems
> extraordinary given how simple something like an IR blaster/receiver
> is supposed to be.  I guess that's the fun of proving out a new
> hardware design as opposed to just making something work under Linux
> that is already known to work under Windows.
> 
> > I never owned an HD-PVR.
> 
> I'm sure I have a spare or two if you really want one (not that you
> have the time to muck with such things nowadays).  :-)
> 
> The HD-PVR was a bit of a weird case compared to devices like ivtv and
> cx18 because it was technically multi-master (I2C commands came both
> from the host and from the onboard SOC).  Hence you could have weird
> cases where one would block the other at unexpected times.  I2C
> commands to the Zilog would hold the bus which would delay the onboard
> firmware from issuing commands to the video decoder (fun timing
> issues).  There was also some weird edge case I don't recall the
> details of that prompted them to add an I2C gate in later board
> revisions.

Interesting.

Thanks

Sean

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 26/26] kfifo: DECLARE_KIFO_PTR(fifo, u64) does not work on arm 32 bit
  2017-10-10  7:59 ` Sean Young
@ 2017-11-30 12:29   ` Mauro Carvalho Chehab
  2017-11-30 12:34     ` Stefani Seibold
  0 siblings, 1 reply; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2017-11-30 12:29 UTC (permalink / raw)
  To: Sean Young, Stefani Seibold, Andrew Morton
  Cc: linux-media, linux-kernel, Randy Dunlap

Em Tue, 10 Oct 2017 09:59:42 +0200
Sean Young <sean@mess.org> escreveu:

> If you try to store u64 in a kfifo (or a struct with u64 members),
> then the buf member of __STRUCT_KFIFO_PTR will cause 4 bytes
> padding due to alignment (note that struct __kfifo is 20 bytes
> on 32 bit).
> 
> That in turn causes the __is_kfifo_ptr() to fail, which is caught
> by kfifo_alloc(), which now returns EINVAL.
> 
> So, ensure that __is_kfifo_ptr() compares to the right structure.
> 
> Signed-off-by: Sean Young <sean@mess.org>
> Acked-by: Stefani Seibold <stefani@seibold.net>

Hi Stefani/Andrew,

As this patch is required for the LIRC rework, would be ok if I would
merge it via the media tree?

Thanks!
Mauro


> 
> ---
>  include/linux/kfifo.h | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
> index 41eb6fdf87a8..86b5fb08e96c 100644
> --- a/include/linux/kfifo.h
> +++ b/include/linux/kfifo.h
> @@ -113,7 +113,8 @@ struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PTR(unsigned char, 2, void);
>   * array is a part of the structure and the fifo type where the array is
>   * outside of the fifo structure.
>   */
> -#define	__is_kfifo_ptr(fifo)	(sizeof(*fifo) == sizeof(struct __kfifo))
> +#define	__is_kfifo_ptr(fifo) \
> +	(sizeof(*fifo) == sizeof(STRUCT_KFIFO_PTR(typeof(*(fifo)->type))))
>  
>  /**
>   * DECLARE_KFIFO_PTR - macro to declare a fifo pointer object



Thanks,
Mauro

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 26/26] kfifo: DECLARE_KIFO_PTR(fifo, u64) does not work on arm 32 bit
  2017-11-30 12:29   ` Mauro Carvalho Chehab
@ 2017-11-30 12:34     ` Stefani Seibold
  2017-12-08 14:07       ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 39+ messages in thread
From: Stefani Seibold @ 2017-11-30 12:34 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Sean Young, Andrew Morton
  Cc: linux-media, linux-kernel, Randy Dunlap

On Thu, 2017-11-30 at 10:29 -0200, Mauro Carvalho Chehab wrote:
> Em Tue, 10 Oct 2017 09:59:42 +0200
> Sean Young <sean@mess.org> escreveu:
> 
> > If you try to store u64 in a kfifo (or a struct with u64 members),
> > then the buf member of __STRUCT_KFIFO_PTR will cause 4 bytes
> > padding due to alignment (note that struct __kfifo is 20 bytes
> > on 32 bit).
> > 
> > That in turn causes the __is_kfifo_ptr() to fail, which is caught
> > by kfifo_alloc(), which now returns EINVAL.
> > 
> > So, ensure that __is_kfifo_ptr() compares to the right structure.
> > 
> > Signed-off-by: Sean Young <sean@mess.org>
> > Acked-by: Stefani Seibold <stefani@seibold.net>
> 
> Hi Stefani/Andrew,
> 
> As this patch is required for the LIRC rework, would be ok if I would
> merge it via the media tree?
> 

It is okay by me. But the question remains why this patch wasn't
already merged?

Andrew: Any objections against this patch?


> > 
> > ---
> >  include/linux/kfifo.h | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> > 
> > diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
> > index 41eb6fdf87a8..86b5fb08e96c 100644
> > --- a/include/linux/kfifo.h
> > +++ b/include/linux/kfifo.h
> > @@ -113,7 +113,8 @@ struct kfifo_rec_ptr_2
> > __STRUCT_KFIFO_PTR(unsigned char, 2, void);
> >   * array is a part of the structure and the fifo type where the
> > array is
> >   * outside of the fifo structure.
> >   */
> > -#define	__is_kfifo_ptr(fifo)	(sizeof(*fifo) ==
> > sizeof(struct __kfifo))
> > +#define	__is_kfifo_ptr(fifo) \
> > +	(sizeof(*fifo) == sizeof(STRUCT_KFIFO_PTR(typeof(*(fifo)-
> > >type))))
> >  
> >  /**
> >   * DECLARE_KFIFO_PTR - macro to declare a fifo pointer object
> 
> 
> 
> Thanks,
> Mauro

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 26/26] kfifo: DECLARE_KIFO_PTR(fifo, u64) does not work on arm 32 bit
  2017-11-30 12:34     ` Stefani Seibold
@ 2017-12-08 14:07       ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2017-12-08 14:07 UTC (permalink / raw)
  To: Stefani Seibold, Andrew Morton
  Cc: Sean Young, linux-media, linux-kernel, Randy Dunlap

Em Thu, 30 Nov 2017 13:34:10 +0100
Stefani Seibold <stefani@seibold.net> escreveu:

> On Thu, 2017-11-30 at 10:29 -0200, Mauro Carvalho Chehab wrote:
> > Em Tue, 10 Oct 2017 09:59:42 +0200
> > Sean Young <sean@mess.org> escreveu:
> >   
> > > If you try to store u64 in a kfifo (or a struct with u64 members),
> > > then the buf member of __STRUCT_KFIFO_PTR will cause 4 bytes
> > > padding due to alignment (note that struct __kfifo is 20 bytes
> > > on 32 bit).
> > > 
> > > That in turn causes the __is_kfifo_ptr() to fail, which is caught
> > > by kfifo_alloc(), which now returns EINVAL.
> > > 
> > > So, ensure that __is_kfifo_ptr() compares to the right structure.
> > > 
> > > Signed-off-by: Sean Young <sean@mess.org>
> > > Acked-by: Stefani Seibold <stefani@seibold.net>  
> > 
> > Hi Stefani/Andrew,
> > 
> > As this patch is required for the LIRC rework, would be ok if I would
> > merge it via the media tree?
> >   
> 
> It is okay by me. But the question remains why this patch wasn't
> already merged?
> 
> Andrew: Any objections against this patch?


I'm assuming that merging via media tree is ok for Andrew. So, I guess
I'll just go ahead and merge it via my tree.


Thanks,
Mauro

^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2017-12-08 14:07 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-10  7:17 [PATCH v3 00/26] lirc scancode interface, and more Sean Young
2017-10-10  7:17 ` [PATCH v3 01/26] media: lirc: implement scancode sending Sean Young
2017-10-10  7:17 ` [PATCH v3 02/26] media: lirc: use the correct carrier for scancode transmit Sean Young
2017-10-10  7:17 ` [PATCH v3 03/26] media: rc: auto load encoder if necessary Sean Young
2017-10-10  7:17 ` [PATCH v3 04/26] media: lirc_zilog: remove receiver Sean Young
2017-10-11 19:43   ` Andy Walls
2017-10-11 21:02     ` Sean Young
2017-10-11 23:24       ` Andy Walls
2017-10-12  0:25         ` Devin Heitmueller
2017-10-12  0:50           ` Andy Walls
2017-10-12  2:25             ` Devin Heitmueller
2017-10-12 12:25               ` Sean Young
2017-10-12 11:40           ` Sean Young
2017-10-10  7:17 ` [PATCH v3 05/26] media: lirc_zilog: fix variable types and other ugliness Sean Young
2017-10-10  7:17 ` [PATCH v3 06/26] media: lirc_zilog: port to rc-core using scancode tx interface Sean Young
2017-10-10  7:17 ` [PATCH v3 07/26] media: promote lirc_zilog out of staging Sean Young
2017-10-10  7:17 ` [PATCH v3 08/26] media: lirc: remove LIRCCODE and LIRC_GET_LENGTH Sean Young
2017-10-10  7:17 ` [PATCH v3 09/26] media: lirc: lirc interface should not be a raw decoder Sean Young
2017-10-10  7:17 ` [PATCH v3 10/26] media: lirc: validate scancode for transmit Sean Young
2017-10-10  7:18 ` [PATCH v3 11/26] media: rc: document and fix rc_validate_scancode() Sean Young
2017-10-10  7:18 ` [PATCH v3 12/26] media: lirc: merge lirc_dev_fop_ioctl and ir_lirc_ioctl Sean Young
2017-10-10  7:18 ` [PATCH v3 13/26] media: lirc: use kfifo rather than lirc_buffer for raw IR Sean Young
2017-10-10  7:18 ` [PATCH v3 14/26] media: lirc: move lirc_dev->attached to rc_dev->registered Sean Young
2017-10-10  7:18 ` [PATCH v3 15/26] media: lirc: do not call rc_close() on unregistered devices Sean Young
2017-10-10  7:18 ` [PATCH v3 16/26] media: lirc: create rc-core open and close lirc functions Sean Young
2017-10-10  7:18 ` [PATCH v3 17/26] media: lirc: remove name from lirc_dev Sean Young
2017-10-10  7:18 ` [PATCH v3 18/26] media: lirc: remove last remnants of lirc kapi Sean Young
2017-10-10  7:18 ` [PATCH v3 19/26] media: lirc: implement reading scancode Sean Young
2017-10-10  7:18 ` [PATCH v3 20/26] media: rc: ensure lirc device receives nec repeats Sean Young
2017-10-10  7:18 ` [PATCH v3 21/26] media: lirc: document LIRC_MODE_SCANCODE Sean Young
2017-10-10  7:18 ` [PATCH v3 22/26] media: lirc: introduce LIRC_SET_POLL_MODES Sean Young
2017-10-10  7:18 ` [PATCH v3 23/26] media: lirc: scancode rc devices should have a lirc device too Sean Young
2017-10-10  7:18 ` [PATCH v3 24/26] media: MAINTAINERS: remove lirc staging area Sean Young
2017-10-10  7:18 ` [PATCH v3 25/26] media: MAINTAINERS: add entry for zilog_ir Sean Young
2017-10-10  7:18 ` [PATCH v3 26/26] kfifo: DECLARE_KIFO_PTR(fifo, u64) does not work on arm 32 bit Sean Young
2017-10-10  7:59 ` Sean Young
2017-11-30 12:29   ` Mauro Carvalho Chehab
2017-11-30 12:34     ` Stefani Seibold
2017-12-08 14:07       ` Mauro Carvalho Chehab

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.