Skip to contentSkip to conversation

Teach lirc how to send and receive scancodes

PATCH Superseded Sean Young 2 participants 23 messages Feb 21, 2017 – Feb 22, 2017

Subsystems (8)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Sean Young

author maintainer
#0 lore raw

v2 cover Teach lirc how to send and receive scancodes

This patch series has some general cleanup work, then the lirc scancode interface (v2) and lirc documentation fixes. The cleanups are needed for the new scancode interface.

lirc already supports LIRC_MODE_LIRCCODE, but that mode is entirely driver dependant and makes no provision for protocol information.

Receiving LIRC_MODE_SCANCODE
----------------------------
If a lirc device has the LIRC_CAN_REC_SCANCODE feature, LIRC_MODE_SCANCODE can be set set using LIRC_SET_REC_MODE ioctl. Now when you read from the device you receive struct lirc_scancode. In this structure you have the scancode, rc_type, and flags. RC_TYPE_* is now in uapi, so now you can see exactly which protocol variant was used. flags might contain LIRC_SCANCODE_FLAGS_TOGGLE (rc5, rc6) or LIRC_SCANCODE_FLAGS_REPEAT (nec).

Using this interface, you can see what IR protocol a remote is using. This was not easy to do before.

Sending LIRC_MODE_SCANCODE
--------------------------
If a lirc device has the LIRC_CAN_SEND_SCANCODE features, LIRC_MODE_SCANCODE can be set using the LIRC_SET_SEND_MODE ioctl. Now you can write struct lirc_scancode. flags should be 0, rc_type to the RC_TYPE_* and the scancode must be set. You can only tranmsit one lirc_scancode at a time.

This interface uses the in-kernel IR encoders to work. Using this interface it will be possible to port lirc_zilog to rc-core. This device cannot send raw IR, so it will not use the IR encoders but provide the same userspace interface.

Other user-visible changes
--------------------------
Now all RC devices will have a lirc char device, including devices which do not produce raw IR. They will be fixed in mode LIRC_MODE_SCANCODE.

Changes v1 -> v2:
- changed the scancode to 64 bit. There are many IR protocols which encode more than 32 bits; we don't support any at the moment but might as well future-proof it
http://www.hifi-remote.com/wiki/index.php?title=DecodeIR
- Various small fixes.
- Added documentation

Sean Young (19):
[media] lirc: document lirc modes better
[media] lirc: return ENOTTY when ioctl is not supported [media] lirc: return ENOTTY when device does support ioctl [media] winbond: allow timeout to be set
[media] gpio-ir: do not allow a timeout of 0
[media] rc: lirc keymap no longer makes any sense [media] lirc: advertise LIRC_CAN_GET_REC_RESOLUTION and improve [media] lirc: use refcounting for lirc devices [media] mce_kbd: add encoder
[media] serial_ir: iommap is a memory address, not bool [media] lirc: lirc interface should not be a raw decoder [media] lirc: exorcise struct irctl
[media] lirc: use plain kfifo rather than lirc_buffer [media] lirc: implement scancode sending
[media] rc: use the correct carrier for scancode transmit [media] rc: auto load encoder if necessary
[media] lirc: implement reading scancode
[media] lirc: scancode rc devices should have a lirc device too [media] lirc: document LIRC_MODE_SCANCODE

 Documentation/media/uapi/rc/lirc-dev-intro.rst     |  73 +++-
 Documentation/media/uapi/rc/lirc-get-features.rst  |  28 +-
 Documentation/media/uapi/rc/lirc-get-length.rst    |   3 +-
 Documentation/media/uapi/rc/lirc-get-rec-mode.rst  |   8 +-
 Documentation/media/uapi/rc/lirc-get-send-mode.rst |   8 +-
 Documentation/media/uapi/rc/lirc-read.rst          |  22 +-
 .../media/uapi/rc/lirc-set-rec-carrier-range.rst   |   2 +-
 Documentation/media/uapi/rc/lirc-write.rst         |  25 +-
 drivers/media/rc/Kconfig                           |  15 +-
 drivers/media/rc/Makefile                          |   6 +-
 drivers/media/rc/gpio-ir-recv.c                    |   2 +-
 drivers/media/rc/igorplugusb.c                     |   2 +-
 drivers/media/rc/ir-jvc-decoder.c                  |   1 +
 drivers/media/rc/ir-lirc-codec.c                   | 361 ++++++++++-------
 drivers/media/rc/ir-mce_kbd-decoder.c              |  57 ++-
 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/keymaps/Makefile                  |   1 -
 drivers/media/rc/keymaps/rc-lirc.c                 |  42 --
 drivers/media/rc/lirc_dev.c                        | 431 +++++++++------------
 drivers/media/rc/rc-core-priv.h                    |  56 ++-
 drivers/media/rc/rc-ir-raw.c                       |  55 ++-
 drivers/media/rc/rc-main.c                         |  77 ++--
 drivers/media/rc/serial_ir.c                       |   4 +-
 drivers/media/rc/st_rc.c                           |   2 +-
 drivers/media/rc/winbond-cir.c                     |   4 +-
 drivers/staging/media/lirc/lirc_sasem.c            |   3 +-
 drivers/staging/media/lirc/lirc_zilog.c            | 109 +++---
 include/media/lirc_dev.h                           |  29 +-
 include/media/rc-core.h                            |  15 +-
 include/media/rc-map.h                             | 109 ++----
 include/uapi/linux/lirc.h                          |  68 ++++
 36 files changed, 974 insertions(+), 650 deletions(-)
 delete mode 100644 drivers/media/rc/keymaps/rc-lirc.c
Signature · 1 line
2.9.3
author maintainer
#1 lore raw

PATCH v2 1/19 lirc: document lirc modes better

LIRC_MODE_MODE2 and LIRC_MODE_LIRCCODE were not covered at all.

---
 Documentation/media/uapi/rc/lirc-dev-intro.rst     | 53 +++++++++++++++++++---
 Documentation/media/uapi/rc/lirc-get-features.rst  | 13 ++++--
 Documentation/media/uapi/rc/lirc-get-length.rst    |  3 +-
 Documentation/media/uapi/rc/lirc-get-rec-mode.rst  |  4 +-
 Documentation/media/uapi/rc/lirc-get-send-mode.rst |  7 ++-
 Documentation/media/uapi/rc/lirc-read.rst          | 18 ++++----
 .../media/uapi/rc/lirc-set-rec-carrier-range.rst   |  2 +-
 Documentation/media/uapi/rc/lirc-write.rst         | 19 +++++---
 8 files changed, 84 insertions(+), 35 deletions(-)
Documentation/media/uapi/rc/lirc-dev-intro.rst +46 -7
index ef97e40..1250d4c 100644
@@ -27,6 +27,8 @@ What you should see for a chardev:
     $ ls -l /dev/lirc*
     crw-rw---- 1 root root 248, 0 Jul 2 22:20 /dev/lirc0
 
+.. _lirc_modes:
+
 **********
 LIRC modes
 **********
@@ -38,25 +40,62 @@ on the following table.
 
 ``LIRC_MODE_MODE2``
 
-    The driver returns a sequence of pulse and space codes to userspace.
+    The driver returns a sequence of pulse and space codes to userspace,
+    as a series of u32 values.
 
     This mode is used only for IR receive.
 
+    The upper 8 bits determine the packet type, and the lower 24 bits
+    the payload. Use ``LIRC_VALUE()`` macro to get the payload, and
+    the macro ``LIRC_MODE2()`` will give you the type, which
+    is one of:
+
+    ``LIRC_MODE2_PULSE``
+
+        Signifies the presence of IR in microseconds.
+
+    ``LIRC_MODE2_SPACE``
+
+        Signifies absence of IR in microseconds.
+
+    ``LIRC_MODE2_FREQUENCY``
+
+        If measurement of the carrier frequency was enabled with
+        :ref:`lirc_set_measure_carrier_mode` then this packet gives you
+        the carrier frequency in Hertz.
+
+    ``LIRC_MODE2_TIMEOUT``
+
+        If timeout reports are enabled with
+        :ref:`lirc_set_rec_timeout_reports`, when the timeout set with
+        :ref:`lirc_set_timeout` expires due to no IR being detected,
+        this packet will be sent, with the number of microseconds with
+        no IR.
+
 .. _lirc-mode-lirccode:
 
 ``LIRC_MODE_LIRCCODE``
 
-    The IR signal is decoded internally by the receiver. The LIRC interface
-    returns the scancode as an integer value. This is the usual mode used
-    by several TV media cards.
+    This mode can be used for IR receive and send.
 
-    This mode is used only for IR receive.
+    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``
 
-    On puse mode, a sequence of pulse/space integer values are written to the
-    lirc device using :Ref:`lirc-write`.
+    In pulse mode, a sequence of pulse/space integer values are written to the
+    lirc device using :ref:`lirc-write`.
+
+    The values are alternating pulse and space lengths, in microseconds. The
+    first and last entry must be a pulse, so there must be an odd number
+    of entries.
 
     This mode is used only for IR send.
Documentation/media/uapi/rc/lirc-get-features.rst +8 -5
index 79e07b4..64f89a4 100644
@@ -48,8 +48,8 @@ LIRC features
 
 ``LIRC_CAN_REC_PULSE``
 
-    The driver is capable of receiving using
-    :ref:`LIRC_MODE_PULSE <lirc-mode-pulse>`.
+    Unused. Kept just to avoid breaking uAPI.
+    :ref:`LIRC_MODE_PULSE <lirc-mode-pulse>` can only be used for transmitting.
 
 .. _LIRC-CAN-REC-MODE2:
 
@@ -156,19 +156,22 @@ LIRC features
 
 ``LIRC_CAN_SEND_PULSE``
 
-    The driver supports sending using :ref:`LIRC_MODE_PULSE <lirc-mode-pulse>`.
+    The driver supports sending (also called as IR blasting or IR TX) using
+    :ref:`LIRC_MODE_PULSE <lirc-mode-pulse>`.
 
 .. _LIRC-CAN-SEND-MODE2:
 
 ``LIRC_CAN_SEND_MODE2``
 
-    The driver supports sending using :ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>`.
+    Unused. Kept just to avoid breaking uAPI.
+    :ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>` can only be used for receiving.
 
 .. _LIRC-CAN-SEND-LIRCCODE:
 
 ``LIRC_CAN_SEND_LIRCCODE``
 
-    The driver supports sending codes (also called as IR blasting or IR TX).
+    The driver supports sending (also called as IR blasting or IR TX) using
+    :ref:`LIRC_MODE_LIRCCODE <lirc-mode-LIRCCODE>`.
 
 
 Return Value
Documentation/media/uapi/rc/lirc-get-length.rst +2 -1
index 8c2747c..3990af5 100644
@@ -30,7 +30,8 @@ Arguments
 Description
 ===========
 
-Retrieves the code length in bits (only for ``LIRC-MODE-LIRCCODE``).
+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.
 
Documentation/media/uapi/rc/lirc-get-rec-mode.rst +2 -2
index a5023e0..a4eb6c0 100644
@@ -35,8 +35,8 @@ 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.
-
+receive. Use :ref:`lirc_get_features` to find out which modes the driver
+supports.
 
 Return Value
 ============
Documentation/media/uapi/rc/lirc-get-send-mode.rst +5 -2
index 51ac134..a169b23 100644
@@ -34,9 +34,12 @@ Arguments
 Description
 ===========
 
-Get/set supported transmit mode.
+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_LIRCCODE <lirc-mode-lirccode>` is supported by for IR send,
+depending on the driver. Use :ref:`lirc_get_features` to find out which
+modes the driver supports.
 
 Return Value
 ============
Documentation/media/uapi/rc/lirc-read.rst +8 -10
index 4c678f6..ffa2830 100644
@@ -44,17 +44,15 @@ descriptor ``fd`` into the buffer starting at ``buf``.  If ``count`` is zero,
 :ref:`read() <lirc-read>` returns zero and has no other results. If ``count``
 is greater than ``SSIZE_MAX``, the result is unspecified.
 
-The lircd userspace daemon reads raw IR data from the LIRC chardev. The
-exact format of the data depends on what modes a driver supports, and
-what mode has been selected. lircd obtains supported modes and sets the
-active mode via the ioctl interface, detailed at :ref:`lirc_func`.
-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 read from the chardev.
+The exact format of the data depends on what :ref:`lirc_modes` a driver
+supports, and which mode has been selected. Use :ref:`lirc_get_features` to
+get a list of supported modes, and :ref:`lirc_get_rec_mode` to get or set the
+recording mode if multiple modes are available.
 
-See also
-`http://www.lirc.org/html/technical.html <http://www.lirc.org/html/technical.html>`__
-for more info.
+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
+read from the chardev.
 
 Return Value
 ============
Documentation/media/uapi/rc/lirc-set-rec-carrier-range.rst +1 -1
index a83fbbf..a892468 100644
@@ -9,7 +9,7 @@ ioctl LIRC_SET_REC_CARRIER_RANGE
 Name
 ====
 
-LIRC_SET_REC_CARRIER_RANGE - Set lower bond of the carrier used to modulate
+LIRC_SET_REC_CARRIER_RANGE - Set lower bound of the carrier used to modulate
 IR receive.
 
 Synopsis
Documentation/media/uapi/rc/lirc-write.rst +12 -7
index 3b035c6..6b44e0d 100644
@@ -42,13 +42,18 @@ Description
 referenced by the file descriptor ``fd`` from the buffer starting at
 ``buf``.
 
-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 by the hardware. If more data
-is provided than the hardware can send, the driver returns ``EINVAL``.
-
+The exact format of the data depends on what modes a driver supports,
+and what mode has been selected. Use :ref:`lirc_get_features` to get a
+list of supported modes, and :ref:`lirc_get_send_mode` to get or set
+the sending mode if multiple modes are available.
+
+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
+by the hardware. If more data is provided than the hardware can send, the
+driver returns ``EINVAL``.
 
 Return Value
 ============
Signature · 1 line
2.9.3
author maintainer
#2 lore raw

PATCH v2 2/19 lirc: return ENOTTY when ioctl is not supported

In reply to Sean Young

We shouldn't be using ENOSYS when a feature is not available. I've tested lirc; nothing is broken as far as I can make out.

---
 drivers/media/rc/ir-lirc-codec.c | 20 ++++++++++----------
 drivers/media/rc/lirc_dev.c      |  2 +-
 2 files changed, 11 insertions(+), 11 deletions(-)
drivers/media/rc/ir-lirc-codec.c +10 -10
index 8517d51..637b583 100644
@@ -139,7 +139,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 	}
 
 	if (!dev->tx_ir) {
-		ret = -ENOSYS;
+		ret = -EINVAL;
 		goto out;
 	}
 
@@ -221,19 +221,19 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 	/* TX settings */
 	case LIRC_SET_TRANSMITTER_MASK:
 		if (!dev->s_tx_mask)
-			return -ENOSYS;
+			return -ENOTTY;
 
 		return dev->s_tx_mask(dev, val);
 
 	case LIRC_SET_SEND_CARRIER:
 		if (!dev->s_tx_carrier)
-			return -ENOSYS;
+			return -ENOTTY;
 
 		return dev->s_tx_carrier(dev, val);
 
 	case LIRC_SET_SEND_DUTY_CYCLE:
 		if (!dev->s_tx_duty_cycle)
-			return -ENOSYS;
+			return -ENOTTY;
 
 		if (val <= 0 || val >= 100)
 			return -EINVAL;
@@ -243,7 +243,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 	/* RX settings */
 	case LIRC_SET_REC_CARRIER:
 		if (!dev->s_rx_carrier_range)
-			return -ENOSYS;
+			return -ENOTTY;
 
 		if (val <= 0)
 			return -EINVAL;
@@ -265,32 +265,32 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 
 	case LIRC_SET_WIDEBAND_RECEIVER:
 		if (!dev->s_learning_mode)
-			return -ENOSYS;
+			return -ENOTTY;
 
 		return dev->s_learning_mode(dev, !!val);
 
 	case LIRC_SET_MEASURE_CARRIER_MODE:
 		if (!dev->s_carrier_report)
-			return -ENOSYS;
+			return -ENOTTY;
 
 		return dev->s_carrier_report(dev, !!val);
 
 	/* Generic timeout support */
 	case LIRC_GET_MIN_TIMEOUT:
 		if (!dev->max_timeout)
-			return -ENOSYS;
+			return -ENOTTY;
 		val = DIV_ROUND_UP(dev->min_timeout, 1000);
 		break;
 
 	case LIRC_GET_MAX_TIMEOUT:
 		if (!dev->max_timeout)
-			return -ENOSYS;
+			return -ENOTTY;
 		val = dev->max_timeout / 1000;
 		break;
 
 	case LIRC_SET_REC_TIMEOUT:
 		if (!dev->max_timeout)
-			return -ENOSYS;
+			return -ENOTTY;
 
 		tmp = val * 1000;
 
drivers/media/rc/lirc_dev.c +1 -1
index a54ca53..ccbdce0 100644
@@ -623,7 +623,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		result = put_user(ir->d.max_timeout, (__u32 __user *)arg);
 		break;
 	default:
-		result = -EINVAL;
+		result = -ENOTTY;
 	}
 
 	mutex_unlock(&ir->irctl_lock);
Signature · 1 line
2.9.3
author maintainer
#3 lore raw

PATCH v2 3/19 lirc: return ENOTTY when device does support ioctl

In reply to Sean Young

If timeouts or carrier range is not supported, return proper error.

---
 drivers/media/rc/ir-lirc-codec.c | 6 ++++++
 1 file changed, 6 insertions(+)
drivers/media/rc/ir-lirc-codec.c +6 -0
index 637b583..235d74a 100644
@@ -253,6 +253,9 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 					       val);
 
 	case LIRC_SET_REC_CARRIER_RANGE:
+		if (!dev->s_rx_carrier_range)
+			return -ENOTTY;
+
 		if (val <= 0)
 			return -EINVAL;
 
@@ -305,6 +308,9 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		break;
 
 	case LIRC_SET_REC_TIMEOUT_REPORTS:
+		if (!dev->timeout)
+			return -ENOTTY;
+
 		lirc->send_timeout_reports = !!val;
 		break;
 
Signature · 1 line
2.9.3
author maintainer
#4 lore raw

PATCH v2 4/19 winbond: allow timeout to be set

In reply to Sean Young

The drivers sets the hardware to idle when a timeout occurs. This can be any reasonable value.

---
 drivers/media/rc/winbond-cir.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/media/rc/winbond-cir.c +3 -1
index dc1c830..5a4d4a6 100644
@@ -1082,7 +1082,9 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
 	data->dev->tx_ir = wbcir_tx;
 	data->dev->priv = data;
 	data->dev->dev.parent = &device->dev;
-	data->dev->timeout = MS_TO_NS(100);
+	data->dev->min_timeout = 1;
+	data->dev->timeout = IR_DEFAULT_TIMEOUT;
+	data->dev->max_timeout = 10 * IR_DEFAULT_TIMEOUT;
 	data->dev->rx_resolution = US_TO_NS(2);
 	data->dev->allowed_protocols = RC_BIT_ALL_IR_DECODER;
 	data->dev->allowed_wakeup_protocols = RC_BIT_NEC | RC_BIT_NECX |
Signature · 1 line
2.9.3
author maintainer
#5 lore raw

PATCH v2 5/19 gpio-ir: do not allow a timeout of 0

In reply to Sean Young

According to the documentation, a timeout of 0 turns off timeouts, which is not the case.

---
 drivers/media/rc/gpio-ir-recv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/rc/gpio-ir-recv.c +1 -1
index 4a4895e..b4f773b 100644
@@ -158,7 +158,7 @@ static int gpio_ir_recv_probe(struct platform_device *pdev)
 	rcdev->input_id.version = 0x0100;
 	rcdev->dev.parent = &pdev->dev;
 	rcdev->driver_name = GPIO_IR_DRIVER_NAME;
-	rcdev->min_timeout = 0;
+	rcdev->min_timeout = 1;
 	rcdev->timeout = IR_DEFAULT_TIMEOUT;
 	rcdev->max_timeout = 10 * IR_DEFAULT_TIMEOUT;
 	if (pdata->allowed_protos)
Signature · 1 line
2.9.3
author maintainer
#6 lore raw

PATCH v2 6/19 rc: lirc keymap no longer makes any sense

In reply to Sean Young

The lirc keymap existed once upon a time to select the lirc protocol. Since '275ddb4 [media] rc-core: remove the LIRC "protocol"', IR is always passed to the lirc decoder so this keymap is no longer needed.

---
 drivers/media/rc/keymaps/Makefile  |  1 -
 drivers/media/rc/keymaps/rc-lirc.c | 42 --------------------------------------
 drivers/media/rc/st_rc.c           |  2 +-
 include/media/rc-map.h             |  1 -
 4 files changed, 1 insertion(+), 45 deletions(-)
 delete mode 100644 drivers/media/rc/keymaps/rc-lirc.c
drivers/media/rc/keymaps/Makefile +0 -1
index ffe9e61..2945f99 100644
@@ -57,7 +57,6 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
 			rc-kworld-pc150u.o \
 			rc-kworld-plus-tv-analog.o \
 			rc-leadtek-y04g0051.o \
-			rc-lirc.o \
 			rc-lme2510.o \
 			rc-manli.o \
 			rc-medion-x10.o \
drivers/media/rc/keymaps/rc-lirc.c deleted +0 -42

42 lines not on this page · raw message

drivers/media/rc/st_rc.c +1 -1
index f0d7190..6228d93 100644
@@ -298,7 +298,7 @@ static int st_rc_probe(struct platform_device *pdev)
 	rdev->open = st_rc_open;
 	rdev->close = st_rc_close;
 	rdev->driver_name = IR_ST_NAME;
-	rdev->map_name = RC_MAP_LIRC;
+	rdev->map_name = RC_MAP_EMPTY;
 	rdev->input_name = "ST Remote Control Receiver";
 
 	ret = rc_register_device(rdev);
include/media/rc-map.h +0 -1
index a704749..878d852 100644
@@ -255,7 +255,6 @@ struct rc_map *rc_map_get(const char *name);
 #define RC_MAP_KWORLD_PC150U             "rc-kworld-pc150u"
 #define RC_MAP_KWORLD_PLUS_TV_ANALOG     "rc-kworld-plus-tv-analog"
 #define RC_MAP_LEADTEK_Y04G0051          "rc-leadtek-y04g0051"
-#define RC_MAP_LIRC                      "rc-lirc"
 #define RC_MAP_LME2510                   "rc-lme2510"
 #define RC_MAP_MANLI                     "rc-manli"
 #define RC_MAP_MEDION_X10                "rc-medion-x10"
Signature · 1 line
2.9.3
author maintainer
#7 lore raw

PATCH v2 7/19 lirc: advertise LIRC_CAN_GET_REC_RESOLUTION and improve

In reply to Sean Young

This feature was never set. The ioctl should fail if no resolution is set.

---
 drivers/media/rc/ir-lirc-codec.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/media/rc/ir-lirc-codec.c +7 -1
index 235d74a..de85f1d 100644
@@ -263,6 +263,9 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		return 0;
 
 	case LIRC_GET_REC_RESOLUTION:
+		if (!dev->rx_resolution)
+			return -ENOTTY;
+
 		val = dev->rx_resolution;
 		break;
 
@@ -367,8 +370,11 @@ static int ir_lirc_register(struct rc_dev *dev)
 	if (rc)
 		goto rbuf_init_failed;
 
-	if (dev->driver_type != RC_DRIVER_IR_RAW_TX)
+	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_ir) {
 		features |= LIRC_CAN_SEND_PULSE;
 		if (dev->s_tx_mask)
Signature · 1 line
2.9.3
author maintainer
#8 lore raw

PATCH v2 8/19 lirc: use refcounting for lirc devices

In reply to Sean Young

If a lirc device is unplugged, the struct rc_dev is freed even though userspace can still have a file descriptor open on the lirc chardev. The rc_dev structure can be used in a subsequent, or even currently executing ioctl, read or write.

---
 drivers/media/rc/lirc_dev.c | 120 +++++++++++++++++++-------------------------
 1 file changed, 51 insertions(+), 69 deletions(-)
drivers/media/rc/lirc_dev.c +51 -69
index ccbdce0..988758b 100644
@@ -54,7 +54,8 @@ struct irctl {
 	struct lirc_buffer *buf;
 	unsigned int chunk_size;
 
-	struct cdev *cdev;
+	struct device dev;
+	struct cdev cdev;
 
 	struct task_struct *task;
 	long jiffies_to_wait;
@@ -76,15 +77,21 @@ static void lirc_irctl_init(struct irctl *ir)
 	ir->d.minor = NOPLUG;
 }
 
-static void lirc_irctl_cleanup(struct irctl *ir)
+static void lirc_release(struct device *ld)
 {
-	device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
+	struct irctl *ir = container_of(ld, struct irctl, dev);
+
+	put_device(ir->dev.parent);
 
 	if (ir->buf != ir->d.rbuf) {
 		lirc_buffer_free(ir->buf);
 		kfree(ir->buf);
 	}
-	ir->buf = NULL;
+
+	mutex_lock(&lirc_dev_lock);
+	irctls[ir->d.minor] = NULL;
+	mutex_unlock(&lirc_dev_lock);
+	kfree(ir);
 }
 
 /*  helper function
@@ -157,32 +164,21 @@ static int lirc_cdev_add(struct irctl *ir)
 	struct cdev *cdev;
 	int retval;
 
-	cdev = cdev_alloc();
-	if (!cdev)
-		return -ENOMEM;
+	cdev = &ir->cdev;
 
 	if (d->fops) {
-		cdev->ops = d->fops;
+		cdev_init(cdev, d->fops);
 		cdev->owner = d->owner;
 	} else {
-		cdev->ops = &lirc_dev_fops;
+		cdev_init(cdev, &lirc_dev_fops);
 		cdev->owner = THIS_MODULE;
 	}
 	retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
 	if (retval)
-		goto err_out;
-
-	retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
-	if (retval)
-		goto err_out;
-
-	ir->cdev = cdev;
-
-	return 0;
+		return retval;
 
-err_out:
-	cdev_del(cdev);
-	return retval;
+	cdev->kobj.parent = &ir->dev.kobj;
+	return cdev_add(cdev, ir->dev.devt, 1);
 }
 
 static int lirc_allocate_buffer(struct irctl *ir)
@@ -304,9 +300,12 @@ static int lirc_allocate_driver(struct lirc_driver *d)
 
 	ir->d = *d;
 
-	device_create(lirc_class, ir->d.dev,
-		      MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL,
-		      "lirc%u", ir->d.minor);
+	ir->dev.devt = MKDEV(MAJOR(lirc_base_dev), ir->d.minor);
+	ir->dev.class = lirc_class;
+	ir->dev.parent = d->dev;
+	ir->dev.release = lirc_release;
+	dev_set_name(&ir->dev, "lirc%d", ir->d.minor);
+	device_initialize(&ir->dev);
 
 	if (d->sample_rate) {
 		ir->jiffies_to_wait = HZ / d->sample_rate;
@@ -329,14 +328,22 @@ static int lirc_allocate_driver(struct lirc_driver *d)
 		goto out_sysfs;
 
 	ir->attached = 1;
+
+	err = device_add(&ir->dev);
+	if (err)
+		goto out_cdev;
+
 	mutex_unlock(&lirc_dev_lock);
 
+	get_device(ir->dev.parent);
+
 	dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
 		 ir->d.name, ir->d.minor);
 	return minor;
-
+out_cdev:
+	cdev_del(&ir->cdev);
 out_sysfs:
-	device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
+	put_device(&ir->dev);
 out_lock:
 	mutex_unlock(&lirc_dev_lock);
 
@@ -364,7 +371,6 @@ EXPORT_SYMBOL(lirc_register_driver);
 int lirc_unregister_driver(int minor)
 {
 	struct irctl *ir;
-	struct cdev *cdev;
 
 	if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
 		pr_err("minor (%d) must be between 0 and %d!\n",
@@ -378,8 +384,6 @@ int lirc_unregister_driver(int minor)
 		return -ENOENT;
 	}
 
-	cdev = ir->cdev;
-
 	mutex_lock(&lirc_dev_lock);
 
 	if (ir->d.minor != minor) {
@@ -401,22 +405,20 @@ int lirc_unregister_driver(int minor)
 		dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
 			ir->d.name, ir->d.minor);
 		wake_up_interruptible(&ir->buf->wait_poll);
-		mutex_lock(&ir->irctl_lock);
+	}
 
-		if (ir->d.set_use_dec)
-			ir->d.set_use_dec(ir->d.data);
+	mutex_lock(&ir->irctl_lock);
 
-		module_put(cdev->owner);
-		mutex_unlock(&ir->irctl_lock);
-	} else {
-		lirc_irctl_cleanup(ir);
-		cdev_del(cdev);
-		kfree(ir);
-		irctls[minor] = NULL;
-	}
+	if (ir->d.set_use_dec)
+		ir->d.set_use_dec(ir->d.data);
 
+	mutex_unlock(&ir->irctl_lock);
 	mutex_unlock(&lirc_dev_lock);
 
+	device_del(&ir->dev);
+	cdev_del(&ir->cdev);
+	put_device(&ir->dev);
+
 	return 0;
 }
 EXPORT_SYMBOL(lirc_unregister_driver);
@@ -424,7 +426,6 @@ EXPORT_SYMBOL(lirc_unregister_driver);
 int lirc_dev_fop_open(struct inode *inode, struct file *file)
 {
 	struct irctl *ir;
-	struct cdev *cdev;
 	int retval = 0;
 
 	if (iminor(inode) >= MAX_IRCTL_DEVICES) {
@@ -459,18 +460,14 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
 			goto error;
 	}
 
-	cdev = ir->cdev;
-	if (try_module_get(cdev->owner)) {
-		ir->open++;
-		if (ir->d.set_use_inc)
-			retval = ir->d.set_use_inc(ir->d.data);
-
-		if (retval) {
-			module_put(cdev->owner);
-			ir->open--;
-		} else if (ir->buf) {
+	ir->open++;
+	if (ir->d.set_use_inc)
+		retval = ir->d.set_use_inc(ir->d.data);
+	if (retval) {
+		ir->open--;
+	} else {
+		if (ir->buf)
 			lirc_buffer_clear(ir->buf);
-		}
 		if (ir->task)
 			wake_up_process(ir->task);
 	}
@@ -487,7 +484,6 @@ EXPORT_SYMBOL(lirc_dev_fop_open);
 int lirc_dev_fop_close(struct inode *inode, struct file *file)
 {
 	struct irctl *ir = irctls[iminor(inode)];
-	struct cdev *cdev;
 	int ret;
 
 	if (!ir) {
@@ -495,25 +491,14 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file)
 		return -EINVAL;
 	}
 
-	cdev = ir->cdev;
-
 	ret = mutex_lock_killable(&lirc_dev_lock);
 	WARN_ON(ret);
 
 	rc_close(ir->d.rdev);
 
 	ir->open--;
-	if (ir->attached) {
-		if (ir->d.set_use_dec)
-			ir->d.set_use_dec(ir->d.data);
-		module_put(cdev->owner);
-	} else {
-		lirc_irctl_cleanup(ir);
-		cdev_del(cdev);
-		irctls[ir->d.minor] = NULL;
-		kfree(ir);
-	}
-
+	if (ir->d.set_use_dec)
+		ir->d.set_use_dec(ir->d.data);
 	if (!ret)
 		mutex_unlock(&lirc_dev_lock);
 
@@ -780,15 +765,12 @@ static int __init lirc_dev_init(void)
 		return retval;
 	}
 
-
 	pr_info("IR Remote Control driver registered, major %d\n",
 						MAJOR(lirc_base_dev));
 
 	return 0;
 }
 
-
-
 static void __exit lirc_dev_exit(void)
 {
 	class_destroy(lirc_class);
Signature · 1 line
2.9.3
author maintainer
#9 lore raw

PATCH v2 9/19 mce_kbd: add encoder

In reply to Sean Young

Split the protocol into two variants, one for keyboard and one for mouse data.

Note that the mce_kbd protocol cannot be used on the igorplugusb, since the IR is too long.

---
 drivers/media/rc/igorplugusb.c        |  2 +-
 drivers/media/rc/ir-mce_kbd-decoder.c | 49 +++++++++++++++++++++-
 drivers/media/rc/rc-core-priv.h       |  2 +-
 drivers/media/rc/rc-ir-raw.c          |  6 +--
 drivers/media/rc/rc-main.c            |  8 +++-
 include/media/rc-map.h                | 78 ++++++++++++++++++-----------------
 6 files changed, 99 insertions(+), 46 deletions(-)
drivers/media/rc/igorplugusb.c +1 -1
index 0f0ed4e..cb6d4f1 100644
@@ -205,7 +205,7 @@ static int igorplugusb_probe(struct usb_interface *intf,
 	rc->allowed_protocols = RC_BIT_ALL_IR_DECODER & ~(RC_BIT_NEC |
 			RC_BIT_NECX | RC_BIT_NEC32 | RC_BIT_RC6_6A_20 |
 			RC_BIT_RC6_6A_24 | RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE |
-			RC_BIT_SONY20 | RC_BIT_MCE_KBD | RC_BIT_SANYO);
+			RC_BIT_SONY20 | RC_BIT_SANYO);
 
 	rc->priv = ir;
 	rc->driver_name = DRIVER_NAME;
drivers/media/rc/ir-mce_kbd-decoder.c +47 -2

69 lines not on this page · raw message

drivers/media/rc/rc-core-priv.h +1 -1
index a70a5c55..0455b27 100644
@@ -185,7 +185,7 @@ struct ir_raw_timings_manchester {
 
 int ir_raw_gen_manchester(struct ir_raw_event **ev, unsigned int max,
 			  const struct ir_raw_timings_manchester *timings,
-			  unsigned int n, unsigned int data);
+			  unsigned int n, u64 data);
 
 /**
  * ir_raw_gen_pulse_space() - generate pulse and space raw events.
drivers/media/rc/rc-ir-raw.c +3 -3
index 7fa84b6..90f66dc 100644
@@ -258,13 +258,13 @@ static void ir_raw_disable_protocols(struct rc_dev *dev, u64 protocols)
  */
 int ir_raw_gen_manchester(struct ir_raw_event **ev, unsigned int max,
 			  const struct ir_raw_timings_manchester *timings,
-			  unsigned int n, unsigned int data)
+			  unsigned int n, u64 data)
 {
 	bool need_pulse;
-	unsigned int i;
+	u64 i;
 	int ret = -ENOBUFS;
 
-	i = 1 << (n - 1);
+	i = BIT_ULL(n - 1);
 
 	if (timings->leader) {
 		if (!max--)
drivers/media/rc/rc-main.c +6 -2
index 2424946..b189f24 100644
@@ -746,6 +746,8 @@ static int rc_validate_filter(struct rc_dev *dev,
 		[RC_TYPE_NECX] = 0xffffff,
 		[RC_TYPE_NEC32] = 0xffffffff,
 		[RC_TYPE_SANYO] = 0x1fffff,
+		[RC_TYPE_MCIR2_KBD] = 0xffff,
+		[RC_TYPE_MCIR2_MSE] = 0x1fffff,
 		[RC_TYPE_RC6_0] = 0xffff,
 		[RC_TYPE_RC6_6A_20] = 0xfffff,
 		[RC_TYPE_RC6_6A_24] = 0xffffff,
@@ -878,7 +880,8 @@ static const struct {
 	{ RC_BIT_RC5_SZ,	"rc-5-sz",	"ir-rc5-decoder"	},
 	{ RC_BIT_SANYO,		"sanyo",	"ir-sanyo-decoder"	},
 	{ RC_BIT_SHARP,		"sharp",	"ir-sharp-decoder"	},
-	{ RC_BIT_MCE_KBD,	"mce_kbd",	"ir-mce_kbd-decoder"	},
+	{ RC_BIT_MCIR2_KBD |
+	  RC_BIT_MCIR2_MSE,	"mce_kbd",	"ir-mce_kbd-decoder"	},
 	{ RC_BIT_XMP,		"xmp",		"ir-xmp-decoder"	},
 	{ RC_BIT_CEC,		"cec",		NULL			},
 };
@@ -1346,7 +1349,8 @@ static const char * const proto_variant_names[] = {
 	[RC_TYPE_NECX] = "nec-x",
 	[RC_TYPE_NEC32] = "nec-32",
 	[RC_TYPE_SANYO] = "sanyo",
-	[RC_TYPE_MCE_KBD] = "mce_kbd",
+	[RC_TYPE_MCIR2_KBD] = "mcir2-kbd",
+	[RC_TYPE_MCIR2_MSE] = "mcir2-mse",
 	[RC_TYPE_RC6_0] = "rc-6-0",
 	[RC_TYPE_RC6_6A_20] = "rc-6-6a-20",
 	[RC_TYPE_RC6_6A_24] = "rc-6-6a-24",
include/media/rc-map.h +41 -37

111 lines not on this page · raw message

Signature · 1 line
2.9.3
author maintainer
#10 lore raw

PATCH v2 10/19 serial_ir: iommap is a memory address, not bool

In reply to Sean Young

This has been broken for a long time, so presumably it is not used. I have no hardware to test this on.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=61401

Fixes 90ab5ee ("module_param: make bool parameters really bool")
---
 drivers/media/rc/serial_ir.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/rc/serial_ir.c +2 -2
index 923fb22..7b3a3b5 100644
@@ -56,7 +56,7 @@ struct serial_ir_hw {
 static int type;
 static int io;
 static int irq;
-static bool iommap;
+static ulong iommap;
 static int ioshift;
 static bool softcarrier = true;
 static bool share_irq;
@@ -836,7 +836,7 @@ module_param(io, int, 0444);
 MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)");
 
 /* some architectures (e.g. intel xscale) have memory mapped registers */
-module_param(iommap, bool, 0444);
+module_param(iommap, ulong, 0444);
 MODULE_PARM_DESC(iommap, "physical base for memory mapped I/O (0 = no memory mapped io)");
 
 /*
Signature · 1 line
2.9.3
author maintainer
#11 lore raw

PATCH v2 11/19 lirc: lirc interface should not be a raw decoder

In reply to Sean Young

The lirc bridge exists as a raw decoder. We would like to make the bridge to also work for scancode drivers in further commits, so it cannot be a raw decoder.

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().

---
 drivers/media/rc/Kconfig         | 15 ++++++------
 drivers/media/rc/Makefile        |  6 ++---
 drivers/media/rc/ir-lirc-codec.c | 41 ++++-----------------------------
 drivers/media/rc/lirc_dev.c      | 19 +++-------------
 drivers/media/rc/rc-core-priv.h  | 24 +++++++++++++++++++-
 drivers/media/rc/rc-ir-raw.c     | 17 +++++---------
 drivers/media/rc/rc-main.c       | 49 ++++++++++++++++++++--------------------
 7 files changed, 71 insertions(+), 100 deletions(-)
drivers/media/rc/Kconfig +7 -8
index d1d3fd0..8787bf1 100644
@@ -6,14 +6,8 @@ config 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 interface driver"
 	depends on RC_CORE
 
 	---help---
@@ -24,7 +18,7 @@ config LIRC
 	   encoding for IR transmitting (aka "blasting").
 
 config IR_LIRC_CODEC
-	tristate "Enable IR to LIRC bridge"
+	bool "Enable IR to LIRC bridge"
 	depends on RC_CORE
 	depends on LIRC
 	default y
@@ -33,7 +27,12 @@ config IR_LIRC_CODEC
 	   Enable this option to pass raw IR to and from userspace via
 	   the LIRC interface.
 
+menuconfig RC_DECODERS
+	bool "Remote controller decoders"
+	depends on RC_CORE
+	default y
 
+if RC_DECODERS
 config IR_NEC_DECODER
 	tristate "Enable IR raw decoder for the NEC protocol"
 	depends on RC_CORE
drivers/media/rc/Makefile +3 -3
index 679aa0a..f9dee1c 100644
@@ -1,9 +1,10 @@
-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
+rc-core-$(CONFIG_IR_LIRC_CODEC) += 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 +13,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
drivers/media/rc/ir-lirc-codec.c +5 -36

74 lines not on this page · raw message

drivers/media/rc/lirc_dev.c +3 -16
index 988758b..26e1983 100644
@@ -33,12 +33,10 @@
 #include <linux/device.h>
 #include <linux/cdev.h>
 
-#include <media/rc-core.h>
+#include "rc-core-priv.h"
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
 
-static bool debug;
-
 #define IRCTL_DEV_NAME	"BaseRemoteCtl"
 #define NOPLUG		-1
 #define LOGHEAD		"lirc_dev (%s[%d]): "
@@ -747,7 +745,7 @@ ssize_t lirc_dev_fop_write(struct file *file, const char __user *buffer,
 EXPORT_SYMBOL(lirc_dev_fop_write);
 
 
-static int __init lirc_dev_init(void)
+int __init lirc_dev_init(void)
 {
 	int retval;
 
@@ -771,19 +769,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, MAX_IRCTL_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");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging messages");
drivers/media/rc/rc-core-priv.h +23 -1
index 0455b27..da31738 100644
@@ -30,7 +30,7 @@ struct ir_raw_handler {
 	int (*encode)(enum rc_type protocol, u32 scancode,
 		      struct ir_raw_event *events, unsigned int max);
 
-	/* 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);
 };
@@ -270,6 +270,28 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
 void ir_raw_init(void);
 
 /*
+ * lirc interface bridge
+ */
+#ifdef CONFIG_IR_LIRC_CODEC
+int 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 ir_lirc_raw_event(struct rc_dev *dev,
+				    struct ir_raw_event ev) { return 0; }
+static inline int ir_lirc_register(struct rc_dev *dev) { return 0; }
+static inline void ir_lirc_unregister(struct rc_dev *dev) { }
+#endif
+
+#ifdef CONFIG_LIRC
+int lirc_dev_init(void);
+void lirc_dev_exit(void);
+#else
+static inline int lirc_dev_init(void) { return 0; }
+static inline void lirc_dev_exit(void) {}
+#endif
+
+/*
  * Decoder initialization code
  *
  * Those load logic are called during ir-core init, and automatically
drivers/media/rc/rc-ir-raw.c +6 -11
index 90f66dc..6bfccf8 100644
@@ -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);
@@ -502,18 +503,12 @@ int ir_raw_event_register(struct rc_dev *dev)
 	dev->change_protocol = change_protocol;
 	INIT_KFIFO(dev->raw->kfifo);
 
-	/*
-	 * raw transmitters do not need any event registration
-	 * because the event is coming from userspace
-	 */
-	if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
-		dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
-					       "rc%u", dev->minor);
+	dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
+				       "rc%u", dev->minor);
 
-		if (IS_ERR(dev->raw->thread)) {
-			rc = PTR_ERR(dev->raw->thread);
-			goto out;
-		}
+	if (IS_ERR(dev->raw->thread)) {
+		rc = PTR_ERR(dev->raw->thread);
+		goto out;
 	}
 
 	mutex_lock(&ir_raw_handler_lock);
drivers/media/rc/rc-main.c +24 -25

103 lines not on this page · raw message

Signature · 1 line
2.9.3
author maintainer
#12 lore raw

PATCH v2 12/19 lirc: exorcise struct irctl

In reply to Sean Young

lirc_register_driver() takes a struct lirc_driver argument, it then allocates a new struct irctl which contains another struct lirc_driver and then copies it over.

By moving the members of struct irctl to struct lirc_driver, we avoid the extra allocation and we can remove struct irctl completely. We also remove the duplicate chunk_size member.

In addition, the members of irctl are now visible elsewhere.

---
 drivers/media/rc/ir-lirc-codec.c        |   3 +-
 drivers/media/rc/lirc_dev.c             | 353 +++++++++++++++-----------------
 drivers/staging/media/lirc/lirc_sasem.c |   3 +-
 drivers/staging/media/lirc/lirc_zilog.c | 109 +++++-----
 include/media/lirc_dev.h                |  29 ++-
 5 files changed, 253 insertions(+), 244 deletions(-)
drivers/media/rc/ir-lirc-codec.c +1 -2
index 16ac65a..78f354a 100644
@@ -407,7 +407,7 @@ int ir_lirc_register(struct rc_dev *dev)
 	drv->set_use_dec = &ir_lirc_close;
 	drv->code_length = sizeof(struct ir_raw_event) * 8;
 	drv->fops = &lirc_fops;
-	drv->dev = &dev->dev;
+	drv->dev.parent = &dev->dev;
 	drv->rdev = dev;
 	drv->owner = THIS_MODULE;
 
@@ -437,5 +437,4 @@ void ir_lirc_unregister(struct rc_dev *dev)
 	lirc_unregister_driver(lirc->drv->minor);
 	lirc_buffer_free(lirc->drv->rbuf);
 	kfree(lirc->drv->rbuf);
-	kfree(lirc->drv);
 }
drivers/media/rc/lirc_dev.c +163 -190

767 lines not on this page · raw message

drivers/staging/media/lirc/lirc_sasem.c +1 -2
index b0c176e..583e12e 100644
@@ -167,7 +167,6 @@ static void delete_context(struct sasem_context *context)
 	usb_free_urb(context->rx_urb);  /* IR */
 	lirc_buffer_free(context->driver->rbuf);
 	kfree(context->driver->rbuf);
-	kfree(context->driver);
 	kfree(context);
 }
 
@@ -771,7 +770,7 @@ static int sasem_probe(struct usb_interface *interface,
 	driver->rbuf = rbuf;
 	driver->set_use_inc = ir_open;
 	driver->set_use_dec = ir_close;
-	driver->dev   = &interface->dev;
+	driver->dev.parent = &interface->dev;
 	driver->owner = THIS_MODULE;
 
 	mutex_lock(&context->ctx_lock);
drivers/staging/media/lirc/lirc_zilog.c +60 -49

365 lines not on this page · raw message

include/media/lirc_dev.h +28 -1
index cec7d35..3e5c467 100644
@@ -15,6 +15,8 @@
 #define mod(n, div) ((n) % (div))
 
 #include <linux/slab.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
 #include <linux/poll.h>
@@ -182,6 +184,20 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
  *			device.
  *
  * @owner:		the module owning this struct
+ *
+ * @attached:		1 if the device is still attached, 0 otherwise
+ *
+ * @open:		1 if the lirc char device has been opened
+ *
+ * @irctl_lock:		mutex for the structure
+ *
+ * @buf:		read buffer used if rbuf is not set
+ *
+ * @cdev:		the char device structure
+ *
+ * @task:		thread performing read polling, if present
+ *
+ * @jiffies_to_wait:	jiffies to sleep in read polling thread
  */
 struct lirc_driver {
 	char name[40];
@@ -202,8 +218,19 @@ struct lirc_driver {
 	void (*set_use_dec)(void *data);
 	struct rc_dev *rdev;
 	const struct file_operations *fops;
-	struct device *dev;
+	struct device dev;
 	struct module *owner;
+
+	int attached;
+	int open;
+
+	struct mutex irctl_lock; /* locks this driver */
+	struct lirc_buffer *buf;
+
+	struct cdev cdev;
+
+	struct task_struct *task;
+	long jiffies_to_wait;
 };
 
 /* following functions can be called ONLY from user context
Signature · 1 line
2.9.3
author maintainer
#13 lore raw

PATCH v2 13/19 lirc: use plain kfifo rather than lirc_buffer

In reply to Sean Young

Since a lirc char device can only be opened once, there can only be one reader. By using a plain kfifo we don't need a spinlock and we can use kfifo_to_user. The code is much simplified.

Unfortunately we cannot eliminate lirc_buffer from the tree yet, as there are still some staging lirc drivers which use it.

---
 drivers/media/rc/ir-lirc-codec.c | 102 +++++++++++++++++++++++++--------------
 drivers/media/rc/lirc_dev.c      |   5 +-
 drivers/media/rc/rc-core-priv.h  |  26 ++++++++++
 3 files changed, 96 insertions(+), 37 deletions(-)
drivers/media/rc/ir-lirc-codec.c +67 -35
index 78f354a..d5d408c 100644
@@ -19,8 +19,6 @@
 #include <media/rc-core.h>
 #include "rc-core-priv.h"
 
-#define LIRCBUF_SIZE 256
-
 /**
  * ir_lirc_raw_event() - Send raw IR data to lirc to be relayed to userspace
  *
@@ -32,10 +30,7 @@
 int 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.drv || !dev->raw->lirc.drv->rbuf)
-		return -EINVAL;
+	unsigned int sample;
 
 	/* Packet start */
 	if (ev.reset) {
@@ -70,10 +65,7 @@ int ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev)
 
 	/* Normal sample */
 	} else {
-
 		if (lirc->gap) {
-			int gap_sample;
-
 			lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
 				lirc->gap_start));
 
@@ -82,9 +74,7 @@ int ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev)
 			lirc->gap_duration = min(lirc->gap_duration,
 							(u64)LIRC_VALUE_MASK);
 
-			gap_sample = LIRC_SPACE(lirc->gap_duration);
-			lirc_buffer_write(dev->raw->lirc.drv->rbuf,
-						(unsigned char *) &gap_sample);
+			kfifo_put(&lirc->kfifo, LIRC_SPACE(lirc->gap_duration));
 			lirc->gap = false;
 		}
 
@@ -94,9 +84,8 @@ int 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->raw->lirc.drv->rbuf,
-			  (unsigned char *) &sample);
-	wake_up(&dev->raw->lirc.drv->rbuf->wait_poll);
+	kfifo_put(&lirc->kfifo, sample);
+	wake_up_poll(&lirc->wait_poll, POLLIN);
 
 	return 0;
 }
@@ -326,8 +315,64 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 	return ret;
 }
 
+static unsigned int ir_lirc_poll(struct file *filep,
+				 struct poll_table_struct *wait)
+{
+	struct lirc_codec *lirc = lirc_get_pdata(filep);
+	unsigned int events = 0;
+
+	poll_wait(filep, &lirc->wait_poll, wait);
+
+	if (!lirc->drv->attached)
+		events = POLLERR;
+	else if (!kfifo_is_empty(&lirc->kfifo))
+		events = POLLIN | POLLRDNORM;
+
+	return events;
+}
+
+static ssize_t ir_lirc_read(struct file *filep, char __user *buffer,
+			    size_t length, loff_t *ppos)
+{
+	struct lirc_codec *lirc = lirc_get_pdata(filep);
+	unsigned int copied;
+	int ret;
+
+	if (length % sizeof(unsigned int))
+		return -EINVAL;
+
+	if (!lirc->drv->attached)
+		return -ENODEV;
+
+	do {
+		if (kfifo_is_empty(&lirc->kfifo)) {
+			if (filep->f_flags & O_NONBLOCK)
+				return -EAGAIN;
+
+			ret = wait_event_interruptible(lirc->wait_poll,
+					!kfifo_is_empty(&lirc->kfifo) ||
+					!lirc->drv->attached);
+			if (ret)
+				return ret;
+		}
+
+		if (!lirc->drv->attached)
+			return -ENODEV;
+
+		ret = kfifo_to_user(&lirc->kfifo, buffer, length, &copied);
+		if (ret)
+			return ret;
+	} while (copied == 0);
+
+	return copied;
+}
+
 static int ir_lirc_open(void *data)
 {
+	struct lirc_codec *lirc = data;
+
+	kfifo_reset_out(&lirc->kfifo);
+
 	return 0;
 }
 
@@ -343,8 +388,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,
@@ -353,21 +398,12 @@ static const struct file_operations lirc_fops = {
 int ir_lirc_register(struct rc_dev *dev)
 {
 	struct lirc_driver *drv;
-	struct lirc_buffer *rbuf;
 	int rc = -ENOMEM;
 	unsigned long features = 0;
 
-	drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
+	drv = kzalloc(sizeof(*drv), GFP_KERNEL);
 	if (!drv)
-		return rc;
-
-	rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
-	if (!rbuf)
-		goto rbuf_alloc_failed;
-
-	rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE);
-	if (rc)
-		goto rbuf_init_failed;
+		return -ENOMEM;
 
 	if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
 		features |= LIRC_CAN_REC_MODE2;
@@ -402,7 +438,6 @@ int ir_lirc_register(struct rc_dev *dev)
 	drv->minor = -1;
 	drv->features = features;
 	drv->data = &dev->raw->lirc;
-	drv->rbuf = rbuf;
 	drv->set_use_inc = &ir_lirc_open;
 	drv->set_use_dec = &ir_lirc_close;
 	drv->code_length = sizeof(struct ir_raw_event) * 8;
@@ -410,6 +445,8 @@ int ir_lirc_register(struct rc_dev *dev)
 	drv->dev.parent = &dev->dev;
 	drv->rdev = dev;
 	drv->owner = THIS_MODULE;
+	INIT_KFIFO(dev->raw->lirc.kfifo);
+	init_waitqueue_head(&dev->raw->lirc.wait_poll);
 
 	drv->minor = lirc_register_driver(drv);
 	if (drv->minor < 0) {
@@ -422,11 +459,7 @@ int ir_lirc_register(struct rc_dev *dev)
 	return 0;
 
 lirc_register_failed:
-rbuf_init_failed:
-	kfree(rbuf);
-rbuf_alloc_failed:
 	kfree(drv);
-
 	return rc;
 }
 
@@ -434,7 +467,6 @@ void ir_lirc_unregister(struct rc_dev *dev)
 {
 	struct lirc_codec *lirc = &dev->raw->lirc;
 
+	wake_up_poll(&lirc->wait_poll, POLLERR);
 	lirc_unregister_driver(lirc->drv->minor);
-	lirc_buffer_free(lirc->drv->rbuf);
-	kfree(lirc->drv->rbuf);
 }
drivers/media/rc/lirc_dev.c +3 -2
index 44650e4..7d705af 100644
@@ -328,7 +328,7 @@ int lirc_register_driver(struct lirc_driver *d)
 	if (minor < 0)
 		return minor;
 
-	if (LIRC_CAN_REC(d->features)) {
+	if (!d->rdev) {
 		err = lirc_allocate_buffer(irctls[minor]);
 		if (err)
 			lirc_unregister_driver(minor);
@@ -374,7 +374,8 @@ int lirc_unregister_driver(int minor)
 	if (d->open) {
 		dev_dbg(d->dev.parent, LOGHEAD "releasing opened driver\n",
 			d->name, d->minor);
-		wake_up_interruptible(&d->buf->wait_poll);
+		if (d->buf)
+			wake_up_interruptible(&d->buf->wait_poll);
 	}
 
 	mutex_lock(&d->irctl_lock);
drivers/media/rc/rc-core-priv.h +26 -0
index da31738..be34935 100644
@@ -19,7 +19,11 @@
 /* Define the max number of pulse/space transitions to buffer */
 #define	MAX_IR_EVENT_SIZE	512
 
+/* Define the number */
+#define LIRCBUF_SIZE		256
+
 #include <linux/slab.h>
+#include <media/lirc_dev.h>
 #include <media/rc-core.h>
 
 struct ir_raw_handler {
@@ -47,6 +51,7 @@ struct ir_raw_event_ctrl {
 	/* raw decoder state follows */
 	struct ir_raw_event prev_ev;
 	struct ir_raw_event this_ev;
+#if IS_ENABLED(CONFIG_IR_NEC_DECODER)
 	struct nec_dec {
 		int state;
 		unsigned count;
@@ -54,12 +59,16 @@ struct ir_raw_event_ctrl {
 		bool is_nec_x;
 		bool necx_repeat;
 	} nec;
+#endif
+#if IS_ENABLED(CONFIG_IR_RC5_DECODER)
 	struct rc5_dec {
 		int state;
 		u32 bits;
 		unsigned count;
 		bool is_rc5x;
 	} rc5;
+#endif
+#if IS_ENABLED(CONFIG_IR_RC6_DECODER)
 	struct rc6_dec {
 		int state;
 		u8 header;
@@ -68,11 +77,15 @@ struct ir_raw_event_ctrl {
 		unsigned count;
 		unsigned wanted_bits;
 	} rc6;
+#endif
+#if IS_ENABLED(CONFIG_IR_SONY_DECODER)
 	struct sony_dec {
 		int state;
 		u32 bits;
 		unsigned count;
 	} sony;
+#endif
+#if IS_ENABLED(CONFIG_IR_JVC_DECODER)
 	struct jvc_dec {
 		int state;
 		u16 bits;
@@ -81,17 +94,23 @@ struct ir_raw_event_ctrl {
 		bool first;
 		bool toggle;
 	} jvc;
+#endif
+#if IS_ENABLED(CONFIG_IR_SANYO_DECODER)
 	struct sanyo_dec {
 		int state;
 		unsigned count;
 		u64 bits;
 	} sanyo;
+#endif
+#if IS_ENABLED(CONFIG_IR_SHARP_DECODER)
 	struct sharp_dec {
 		int state;
 		unsigned count;
 		u32 bits;
 		unsigned int pulse_len;
 	} sharp;
+#endif
+#if IS_ENABLED(CONFIG_IR_MCE_KBD_DECODER)
 	struct mce_kbd_dec {
 		struct input_dev *idev;
 		struct timer_list rx_timeout;
@@ -103,9 +122,13 @@ struct ir_raw_event_ctrl {
 		unsigned count;
 		unsigned wanted_bits;
 	} mce_kbd;
+#endif
+#if IS_ENABLED(CONFIG_IR_LIRC_CODEC)
 	struct lirc_codec {
 		struct rc_dev *dev;
 		struct lirc_driver *drv;
+		DECLARE_KFIFO(kfifo, unsigned int, LIRCBUF_SIZE);
+		wait_queue_head_t wait_poll;
 		int carrier_low;
 
 		ktime_t gap_start;
@@ -114,11 +137,14 @@ struct ir_raw_event_ctrl {
 		bool send_timeout_reports;
 
 	} lirc;
+#endif
+#if IS_ENABLED(CONFIG_IR_XMP_DECODER)
 	struct xmp_dec {
 		int state;
 		unsigned count;
 		u32 durations[16];
 	} xmp;
+#endif
 };
 
 /* macros for IR decoders */
Signature · 1 line
2.9.3
author maintainer
#14 lore raw

PATCH v2 14/19 lirc: implement scancode sending

In reply to Sean Young

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

int main()

{
	int fd, mode, rc;
	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_type = RC_TYPE_RC5,
		.flags = 0
	};
	write(fd, &scancode, sizeof(scancode));
	close(fd);
}

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

---
 drivers/media/rc/ir-lirc-codec.c | 64 ++++++++++++++++++++++++++++++-------
 drivers/media/rc/rc-core-priv.h  |  2 +-
 include/media/rc-map.h           | 54 +------------------------------
 include/uapi/linux/lirc.h        | 68 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 122 insertions(+), 66 deletions(-)
drivers/media/rc/ir-lirc-codec.c +52 -12
index d5d408c..762fa5e 100644
@@ -96,6 +96,7 @@ 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 */
+	struct ir_raw_event *raw = NULL;
 	ssize_t ret = -EINVAL;
 	size_t count;
 	ktime_t start;
@@ -109,16 +110,49 @@ 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;
+
+		if (copy_from_user(&scan, buf, sizeof(scan)))
+			return -EFAULT;
+
+		if (scan.flags)
+			return -EINVAL;
+
+		raw = kmalloc_array(LIRCBUF_SIZE, sizeof(*raw), GFP_KERNEL);
+		if (!raw)
+			return -ENOMEM;
+
+		ret = ir_raw_encode_scancode(scan.rc_type, scan.scancode,
+					     raw, LIRCBUF_SIZE);
+		if (ret < 0)
+			goto out;
+
+		count = ret;
 
-	txbuf = memdup_user(buf, n);
-	if (IS_ERR(txbuf))
-		return PTR_ERR(txbuf);
+		txbuf = kmalloc_array(count, sizeof(unsigned int), GFP_KERNEL);
+		if (!txbuf) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		for (i = 0; i < count; i++)
+			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) {
@@ -147,7 +181,10 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 	for (duration = i = 0; i < ret; i++)
 		duration += txbuf[i];
 
-	ret *= sizeof(unsigned int);
+	if (lirc->send_mode == LIRC_MODE_SCANCODE)
+		ret = n;
+	else
+		ret *= sizeof(unsigned int);
 
 	/*
 	 * The lircd gap calculation expects the write function to
@@ -162,6 +199,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 
 out:
 	kfree(txbuf);
+	kfree(raw);
 	return ret;
 }
 
@@ -195,15 +233,17 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		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 */
@@ -411,7 +451,7 @@ int ir_lirc_register(struct rc_dev *dev)
 			features |= LIRC_CAN_GET_REC_RESOLUTION;
 	}
 	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)
drivers/media/rc/rc-core-priv.h +1 -1
index be34935..3318127 100644
@@ -135,7 +135,7 @@ struct ir_raw_event_ctrl {
 		u64 gap_duration;
 		bool gap;
 		bool send_timeout_reports;
-
+		int send_mode;
 	} lirc;
 #endif
 #if IS_ENABLED(CONFIG_IR_XMP_DECODER)
include/media/rc-map.h +1 -53

60 lines not on this page · raw message

include/uapi/linux/lirc.h +68 -0

90 lines not on this page · raw message

Signature · 1 line
2.9.3
author maintainer
#15 lore raw

PATCH v2 15/19 rc: use the correct carrier for scancode transmit

In reply to Sean Young

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

---
 drivers/media/rc/ir-jvc-decoder.c     |  1 +
 drivers/media/rc/ir-lirc-codec.c      | 28 ++++++++++++++++------------
 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, 56 insertions(+), 12 deletions(-)
drivers/media/rc/ir-jvc-decoder.c +1 -0
index 674bf15..f3a1f6e 100644
@@ -212,6 +212,7 @@ static struct ir_raw_handler jvc_handler = {
 	.protocols	= RC_BIT_JVC,
 	.decode		= ir_jvc_decode,
 	.encode		= ir_jvc_encode,
+	.carrier	= 38000,
 };
 
 static int __init ir_jvc_decode_init(void)
drivers/media/rc/ir-lirc-codec.c +16 -12
index 762fa5e..2189321 100644
@@ -95,7 +95,7 @@ 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; /* buffer with values to transmit */
 	struct ir_raw_event *raw = NULL;
 	ssize_t ret = -EINVAL;
 	size_t count;
@@ -110,6 +110,13 @@ 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 (!dev->tx_ir)
+		return -EINVAL;
+
 	if (lirc->send_mode == LIRC_MODE_SCANCODE) {
 		struct lirc_scancode scan;
 
@@ -140,7 +147,15 @@ 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_type);
+
+			if (carrier > 0)
+				dev->s_tx_carrier(dev, carrier);
+		}
 	} else {
 		if (n < sizeof(unsigned int) || n % sizeof(unsigned int))
 			return -EINVAL;
@@ -154,17 +169,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;
-	}
-
 	for (i = 0; i < count; i++) {
 		if (txbuf[i] > IR_MAX_DURATION / 1000 - duration || !txbuf[i]) {
 			ret = -EINVAL;
drivers/media/rc/ir-mce_kbd-decoder.c +1 -0
index 6a4d58b..79c8f40 100644
@@ -468,6 +468,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)
drivers/media/rc/ir-nec-decoder.c +1 -0
index 3ce8503..8f9ca71 100644
@@ -288,6 +288,7 @@ static struct ir_raw_handler nec_handler = {
 	.protocols	= RC_BIT_NEC | RC_BIT_NECX | RC_BIT_NEC32,
 	.decode		= ir_nec_decode,
 	.encode		= ir_nec_encode,
+	.carrier	= 38000,
 };
 
 static int __init ir_nec_decode_init(void)
drivers/media/rc/ir-rc5-decoder.c +1 -0
index fcfedf9..d92e49b 100644
@@ -281,6 +281,7 @@ static struct ir_raw_handler rc5_handler = {
 	.protocols	= RC_BIT_RC5 | RC_BIT_RC5X_20 | RC_BIT_RC5_SZ,
 	.decode		= ir_rc5_decode,
 	.encode		= ir_rc5_encode,
+	.carrier	= 36000,
 };
 
 static int __init ir_rc5_decode_init(void)
drivers/media/rc/ir-rc6-decoder.c +1 -0
index 6fe2268..83a36f4 100644
@@ -408,6 +408,7 @@ static struct ir_raw_handler rc6_handler = {
 			  RC_BIT_RC6_MCE,
 	.decode		= ir_rc6_decode,
 	.encode		= ir_rc6_encode,
+	.carrier	= 36000,
 };
 
 static int __init ir_rc6_decode_init(void)
drivers/media/rc/ir-sanyo-decoder.c +1 -0
index 520bb77..7d3bc03 100644
@@ -222,6 +222,7 @@ static struct ir_raw_handler sanyo_handler = {
 	.protocols	= RC_BIT_SANYO,
 	.decode		= ir_sanyo_decode,
 	.encode		= ir_sanyo_encode,
+	.carrier	= 38000,
 };
 
 static int __init ir_sanyo_decode_init(void)
drivers/media/rc/ir-sharp-decoder.c +1 -0
index b47e89e..2b08da4 100644
@@ -226,6 +226,7 @@ static struct ir_raw_handler sharp_handler = {
 	.protocols	= RC_BIT_SHARP,
 	.decode		= ir_sharp_decode,
 	.encode		= ir_sharp_encode,
+	.carrier	= 38000,
 };
 
 static int __init ir_sharp_decode_init(void)
drivers/media/rc/ir-sony-decoder.c +1 -0
index 355fa81..e36e779 100644
@@ -220,6 +220,7 @@ static struct ir_raw_handler sony_handler = {
 	.protocols	= RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20,
 	.decode		= ir_sony_decode,
 	.encode		= ir_sony_encode,
+	.carrier	= 40000,
 };
 
 static int __init ir_sony_decode_init(void)
drivers/media/rc/rc-core-priv.h +1 -0
index 3318127..1b53409 100644
@@ -33,6 +33,7 @@ struct ir_raw_handler {
 	int (*decode)(struct rc_dev *dev, struct ir_raw_event event);
 	int (*encode)(enum rc_type protocol, u32 scancode,
 		      struct ir_raw_event *events, unsigned int max);
+	u32 carrier;
 
 	/* These two should only be used by the mce kbd decoder */
 	int (*raw_register)(struct rc_dev *dev);
drivers/media/rc/rc-ir-raw.c +30 -0
index 6bfccf8..9ffa5a9 100644
@@ -484,6 +484,36 @@ int ir_raw_encode_scancode(enum rc_type protocol, u32 scancode,
 }
 EXPORT_SYMBOL(ir_raw_encode_scancode);
 
+/**
+ * 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_type protocol)
+{
+	struct ir_raw_handler *handler;
+	int ret = -EINVAL;
+	u64 mask = 1ULL << 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
  */
include/media/rc-core.h +1 -0
index 73ddd721..f06d9ae 100644
@@ -316,6 +316,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_type protocol, u32 scancode,
 			   struct ir_raw_event *events, unsigned int max);
+int ir_raw_encode_carrier(enum rc_type protocol);
 
 static inline void ir_raw_event_reset(struct rc_dev *dev)
 {
Signature · 1 line
2.9.3
author maintainer
#16 lore raw

PATCH v2 16/19 rc: auto load encoder if necessary

In reply to Sean Young

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

---
 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(-)
drivers/media/rc/rc-core-priv.h +1 -0
index 1b53409..db0d2e0 100644
@@ -294,6 +294,7 @@ int ir_raw_event_register(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);
 
 /*
drivers/media/rc/rc-ir-raw.c +2 -0
index 9ffa5a9..65531c5 100644
@@ -470,6 +470,8 @@ int ir_raw_encode_scancode(enum rc_type 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) {
drivers/media/rc/rc-main.c +1 -1
index de533b5..68888f3 100644
@@ -1039,7 +1039,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;
Signature · 1 line
2.9.3
author maintainer
#17 lore raw

PATCH v2 17/19 lirc: implement reading scancode

In reply to Sean Young

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

int main()

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

	mode = LIRC_MODE_SCANCODE;
	if (ioctl(fd, LIRC_SET_REC_MODE, &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_type, scancode.scancode,
			!!(scancode.flags & LIRC_SCANCODE_FLAG_TOGGLE),
			!!(scancode.flags & LIRC_SCANCODE_FLAG_REPEAT));
	}
	close(fd);
}

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

---
 drivers/media/rc/ir-lirc-codec.c      | 107 +++++++++++++++++++++++++++-------
 drivers/media/rc/ir-mce_kbd-decoder.c |   7 +++
 drivers/media/rc/rc-core-priv.h       |  11 ++++
 drivers/media/rc/rc-main.c            |  17 ++++++
 include/media/rc-core.h               |   4 +-
 5 files changed, 123 insertions(+), 23 deletions(-)
drivers/media/rc/ir-lirc-codec.c +85 -22
index 2189321..1847f5f 100644
@@ -231,8 +231,31 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 	}
 
 	switch (cmd) {
+	case LIRC_GET_REC_MODE:
+		if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
+			return -ENOTTY;
+
+		val = lirc->rec_mode;
+		break;
+
+	case LIRC_SET_REC_MODE:
+		switch (dev->driver_type) {
+		case RC_DRIVER_SCANCODE:
+			if (val != LIRC_MODE_SCANCODE)
+				return -EINVAL;
+			break;
+		case RC_DRIVER_IR_RAW:
+			if (!(val == LIRC_MODE_SCANCODE ||
+			      val == LIRC_MODE_MODE2))
+				return -EINVAL;
+			break;
+		default:
+			return -ENOTTY;
+		}
+
+		lirc->rec_mode = val;
+		return 0;
 
-	/* legacy support */
 	case LIRC_GET_SEND_MODE:
 		if (!dev->tx_ir)
 			return -ENOTTY;
@@ -367,10 +390,15 @@ static unsigned int ir_lirc_poll(struct file *filep,
 
 	poll_wait(filep, &lirc->wait_poll, wait);
 
-	if (!lirc->drv->attached)
+	if (!drv->attached) {
 		events = POLLERR;
-	else if (!kfifo_is_empty(&lirc->kfifo))
-		events = POLLIN | POLLRDNORM;
+	} else if (dev->rec_mode == LIRC_MODE_SCANCODE) {
+		if (!kfifo_is_empty(&dev->kfifo))
+			events = POLLIN | POLLRDNORM;
+	} else if (dev->rec_mode == LIRC_MODE_MODE2) {
+		if (!kfifo_is_empty(&dev->raw->lirc.kfifo))
+			events = POLLIN | POLLRDNORM;
+	}
 
 	return events;
 }
@@ -382,31 +410,60 @@ static ssize_t ir_lirc_read(struct file *filep, char __user *buffer,
 	unsigned int copied;
 	int ret;
 
-	if (length % sizeof(unsigned int))
-		return -EINVAL;
-
 	if (!lirc->drv->attached)
 		return -ENODEV;
 
-	do {
-		if (kfifo_is_empty(&lirc->kfifo)) {
-			if (filep->f_flags & O_NONBLOCK)
-				return -EAGAIN;
+	if (lirc->rec_mode == LIRC_MODE_SCANCODE) {
+		struct rc_dev *rcdev = lirc->dev;
 
-			ret = wait_event_interruptible(lirc->wait_poll,
-					!kfifo_is_empty(&lirc->kfifo) ||
+		if (length % sizeof(struct lirc_scancode))
+			return -EINVAL;
+
+		do {
+			if (kfifo_is_empty(&rcdev->kfifo)) {
+				if (filep->f_flags & O_NONBLOCK)
+					return -EAGAIN;
+
+				ret = wait_event_interruptible(lirc->wait_poll,
+					!kfifo_is_empty(&rcdev->kfifo) ||
 					!lirc->drv->attached);
+				if (ret)
+					return ret;
+			}
+
+			if (!lirc->drv->attached)
+				return -ENODEV;
+
+			ret = kfifo_to_user(&rcdev->kfifo, buffer, length,
+					    &copied);
 			if (ret)
 				return ret;
-		}
+		} while (copied == 0);
+	} else {
+		if (length % sizeof(unsigned int))
+			return -EINVAL;
 
-		if (!lirc->drv->attached)
-			return -ENODEV;
+		do {
+			if (kfifo_is_empty(&lirc->kfifo)) {
+				if (filep->f_flags & O_NONBLOCK)
+					return -EAGAIN;
 
-		ret = kfifo_to_user(&lirc->kfifo, buffer, length, &copied);
-		if (ret)
-			return ret;
-	} while (copied == 0);
+				ret = wait_event_interruptible(lirc->wait_poll,
+						!kfifo_is_empty(&lirc->kfifo) ||
+						!lirc->drv->attached);
+				if (ret)
+					return ret;
+			}
+
+			if (!lirc->drv->attached)
+				return -ENODEV;
+
+			ret = kfifo_to_user(&lirc->kfifo, buffer, length,
+					    &copied);
+			if (ret)
+				return ret;
+		} while (copied == 0);
+	}
 
 	return copied;
 }
@@ -416,6 +473,7 @@ static int ir_lirc_open(void *data)
 	struct lirc_codec *lirc = data;
 
 	kfifo_reset_out(&lirc->kfifo);
+	kfifo_reset_out(&lirc->dev->kfifo);
 
 	return 0;
 }
@@ -449,12 +507,17 @@ int ir_lirc_register(struct rc_dev *dev)
 	if (!drv)
 		return -ENOMEM;
 
-	if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
-		features |= LIRC_CAN_REC_MODE2;
+	if (dev->driver_type == RC_DRIVER_SCANCODE) {
+		features |= LIRC_CAN_REC_SCANCODE;
+		dev->raw->lirc.rec_mode = LIRC_MODE_SCANCODE;
+	} else if (dev->driver_type == RC_DRIVER_IR_RAW) {
+		features |= LIRC_CAN_REC_MODE2 | LIRC_CAN_REC_SCANCODE;
 		if (dev->rx_resolution)
 			features |= LIRC_CAN_GET_REC_RESOLUTION;
+		dev->raw->lirc.rec_mode = LIRC_MODE_MODE2;
 	}
 	if (dev->tx_ir) {
+		dev->raw->lirc.send_mode = LIRC_MODE_PULSE;
 		features |= LIRC_CAN_SEND_PULSE | LIRC_CAN_SEND_SCANCODE;
 		if (dev->s_tx_mask)
 			features |= LIRC_CAN_SET_TRANSMITTER_MASK;
drivers/media/rc/ir-mce_kbd-decoder.c +7 -0
index 79c8f40..c4b2998 100644
@@ -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,24 @@ 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_type = RC_TYPE_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_type = RC_TYPE_MCIR2_MSE;
 			break;
 		default:
 			IR_dprintk(1, "not keyboard or mouse data\n");
 			goto out;
 		}
 
+		lsc.scancode = scancode;
+		lsc.flags = 0;
+		if (kfifo_put(&dev->kfifo, lsc))
+			ir_wakeup_poll(dev->raw);
 		data->state = STATE_INACTIVE;
 		input_event(data->idev, EV_MSC, MSC_SCAN, scancode);
 		input_sync(data->idev);
drivers/media/rc/rc-core-priv.h +11 -0
index db0d2e0..858c467 100644
@@ -137,6 +137,7 @@ struct ir_raw_event_ctrl {
 		bool gap;
 		bool send_timeout_reports;
 		int send_mode;
+		int rec_mode;
 	} lirc;
 #endif
 #if IS_ENABLED(CONFIG_IR_XMP_DECODER)
@@ -148,6 +149,16 @@ struct ir_raw_event_ctrl {
 #endif
 };
 
+#if IS_ENABLED(CONFIG_IR_LIRC_CODEC)
+static inline void ir_wakeup_poll(struct ir_raw_event_ctrl *ctrl)
+{
+	if (ctrl)
+		wake_up_poll(&ctrl->lirc.wait_poll, POLLIN);
+}
+#else
+static inline void ir_wakeup_poll(struct ir_raw_event_ctrl *ctrl) {}
+#endif
+
 /* macros for IR decoders */
 static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin)
 {
drivers/media/rc/rc-main.c +17 -0
index 68888f3..feff1f3 100644
@@ -614,6 +614,15 @@ static void ir_timer_keyup(unsigned long cookie)
 void rc_repeat(struct rc_dev *dev)
 {
 	unsigned long flags;
+	struct lirc_scancode sc = {
+		.scancode = dev->last_scancode,
+		.rc_type = dev->last_protocol,
+		.flags = LIRC_SCANCODE_FLAG_REPEAT |
+			(dev->last_toggle ? LIRC_SCANCODE_FLAG_TOGGLE : 0),
+	};
+
+	if (kfifo_put(&dev->kfifo, sc))
+		ir_wakeup_poll(dev->raw);
 
 	spin_lock_irqsave(&dev->keylock, flags);
 
@@ -649,6 +658,13 @@ static void ir_do_keydown(struct rc_dev *dev, enum rc_type protocol,
 			  dev->last_protocol != protocol ||
 			  dev->last_scancode != scancode ||
 			  dev->last_toggle   != toggle);
+	struct lirc_scancode sc = {
+		.scancode = scancode, .rc_type = protocol,
+		.flags = toggle ? LIRC_SCANCODE_FLAG_TOGGLE : 0
+	};
+
+	if (kfifo_put(&dev->kfifo, sc))
+		ir_wakeup_poll(dev->raw);
 
 	if (new_event && dev->keypressed)
 		ir_do_keyup(dev, false);
@@ -1589,6 +1605,7 @@ struct rc_dev *rc_allocate_device(enum rc_driver_type type)
 
 		spin_lock_init(&dev->rc_map.lock);
 		spin_lock_init(&dev->keylock);
+		INIT_KFIFO(dev->kfifo);
 	}
 	mutex_init(&dev->lock);
 
include/media/rc-core.h +3 -1
index f06d9ae..24486d7 100644
@@ -18,7 +18,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/kfifo.h>
-#include <linux/time.h>
+#include <linux/lirc.h>
 #include <linux/timer.h>
 #include <media/rc-map.h>
 
@@ -95,6 +95,7 @@ enum rc_filter_type {
  *	RC_TYPE_UNKNOWN if disabled.
  * @scancode_filter: scancode filter
  * @scancode_wakeup_filter: scancode wakeup filters
+ * @kfifo: queue of received scancodes, using for lirc scancode reading
  * @scancode_mask: some hardware decoders are not capable of providing the full
  *	scancode to the application. As this is a hardware limit, we can't do
  *	anything with it. Yet, as the same keycode table can be used with other
@@ -160,6 +161,7 @@ struct rc_dev {
 	struct rc_scancode_filter	scancode_filter;
 	struct rc_scancode_filter	scancode_wakeup_filter;
 	u32				scancode_mask;
+	DECLARE_KFIFO(kfifo, struct lirc_scancode, 32);
 	u32				users;
 	void				*priv;
 	spinlock_t			keylock;
Signature · 1 line
2.9.3
#18 lore raw

Re: [PATCH v2 17/19] [media] lirc: implement reading scancode

reproduce:

Hi Sean,

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on next-20170221]
[cannot apply to v4.10]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Sean-Young/Teach-lirc-how-to-send-and-receive-scancodes/20170222-073718
base:   git://linuxtv.org/media_tree.git master
config: i386-randconfig-x015-201708 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

Note: the linux-review/Sean-Young/Teach-lirc-how-to-send-and-receive-scancodes/20170222-073718 HEAD 9a4d3444d507190ad7996731c8c7e4ef80979de4 builds fine.
It only hurts bisectibility.

All error/warnings (new ones prefixed by >>):

drivers/media/rc/ir-lirc-codec.c: In function 'ir_lirc_poll':

>> drivers/media/rc/ir-lirc-codec.c:393:7: error: 'drv' undeclared (first use in this function)
     if (!drv->attached) {
          ^~~
   drivers/media/rc/ir-lirc-codec.c:393:7: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/media/rc/ir-lirc-codec.c:395:13: error: 'dev' undeclared (first use in this function)
     } else if (dev->rec_mode == LIRC_MODE_SCANCODE) {
                ^~~
   In file included from include/media/lirc_dev.h:23:0,
                    from drivers/media/rc/ir-lirc-codec.c:18:
>> include/linux/kfifo.h:259:8: error: invalid type argument of '->' (have 'int')
     __tmpq->kfifo.in == __tmpq->kfifo.out; \
           ^
>> drivers/media/rc/ir-lirc-codec.c:396:8: note: in expansion of macro 'kfifo_is_empty'
      if (!kfifo_is_empty(&dev->kfifo))
           ^~~~~~~~~~~~~~
   include/linux/kfifo.h:259:28: error: invalid type argument of '->' (have 'int')
     __tmpq->kfifo.in == __tmpq->kfifo.out; \
                               ^
>> drivers/media/rc/ir-lirc-codec.c:396:8: note: in expansion of macro 'kfifo_is_empty'
      if (!kfifo_is_empty(&dev->kfifo))
           ^~~~~~~~~~~~~~
>> include/linux/kfifo.h:259:8: error: invalid type argument of '->' (have 'int')
     __tmpq->kfifo.in == __tmpq->kfifo.out; \
           ^
   drivers/media/rc/ir-lirc-codec.c:399:8: note: in expansion of macro 'kfifo_is_empty'
      if (!kfifo_is_empty(&dev->raw->lirc.kfifo))
           ^~~~~~~~~~~~~~
   include/linux/kfifo.h:259:28: error: invalid type argument of '->' (have 'int')
     __tmpq->kfifo.in == __tmpq->kfifo.out; \
                               ^
   drivers/media/rc/ir-lirc-codec.c:399:8: note: in expansion of macro 'kfifo_is_empty'
      if (!kfifo_is_empty(&dev->raw->lirc.kfifo))
           ^~~~~~~~~~~~~~

vim +/drv +393 drivers/media/rc/ir-lirc-codec.c

387 {
388 struct lirc_codec *lirc = lirc_get_pdata(filep);
389 unsigned int events = 0;
390
391 poll_wait(filep, &lirc->wait_poll, wait);
392

 > 393		if (!drv->attached) {
   394			events = POLLERR;
 > 395		} else if (dev->rec_mode == LIRC_MODE_SCANCODE) {
 > 396			if (!kfifo_is_empty(&dev->kfifo))

397 events = POLLIN | POLLRDNORM;
398 } else if (dev->rec_mode == LIRC_MODE_MODE2) {
399 if (!kfifo_is_empty(&dev->raw->lirc.kfifo))

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

author maintainer
#19 lore raw

Re: [PATCH v2 17/19] [media] lirc: implement reading scancode

Quoted 15 lines · kbuild test robot

Hi Sean,

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on next-20170221]
[cannot apply to v4.10]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Sean-Young/Teach-lirc-how-to-send-and-receive-scancodes/20170222-073718
base:   git://linuxtv.org/media_tree.git master
config: i386-randconfig-x015-201708 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 
Quoted 8 lines

Note: the linux-review/Sean-Young/Teach-lirc-how-to-send-and-receive-scancodes/20170222-073718 HEAD 9a4d3444d507190ad7996731c8c7e4ef80979de4 builds fine.
It only hurts bisectibility.

All error/warnings (new ones prefixed by >>):

drivers/media/rc/ir-lirc-codec.c: In function 'ir_lirc_poll':

Quoted 1 line
Quoted 1 line

drivers/media/rc/ir-lirc-codec.c:393:7: error: 'drv' undeclared (first use in this function)

     if (!drv->attached) {

Oops, too much rebasing without testing. :( The final commit compiles fine, I'll have to do some better testing of each commit and resend.

Sean

#20 lore raw

Re: [PATCH v2 17/19] [media] lirc: implement reading scancode

In reply to Sean Young
All warnings (new ones prefixed by >>):

Hi Sean,

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on next-20170221]
[cannot apply to v4.10]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Sean-Young/Teach-lirc-how-to-send-and-receive-scancodes/20170222-073718
base:   git://linuxtv.org/media_tree.git master
reproduce: make htmldocs

All warnings (new ones prefixed by >>):

make[3]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule. include/linux/init.h:1: warning: no structured comments found include/linux/kthread.h:26: warning: Excess function parameter '...' description in 'kthread_create' kernel/sys.c:1: warning: no structured comments found drivers/dma-buf/seqno-fence.c:1: warning: no structured comments found include/drm/drm_drv.h:409: warning: No description found for parameter 'load' include/drm/drm_drv.h:409: warning: No description found for parameter 'firstopen' include/drm/drm_drv.h:409: warning: No description found for parameter 'open' include/drm/drm_drv.h:409: warning: No description found for parameter 'preclose' include/drm/drm_drv.h:409: warning: No description found for parameter 'postclose' include/drm/drm_drv.h:409: warning: No description found for parameter 'lastclose' include/drm/drm_drv.h:409: warning: No description found for parameter 'unload' include/drm/drm_drv.h:409: warning: No description found for parameter 'dma_ioctl' include/drm/drm_drv.h:409: warning: No description found for parameter 'dma_quiescent' include/drm/drm_drv.h:409: warning: No description found for parameter 'context_dtor' include/drm/drm_drv.h:409: warning: No description found for parameter 'set_busid' include/drm/drm_drv.h:409: warning: No description found for parameter 'irq_handler' include/drm/drm_drv.h:409: warning: No description found for parameter 'irq_preinstall' include/drm/drm_drv.h:409: warning: No description found for parameter 'irq_postinstall' include/drm/drm_drv.h:409: warning: No description found for parameter 'irq_uninstall' include/drm/drm_drv.h:409: warning: No description found for parameter 'debugfs_init' include/drm/drm_drv.h:409: warning: No description found for parameter 'debugfs_cleanup' include/drm/drm_drv.h:409: warning: No description found for parameter 'gem_open_object' include/drm/drm_drv.h:409: warning: No description found for parameter 'gem_close_object' include/drm/drm_drv.h:409: warning: No description found for parameter 'prime_handle_to_fd' include/drm/drm_drv.h:409: warning: No description found for parameter 'prime_fd_to_handle' include/drm/drm_drv.h:409: warning: No description found for parameter 'gem_prime_export' include/drm/drm_drv.h:409: warning: No description found for parameter 'gem_prime_import' include/drm/drm_drv.h:409: warning: No description found for parameter 'gem_prime_pin' include/drm/drm_drv.h:409: warning: No description found for parameter 'gem_prime_unpin' include/drm/drm_drv.h:409: warning: No description found for parameter 'gem_prime_res_obj' include/drm/drm_drv.h:409: warning: No description found for parameter 'gem_prime_get_sg_table' include/drm/drm_drv.h:409: warning: No description found for parameter 'gem_prime_import_sg_table' include/drm/drm_drv.h:409: warning: No description found for parameter 'gem_prime_vmap' include/drm/drm_drv.h:409: warning: No description found for parameter 'gem_prime_vunmap' include/drm/drm_drv.h:409: warning: No description found for parameter 'gem_prime_mmap' include/drm/drm_drv.h:409: warning: No description found for parameter 'vgaarb_irq' include/drm/drm_drv.h:409: warning: No description found for parameter 'gem_vm_ops' include/drm/drm_drv.h:409: warning: No description found for parameter 'major' include/drm/drm_drv.h:409: warning: No description found for parameter 'minor' include/drm/drm_drv.h:409: warning: No description found for parameter 'patchlevel' include/drm/drm_drv.h:409: warning: No description found for parameter 'name' include/drm/drm_drv.h:409: warning: No description found for parameter 'desc' include/drm/drm_drv.h:409: warning: No description found for parameter 'date' include/drm/drm_drv.h:409: warning: No description found for parameter 'driver_features' include/drm/drm_drv.h:409: warning: No description found for parameter 'dev_priv_size' include/drm/drm_drv.h:409: warning: No description found for parameter 'ioctls' include/drm/drm_drv.h:409: warning: No description found for parameter 'num_ioctls' include/drm/drm_drv.h:409: warning: No description found for parameter 'fops' include/drm/drm_drv.h:409: warning: No description found for parameter 'legacy_dev_list' drivers/media/dvb-core/dvb_frontend.h:677: warning: No description found for parameter 'refcount'

>> include/media/rc-core.h:197: warning: No description found for parameter '32)'
>> include/media/rc-core.h:197: warning: Excess struct/union/enum/typedef member 'kfifo' description in 'rc_dev'

drivers/char/tpm/tpm_vtpm_proxy.c:73: warning: No description found for parameter 'filp'
drivers/char/tpm/tpm_vtpm_proxy.c:73: warning: No description found for parameter 'buf'
drivers/char/tpm/tpm_vtpm_proxy.c:73: warning: No description found for parameter 'count'
drivers/char/tpm/tpm_vtpm_proxy.c:73: warning: No description found for parameter 'off'
drivers/char/tpm/tpm_vtpm_proxy.c:123: warning: No description found for parameter 'filp'
drivers/char/tpm/tpm_vtpm_proxy.c:123: warning: No description found for parameter 'buf'
drivers/char/tpm/tpm_vtpm_proxy.c:123: warning: No description found for parameter 'count'
drivers/char/tpm/tpm_vtpm_proxy.c:123: warning: No description found for parameter 'off'
drivers/char/tpm/tpm_vtpm_proxy.c:203: warning: No description found for parameter 'proxy_dev'
sound/soc/soc-core.c:994: warning: No description found for parameter 'stream_name'
Documentation/core-api/assoc_array.rst:13: WARNING: Enumerated list ends without a blank line; unexpected unindent. Documentation/doc-guide/sphinx.rst:110: ERROR: Unknown target name: "sphinx c domain".
include/net/cfg80211.h:3154: ERROR: Unexpected indentation.
include/net/mac80211.h:3214: ERROR: Unexpected indentation.
include/net/mac80211.h:3217: WARNING: Block quote ends without a blank line; unexpected unindent.
include/net/mac80211.h:3219: ERROR: Unexpected indentation.
include/net/mac80211.h:3220: WARNING: Block quote ends without a blank line; unexpected unindent.
include/net/mac80211.h:1773: ERROR: Unexpected indentation.
include/net/mac80211.h:1777: WARNING: Block quote ends without a blank line; unexpected unindent.
kernel/sched/fair.c:7587: WARNING: Inline emphasis start-string without end-string.
kernel/time/timer.c:1240: ERROR: Unexpected indentation.
kernel/time/timer.c:1242: ERROR: Unexpected indentation.
kernel/time/timer.c:1243: WARNING: Block quote ends without a blank line; unexpected unindent.
include/linux/wait.h:121: WARNING: Block quote ends without a blank line; unexpected unindent.
include/linux/wait.h:124: ERROR: Unexpected indentation.
include/linux/wait.h:126: WARNING: Block quote ends without a blank line; unexpected unindent.
kernel/time/hrtimer.c:1021: WARNING: Block quote ends without a blank line; unexpected unindent.
kernel/signal.c:317: WARNING: Inline literal start-string without end-string.
drivers/message/fusion/mptbase.c:5051: WARNING: Definition list ends without a blank line; unexpected unindent. drivers/tty/serial/serial_core.c:1897: WARNING: Definition list ends without a blank line; unexpected unindent. include/linux/spi/spi.h:369: ERROR: Unexpected indentation.
drivers/usb/core/message.c:481: ERROR: Unexpected indentation.
drivers/usb/core/message.c:482: WARNING: Block quote ends without a blank line; unexpected unindent. Documentation/driver-api/usb.rst:623: ERROR: Unknown target name: "usb_type".
Documentation/driver-api/usb.rst:623: ERROR: Unknown target name: "usb_dir".
Documentation/driver-api/usb.rst:623: ERROR: Unknown target name: "usb_recip".
Documentation/driver-api/usb.rst:689: ERROR: Unknown target name: "usbdevfs_urb_type".
sound/soc/soc-core.c:2508: ERROR: Unknown target name: "snd_soc_daifmt".
sound/core/jack.c:312: ERROR: Unknown target name: "snd_jack_btn".
Documentation/translations/ko_KR/howto.rst:293: WARNING: Inline emphasis start-string without end-string.
WARNING: dvipng command 'dvipng' cannot be run (needed for math display), check the imgmath_dvipng setting Documentation/media/uapi/rc/lirc-dev-intro.rst:69: WARNING: undefined label: lirc_set_timeout (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: lirc-mode-scancode (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: lirc-can-send-scancode (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: lirc-mode-scancode (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: lirc-can-rec-scancode (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: lirc-mode-scancode (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: lirc-scancode-flag-toggle (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: lirc-scancode-flag-repeat (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-unknown (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-other (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc5 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc5x-20 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc5-sz (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-jvc (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-sony12 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-sony15 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-sony20 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-nec (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-necx (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-nec32 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-sanyo (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-mcir2-kbd (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-mcir2-mse (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc6-0 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc6-6a-20 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc6-6a-24 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc6-6a-32 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc6-mce (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-sharp (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-xmp (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-cec (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-unknown (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-other (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc5 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc5x-20 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc5-sz (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-jvc (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-sony12 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-sony15 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-sony20 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-nec (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-necx (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-nec32 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-sanyo (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-mcir2-kbd (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-mcir2-mse (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc6-0 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc6-6a-20 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc6-6a-24 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc6-6a-32 (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-rc6-mce (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-sharp (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-xmp (if the link has no caption the label must precede a section header) Documentation/output/lirc.h.rst:6: WARNING: undefined label: rc-type-cec (if the link has no caption the label must precede a section header)

vim +197 include/media/rc-core.h

d8b4b582 include/media/ir-core.h David Härdeman       2010-10-29  181  	int				(*open)(struct rc_dev *dev);
d8b4b582 include/media/ir-core.h David Härdeman       2010-10-29  182  	void				(*close)(struct rc_dev *dev);
d8b4b582 include/media/ir-core.h David Härdeman       2010-10-29  183  	int				(*s_tx_mask)(struct rc_dev *dev, u32 mask);
d8b4b582 include/media/ir-core.h David Härdeman       2010-10-29  184  	int				(*s_tx_carrier)(struct rc_dev *dev, u32 carrier);
d8b4b582 include/media/ir-core.h David Härdeman       2010-10-29  185  	int				(*s_tx_duty_cycle)(struct rc_dev *dev, u32 duty_cycle);
d8b4b582 include/media/ir-core.h David Härdeman       2010-10-29  186  	int				(*s_rx_carrier_range)(struct rc_dev *dev, u32 min, u32 max);
5588dc2b include/media/rc-core.h David Härdeman        2011-04-28  187  	int				(*tx_ir)(struct rc_dev *dev, unsigned *txbuf, unsigned n);
d8b4b582 include/media/ir-core.h David Härdeman       2010-10-29  188  	void				(*s_idle)(struct rc_dev *dev, bool enable);
d8b4b582 include/media/ir-core.h David Härdeman       2010-10-29  189  	int				(*s_learning_mode)(struct rc_dev *dev, int enable);
d8b4b582 include/media/ir-core.h David Härdeman       2010-10-29  190  	int				(*s_carrier_report) (struct rc_dev *dev, int enable);
00942d1a include/media/rc-core.h James Hogan           2014-01-17  191  	int				(*s_filter)(struct rc_dev *dev,
23c843b5 include/media/rc-core.h David Härdeman        2014-04-04  192  						    struct rc_scancode_filter *filter);
23c843b5 include/media/rc-core.h David Härdeman        2014-04-04  193  	int				(*s_wakeup_filter)(struct rc_dev *dev,
00942d1a include/media/rc-core.h James Hogan           2014-01-17  194  							   struct rc_scancode_filter *filter);
4f253cec include/media/rc-core.h Sean Young            2016-07-10  195  	int				(*s_timeout)(struct rc_dev *dev,
4f253cec include/media/rc-core.h Sean Young            2016-07-10  196  						     unsigned int timeout);
75543cce include/media/ir-core.h Mauro Carvalho Chehab 2009-12-11 @197  };
a3572c34 include/media/ir-core.h Mauro Carvalho Chehab 2010-03-20  198  
ca86674b include/media/rc-core.h Mauro Carvalho Chehab 2010-11-17  199  #define to_rc_dev(d) container_of(d, struct rc_dev, dev)
ca86674b include/media/rc-core.h Mauro Carvalho Chehab 2010-11-17  200  
ca86674b include/media/rc-core.h Mauro Carvalho Chehab 2010-11-17  201  /*
ca86674b include/media/rc-core.h Mauro Carvalho Chehab 2010-11-17  202   * From rc-main.c
ca86674b include/media/rc-core.h Mauro Carvalho Chehab 2010-11-17  203   * Those functions can be used on any type of Remote Controller. They
ca86674b include/media/rc-core.h Mauro Carvalho Chehab 2010-11-17  204   * basically creates an input_dev and properly reports the device as a
ca86674b include/media/rc-core.h Mauro Carvalho Chehab 2010-11-17  205   * Remote Controller, at sys/class/rc.

:::::: The code at line 197 was first introduced by commit
:::::: 75543cce0c1f46be495b981d8d3eda0882721d07 V4L/DVB (13615): ir-core: create ir_input_register

:::::: TO: Mauro Carvalho Chehab <[email protected]> :::::: CC: Mauro Carvalho Chehab <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

author maintainer
#21 lore raw

PATCH v2 18/19 lirc: scancode rc devices should have a lirc device too

In reply to Sean Young

Now that the lirc interface supports scancodes, RC scancode devices can also have a lirc device, except for cec devices which have their own /dev/cecN interface.

---
 drivers/media/rc/ir-lirc-codec.c      | 106 ++++++++++++++--------------------
 drivers/media/rc/ir-mce_kbd-decoder.c |   2 +-
 drivers/media/rc/rc-core-priv.h       |  15 -----
 drivers/media/rc/rc-main.c            |   9 +--
 include/media/rc-core.h               |  10 ++++
 5 files changed, 60 insertions(+), 82 deletions(-)
drivers/media/rc/ir-lirc-codec.c +44 -62
index 1847f5f..d0dc9b4 100644
@@ -85,7 +85,7 @@ int ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev)
 	}
 
 	kfifo_put(&lirc->kfifo, sample);
-	wake_up_poll(&lirc->wait_poll, POLLIN);
+	wake_up_poll(&dev->wait_poll, POLLIN);
 
 	return 0;
 }
@@ -93,8 +93,7 @@ int ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev)
 static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 				   size_t n, loff_t *ppos)
 {
-	struct lirc_codec *lirc;
-	struct rc_dev *dev;
+	struct rc_dev *dev = lirc_get_pdata(file);
 	unsigned int *txbuf = NULL; /* buffer with values to transmit */
 	struct ir_raw_event *raw = NULL;
 	ssize_t ret = -EINVAL;
@@ -106,18 +105,10 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 
 	start = ktime_get();
 
-	lirc = lirc_get_pdata(file);
-	if (!lirc)
-		return -EFAULT;
-
-	dev = lirc->dev;
-	if (!dev)
-		return -EFAULT;
-
 	if (!dev->tx_ir)
 		return -EINVAL;
 
-	if (lirc->send_mode == LIRC_MODE_SCANCODE) {
+	if (dev->send_mode == LIRC_MODE_SCANCODE) {
 		struct lirc_scancode scan;
 
 		if (n != sizeof(scan))
@@ -185,7 +176,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 	for (duration = i = 0; i < ret; i++)
 		duration += txbuf[i];
 
-	if (lirc->send_mode == LIRC_MODE_SCANCODE)
+	if (dev->send_mode == LIRC_MODE_SCANCODE)
 		ret = n;
 	else
 		ret *= sizeof(unsigned int);
@@ -210,20 +201,11 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 			unsigned long arg)
 {
-	struct lirc_codec *lirc;
-	struct rc_dev *dev;
+	struct rc_dev *dev = lirc_get_pdata(filep);
 	u32 __user *argp = (u32 __user *)(arg);
 	int ret = 0;
 	__u32 val = 0, tmp;
 
-	lirc = lirc_get_pdata(filep);
-	if (!lirc)
-		return -EFAULT;
-
-	dev = lirc->dev;
-	if (!dev)
-		return -EFAULT;
-
 	if (_IOC_DIR(cmd) & _IOC_WRITE) {
 		ret = get_user(val, argp);
 		if (ret)
@@ -235,7 +217,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
 			return -ENOTTY;
 
-		val = lirc->rec_mode;
+		val = dev->rec_mode;
 		break;
 
 	case LIRC_SET_REC_MODE:
@@ -253,14 +235,14 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 			return -ENOTTY;
 		}
 
-		lirc->rec_mode = val;
+		dev->rec_mode = val;
 		return 0;
 
 	case LIRC_GET_SEND_MODE:
 		if (!dev->tx_ir)
 			return -ENOTTY;
 
-		val = lirc->send_mode;
+		val = dev->send_mode;
 		break;
 
 	case LIRC_SET_SEND_MODE:
@@ -270,7 +252,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		if (!(val == LIRC_MODE_PULSE || val == LIRC_MODE_SCANCODE))
 			return -EINVAL;
 
-		lirc->send_mode = val;
+		dev->send_mode = val;
 		return 0;
 
 	/* TX settings */
@@ -297,7 +279,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 
 	/* RX settings */
 	case LIRC_SET_REC_CARRIER:
-		if (!dev->s_rx_carrier_range)
+		if (!dev->s_rx_carrier_range || !dev->raw)
 			return -ENOTTY;
 
 		if (val <= 0)
@@ -308,7 +290,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 					       val);
 
 	case LIRC_SET_REC_CARRIER_RANGE:
-		if (!dev->s_rx_carrier_range)
+		if (!dev->s_rx_carrier_range || !dev->raw)
 			return -ENOTTY;
 
 		if (val <= 0)
@@ -366,10 +348,10 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		break;
 
 	case LIRC_SET_REC_TIMEOUT_REPORTS:
-		if (!dev->timeout)
+		if (!dev->timeout || !dev->raw)
 			return -ENOTTY;
 
-		lirc->send_timeout_reports = !!val;
+		dev->raw->lirc.send_timeout_reports = !!val;
 		break;
 
 	default:
@@ -385,10 +367,11 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 static unsigned int ir_lirc_poll(struct file *filep,
 				 struct poll_table_struct *wait)
 {
-	struct lirc_codec *lirc = lirc_get_pdata(filep);
+	struct rc_dev *dev = lirc_get_pdata(filep);
+	struct lirc_driver *drv = dev->lirc_drv;
 	unsigned int events = 0;
 
-	poll_wait(filep, &lirc->wait_poll, wait);
+	poll_wait(filep, &dev->wait_poll, wait);
 
 	if (!drv->attached) {
 		events = POLLERR;
@@ -406,35 +389,35 @@ static unsigned int ir_lirc_poll(struct file *filep,
 static ssize_t ir_lirc_read(struct file *filep, char __user *buffer,
 			    size_t length, loff_t *ppos)
 {
-	struct lirc_codec *lirc = lirc_get_pdata(filep);
+	struct rc_dev *dev = lirc_get_pdata(filep);
+	struct lirc_driver *drv = dev->lirc_drv;
+	struct lirc_codec *lirc = &dev->raw->lirc;
 	unsigned int copied;
 	int ret;
 
-	if (!lirc->drv->attached)
+	if (!drv->attached)
 		return -ENODEV;
 
-	if (lirc->rec_mode == LIRC_MODE_SCANCODE) {
-		struct rc_dev *rcdev = lirc->dev;
-
+	if (dev->rec_mode == LIRC_MODE_SCANCODE) {
 		if (length % sizeof(struct lirc_scancode))
 			return -EINVAL;
 
 		do {
-			if (kfifo_is_empty(&rcdev->kfifo)) {
+			if (kfifo_is_empty(&dev->kfifo)) {
 				if (filep->f_flags & O_NONBLOCK)
 					return -EAGAIN;
 
-				ret = wait_event_interruptible(lirc->wait_poll,
-					!kfifo_is_empty(&rcdev->kfifo) ||
-					!lirc->drv->attached);
+				ret = wait_event_interruptible(dev->wait_poll,
+					!kfifo_is_empty(&dev->kfifo) ||
+					!drv->attached);
 				if (ret)
 					return ret;
 			}
 
-			if (!lirc->drv->attached)
+			if (!drv->attached)
 				return -ENODEV;
 
-			ret = kfifo_to_user(&rcdev->kfifo, buffer, length,
+			ret = kfifo_to_user(&dev->kfifo, buffer, length,
 					    &copied);
 			if (ret)
 				return ret;
@@ -448,14 +431,14 @@ static ssize_t ir_lirc_read(struct file *filep, char __user *buffer,
 				if (filep->f_flags & O_NONBLOCK)
 					return -EAGAIN;
 
-				ret = wait_event_interruptible(lirc->wait_poll,
+				ret = wait_event_interruptible(dev->wait_poll,
 						!kfifo_is_empty(&lirc->kfifo) ||
-						!lirc->drv->attached);
+						!drv->attached);
 				if (ret)
 					return ret;
 			}
 
-			if (!lirc->drv->attached)
+			if (!drv->attached)
 				return -ENODEV;
 
 			ret = kfifo_to_user(&lirc->kfifo, buffer, length,
@@ -470,10 +453,11 @@ static ssize_t ir_lirc_read(struct file *filep, char __user *buffer,
 
 static int ir_lirc_open(void *data)
 {
-	struct lirc_codec *lirc = data;
+	struct rc_dev *dev = data;
 
-	kfifo_reset_out(&lirc->kfifo);
-	kfifo_reset_out(&lirc->dev->kfifo);
+	kfifo_reset_out(&dev->kfifo);
+	if (dev->raw)
+		kfifo_reset_out(&dev->raw->lirc.kfifo);
 
 	return 0;
 }
@@ -509,15 +493,15 @@ int ir_lirc_register(struct rc_dev *dev)
 
 	if (dev->driver_type == RC_DRIVER_SCANCODE) {
 		features |= LIRC_CAN_REC_SCANCODE;
-		dev->raw->lirc.rec_mode = LIRC_MODE_SCANCODE;
+		dev->rec_mode = LIRC_MODE_SCANCODE;
 	} else if (dev->driver_type == RC_DRIVER_IR_RAW) {
 		features |= LIRC_CAN_REC_MODE2 | LIRC_CAN_REC_SCANCODE;
 		if (dev->rx_resolution)
 			features |= LIRC_CAN_GET_REC_RESOLUTION;
-		dev->raw->lirc.rec_mode = LIRC_MODE_MODE2;
+		dev->rec_mode = LIRC_MODE_MODE2;
 	}
 	if (dev->tx_ir) {
-		dev->raw->lirc.send_mode = LIRC_MODE_PULSE;
+		dev->send_mode = LIRC_MODE_PULSE;
 		features |= LIRC_CAN_SEND_PULSE | LIRC_CAN_SEND_SCANCODE;
 		if (dev->s_tx_mask)
 			features |= LIRC_CAN_SET_TRANSMITTER_MASK;
@@ -544,16 +528,16 @@ int ir_lirc_register(struct rc_dev *dev)
 		 dev->driver_name);
 	drv->minor = -1;
 	drv->features = features;
-	drv->data = &dev->raw->lirc;
 	drv->set_use_inc = &ir_lirc_open;
 	drv->set_use_dec = &ir_lirc_close;
 	drv->code_length = sizeof(struct ir_raw_event) * 8;
 	drv->fops = &lirc_fops;
 	drv->dev.parent = &dev->dev;
+	drv->data = dev;
 	drv->rdev = dev;
 	drv->owner = THIS_MODULE;
-	INIT_KFIFO(dev->raw->lirc.kfifo);
-	init_waitqueue_head(&dev->raw->lirc.wait_poll);
+	if (dev->raw)
+		INIT_KFIFO(dev->raw->lirc.kfifo);
 
 	drv->minor = lirc_register_driver(drv);
 	if (drv->minor < 0) {
@@ -561,8 +545,8 @@ int ir_lirc_register(struct rc_dev *dev)
 		goto lirc_register_failed;
 	}
 
-	dev->raw->lirc.drv = drv;
-	dev->raw->lirc.dev = dev;
+	dev->lirc_drv = drv;
+
 	return 0;
 
 lirc_register_failed:
@@ -572,8 +556,6 @@ int ir_lirc_register(struct rc_dev *dev)
 
 void ir_lirc_unregister(struct rc_dev *dev)
 {
-	struct lirc_codec *lirc = &dev->raw->lirc;
-
-	wake_up_poll(&lirc->wait_poll, POLLERR);
-	lirc_unregister_driver(lirc->drv->minor);
+	wake_up_poll(&dev->wait_poll, POLLERR);
+	lirc_unregister_driver(dev->lirc_drv->minor);
 }
drivers/media/rc/ir-mce_kbd-decoder.c +1 -1
index c4b2998..552d0fe 100644
@@ -344,7 +344,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
 		lsc.scancode = scancode;
 		lsc.flags = 0;
 		if (kfifo_put(&dev->kfifo, lsc))
-			ir_wakeup_poll(dev->raw);
+			wake_up_poll(&dev->wait_poll, POLLIN);
 		data->state = STATE_INACTIVE;
 		input_event(data->idev, EV_MSC, MSC_SCAN, scancode);
 		input_sync(data->idev);
drivers/media/rc/rc-core-priv.h +0 -15
index 858c467..001911d 100644
@@ -126,18 +126,13 @@ struct ir_raw_event_ctrl {
 #endif
 #if IS_ENABLED(CONFIG_IR_LIRC_CODEC)
 	struct lirc_codec {
-		struct rc_dev *dev;
-		struct lirc_driver *drv;
 		DECLARE_KFIFO(kfifo, unsigned int, LIRCBUF_SIZE);
-		wait_queue_head_t wait_poll;
 		int carrier_low;
 
 		ktime_t gap_start;
 		u64 gap_duration;
 		bool gap;
 		bool send_timeout_reports;
-		int send_mode;
-		int rec_mode;
 	} lirc;
 #endif
 #if IS_ENABLED(CONFIG_IR_XMP_DECODER)
@@ -149,16 +144,6 @@ struct ir_raw_event_ctrl {
 #endif
 };
 
-#if IS_ENABLED(CONFIG_IR_LIRC_CODEC)
-static inline void ir_wakeup_poll(struct ir_raw_event_ctrl *ctrl)
-{
-	if (ctrl)
-		wake_up_poll(&ctrl->lirc.wait_poll, POLLIN);
-}
-#else
-static inline void ir_wakeup_poll(struct ir_raw_event_ctrl *ctrl) {}
-#endif
-
 /* macros for IR decoders */
 static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin)
 {
drivers/media/rc/rc-main.c +5 -4
index feff1f3..ebca5bf 100644
@@ -622,7 +622,7 @@ void rc_repeat(struct rc_dev *dev)
 	};
 
 	if (kfifo_put(&dev->kfifo, sc))
-		ir_wakeup_poll(dev->raw);
+		wake_up_poll(&dev->wait_poll, POLLIN);
 
 	spin_lock_irqsave(&dev->keylock, flags);
 
@@ -664,7 +664,7 @@ static void ir_do_keydown(struct rc_dev *dev, enum rc_type protocol,
 	};
 
 	if (kfifo_put(&dev->kfifo, sc))
-		ir_wakeup_poll(dev->raw);
+		wake_up_poll(&dev->wait_poll, POLLIN);
 
 	if (new_event && dev->keypressed)
 		ir_do_keyup(dev, false);
@@ -1606,6 +1606,7 @@ struct rc_dev *rc_allocate_device(enum rc_driver_type type)
 		spin_lock_init(&dev->rc_map.lock);
 		spin_lock_init(&dev->keylock);
 		INIT_KFIFO(dev->kfifo);
+		init_waitqueue_head(&dev->wait_poll);
 	}
 	mutex_init(&dev->lock);
 
@@ -1794,7 +1795,7 @@ int rc_register_device(struct rc_dev *dev)
 			goto out_rx;
 	}
 
-	if (dev->driver_type != RC_DRIVER_SCANCODE) {
+	if (dev->allowed_protocols != RC_BIT_CEC) {
 		rc = ir_lirc_register(dev);
 		if (rc < 0)
 			goto out_raw;
@@ -1859,7 +1860,7 @@ void rc_unregister_device(struct rc_dev *dev)
 	if (dev->driver_type == RC_DRIVER_IR_RAW)
 		ir_raw_event_unregister(dev);
 
-	if (dev->driver_type != RC_DRIVER_SCANCODE)
+	if (dev->allowed_protocols != RC_BIT_CEC)
 		ir_lirc_unregister(dev);
 
 	rc_free_rx_device(dev);
include/media/rc-core.h +10 -0
index 24486d7..52e818d 100644
@@ -111,6 +111,12 @@ enum rc_filter_type {
  * @last_protocol: protocol of last keypress
  * @last_scancode: scancode of last keypress
  * @last_toggle: toggle value of last command
+ * @lirc_drv: lirc driver associated with this rc device
+ * @wait_poll: used for implementing poll on lirc char device
+ * @rec_mode: lirc char device recording mode (LIRC_MODE_MODE2 or
+ *	LIRC_MODE_SCANCODE).
+ * @send_mode: lirc char device sending mode (LIRC_MODE_PULSE or
+ *	LIRC_MODE_SCANCODE).
  * @timeout: optional time after which device stops sending data
  * @min_timeout: minimum timeout supported by device
  * @max_timeout: maximum timeout supported by device
@@ -172,6 +178,10 @@ struct rc_dev {
 	enum rc_type			last_protocol;
 	u32				last_scancode;
 	u8				last_toggle;
+	struct lirc_driver		*lirc_drv;
+	wait_queue_head_t		wait_poll;
+	u8				rec_mode;
+	u8				send_mode;
 	u32				timeout;
 	u32				min_timeout;
 	u32				max_timeout;
Signature · 1 line
2.9.3
author maintainer
#22 lore raw

PATCH v2 19/19 lirc: document LIRC_MODE_SCANCODE

In reply to Sean Young

Lirc supports a new mode which requires documentation.

---
 Documentation/media/uapi/rc/lirc-dev-intro.rst     | 20 ++++++++++++++++++++
 Documentation/media/uapi/rc/lirc-get-features.rst  | 15 +++++++++++++++
 Documentation/media/uapi/rc/lirc-get-rec-mode.rst  |  8 ++++----
 Documentation/media/uapi/rc/lirc-get-send-mode.rst |  5 +++--
 Documentation/media/uapi/rc/lirc-read.rst          |  6 ++++++
 Documentation/media/uapi/rc/lirc-write.rst         |  8 ++++++++
 6 files changed, 56 insertions(+), 6 deletions(-)
Documentation/media/uapi/rc/lirc-dev-intro.rst +20 -0
index 1250d4c..ed0706b 100644
@@ -36,6 +36,26 @@ LIRC modes
 LIRC supports some modes of receiving and sending IR codes, as shown
 on the following table.
 
+.. _lirc-mode-scancode:
+
+``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_type`` set
+    the IR protocol, and ``flags`` set to 0. Write this to the lirc device.
+
+    For receiving, you read ``struct lirc_scancode`` from the lirc device,
+    with ``scancode`` set to the received scancode in the IR protocol
+    ``rc_type``. 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).
+
+    An ``enum rc_type`` in the :ref:`lirc_header` lists all the supported
+    IR protocols.
+
 .. _lirc-mode-mode2:
 
 ``LIRC_MODE_MODE2``
Documentation/media/uapi/rc/lirc-get-features.rst +15 -0
index 64f89a4..76bc99a 100644
@@ -65,6 +65,14 @@ LIRC features
     The driver is capable of receiving using
     :ref:`LIRC_MODE_LIRCCODE <lirc-mode-LIRCCODE>`.
 
+.. _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``
@@ -173,6 +181,13 @@ LIRC features
     The driver supports sending (also called as IR blasting or IR TX) using
     :ref:`LIRC_MODE_LIRCCODE <lirc-mode-LIRCCODE>`.
 
+.. _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
 ============
Documentation/media/uapi/rc/lirc-get-rec-mode.rst +4 -4
index a4eb6c0..221f093d 100644
@@ -33,10 +33,10 @@ Arguments
 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.
+Get/set supported receive modes. Only :ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>`,
+:ref:`LIRC_MODE_LIRCCODE <lirc-mode-lirccode>` and
+:ref:`LIRC_MODE_SCANCODE <lirc-mode-scancode>` are supported for IR
+Use :ref:`lirc_get_features` to find out which modes the driver supports.
 
 Return Value
 ============
Documentation/media/uapi/rc/lirc-get-send-mode.rst +3 -2
index a169b23..be0992e 100644
@@ -36,8 +36,9 @@ 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>`,
+:ref:`LIRC_MODE_LIRCCODE <lirc-mode-lirccode>` and
+:ref:`LIRC_MODE_SCANCODE <lirc-mode-scancode>` is supported by for IR send,
 depending on the driver. Use :ref:`lirc_get_features` to find out which
 modes the driver supports.
 
Documentation/media/uapi/rc/lirc-read.rst +6 -0
index ffa2830..b4e5a56 100644
@@ -54,6 +54,12 @@ The generally preferred mode for receive is
 in which packets containing an int value describing an IR signal are
 read from the chardev.
 
+Alternatively, :ref:`LIRC_MODE_SCANCODE <lirc-mode-scancode>` might be available.
+Some hardware only produces scancodes so this might be the only available mode.
+In this mode, full decoded scancodes read from the chardev with their protocol
+information.
+
+
 Return Value
 ============
 
Documentation/media/uapi/rc/lirc-write.rst +8 -0
index 6b44e0d..d3bb974 100644
@@ -55,6 +55,14 @@ samples. The write function must block 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. The ``flags``
+member must be 0, and ``rc_type`` must be set to a valid protocol. Set
+the desired scancode in the ``scancode`` member. If there is no protocol
+encoder for the protocol, ``EINVAL`` is returned, or the scancode might
+not be valid for the specified protocol.
+
+
 Return Value
 ============
 
Signature · 1 line
2.9.3