Jesse Keating 7a3296
Patch generated from the linuxtv staging/other branch, with a few
Jesse Keating 7a3296
additional pending fixes merged in, and just about everything not
Jesse Keating 7a3296
essential to the ir-core update chopped out.
Jesse Keating 7a3296
Jesse Keating 7a3296
(Patch generated 2010.07.16)
Jesse Keating 7a3296
Jesse Keating 7a3296
Signed-off-by: Jarod Wilson <jarod@redhat.com>
Jesse Keating 7a3296
Jesse Keating 7a3296
---
Jesse Keating 7a3296
 Documentation/DocBook/media-entities.tmpl           |    1 
Jesse Keating 7a3296
 Documentation/DocBook/media.tmpl                    |    8 
Jesse Keating 7a3296
 Documentation/DocBook/v4l/lirc_device_interface.xml |  235 ++++
Jesse Keating 7a3296
 Documentation/DocBook/v4l/remote_controllers.xml    |    2 
Jesse Keating 7a3296
 Documentation/dvb/get_dvb_firmware                  |   19 
Jesse Keating 7a3296
 Documentation/video4linux/CARDLIST.cx23885          |    6 
Jesse Keating 7a3296
 drivers/input/evdev.c                               |   39 
Jesse Keating 7a3296
 drivers/input/input.c                               |  268 ++++
Jesse Keating 7a3296
 drivers/media/IR/Kconfig                            |   34 
Jesse Keating 7a3296
 drivers/media/IR/Makefile                           |    3 
Jesse Keating 7a3296
 drivers/media/IR/imon.c                             |    5 
Jesse Keating 7a3296
 drivers/media/IR/ir-core-priv.h                     |   54 
Jesse Keating 7a3296
 drivers/media/IR/ir-jvc-decoder.c                   |  152 --
Jesse Keating 7a3296
 drivers/media/IR/ir-lirc-codec.c                    |  283 ++++
Jesse Keating 7a3296
 drivers/media/IR/ir-nec-decoder.c                   |  151 --
Jesse Keating 7a3296
 drivers/media/IR/ir-raw-event.c                     |  167 +-
Jesse Keating 7a3296
 drivers/media/IR/ir-rc5-decoder.c                   |  167 --
Jesse Keating 7a3296
 drivers/media/IR/ir-rc6-decoder.c                   |  153 --
Jesse Keating 7a3296
 drivers/media/IR/ir-sony-decoder.c                  |  155 --
Jesse Keating 7a3296
 drivers/media/IR/ir-sysfs.c                         |  261 ++--
Jesse Keating 7a3296
 drivers/media/IR/keymaps/Makefile                   |    2 
Jesse Keating 7a3296
 drivers/media/IR/keymaps/rc-lirc.c                  |   41 
Jesse Keating 7a3296
 drivers/media/IR/keymaps/rc-rc6-mce.c               |  105 +
Jesse Keating 7a3296
 drivers/media/IR/lirc_dev.c                         |  764 +++++++++++++
Jesse Keating 7a3296
 drivers/media/IR/mceusb.c                           | 1143 ++++++++++++++++++++
Jesse Keating 7a3296
 drivers/media/common/tuners/tda18271-fe.c           |    8 
Jesse Keating 7a3296
 drivers/media/dvb/mantis/Kconfig                    |   14 
Jesse Keating 7a3296
 drivers/media/dvb/mantis/mantis_input.c             |    5 
Jesse Keating 7a3296
 drivers/media/video/cx23885/cx23885-cards.c         |   40 
Jesse Keating 7a3296
 drivers/media/video/cx23885/cx23885-core.c          |   11 
Jesse Keating 7a3296
 drivers/media/video/cx23885/cx23885-dvb.c           |    2 
Jesse Keating 7a3296
 drivers/media/video/cx23885/cx23885-input.c         |  317 +----
Jesse Keating 7a3296
 drivers/media/video/cx23885/cx23885-ir.c            |    2 
Jesse Keating 7a3296
 drivers/media/video/cx23885/cx23885.h               |   12 
Jesse Keating 7a3296
 drivers/media/video/cx88/cx88-cards.c               |    9 
Jesse Keating 7a3296
 drivers/media/video/cx88/cx88-i2c.c                 |    6 
Jesse Keating 7a3296
 drivers/media/video/cx88/cx88-input.c               |   46 
Jesse Keating 7a3296
 drivers/media/video/cx88/cx88.h                     |    1 
Jesse Keating 7a3296
 drivers/media/video/em28xx/em28xx-input.c           |   80 -
Jesse Keating 7a3296
 drivers/media/video/em28xx/em28xx-video.c           |    4 
Jesse Keating 7a3296
 drivers/media/video/em28xx/em28xx.h                 |    1 
Jesse Keating 7a3296
 drivers/media/video/hdpvr/hdpvr-core.c              |    5 
Jesse Keating 7a3296
 drivers/media/video/ir-kbd-i2c.c                    |   14 
Jesse Keating 7a3296
 drivers/media/video/pvrusb2/pvrusb2-ioread.c        |    5 
Jesse Keating 7a3296
 include/linux/input.h                               |   39 
Jesse Keating 7a3296
 include/media/ir-core.h                             |    8 
Jesse Keating 7a3296
 include/media/ir-kbd-i2c.h                          |    2 
Jesse Keating 7a3296
 include/media/lirc.h                                |  165 ++
Jesse Keating 7a3296
 include/media/lirc_dev.h                            |  225 +++
Jesse Keating 7a3296
 include/media/rc-map.h                              |    7 
Jesse Keating 7a3296
 50 files changed, 3971 insertions(+), 1275 deletions(-)
Jesse Keating 7a3296
Jesse Keating 7a3296
diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
Jesse Keating 7a3296
index 5d4d40f..6ae9715 100644
Jesse Keating 7a3296
--- a/Documentation/DocBook/media-entities.tmpl
Jesse Keating 7a3296
+++ b/Documentation/DocBook/media-entities.tmpl
Jesse Keating 7a3296
@@ -218,6 +218,7 @@
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 
Jesse Keating 7a3296
diff --git a/Documentation/DocBook/media.tmpl b/Documentation/DocBook/media.tmpl
Jesse Keating 7a3296
index eea564b..f11048d 100644
Jesse Keating 7a3296
--- a/Documentation/DocBook/media.tmpl
Jesse Keating 7a3296
+++ b/Documentation/DocBook/media.tmpl
Jesse Keating 7a3296
@@ -28,7 +28,7 @@
Jesse Keating 7a3296
 <title>LINUX MEDIA INFRASTRUCTURE API</title>
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 <copyright>
Jesse Keating 7a3296
-	<year>2009</year>
Jesse Keating 7a3296
+	<year>2009-2010</year>
Jesse Keating 7a3296
 	<holder>LinuxTV Developers</holder>
Jesse Keating 7a3296
 </copyright>
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -61,7 +61,7 @@ Foundation. A copy of the license is included in the chapter entitled
Jesse Keating 7a3296
 		in fact it covers several different video standards including
Jesse Keating 7a3296
 		DVB-T, DVB-S, DVB-C and ATSC. The API is currently being updated
Jesse Keating 7a3296
 		to documment support also for DVB-S2, ISDB-T and ISDB-S.</para>
Jesse Keating 7a3296
-	<para>The third part covers other API's used by all media infrastructure devices</para>
Jesse Keating 7a3296
+	<para>The third part covers Remote Controller API</para>
Jesse Keating 7a3296
 	<para>For additional information and for the latest development code,
Jesse Keating 7a3296
 		see: <ulink url="http://linuxtv.org">http://linuxtv.org</ulink>.</para>
Jesse Keating 7a3296
 	<para>For discussing improvements, reporting troubles, sending new drivers, etc, please mail to: <ulink url="http://vger.kernel.org/vger-lists.html#linux-media">Linux Media Mailing List (LMML).</ulink>.</para>
Jesse Keating 7a3296
@@ -86,7 +86,7 @@ Foundation. A copy of the license is included in the chapter entitled
Jesse Keating 7a3296
 </author>
Jesse Keating 7a3296
 </authorgroup>
Jesse Keating 7a3296
 <copyright>
Jesse Keating 7a3296
-	<year>2009</year>
Jesse Keating 7a3296
+	<year>2009-2010</year>
Jesse Keating 7a3296
 	<holder>Mauro Carvalho Chehab</holder>
Jesse Keating 7a3296
 </copyright>
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -101,7 +101,7 @@ Foundation. A copy of the license is included in the chapter entitled
Jesse Keating 7a3296
 </revhistory>
Jesse Keating 7a3296
 </partinfo>
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-<title>Other API's used by media infrastructure drivers</title>
Jesse Keating 7a3296
+<title>Remote Controller API</title>
Jesse Keating 7a3296
 <chapter id="remote_controllers">
Jesse Keating 7a3296
 &sub-remote_controllers;
Jesse Keating 7a3296
 </chapter>
Jesse Keating 7a3296
diff --git a/Documentation/DocBook/v4l/lirc_device_interface.xml b/Documentation/DocBook/v4l/lirc_device_interface.xml
Jesse Keating 7a3296
new file mode 100644
Jesse Keating 7a3296
index 0000000..0413234
Jesse Keating 7a3296
--- /dev/null
Jesse Keating 7a3296
+++ b/Documentation/DocBook/v4l/lirc_device_interface.xml
Jesse Keating 7a3296
@@ -0,0 +1,235 @@
Jesse Keating 7a3296
+<section id="lirc_dev">
Jesse Keating 7a3296
+<title>LIRC Device Interface</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<section id="lirc_dev_intro">
Jesse Keating 7a3296
+<title>Introduction</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>The LIRC device interface is a bi-directional interface for
Jesse Keating 7a3296
+transporting raw IR data between userspace and kernelspace. Fundamentally,
Jesse Keating 7a3296
+it is just a chardev (/dev/lircX, for X = 0, 1, 2, ...), with a number
Jesse Keating 7a3296
+of standard struct file_operations defined on it. With respect to
Jesse Keating 7a3296
+transporting raw IR data to and fro, the essential fops are read, write
Jesse Keating 7a3296
+and ioctl.</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>Example dmesg output upon a driver registering w/LIRC:</para>
Jesse Keating 7a3296
+  
Jesse Keating 7a3296
+    <para>$ dmesg |grep lirc_dev</para>
Jesse Keating 7a3296
+    <para>lirc_dev: IR Remote Control driver registered, major 248</para>
Jesse Keating 7a3296
+    <para>rc rc0: lirc_dev: driver ir-lirc-codec (mceusb) registered at minor = 0</para>
Jesse Keating 7a3296
+  
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>What you should see for a chardev:</para>
Jesse Keating 7a3296
+  
Jesse Keating 7a3296
+    <para>$ ls -l /dev/lirc*</para>
Jesse Keating 7a3296
+    <para>crw-rw---- 1 root root 248, 0 Jul  2 22:20 /dev/lirc0</para>
Jesse Keating 7a3296
+  
Jesse Keating 7a3296
+</section>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<section id="lirc_read">
Jesse Keating 7a3296
+<title>LIRC read fop</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>The lircd userspace daemon reads raw IR data from the LIRC chardev. The
Jesse Keating 7a3296
+exact format of the data depends on what modes a driver supports, and what
Jesse Keating 7a3296
+mode has been selected. lircd obtains supported modes and sets the active mode
Jesse Keating 7a3296
+via the ioctl interface, detailed at <xref linkend="lirc_ioctl"/>. The generally
Jesse Keating 7a3296
+preferred mode is LIRC_MODE_MODE2, in which packets containing an int value
Jesse Keating 7a3296
+describing an IR signal are read from the chardev.</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>See also <ulink url="http://www.lirc.org/html/technical.html">http://www.lirc.org/html/technical.html</ulink> for more info.</para>
Jesse Keating 7a3296
+</section>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<section id="lirc_write">
Jesse Keating 7a3296
+<title>LIRC write fop</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>The data written to the chardev is a pulse/space sequence of integer
Jesse Keating 7a3296
+values. Pulses and spaces are only marked implicitly by their position. The
Jesse Keating 7a3296
+data must start and end with a pulse, therefore, the data must always include
Jesse Keating 7a3296
+an unevent number of samples. The write function must block until the data has
Jesse Keating 7a3296
+been transmitted by the hardware.</para>
Jesse Keating 7a3296
+</section>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<section id="lirc_ioctl">
Jesse Keating 7a3296
+<title>LIRC ioctl fop</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>The LIRC device's ioctl definition is bound by the ioctl function
Jesse Keating 7a3296
+definition of struct file_operations, leaving us with an unsigned int
Jesse Keating 7a3296
+for the ioctl command and an unsigned long for the arg. For the purposes
Jesse Keating 7a3296
+of ioctl portability across 32-bit and 64-bit, these values are capped
Jesse Keating 7a3296
+to their 32-bit sizes.</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>The following ioctls can be used to change specific hardware settings.
Jesse Keating 7a3296
+In general each driver should have a default set of settings. The driver
Jesse Keating 7a3296
+implementation is expected to re-apply the default settings when the device
Jesse Keating 7a3296
+is closed by user-space, so that every application opening the device can rely
Jesse Keating 7a3296
+on working with the default settings initially.</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<variablelist>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_GET_FEATURES</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Obviously, get the underlying hardware device's features. If a driver
Jesse Keating 7a3296
+      does not announce support of certain features, calling of the corresponding
Jesse Keating 7a3296
+      ioctls is undefined.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_GET_SEND_MODE</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Get supported transmit mode. Only LIRC_MODE_PULSE is supported by lircd.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_GET_REC_MODE</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Get supported receive modes. Only LIRC_MODE_MODE2 and LIRC_MODE_LIRCCODE
Jesse Keating 7a3296
+      are supported by lircd.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_GET_SEND_CARRIER</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Get carrier frequency (in Hz) currently used for transmit.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_GET_REC_CARRIER</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Get carrier frequency (in Hz) currently used for IR reception.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_{G,S}ET_{SEND,REC}_DUTY_CYCLE</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Get/set the duty cycle (from 0 to 100) of the carrier signal. Currently,
Jesse Keating 7a3296
+      no special meaning is defined for 0 or 100, but this could be used to switch
Jesse Keating 7a3296
+      off carrier generation in the future, so these values should be reserved.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_GET_REC_RESOLUTION</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Some receiver have maximum resolution which is defined by internal
Jesse Keating 7a3296
+      sample rate or data format limitations. E.g. it's common that signals can
Jesse Keating 7a3296
+      only be reported in 50 microsecond steps. This integer value is used by
Jesse Keating 7a3296
+      lircd to automatically adjust the aeps tolerance value in the lircd
Jesse Keating 7a3296
+      config file.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_GET_M{IN,AX}_TIMEOUT</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Some devices have internal timers that can be used to detect when
Jesse Keating 7a3296
+      there's no IR activity for a long time. This can help lircd in detecting
Jesse Keating 7a3296
+      that a IR signal is finished and can speed up the decoding process.
Jesse Keating 7a3296
+      Returns an integer value with the minimum/maximum timeout that can be
Jesse Keating 7a3296
+      set. Some devices have a fixed timeout, in that case both ioctls will
Jesse Keating 7a3296
+      return the same value even though the timeout cannot be changed.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_GET_M{IN,AX}_FILTER_{PULSE,SPACE}</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Some devices are able to filter out spikes in the incoming signal
Jesse Keating 7a3296
+      using given filter rules. These ioctls return the hardware capabilities
Jesse Keating 7a3296
+      that describe the bounds of the possible filters. Filter settings depend
Jesse Keating 7a3296
+      on the IR protocols that are expected. lircd derives the settings from
Jesse Keating 7a3296
+      all protocols definitions found in its config file.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_GET_LENGTH</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Retrieves the code length in bits (only for LIRC_MODE_LIRCCODE).
Jesse Keating 7a3296
+      Reads on the device must be done in blocks matching the bit count.
Jesse Keating 7a3296
+      The bit could should be rounded up so that it matches full bytes.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_SET_{SEND,REC}_MODE</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Set send/receive mode. Largely obsolete for send, as only
Jesse Keating 7a3296
+      LIRC_MODE_PULSE is supported.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_SET_{SEND,REC}_CARRIER</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Set send/receive carrier (in Hz).</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_SET_TRANSMITTER_MASK</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>This enables the given set of transmitters. The first transmitter
Jesse Keating 7a3296
+      is encoded by the least significant bit, etc. When an invalid bit mask
Jesse Keating 7a3296
+      is given, i.e. a bit is set, even though the device does not have so many
Jesse Keating 7a3296
+      transitters, then this ioctl returns the number of available transitters
Jesse Keating 7a3296
+      and does nothing otherwise.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_SET_REC_TIMEOUT</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Sets the integer value for IR inactivity timeout (cf.
Jesse Keating 7a3296
+      LIRC_GET_MIN_TIMEOUT and LIRC_GET_MAX_TIMEOUT). A value of 0 (if
Jesse Keating 7a3296
+      supported by the hardware) disables all hardware timeouts and data should
Jesse Keating 7a3296
+      be reported as soon as possible. If the exact value cannot be set, then
Jesse Keating 7a3296
+      the next possible value _greater_ than the given value should be set.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_SET_REC_TIMEOUT_REPORTS</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Enable (1) or disable (0) timeout reports in LIRC_MODE_MODE2. By
Jesse Keating 7a3296
+      default, timeout reports should be turned off.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_SET_REC_FILTER_{,PULSE,SPACE}</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Pulses/spaces shorter than this are filtered out by hardware. If
Jesse Keating 7a3296
+      filters cannot be set independently for pulse/space, the corresponding
Jesse Keating 7a3296
+      ioctls must return an error and LIRC_SET_REC_FILTER shall be used instead.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_SET_MEASURE_CARRIER_MODE</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Enable (1)/disable (0) measure mode. If enabled, from the next key
Jesse Keating 7a3296
+      press on, the driver will send LIRC_MODE2_FREQUENCY packets. By default
Jesse Keating 7a3296
+      this should be turned off.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_SET_REC_{DUTY_CYCLE,CARRIER}_RANGE</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>To set a range use LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE
Jesse Keating 7a3296
+      with the lower bound first and later LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER
Jesse Keating 7a3296
+      with the upper bound.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_NOTIFY_DECODE</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>This ioctl is called by lircd whenever a successful decoding of an
Jesse Keating 7a3296
+      incoming IR signal could be done. This can be used by supporting hardware
Jesse Keating 7a3296
+      to give visual feedback to the user e.g. by flashing a LED.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+  <varlistentry>
Jesse Keating 7a3296
+    <term>LIRC_SETUP_{START,END}</term>
Jesse Keating 7a3296
+    <listitem>
Jesse Keating 7a3296
+      <para>Setting of several driver parameters can be optimized by encapsulating
Jesse Keating 7a3296
+      the according ioctl calls with LIRC_SETUP_START/LIRC_SETUP_END. When a
Jesse Keating 7a3296
+      driver receives a LIRC_SETUP_START ioctl it can choose to not commit
Jesse Keating 7a3296
+      further setting changes to the hardware until a LIRC_SETUP_END is received.
Jesse Keating 7a3296
+      But this is open to the driver implementation and every driver must also
Jesse Keating 7a3296
+      handle parameter changes which are not encapsulated by LIRC_SETUP_START
Jesse Keating 7a3296
+      and LIRC_SETUP_END. Drivers can also choose to ignore these ioctls.</para>
Jesse Keating 7a3296
+    </listitem>
Jesse Keating 7a3296
+  </varlistentry>
Jesse Keating 7a3296
+</variablelist>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</section>
Jesse Keating 7a3296
+</section>
Jesse Keating 7a3296
diff --git a/Documentation/DocBook/v4l/remote_controllers.xml b/Documentation/DocBook/v4l/remote_controllers.xml
Jesse Keating 7a3296
index 73f5eab..3c3b667 100644
Jesse Keating 7a3296
--- a/Documentation/DocBook/v4l/remote_controllers.xml
Jesse Keating 7a3296
+++ b/Documentation/DocBook/v4l/remote_controllers.xml
Jesse Keating 7a3296
@@ -173,3 +173,5 @@ keymapping.</para>
Jesse Keating 7a3296
 <para>This program demonstrates how to replace the keymap tables.</para>
Jesse Keating 7a3296
 &sub-keytable-c;
Jesse Keating 7a3296
 </section>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+&sub-lirc_device_interface;
Jesse Keating 7a3296
diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware
Jesse Keating 7a3296
index 239cbdb..9ea94dc 100644
Jesse Keating 7a3296
--- a/Documentation/dvb/get_dvb_firmware
Jesse Keating 7a3296
+++ b/Documentation/dvb/get_dvb_firmware
Jesse Keating 7a3296
@@ -26,7 +26,7 @@ use IO::Handle;
Jesse Keating 7a3296
 		"dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004",
Jesse Keating 7a3296
 		"or51211", "or51132_qam", "or51132_vsb", "bluebird",
Jesse Keating 7a3296
 		"opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718",
Jesse Keating 7a3296
-		"af9015", "ngene");
Jesse Keating 7a3296
+		"af9015", "ngene", "az6027");
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 # Check args
Jesse Keating 7a3296
 syntax() if (scalar(@ARGV) != 1);
Jesse Keating 7a3296
@@ -567,6 +567,23 @@ sub ngene {
Jesse Keating 7a3296
     "$file1, $file2";
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+sub az6027{
Jesse Keating 7a3296
+    my $file = "AZ6027_Linux_Driver.tar.gz";
Jesse Keating 7a3296
+    my $url = "http://linux.terratec.de/files/$file";
Jesse Keating 7a3296
+    my $firmware = "dvb-usb-az6027-03.fw";
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+    wgetfile($file, $url);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+    #untar
Jesse Keating 7a3296
+    if( system("tar xzvf $file $firmware")){
Jesse Keating 7a3296
+        die "failed to untar firmware";
Jesse Keating 7a3296
+    }
Jesse Keating 7a3296
+    if( system("rm $file")){
Jesse Keating 7a3296
+        die ("unable to remove unnecessary files");
Jesse Keating 7a3296
+    }
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+    $firmware;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
 # ---------------------------------------------------------------
Jesse Keating 7a3296
 # Utilities
Jesse Keating 7a3296
 
Jesse Keating 7a3296
diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885
Jesse Keating 7a3296
index 16ca030..87c4634 100644
Jesse Keating 7a3296
--- a/Documentation/video4linux/CARDLIST.cx23885
Jesse Keating 7a3296
+++ b/Documentation/video4linux/CARDLIST.cx23885
Jesse Keating 7a3296
@@ -17,9 +17,9 @@
Jesse Keating 7a3296
  16 -> DVBWorld DVB-S2 2005                                [0001:2005]
Jesse Keating 7a3296
  17 -> NetUP Dual DVB-S2 CI                                [1b55:2a2c]
Jesse Keating 7a3296
  18 -> Hauppauge WinTV-HVR1270                             [0070:2211]
Jesse Keating 7a3296
- 19 -> Hauppauge WinTV-HVR1275                             [0070:2215]
Jesse Keating 7a3296
- 20 -> Hauppauge WinTV-HVR1255                             [0070:2251]
Jesse Keating 7a3296
- 21 -> Hauppauge WinTV-HVR1210                             [0070:2291,0070:2295]
Jesse Keating 7a3296
+ 19 -> Hauppauge WinTV-HVR1275                             [0070:2215,0070:221d,0070:22f2]
Jesse Keating 7a3296
+ 20 -> Hauppauge WinTV-HVR1255                             [0070:2251,0070:2259,0070:22f1]
Jesse Keating 7a3296
+ 21 -> Hauppauge WinTV-HVR1210                             [0070:2291,0070:2295,0070:2299,0070:229d,0070:22f0,0070:22f3,0070:22f4,0070:22f5]
Jesse Keating 7a3296
  22 -> Mygica X8506 DMB-TH                                 [14f1:8651]
Jesse Keating 7a3296
  23 -> Magic-Pro ProHDTV Extreme 2                         [14f1:8657]
Jesse Keating 7a3296
  24 -> Hauppauge WinTV-HVR1850                             [0070:8541]
Jesse Keating 7a3296
diff --git a/Documentation/video4linux/extract_xc3028.pl b/Documentation/video4linux/extract_xc3028.pl
Jesse Keating 7a3296
old mode 100644
Jesse Keating 7a3296
new mode 100755
Jesse Keating 7a3296
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
Jesse Keating 7a3296
index 2ee6c7a..b8a5673 100644
Jesse Keating 7a3296
--- a/drivers/input/evdev.c
Jesse Keating 7a3296
+++ b/drivers/input/evdev.c
Jesse Keating 7a3296
@@ -515,6 +515,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
Jesse Keating 7a3296
 	struct input_absinfo abs;
Jesse Keating 7a3296
 	struct ff_effect effect;
Jesse Keating 7a3296
 	int __user *ip = (int __user *)p;
Jesse Keating 7a3296
+	struct keycode_table_entry kt, *kt_p = p;
Jesse Keating 7a3296
+	char scancode[16];
Jesse Keating 7a3296
 	unsigned int i, t, u, v;
Jesse Keating 7a3296
 	int error;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -569,6 +571,43 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 		return input_set_keycode(dev, t, v);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+	case EVIOCGKEYCODEBIG:
Jesse Keating 7a3296
+		if (copy_from_user(&kt, kt_p, sizeof(kt)))
Jesse Keating 7a3296
+			return -EFAULT;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (kt.len > sizeof(scancode))
Jesse Keating 7a3296
+			return -EINVAL;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		kt.scancode = scancode;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		error = input_get_keycode_big(dev, &kt);
Jesse Keating 7a3296
+		if (error)
Jesse Keating 7a3296
+			return error;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (copy_to_user(kt_p, &kt, sizeof(kt)))
Jesse Keating 7a3296
+			return -EFAULT;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		/* FIXME: probably need some compat32 code */
Jesse Keating 7a3296
+		if (copy_to_user(kt_p->scancode, kt.scancode, kt.len))
Jesse Keating 7a3296
+			return -EFAULT;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		return 0;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case EVIOCSKEYCODEBIG:
Jesse Keating 7a3296
+		if (copy_from_user(&kt, kt_p, sizeof(kt)))
Jesse Keating 7a3296
+			return -EFAULT;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (kt.len > sizeof(scancode))
Jesse Keating 7a3296
+			return -EINVAL;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		kt.scancode = scancode;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		/* FIXME: probably need some compat32 code */
Jesse Keating 7a3296
+		if (copy_from_user(kt.scancode, kt_p->scancode, kt.len))
Jesse Keating 7a3296
+			return -EFAULT;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		return input_set_keycode_big(dev, &kt);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 	case EVIOCRMFF:
Jesse Keating 7a3296
 		return input_ff_erase(dev, (int)(unsigned long) p, file);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
diff --git a/drivers/input/input.c b/drivers/input/input.c
Jesse Keating 7a3296
index 9c79bd5..43aeb71 100644
Jesse Keating 7a3296
--- a/drivers/input/input.c
Jesse Keating 7a3296
+++ b/drivers/input/input.c
Jesse Keating 7a3296
@@ -568,6 +568,11 @@ static void input_disconnect_device(struct input_dev *dev)
Jesse Keating 7a3296
 	spin_unlock_irq(&dev->event_lock);
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * Those routines handle the default case where no [gs]etkeycode() is
Jesse Keating 7a3296
+ * defined. In this case, an array indexed by the scancode is used.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 static int input_fetch_keycode(struct input_dev *dev, int scancode)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
 	switch (dev->keycodesize) {
Jesse Keating 7a3296
@@ -582,27 +587,74 @@ static int input_fetch_keycode(struct input_dev *dev, int scancode)
Jesse Keating 7a3296
 	}
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-static int input_default_getkeycode(struct input_dev *dev,
Jesse Keating 7a3296
-				    unsigned int scancode,
Jesse Keating 7a3296
-				    unsigned int *keycode)
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * Supports only 8, 16 and 32 bit scancodes. It wouldn't be that
Jesse Keating 7a3296
+ * hard to write some machine-endian logic to support 24 bit scancodes,
Jesse Keating 7a3296
+ * but it seemed overkill. It should also be noticed that, since there
Jesse Keating 7a3296
+ * are, in general, less than 256 scancodes sparsed into the scancode
Jesse Keating 7a3296
+ * space, even with 16 bits, the codespace is sparsed, with leads into
Jesse Keating 7a3296
+ * memory and code ineficiency, when retrieving the entire scancode
Jesse Keating 7a3296
+ * space.
Jesse Keating 7a3296
+ * So, it is highly recommended to implement getkeycodebig/setkeycodebig
Jesse Keating 7a3296
+ * instead of using a normal table approach, when more than 8 bits is
Jesse Keating 7a3296
+ * needed for the scancode.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static int input_fetch_scancode(struct keycode_table_entry *kt_entry,
Jesse Keating 7a3296
+				u32 *scancode)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	switch (kt_entry->len) {
Jesse Keating 7a3296
+	case 1:
Jesse Keating 7a3296
+		*scancode = *((u8 *)kt_entry->scancode);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+	case 2:
Jesse Keating 7a3296
+		*scancode = *((u16 *)kt_entry->scancode);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+	case 4:
Jesse Keating 7a3296
+		*scancode = *((u32 *)kt_entry->scancode);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+	default:
Jesse Keating 7a3296
+		return -EINVAL;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+	return 0;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static int input_default_getkeycode_from_index(struct input_dev *dev,
Jesse Keating 7a3296
+				    struct keycode_table_entry *kt_entry)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	u32 scancode = kt_entry->index;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 	if (!dev->keycodesize)
Jesse Keating 7a3296
 		return -EINVAL;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	if (scancode >= dev->keycodemax)
Jesse Keating 7a3296
 		return -EINVAL;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	*keycode = input_fetch_keycode(dev, scancode);
Jesse Keating 7a3296
+	kt_entry->keycode = input_fetch_keycode(dev, scancode);
Jesse Keating 7a3296
+	memcpy(kt_entry->scancode, &scancode, 4);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	return 0;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+static int input_default_getkeycode_from_scancode(struct input_dev *dev,
Jesse Keating 7a3296
+				    struct keycode_table_entry *kt_entry)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	if (input_fetch_scancode(kt_entry, &kt_entry->index))
Jesse Keating 7a3296
+		return -EINVAL;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return input_default_getkeycode_from_index(dev, kt_entry);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 static int input_default_setkeycode(struct input_dev *dev,
Jesse Keating 7a3296
-				    unsigned int scancode,
Jesse Keating 7a3296
-				    unsigned int keycode)
Jesse Keating 7a3296
+				    struct keycode_table_entry *kt_entry)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
-	int old_keycode;
Jesse Keating 7a3296
+	u32 old_keycode;
Jesse Keating 7a3296
 	int i;
Jesse Keating 7a3296
+	u32 scancode;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (input_fetch_scancode(kt_entry, &scancode))
Jesse Keating 7a3296
+		return -EINVAL;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	if (scancode >= dev->keycodemax)
Jesse Keating 7a3296
 		return -EINVAL;
Jesse Keating 7a3296
@@ -610,32 +662,33 @@ static int input_default_setkeycode(struct input_dev *dev,
Jesse Keating 7a3296
 	if (!dev->keycodesize)
Jesse Keating 7a3296
 		return -EINVAL;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
Jesse Keating 7a3296
+	if (dev->keycodesize < sizeof(dev->keycode) &&
Jesse Keating 7a3296
+	    (kt_entry->keycode >> (dev->keycodesize * 8)))
Jesse Keating 7a3296
 		return -EINVAL;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	switch (dev->keycodesize) {
Jesse Keating 7a3296
 		case 1: {
Jesse Keating 7a3296
 			u8 *k = (u8 *)dev->keycode;
Jesse Keating 7a3296
 			old_keycode = k[scancode];
Jesse Keating 7a3296
-			k[scancode] = keycode;
Jesse Keating 7a3296
+			k[scancode] = kt_entry->keycode;
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 		}
Jesse Keating 7a3296
 		case 2: {
Jesse Keating 7a3296
 			u16 *k = (u16 *)dev->keycode;
Jesse Keating 7a3296
 			old_keycode = k[scancode];
Jesse Keating 7a3296
-			k[scancode] = keycode;
Jesse Keating 7a3296
+			k[scancode] = kt_entry->keycode;
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 		}
Jesse Keating 7a3296
 		default: {
Jesse Keating 7a3296
 			u32 *k = (u32 *)dev->keycode;
Jesse Keating 7a3296
 			old_keycode = k[scancode];
Jesse Keating 7a3296
-			k[scancode] = keycode;
Jesse Keating 7a3296
+			k[scancode] = kt_entry->keycode;
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 		}
Jesse Keating 7a3296
 	}
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	__clear_bit(old_keycode, dev->keybit);
Jesse Keating 7a3296
-	__set_bit(keycode, dev->keybit);
Jesse Keating 7a3296
+	__set_bit(kt_entry->keycode, dev->keybit);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	for (i = 0; i < dev->keycodemax; i++) {
Jesse Keating 7a3296
 		if (input_fetch_keycode(dev, i) == old_keycode) {
Jesse Keating 7a3296
@@ -648,6 +701,110 @@ static int input_default_setkeycode(struct input_dev *dev,
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 /**
Jesse Keating 7a3296
+ * input_get_keycode_big - retrieve keycode currently mapped to a given scancode
Jesse Keating 7a3296
+ * @dev: input device which keymap is being queried
Jesse Keating 7a3296
+ * @kt_entry: keytable entry
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This function should be called by anyone interested in retrieving current
Jesse Keating 7a3296
+ * keymap. Presently evdev handlers use it.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+int input_get_keycode_big(struct input_dev *dev,
Jesse Keating 7a3296
+			  struct keycode_table_entry *kt_entry)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	if (dev->getkeycode) {
Jesse Keating 7a3296
+		u32 scancode = kt_entry->index;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		/*
Jesse Keating 7a3296
+		 * Support for legacy drivers, that don't implement the new
Jesse Keating 7a3296
+		 * ioctls
Jesse Keating 7a3296
+		 */
Jesse Keating 7a3296
+		memcpy(kt_entry->scancode, &scancode, 4);
Jesse Keating 7a3296
+		return dev->getkeycode(dev, scancode,
Jesse Keating 7a3296
+				       &kt_entry->keycode);
Jesse Keating 7a3296
+	} else
Jesse Keating 7a3296
+		return dev->getkeycodebig_from_index(dev, kt_entry);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+EXPORT_SYMBOL(input_get_keycode_big);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * input_set_keycode_big - attribute a keycode to a given scancode
Jesse Keating 7a3296
+ * @dev: input device which keymap is being queried
Jesse Keating 7a3296
+ * @kt_entry: keytable entry
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This function should be called by anyone needing to update current
Jesse Keating 7a3296
+ * keymap. Presently keyboard and evdev handlers use it.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+int input_set_keycode_big(struct input_dev *dev,
Jesse Keating 7a3296
+			  struct keycode_table_entry *kt_entry)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	unsigned long flags;
Jesse Keating 7a3296
+	int old_keycode;
Jesse Keating 7a3296
+	int retval = -EINVAL;
Jesse Keating 7a3296
+	u32 uninitialized_var(scancode);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (kt_entry->keycode < 0 || kt_entry->keycode > KEY_MAX)
Jesse Keating 7a3296
+		return -EINVAL;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	spin_lock_irqsave(&dev->event_lock, flags);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * We need to know the old scancode, in order to generate a
Jesse Keating 7a3296
+	 * keyup effect, if the set operation happens successfully
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	if (dev->getkeycode) {
Jesse Keating 7a3296
+		/*
Jesse Keating 7a3296
+		 * Support for legacy drivers, that don't implement the new
Jesse Keating 7a3296
+		 * ioctls
Jesse Keating 7a3296
+		 */
Jesse Keating 7a3296
+		if (!dev->setkeycode)
Jesse Keating 7a3296
+			goto out;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		retval = input_fetch_scancode(kt_entry, &scancode);
Jesse Keating 7a3296
+		if (retval)
Jesse Keating 7a3296
+			goto out;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		retval = dev->getkeycode(dev, scancode,
Jesse Keating 7a3296
+					 &old_keycode);
Jesse Keating 7a3296
+	} else {
Jesse Keating 7a3296
+		int new_keycode = kt_entry->keycode;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		retval = dev->getkeycodebig_from_scancode(dev, kt_entry);
Jesse Keating 7a3296
+		old_keycode = kt_entry->keycode;
Jesse Keating 7a3296
+		kt_entry->keycode = new_keycode;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (retval)
Jesse Keating 7a3296
+		goto out;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (dev->getkeycode)
Jesse Keating 7a3296
+		retval = dev->setkeycode(dev, scancode,
Jesse Keating 7a3296
+					 kt_entry->keycode);
Jesse Keating 7a3296
+	else
Jesse Keating 7a3296
+		retval = dev->setkeycodebig(dev, kt_entry);
Jesse Keating 7a3296
+	if (retval)
Jesse Keating 7a3296
+		goto out;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * Simulate keyup event if keycode is not present
Jesse Keating 7a3296
+	 * in the keymap anymore
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	if (test_bit(EV_KEY, dev->evbit) &&
Jesse Keating 7a3296
+	    !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
Jesse Keating 7a3296
+	    __test_and_clear_bit(old_keycode, dev->key)) {
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		input_pass_event(dev, EV_KEY, old_keycode, 0);
Jesse Keating 7a3296
+		if (dev->sync)
Jesse Keating 7a3296
+			input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+ out:
Jesse Keating 7a3296
+	spin_unlock_irqrestore(&dev->event_lock, flags);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return retval;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+EXPORT_SYMBOL(input_set_keycode_big);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
  * input_get_keycode - retrieve keycode currently mapped to a given scancode
Jesse Keating 7a3296
  * @dev: input device which keymap is being queried
Jesse Keating 7a3296
  * @scancode: scancode (or its equivalent for device in question) for which
Jesse Keating 7a3296
@@ -661,13 +818,35 @@ int input_get_keycode(struct input_dev *dev,
Jesse Keating 7a3296
 		      unsigned int scancode, unsigned int *keycode)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
 	unsigned long flags;
Jesse Keating 7a3296
-	int retval;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	spin_lock_irqsave(&dev->event_lock, flags);
Jesse Keating 7a3296
-	retval = dev->getkeycode(dev, scancode, keycode);
Jesse Keating 7a3296
-	spin_unlock_irqrestore(&dev->event_lock, flags);
Jesse Keating 7a3296
+	if (dev->getkeycode) {
Jesse Keating 7a3296
+		/*
Jesse Keating 7a3296
+		 * Use the legacy calls
Jesse Keating 7a3296
+		 */
Jesse Keating 7a3296
+		return dev->getkeycode(dev, scancode, keycode);
Jesse Keating 7a3296
+	} else {
Jesse Keating 7a3296
+		int retval;
Jesse Keating 7a3296
+		struct keycode_table_entry kt_entry;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	return retval;
Jesse Keating 7a3296
+		/*
Jesse Keating 7a3296
+		 * Userspace is using a legacy call with a driver ported
Jesse Keating 7a3296
+		 * to the new way. This is a bad idea with long sparsed
Jesse Keating 7a3296
+		 * tables, since lots of the retrieved values will be in
Jesse Keating 7a3296
+		 * blank. Also, it makes sense only if the table size is
Jesse Keating 7a3296
+		 * lower than 2^32.
Jesse Keating 7a3296
+		 */
Jesse Keating 7a3296
+		memset(&kt_entry, 0, sizeof(kt_entry));
Jesse Keating 7a3296
+		kt_entry.len = 4;
Jesse Keating 7a3296
+		kt_entry.index = scancode;
Jesse Keating 7a3296
+		kt_entry.scancode = (char *)&scancode;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		spin_lock_irqsave(&dev->event_lock, flags);
Jesse Keating 7a3296
+		retval = dev->getkeycodebig_from_index(dev, &kt_entry);
Jesse Keating 7a3296
+		spin_unlock_irqrestore(&dev->event_lock, flags);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		*keycode = kt_entry.keycode;
Jesse Keating 7a3296
+		return retval;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 EXPORT_SYMBOL(input_get_keycode);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -692,13 +871,42 @@ int input_set_keycode(struct input_dev *dev,
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	spin_lock_irqsave(&dev->event_lock, flags);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	retval = dev->getkeycode(dev, scancode, &old_keycode);
Jesse Keating 7a3296
-	if (retval)
Jesse Keating 7a3296
-		goto out;
Jesse Keating 7a3296
+	if (dev->getkeycode) {
Jesse Keating 7a3296
+		/*
Jesse Keating 7a3296
+		 * Use the legacy calls
Jesse Keating 7a3296
+		 */
Jesse Keating 7a3296
+		retval = dev->getkeycode(dev, scancode, &old_keycode);
Jesse Keating 7a3296
+		if (retval)
Jesse Keating 7a3296
+			goto out;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	retval = dev->setkeycode(dev, scancode, keycode);
Jesse Keating 7a3296
-	if (retval)
Jesse Keating 7a3296
-		goto out;
Jesse Keating 7a3296
+		retval = dev->setkeycode(dev, scancode, keycode);
Jesse Keating 7a3296
+		if (retval)
Jesse Keating 7a3296
+			goto out;
Jesse Keating 7a3296
+	} else {
Jesse Keating 7a3296
+		struct keycode_table_entry kt_entry;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		/*
Jesse Keating 7a3296
+		 * Userspace is using a legacy call with a driver ported
Jesse Keating 7a3296
+		 * to the new way. This is a bad idea with long sparsed
Jesse Keating 7a3296
+		 * tables, since lots of the retrieved values will be in
Jesse Keating 7a3296
+		 * blank. Also, it makes sense only if the table size is
Jesse Keating 7a3296
+		 * lower than 2^32.
Jesse Keating 7a3296
+		 */
Jesse Keating 7a3296
+		memset(&kt_entry, 0, sizeof(kt_entry));
Jesse Keating 7a3296
+		kt_entry.len = 4;
Jesse Keating 7a3296
+		kt_entry.scancode = (char *)&scancode;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		retval = dev->getkeycodebig_from_scancode(dev, &kt_entry);
Jesse Keating 7a3296
+		if (retval)
Jesse Keating 7a3296
+			goto out;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		old_keycode = kt_entry.keycode;
Jesse Keating 7a3296
+		kt_entry.keycode = keycode;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		retval = dev->setkeycodebig(dev, &kt_entry);
Jesse Keating 7a3296
+		if (retval)
Jesse Keating 7a3296
+			goto out;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	/* Make sure KEY_RESERVED did not get enabled. */
Jesse Keating 7a3296
 	__clear_bit(KEY_RESERVED, dev->keybit);
Jesse Keating 7a3296
@@ -1636,11 +1843,17 @@ int input_register_device(struct input_dev *dev)
Jesse Keating 7a3296
 		dev->rep[REP_PERIOD] = 33;
Jesse Keating 7a3296
 	}
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	if (!dev->getkeycode)
Jesse Keating 7a3296
-		dev->getkeycode = input_default_getkeycode;
Jesse Keating 7a3296
+	if (!dev->getkeycode) {
Jesse Keating 7a3296
+		if (!dev->getkeycodebig_from_index)
Jesse Keating 7a3296
+			dev->getkeycodebig_from_index = input_default_getkeycode_from_index;
Jesse Keating 7a3296
+		if (!dev->getkeycodebig_from_scancode)
Jesse Keating 7a3296
+			dev->getkeycodebig_from_scancode = input_default_getkeycode_from_scancode;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	if (!dev->setkeycode)
Jesse Keating 7a3296
-		dev->setkeycode = input_default_setkeycode;
Jesse Keating 7a3296
+	if (!dev->setkeycode) {
Jesse Keating 7a3296
+		if (!dev->setkeycodebig)
Jesse Keating 7a3296
+			dev->setkeycodebig = input_default_setkeycode;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	dev_set_name(&dev->dev, "input%ld",
Jesse Keating 7a3296
 		     (unsigned long) atomic_inc_return(&input_no) - 1);
Jesse Keating 7a3296
diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig
Jesse Keating 7a3296
index d22a8ec..e557ae0 100644
Jesse Keating 7a3296
--- a/drivers/media/IR/Kconfig
Jesse Keating 7a3296
+++ b/drivers/media/IR/Kconfig
Jesse Keating 7a3296
@@ -8,6 +8,17 @@ config VIDEO_IR
Jesse Keating 7a3296
 	depends on IR_CORE
Jesse Keating 7a3296
 	default IR_CORE
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+config LIRC
Jesse Keating 7a3296
+	tristate
Jesse Keating 7a3296
+	default y
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	---help---
Jesse Keating 7a3296
+	   Enable this option to build the Linux Infrared Remote
Jesse Keating 7a3296
+	   Control (LIRC) core device interface driver. The LIRC
Jesse Keating 7a3296
+	   interface passes raw IR to and from userspace, where the
Jesse Keating 7a3296
+	   LIRC daemon handles protocol decoding for IR reception ann
Jesse Keating 7a3296
+	   encoding for IR transmitting (aka "blasting").
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 source "drivers/media/IR/keymaps/Kconfig"
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 config IR_NEC_DECODER
Jesse Keating 7a3296
@@ -42,6 +53,7 @@ config IR_RC6_DECODER
Jesse Keating 7a3296
 config IR_JVC_DECODER
Jesse Keating 7a3296
 	tristate "Enable IR raw decoder for the JVC protocol"
Jesse Keating 7a3296
 	depends on IR_CORE
Jesse Keating 7a3296
+	select BITREVERSE
Jesse Keating 7a3296
 	default y
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	---help---
Jesse Keating 7a3296
@@ -57,6 +69,16 @@ config IR_SONY_DECODER
Jesse Keating 7a3296
 	   Enable this option if you have an infrared remote control which
Jesse Keating 7a3296
 	   uses the Sony protocol, and you need software decoding support.
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+config IR_LIRC_CODEC
Jesse Keating 7a3296
+	tristate "Enable IR to LIRC bridge"
Jesse Keating 7a3296
+	depends on IR_CORE
Jesse Keating 7a3296
+	depends on LIRC
Jesse Keating 7a3296
+	default y
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	---help---
Jesse Keating 7a3296
+	   Enable this option to pass raw IR to and from userspace via
Jesse Keating 7a3296
+	   the LIRC interface.
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 config IR_IMON
Jesse Keating 7a3296
 	tristate "SoundGraph iMON Receiver and Display"
Jesse Keating 7a3296
 	depends on USB_ARCH_HAS_HCD
Jesse Keating 7a3296
@@ -68,3 +90,15 @@ config IR_IMON
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	   To compile this driver as a module, choose M here: the
Jesse Keating 7a3296
 	   module will be called imon.
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+config IR_MCEUSB
Jesse Keating 7a3296
+	tristate "Windows Media Center Ed. eHome Infrared Transceiver"
Jesse Keating 7a3296
+	depends on USB_ARCH_HAS_HCD
Jesse Keating 7a3296
+	depends on IR_CORE
Jesse Keating 7a3296
+	select USB
Jesse Keating 7a3296
+	---help---
Jesse Keating 7a3296
+	   Say Y here if you want to use a Windows Media Center Edition
Jesse Keating 7a3296
+	   eHome Infrared Transceiver.
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	   To compile this driver as a module, choose M here: the
Jesse Keating 7a3296
+	   module will be called mceusb.
Jesse Keating 7a3296
diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile
Jesse Keating 7a3296
index b998fcc..2ae4f3a 100644
Jesse Keating 7a3296
--- a/drivers/media/IR/Makefile
Jesse Keating 7a3296
+++ b/drivers/media/IR/Makefile
Jesse Keating 7a3296
@@ -5,11 +5,14 @@ obj-y += keymaps/
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 obj-$(CONFIG_IR_CORE) += ir-core.o
Jesse Keating 7a3296
 obj-$(CONFIG_VIDEO_IR) += ir-common.o
Jesse Keating 7a3296
+obj-$(CONFIG_LIRC) += lirc_dev.o
Jesse Keating 7a3296
 obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
Jesse Keating 7a3296
 obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
Jesse Keating 7a3296
 obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
Jesse Keating 7a3296
 obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
Jesse Keating 7a3296
 obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
Jesse Keating 7a3296
+obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 # stand-alone IR receivers/transmitters
Jesse Keating 7a3296
 obj-$(CONFIG_IR_IMON) += imon.o
Jesse Keating 7a3296
+obj-$(CONFIG_IR_MCEUSB) += mceusb.o
Jesse Keating 7a3296
diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c
Jesse Keating 7a3296
index 4bbd45f..0195dd5 100644
Jesse Keating 7a3296
--- a/drivers/media/IR/imon.c
Jesse Keating 7a3296
+++ b/drivers/media/IR/imon.c
Jesse Keating 7a3296
@@ -1943,7 +1943,7 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
Jesse Keating 7a3296
 	return ictx;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 urb_submit_failed:
Jesse Keating 7a3296
-	input_unregister_device(ictx->idev);
Jesse Keating 7a3296
+	ir_input_unregister(ictx->idev);
Jesse Keating 7a3296
 	input_free_device(ictx->idev);
Jesse Keating 7a3296
 idev_setup_failed:
Jesse Keating 7a3296
 find_endpoint_failed:
Jesse Keating 7a3296
@@ -2067,6 +2067,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
Jesse Keating 7a3296
 		detected_display_type = IMON_DISPLAY_TYPE_VFD;
Jesse Keating 7a3296
 		break;
Jesse Keating 7a3296
 	/* iMON LCD, MCE IR */
Jesse Keating 7a3296
+	case 0x9e:
Jesse Keating 7a3296
 	case 0x9f:
Jesse Keating 7a3296
 		dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
Jesse Keating 7a3296
 		detected_display_type = IMON_DISPLAY_TYPE_LCD;
Jesse Keating 7a3296
@@ -2306,7 +2307,7 @@ static void __devexit imon_disconnect(struct usb_interface *interface)
Jesse Keating 7a3296
 	if (ifnum == 0) {
Jesse Keating 7a3296
 		ictx->dev_present_intf0 = false;
Jesse Keating 7a3296
 		usb_kill_urb(ictx->rx_urb_intf0);
Jesse Keating 7a3296
-		input_unregister_device(ictx->idev);
Jesse Keating 7a3296
+		ir_input_unregister(ictx->idev);
Jesse Keating 7a3296
 		if (ictx->display_supported) {
Jesse Keating 7a3296
 			if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
Jesse Keating 7a3296
 				usb_deregister_dev(interface, &imon_lcd_class);
Jesse Keating 7a3296
diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h
Jesse Keating 7a3296
index 9a5e65a..babd520 100644
Jesse Keating 7a3296
--- a/drivers/media/IR/ir-core-priv.h
Jesse Keating 7a3296
+++ b/drivers/media/IR/ir-core-priv.h
Jesse Keating 7a3296
@@ -22,17 +22,62 @@
Jesse Keating 7a3296
 struct ir_raw_handler {
Jesse Keating 7a3296
 	struct list_head list;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+	u64 protocols; /* which are handled by this handler */
Jesse Keating 7a3296
 	int (*decode)(struct input_dev *input_dev, struct ir_raw_event event);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	/* These two should only be used by the lirc decoder */
Jesse Keating 7a3296
 	int (*raw_register)(struct input_dev *input_dev);
Jesse Keating 7a3296
 	int (*raw_unregister)(struct input_dev *input_dev);
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 struct ir_raw_event_ctrl {
Jesse Keating 7a3296
+	struct list_head		list;		/* to keep track of raw clients */
Jesse Keating 7a3296
 	struct work_struct		rx_work;	/* for the rx decoding workqueue */
Jesse Keating 7a3296
 	struct kfifo			kfifo;		/* fifo for the pulse/space durations */
Jesse Keating 7a3296
 	ktime_t				last_event;	/* when last event occurred */
Jesse Keating 7a3296
 	enum raw_event_type		last_type;	/* last event type */
Jesse Keating 7a3296
 	struct input_dev		*input_dev;	/* pointer to the parent input_dev */
Jesse Keating 7a3296
+	u64				enabled_protocols; /* enabled raw protocol decoders */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	/* raw decoder state follows */
Jesse Keating 7a3296
+	struct ir_raw_event prev_ev;
Jesse Keating 7a3296
+	struct nec_dec {
Jesse Keating 7a3296
+		int state;
Jesse Keating 7a3296
+		unsigned count;
Jesse Keating 7a3296
+		u32 bits;
Jesse Keating 7a3296
+	} nec;
Jesse Keating 7a3296
+	struct rc5_dec {
Jesse Keating 7a3296
+		int state;
Jesse Keating 7a3296
+		u32 bits;
Jesse Keating 7a3296
+		unsigned count;
Jesse Keating 7a3296
+		unsigned wanted_bits;
Jesse Keating 7a3296
+	} rc5;
Jesse Keating 7a3296
+	struct rc6_dec {
Jesse Keating 7a3296
+		int state;
Jesse Keating 7a3296
+		u8 header;
Jesse Keating 7a3296
+		u32 body;
Jesse Keating 7a3296
+		bool toggle;
Jesse Keating 7a3296
+		unsigned count;
Jesse Keating 7a3296
+		unsigned wanted_bits;
Jesse Keating 7a3296
+	} rc6;
Jesse Keating 7a3296
+	struct sony_dec {
Jesse Keating 7a3296
+		int state;
Jesse Keating 7a3296
+		u32 bits;
Jesse Keating 7a3296
+		unsigned count;
Jesse Keating 7a3296
+	} sony;
Jesse Keating 7a3296
+	struct jvc_dec {
Jesse Keating 7a3296
+		int state;
Jesse Keating 7a3296
+		u16 bits;
Jesse Keating 7a3296
+		u16 old_bits;
Jesse Keating 7a3296
+		unsigned count;
Jesse Keating 7a3296
+		bool first;
Jesse Keating 7a3296
+		bool toggle;
Jesse Keating 7a3296
+	} jvc;
Jesse Keating 7a3296
+	struct lirc_codec {
Jesse Keating 7a3296
+		struct ir_input_dev *ir_dev;
Jesse Keating 7a3296
+		struct lirc_driver *drv;
Jesse Keating 7a3296
+		int lircdata;
Jesse Keating 7a3296
+	} lirc;
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 /* macros for IR decoders */
Jesse Keating 7a3296
@@ -74,6 +119,7 @@ void ir_unregister_class(struct input_dev *input_dev);
Jesse Keating 7a3296
 /*
Jesse Keating 7a3296
  * Routines from ir-raw-event.c to be used internally and by decoders
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
+u64 ir_raw_get_allowed_protocols(void);
Jesse Keating 7a3296
 int ir_raw_event_register(struct input_dev *input_dev);
Jesse Keating 7a3296
 void ir_raw_event_unregister(struct input_dev *input_dev);
Jesse Keating 7a3296
 int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
Jesse Keating 7a3296
@@ -123,4 +169,12 @@ void ir_raw_init(void);
Jesse Keating 7a3296
 #define load_sony_decode()	0
Jesse Keating 7a3296
 #endif
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+/* from ir-lirc-codec.c */
Jesse Keating 7a3296
+#ifdef CONFIG_IR_LIRC_CODEC_MODULE
Jesse Keating 7a3296
+#define load_lirc_codec()	request_module("ir-lirc-codec")
Jesse Keating 7a3296
+#else
Jesse Keating 7a3296
+#define load_lirc_codec()	0
Jesse Keating 7a3296
+#endif
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 #endif /* _IR_RAW_EVENT */
Jesse Keating 7a3296
diff --git a/drivers/media/IR/ir-jvc-decoder.c b/drivers/media/IR/ir-jvc-decoder.c
Jesse Keating 7a3296
index 0b80494..8894d8b 100644
Jesse Keating 7a3296
--- a/drivers/media/IR/ir-jvc-decoder.c
Jesse Keating 7a3296
+++ b/drivers/media/IR/ir-jvc-decoder.c
Jesse Keating 7a3296
@@ -25,10 +25,6 @@
Jesse Keating 7a3296
 #define JVC_TRAILER_PULSE	(1  * JVC_UNIT)
Jesse Keating 7a3296
 #define	JVC_TRAILER_SPACE	(35 * JVC_UNIT)
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-/* Used to register jvc_decoder clients */
Jesse Keating 7a3296
-static LIST_HEAD(decoder_list);
Jesse Keating 7a3296
-DEFINE_SPINLOCK(decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 enum jvc_state {
Jesse Keating 7a3296
 	STATE_INACTIVE,
Jesse Keating 7a3296
 	STATE_HEADER_SPACE,
Jesse Keating 7a3296
@@ -38,87 +34,6 @@ enum jvc_state {
Jesse Keating 7a3296
 	STATE_TRAILER_SPACE,
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-struct decoder_data {
Jesse Keating 7a3296
-	struct list_head	list;
Jesse Keating 7a3296
-	struct ir_input_dev	*ir_dev;
Jesse Keating 7a3296
-	int			enabled:1;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	/* State machine control */
Jesse Keating 7a3296
-	enum jvc_state		state;
Jesse Keating 7a3296
-	u16			jvc_bits;
Jesse Keating 7a3296
-	u16			jvc_old_bits;
Jesse Keating 7a3296
-	unsigned		count;
Jesse Keating 7a3296
-	bool			first;
Jesse Keating 7a3296
-	bool			toggle;
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-/**
Jesse Keating 7a3296
- * get_decoder_data()	- gets decoder data
Jesse Keating 7a3296
- * @input_dev:	input device
Jesse Keating 7a3296
- *
Jesse Keating 7a3296
- * Returns the struct decoder_data that corresponds to a device
Jesse Keating 7a3296
- */
Jesse Keating 7a3296
-static struct decoder_data *get_decoder_data(struct  ir_input_dev *ir_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct decoder_data *data = NULL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_for_each_entry(data, &decoder_list, list) {
Jesse Keating 7a3296
-		if (data->ir_dev == ir_dev)
Jesse Keating 7a3296
-			break;
Jesse Keating 7a3296
-	}
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-	return data;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static ssize_t store_enabled(struct device *d,
Jesse Keating 7a3296
-			     struct device_attribute *mattr,
Jesse Keating 7a3296
-			     const char *buf,
Jesse Keating 7a3296
-			     size_t len)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	unsigned long value;
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
Jesse Keating 7a3296
-	struct decoder_data *data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (strict_strtoul(buf, 10, &value) || value > 1)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data->enabled = value;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return len;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static ssize_t show_enabled(struct device *d,
Jesse Keating 7a3296
-			     struct device_attribute *mattr, char *buf)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
Jesse Keating 7a3296
-	struct decoder_data *data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (data->enabled)
Jesse Keating 7a3296
-		return sprintf(buf, "1\n");
Jesse Keating 7a3296
-	else
Jesse Keating 7a3296
-	return sprintf(buf, "0\n");
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static struct attribute *decoder_attributes[] = {
Jesse Keating 7a3296
-	&dev_attr_enabled.attr,
Jesse Keating 7a3296
-	NULL
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static struct attribute_group decoder_attribute_group = {
Jesse Keating 7a3296
-	.name	= "jvc_decoder",
Jesse Keating 7a3296
-	.attrs	= decoder_attributes,
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 /**
Jesse Keating 7a3296
  * ir_jvc_decode() - Decode one JVC pulse or space
Jesse Keating 7a3296
  * @input_dev:	the struct input_dev descriptor of the device
Jesse Keating 7a3296
@@ -128,14 +43,10 @@ static struct attribute_group decoder_attribute_group = {
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
-	struct decoder_data *data;
Jesse Keating 7a3296
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
+	struct jvc_dec *data = &ir_dev->raw->jvc;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data->enabled)
Jesse Keating 7a3296
+	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC))
Jesse Keating 7a3296
 		return 0;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	if (IS_RESET(ev)) {
Jesse Keating 7a3296
@@ -188,9 +99,9 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
Jesse Keating 7a3296
 		if (ev.pulse)
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-		data->jvc_bits <<= 1;
Jesse Keating 7a3296
+		data->bits <<= 1;
Jesse Keating 7a3296
 		if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) {
Jesse Keating 7a3296
-			data->jvc_bits |= 1;
Jesse Keating 7a3296
+			data->bits |= 1;
Jesse Keating 7a3296
 			decrease_duration(&ev, JVC_BIT_1_SPACE);
Jesse Keating 7a3296
 		} else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2))
Jesse Keating 7a3296
 			decrease_duration(&ev, JVC_BIT_0_SPACE);
Jesse Keating 7a3296
@@ -223,13 +134,13 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 		if (data->first) {
Jesse Keating 7a3296
 			u32 scancode;
Jesse Keating 7a3296
-			scancode = (bitrev8((data->jvc_bits >> 8) & 0xff) << 8) |
Jesse Keating 7a3296
-				   (bitrev8((data->jvc_bits >> 0) & 0xff) << 0);
Jesse Keating 7a3296
+			scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) |
Jesse Keating 7a3296
+				   (bitrev8((data->bits >> 0) & 0xff) << 0);
Jesse Keating 7a3296
 			IR_dprintk(1, "JVC scancode 0x%04x\n", scancode);
Jesse Keating 7a3296
 			ir_keydown(input_dev, scancode, data->toggle);
Jesse Keating 7a3296
 			data->first = false;
Jesse Keating 7a3296
-			data->jvc_old_bits = data->jvc_bits;
Jesse Keating 7a3296
-		} else if (data->jvc_bits == data->jvc_old_bits) {
Jesse Keating 7a3296
+			data->old_bits = data->bits;
Jesse Keating 7a3296
+		} else if (data->bits == data->old_bits) {
Jesse Keating 7a3296
 			IR_dprintk(1, "JVC repeat\n");
Jesse Keating 7a3296
 			ir_repeat(input_dev);
Jesse Keating 7a3296
 		} else {
Jesse Keating 7a3296
@@ -249,54 +160,9 @@ out:
Jesse Keating 7a3296
 	return -EINVAL;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-static int ir_jvc_register(struct input_dev *input_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
-	struct decoder_data *data;
Jesse Keating 7a3296
-	int rc;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-	if (rc < 0)
Jesse Keating 7a3296
-		return rc;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
Jesse Keating 7a3296
-	if (!data) {
Jesse Keating 7a3296
-		sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-		return -ENOMEM;
Jesse Keating 7a3296
-	}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data->ir_dev = ir_dev;
Jesse Keating 7a3296
-	data->enabled = 1;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_add_tail(&data->list, &decoder_list);
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return 0;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static int ir_jvc_unregister(struct input_dev *input_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
-	static struct decoder_data *data;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return 0;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_del(&data->list);
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return 0;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 static struct ir_raw_handler jvc_handler = {
Jesse Keating 7a3296
+	.protocols	= IR_TYPE_JVC,
Jesse Keating 7a3296
 	.decode		= ir_jvc_decode,
Jesse Keating 7a3296
-	.raw_register	= ir_jvc_register,
Jesse Keating 7a3296
-	.raw_unregister	= ir_jvc_unregister,
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 static int __init ir_jvc_decode_init(void)
Jesse Keating 7a3296
diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c
Jesse Keating 7a3296
new file mode 100644
Jesse Keating 7a3296
index 0000000..afb1ada
Jesse Keating 7a3296
--- /dev/null
Jesse Keating 7a3296
+++ b/drivers/media/IR/ir-lirc-codec.c
Jesse Keating 7a3296
@@ -0,0 +1,283 @@
Jesse Keating 7a3296
+/* ir-lirc-codec.c - ir-core to classic lirc interface bridge
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This program is free software; you can redistribute it and/or modify
Jesse Keating 7a3296
+ *  it under the terms of the GNU General Public License as published by
Jesse Keating 7a3296
+ *  the Free Software Foundation version 2 of the License.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ *  This program is distributed in the hope that it will be useful,
Jesse Keating 7a3296
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Jesse Keating 7a3296
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Jesse Keating 7a3296
+ *  GNU General Public License for more details.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#include <linux sched.h="">
Jesse Keating 7a3296
+#include <linux wait.h="">
Jesse Keating 7a3296
+#include <media lirc.h="">
Jesse Keating 7a3296
+#include <media lirc_dev.h="">
Jesse Keating 7a3296
+#include <media ir-core.h="">
Jesse Keating 7a3296
+#include "ir-core-priv.h"
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#define LIRCBUF_SIZE 256
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the
Jesse Keating 7a3296
+ *		      lircd userspace daemon for decoding.
Jesse Keating 7a3296
+ * @input_dev:	the struct input_dev descriptor of the device
Jesse Keating 7a3296
+ * @duration:	the struct ir_raw_event descriptor of the pulse/space
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This function returns -EINVAL if the lirc interfaces aren't wired up.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
Jesse Keating 7a3296
+		return 0;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
Jesse Keating 7a3296
+		return -EINVAL;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
Jesse Keating 7a3296
+		   TO_US(ev.duration), TO_STR(ev.pulse));
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ir_dev->raw->lirc.lircdata += ev.duration / 1000;
Jesse Keating 7a3296
+	if (ev.pulse)
Jesse Keating 7a3296
+		ir_dev->raw->lirc.lircdata |= PULSE_BIT;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
Jesse Keating 7a3296
+			  (unsigned char *) &ir_dev->raw->lirc.lircdata);
Jesse Keating 7a3296
+	wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ir_dev->raw->lirc.lircdata = 0;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return 0;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,
Jesse Keating 7a3296
+				   size_t n, loff_t *ppos)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct lirc_codec *lirc;
Jesse Keating 7a3296
+	struct ir_input_dev *ir_dev;
Jesse Keating 7a3296
+	int *txbuf; /* buffer with values to transmit */
Jesse Keating 7a3296
+	int ret = 0, count;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	lirc = lirc_get_pdata(file);
Jesse Keating 7a3296
+	if (!lirc)
Jesse Keating 7a3296
+		return -EFAULT;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (n % sizeof(int))
Jesse Keating 7a3296
+		return -EINVAL;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	count = n / sizeof(int);
Jesse Keating 7a3296
+	if (count > LIRCBUF_SIZE || count % 2 == 0)
Jesse Keating 7a3296
+		return -EINVAL;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	txbuf = kzalloc(sizeof(int) * LIRCBUF_SIZE, GFP_KERNEL);
Jesse Keating 7a3296
+	if (!txbuf)
Jesse Keating 7a3296
+		return -ENOMEM;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (copy_from_user(txbuf, buf, n)) {
Jesse Keating 7a3296
+		ret = -EFAULT;
Jesse Keating 7a3296
+		goto out;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ir_dev = lirc->ir_dev;
Jesse Keating 7a3296
+	if (!ir_dev) {
Jesse Keating 7a3296
+		ret = -EFAULT;
Jesse Keating 7a3296
+		goto out;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (ir_dev->props && ir_dev->props->tx_ir)
Jesse Keating 7a3296
+		ret = ir_dev->props->tx_ir(ir_dev->props->priv, txbuf, (u32)n);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+out:
Jesse Keating 7a3296
+	kfree(txbuf);
Jesse Keating 7a3296
+	return ret;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct lirc_codec *lirc;
Jesse Keating 7a3296
+	struct ir_input_dev *ir_dev;
Jesse Keating 7a3296
+	int ret = 0;
Jesse Keating 7a3296
+	void *drv_data;
Jesse Keating 7a3296
+	unsigned long val;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	lirc = lirc_get_pdata(filep);
Jesse Keating 7a3296
+	if (!lirc)
Jesse Keating 7a3296
+		return -EFAULT;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ir_dev = lirc->ir_dev;
Jesse Keating 7a3296
+	if (!ir_dev || !ir_dev->props || !ir_dev->props->priv)
Jesse Keating 7a3296
+		return -EFAULT;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	drv_data = ir_dev->props->priv;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	switch (cmd) {
Jesse Keating 7a3296
+	case LIRC_SET_TRANSMITTER_MASK:
Jesse Keating 7a3296
+		ret = get_user(val, (unsigned long *)arg);
Jesse Keating 7a3296
+		if (ret)
Jesse Keating 7a3296
+			return ret;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (ir_dev->props && ir_dev->props->s_tx_mask)
Jesse Keating 7a3296
+			ret = ir_dev->props->s_tx_mask(drv_data, (u32)val);
Jesse Keating 7a3296
+		else
Jesse Keating 7a3296
+			return -EINVAL;
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case LIRC_SET_SEND_CARRIER:
Jesse Keating 7a3296
+		ret = get_user(val, (unsigned long *)arg);
Jesse Keating 7a3296
+		if (ret)
Jesse Keating 7a3296
+			return ret;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (ir_dev->props && ir_dev->props->s_tx_carrier)
Jesse Keating 7a3296
+			ir_dev->props->s_tx_carrier(drv_data, (u32)val);
Jesse Keating 7a3296
+		else
Jesse Keating 7a3296
+			return -EINVAL;
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case LIRC_GET_SEND_MODE:
Jesse Keating 7a3296
+		val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
Jesse Keating 7a3296
+		ret = put_user(val, (unsigned long *)arg);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case LIRC_SET_SEND_MODE:
Jesse Keating 7a3296
+		ret = get_user(val, (unsigned long *)arg);
Jesse Keating 7a3296
+		if (ret)
Jesse Keating 7a3296
+			return ret;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
Jesse Keating 7a3296
+			return -EINVAL;
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	default:
Jesse Keating 7a3296
+		return lirc_dev_fop_ioctl(filep, cmd, arg);
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return ret;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static int ir_lirc_open(void *data)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	return 0;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static void ir_lirc_close(void *data)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	return;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static struct file_operations lirc_fops = {
Jesse Keating 7a3296
+	.owner		= THIS_MODULE,
Jesse Keating 7a3296
+	.write		= ir_lirc_transmit_ir,
Jesse Keating 7a3296
+	.unlocked_ioctl	= ir_lirc_ioctl,
Jesse Keating 7a3296
+	.read		= lirc_dev_fop_read,
Jesse Keating 7a3296
+	.poll		= lirc_dev_fop_poll,
Jesse Keating 7a3296
+	.open		= lirc_dev_fop_open,
Jesse Keating 7a3296
+	.release	= lirc_dev_fop_close,
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static int ir_lirc_register(struct input_dev *input_dev)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
+	struct lirc_driver *drv;
Jesse Keating 7a3296
+	struct lirc_buffer *rbuf;
Jesse Keating 7a3296
+	int rc = -ENOMEM;
Jesse Keating 7a3296
+	unsigned long features;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
Jesse Keating 7a3296
+	if (!drv)
Jesse Keating 7a3296
+		return rc;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
Jesse Keating 7a3296
+	if (!drv)
Jesse Keating 7a3296
+		goto rbuf_alloc_failed;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE);
Jesse Keating 7a3296
+	if (rc)
Jesse Keating 7a3296
+		goto rbuf_init_failed;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	features = LIRC_CAN_REC_MODE2;
Jesse Keating 7a3296
+	if (ir_dev->props->tx_ir) {
Jesse Keating 7a3296
+		features |= LIRC_CAN_SEND_PULSE;
Jesse Keating 7a3296
+		if (ir_dev->props->s_tx_mask)
Jesse Keating 7a3296
+			features |= LIRC_CAN_SET_TRANSMITTER_MASK;
Jesse Keating 7a3296
+		if (ir_dev->props->s_tx_carrier)
Jesse Keating 7a3296
+			features |= LIRC_CAN_SET_SEND_CARRIER;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
Jesse Keating 7a3296
+		 ir_dev->driver_name);
Jesse Keating 7a3296
+	drv->minor = -1;
Jesse Keating 7a3296
+	drv->features = features;
Jesse Keating 7a3296
+	drv->data = &ir_dev->raw->lirc;
Jesse Keating 7a3296
+	drv->rbuf = rbuf;
Jesse Keating 7a3296
+	drv->set_use_inc = &ir_lirc_open;
Jesse Keating 7a3296
+	drv->set_use_dec = &ir_lirc_close;
Jesse Keating 7a3296
+	drv->code_length = sizeof(struct ir_raw_event) * 8;
Jesse Keating 7a3296
+	drv->fops = &lirc_fops;
Jesse Keating 7a3296
+	drv->dev = &ir_dev->dev;
Jesse Keating 7a3296
+	drv->owner = THIS_MODULE;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	drv->minor = lirc_register_driver(drv);
Jesse Keating 7a3296
+	if (drv->minor < 0) {
Jesse Keating 7a3296
+		rc = -ENODEV;
Jesse Keating 7a3296
+		goto lirc_register_failed;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ir_dev->raw->lirc.drv = drv;
Jesse Keating 7a3296
+	ir_dev->raw->lirc.ir_dev = ir_dev;
Jesse Keating 7a3296
+	ir_dev->raw->lirc.lircdata = PULSE_MASK;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return 0;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+lirc_register_failed:
Jesse Keating 7a3296
+rbuf_init_failed:
Jesse Keating 7a3296
+	kfree(rbuf);
Jesse Keating 7a3296
+rbuf_alloc_failed:
Jesse Keating 7a3296
+	kfree(drv);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return rc;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static int ir_lirc_unregister(struct input_dev *input_dev)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
+	struct lirc_codec *lirc = &ir_dev->raw->lirc;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	lirc_unregister_driver(lirc->drv->minor);
Jesse Keating 7a3296
+	lirc_buffer_free(lirc->drv->rbuf);
Jesse Keating 7a3296
+	kfree(lirc->drv);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return 0;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static struct ir_raw_handler lirc_handler = {
Jesse Keating 7a3296
+	.protocols	= IR_TYPE_LIRC,
Jesse Keating 7a3296
+	.decode		= ir_lirc_decode,
Jesse Keating 7a3296
+	.raw_register	= ir_lirc_register,
Jesse Keating 7a3296
+	.raw_unregister	= ir_lirc_unregister,
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static int __init ir_lirc_codec_init(void)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	ir_raw_handler_register(&lirc_handler);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	printk(KERN_INFO "IR LIRC bridge handler initialized\n");
Jesse Keating 7a3296
+	return 0;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static void __exit ir_lirc_codec_exit(void)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	ir_raw_handler_unregister(&lirc_handler);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+module_init(ir_lirc_codec_init);
Jesse Keating 7a3296
+module_exit(ir_lirc_codec_exit);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+MODULE_LICENSE("GPL");
Jesse Keating 7a3296
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
Jesse Keating 7a3296
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
Jesse Keating 7a3296
+MODULE_DESCRIPTION("LIRC IR handler bridge");
Jesse Keating 7a3296
diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c
Jesse Keating 7a3296
index ba79233..52e0f37 100644
Jesse Keating 7a3296
--- a/drivers/media/IR/ir-nec-decoder.c
Jesse Keating 7a3296
+++ b/drivers/media/IR/ir-nec-decoder.c
Jesse Keating 7a3296
@@ -27,10 +27,6 @@
Jesse Keating 7a3296
 #define	NEC_TRAILER_PULSE	(1  * NEC_UNIT)
Jesse Keating 7a3296
 #define	NEC_TRAILER_SPACE	(10 * NEC_UNIT) /* even longer in reality */
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-/* Used to register nec_decoder clients */
Jesse Keating 7a3296
-static LIST_HEAD(decoder_list);
Jesse Keating 7a3296
-static DEFINE_SPINLOCK(decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 enum nec_state {
Jesse Keating 7a3296
 	STATE_INACTIVE,
Jesse Keating 7a3296
 	STATE_HEADER_SPACE,
Jesse Keating 7a3296
@@ -40,84 +36,6 @@ enum nec_state {
Jesse Keating 7a3296
 	STATE_TRAILER_SPACE,
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-struct decoder_data {
Jesse Keating 7a3296
-	struct list_head	list;
Jesse Keating 7a3296
-	struct ir_input_dev	*ir_dev;
Jesse Keating 7a3296
-	int			enabled:1;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	/* State machine control */
Jesse Keating 7a3296
-	enum nec_state		state;
Jesse Keating 7a3296
-	u32			nec_bits;
Jesse Keating 7a3296
-	unsigned		count;
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-/**
Jesse Keating 7a3296
- * get_decoder_data()	- gets decoder data
Jesse Keating 7a3296
- * @input_dev:	input device
Jesse Keating 7a3296
- *
Jesse Keating 7a3296
- * Returns the struct decoder_data that corresponds to a device
Jesse Keating 7a3296
- */
Jesse Keating 7a3296
-static struct decoder_data *get_decoder_data(struct  ir_input_dev *ir_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct decoder_data *data = NULL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_for_each_entry(data, &decoder_list, list) {
Jesse Keating 7a3296
-		if (data->ir_dev == ir_dev)
Jesse Keating 7a3296
-			break;
Jesse Keating 7a3296
-	}
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-	return data;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static ssize_t store_enabled(struct device *d,
Jesse Keating 7a3296
-			     struct device_attribute *mattr,
Jesse Keating 7a3296
-			     const char *buf,
Jesse Keating 7a3296
-			     size_t len)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	unsigned long value;
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
Jesse Keating 7a3296
-	struct decoder_data *data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (strict_strtoul(buf, 10, &value) || value > 1)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data->enabled = value;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return len;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static ssize_t show_enabled(struct device *d,
Jesse Keating 7a3296
-			     struct device_attribute *mattr, char *buf)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
Jesse Keating 7a3296
-	struct decoder_data *data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (data->enabled)
Jesse Keating 7a3296
-		return sprintf(buf, "1\n");
Jesse Keating 7a3296
-	else
Jesse Keating 7a3296
-	return sprintf(buf, "0\n");
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static struct attribute *decoder_attributes[] = {
Jesse Keating 7a3296
-	&dev_attr_enabled.attr,
Jesse Keating 7a3296
-	NULL
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static struct attribute_group decoder_attribute_group = {
Jesse Keating 7a3296
-	.name	= "nec_decoder",
Jesse Keating 7a3296
-	.attrs	= decoder_attributes,
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 /**
Jesse Keating 7a3296
  * ir_nec_decode() - Decode one NEC pulse or space
Jesse Keating 7a3296
  * @input_dev:	the struct input_dev descriptor of the device
Jesse Keating 7a3296
@@ -127,16 +45,12 @@ static struct attribute_group decoder_attribute_group = {
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
-	struct decoder_data *data;
Jesse Keating 7a3296
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
+	struct nec_dec *data = &ir_dev->raw->nec;
Jesse Keating 7a3296
 	u32 scancode;
Jesse Keating 7a3296
 	u8 address, not_address, command, not_command;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data->enabled)
Jesse Keating 7a3296
+	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC))
Jesse Keating 7a3296
 		return 0;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	if (IS_RESET(ev)) {
Jesse Keating 7a3296
@@ -191,9 +105,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
Jesse Keating 7a3296
 		if (ev.pulse)
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-		data->nec_bits <<= 1;
Jesse Keating 7a3296
+		data->bits <<= 1;
Jesse Keating 7a3296
 		if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
Jesse Keating 7a3296
-			data->nec_bits |= 1;
Jesse Keating 7a3296
+			data->bits |= 1;
Jesse Keating 7a3296
 		else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 		data->count++;
Jesse Keating 7a3296
@@ -222,14 +136,14 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
Jesse Keating 7a3296
 		if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-		address     = bitrev8((data->nec_bits >> 24) & 0xff);
Jesse Keating 7a3296
-		not_address = bitrev8((data->nec_bits >> 16) & 0xff);
Jesse Keating 7a3296
-		command	    = bitrev8((data->nec_bits >>  8) & 0xff);
Jesse Keating 7a3296
-		not_command = bitrev8((data->nec_bits >>  0) & 0xff);
Jesse Keating 7a3296
+		address     = bitrev8((data->bits >> 24) & 0xff);
Jesse Keating 7a3296
+		not_address = bitrev8((data->bits >> 16) & 0xff);
Jesse Keating 7a3296
+		command	    = bitrev8((data->bits >>  8) & 0xff);
Jesse Keating 7a3296
+		not_command = bitrev8((data->bits >>  0) & 0xff);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 		if ((command ^ not_command) != 0xff) {
Jesse Keating 7a3296
 			IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
Jesse Keating 7a3296
-				   data->nec_bits);
Jesse Keating 7a3296
+				   data->bits);
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 		}
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -256,54 +170,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
Jesse Keating 7a3296
 	return -EINVAL;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-static int ir_nec_register(struct input_dev *input_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
-	struct decoder_data *data;
Jesse Keating 7a3296
-	int rc;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-	if (rc < 0)
Jesse Keating 7a3296
-		return rc;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
Jesse Keating 7a3296
-	if (!data) {
Jesse Keating 7a3296
-		sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-		return -ENOMEM;
Jesse Keating 7a3296
-	}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data->ir_dev = ir_dev;
Jesse Keating 7a3296
-	data->enabled = 1;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_add_tail(&data->list, &decoder_list);
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return 0;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static int ir_nec_unregister(struct input_dev *input_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
-	static struct decoder_data *data;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return 0;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_del(&data->list);
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return 0;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 static struct ir_raw_handler nec_handler = {
Jesse Keating 7a3296
+	.protocols	= IR_TYPE_NEC,
Jesse Keating 7a3296
 	.decode		= ir_nec_decode,
Jesse Keating 7a3296
-	.raw_register	= ir_nec_register,
Jesse Keating 7a3296
-	.raw_unregister	= ir_nec_unregister,
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 static int __init ir_nec_decode_init(void)
Jesse Keating 7a3296
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
Jesse Keating 7a3296
index ea68a3f..6f192ef 100644
Jesse Keating 7a3296
--- a/drivers/media/IR/ir-raw-event.c
Jesse Keating 7a3296
+++ b/drivers/media/IR/ir-raw-event.c
Jesse Keating 7a3296
@@ -20,35 +20,13 @@
Jesse Keating 7a3296
 /* Define the max number of pulse/space transitions to buffer */
Jesse Keating 7a3296
 #define MAX_IR_EVENT_SIZE      512
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
Jesse Keating 7a3296
+static LIST_HEAD(ir_raw_client_list);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 /* Used to handle IR raw handler extensions */
Jesse Keating 7a3296
-static LIST_HEAD(ir_raw_handler_list);
Jesse Keating 7a3296
 static DEFINE_SPINLOCK(ir_raw_handler_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-/**
Jesse Keating 7a3296
- * RUN_DECODER()	- runs an operation on all IR decoders
Jesse Keating 7a3296
- * @ops:	IR raw handler operation to be called
Jesse Keating 7a3296
- * @arg:	arguments to be passed to the callback
Jesse Keating 7a3296
- *
Jesse Keating 7a3296
- * Calls ir_raw_handler::ops for all registered IR handlers. It prevents
Jesse Keating 7a3296
- * new decode addition/removal while running, by locking ir_raw_handler_lock
Jesse Keating 7a3296
- * mutex. If an error occurs, it stops the ops. Otherwise, it returns a sum
Jesse Keating 7a3296
- * of the return codes.
Jesse Keating 7a3296
- */
Jesse Keating 7a3296
-#define RUN_DECODER(ops, ...) ({					    \
Jesse Keating 7a3296
-	struct ir_raw_handler		*_ir_raw_handler;		    \
Jesse Keating 7a3296
-	int _sumrc = 0, _rc;						    \
Jesse Keating 7a3296
-	spin_lock(&ir_raw_handler_lock);				    \
Jesse Keating 7a3296
-	list_for_each_entry(_ir_raw_handler, &ir_raw_handler_list, list) {  \
Jesse Keating 7a3296
-		if (_ir_raw_handler->ops) {				    \
Jesse Keating 7a3296
-			_rc = _ir_raw_handler->ops(__VA_ARGS__);	    \
Jesse Keating 7a3296
-			if (_rc < 0)					    \
Jesse Keating 7a3296
-				break;					    \
Jesse Keating 7a3296
-			_sumrc += _rc;					    \
Jesse Keating 7a3296
-		}							    \
Jesse Keating 7a3296
-	}								    \
Jesse Keating 7a3296
-	spin_unlock(&ir_raw_handler_lock);				    \
Jesse Keating 7a3296
-	_sumrc;								    \
Jesse Keating 7a3296
-})
Jesse Keating 7a3296
+static LIST_HEAD(ir_raw_handler_list);
Jesse Keating 7a3296
+static u64 available_protocols;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 #ifdef MODULE
Jesse Keating 7a3296
 /* Used to load the decoders */
Jesse Keating 7a3296
@@ -58,57 +36,17 @@ static struct work_struct wq_load;
Jesse Keating 7a3296
 static void ir_raw_event_work(struct work_struct *work)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
 	struct ir_raw_event ev;
Jesse Keating 7a3296
+	struct ir_raw_handler *handler;
Jesse Keating 7a3296
 	struct ir_raw_event_ctrl *raw =
Jesse Keating 7a3296
 		container_of(work, struct ir_raw_event_ctrl, rx_work);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev))
Jesse Keating 7a3296
-		RUN_DECODER(decode, raw->input_dev, ev);
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-int ir_raw_event_register(struct input_dev *input_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir = input_get_drvdata(input_dev);
Jesse Keating 7a3296
-	int rc;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
Jesse Keating 7a3296
-	if (!ir->raw)
Jesse Keating 7a3296
-		return -ENOMEM;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	ir->raw->input_dev = input_dev;
Jesse Keating 7a3296
-	INIT_WORK(&ir->raw->rx_work, ir_raw_event_work);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
Jesse Keating 7a3296
-			 GFP_KERNEL);
Jesse Keating 7a3296
-	if (rc < 0) {
Jesse Keating 7a3296
-		kfree(ir->raw);
Jesse Keating 7a3296
-		ir->raw = NULL;
Jesse Keating 7a3296
-		return rc;
Jesse Keating 7a3296
-	}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	rc = RUN_DECODER(raw_register, input_dev);
Jesse Keating 7a3296
-	if (rc < 0) {
Jesse Keating 7a3296
-		kfifo_free(&ir->raw->kfifo);
Jesse Keating 7a3296
-		kfree(ir->raw);
Jesse Keating 7a3296
-		ir->raw = NULL;
Jesse Keating 7a3296
-		return rc;
Jesse Keating 7a3296
+	while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
Jesse Keating 7a3296
+		spin_lock(&ir_raw_handler_lock);
Jesse Keating 7a3296
+		list_for_each_entry(handler, &ir_raw_handler_list, list)
Jesse Keating 7a3296
+			handler->decode(raw->input_dev, ev);
Jesse Keating 7a3296
+		spin_unlock(&ir_raw_handler_lock);
Jesse Keating 7a3296
+		raw->prev_ev = ev;
Jesse Keating 7a3296
 	}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return rc;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-void ir_raw_event_unregister(struct input_dev *input_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir = input_get_drvdata(input_dev);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!ir->raw)
Jesse Keating 7a3296
-		return;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	cancel_work_sync(&ir->raw->rx_work);
Jesse Keating 7a3296
-	RUN_DECODER(raw_unregister, input_dev);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	kfifo_free(&ir->raw->kfifo);
Jesse Keating 7a3296
-	kfree(ir->raw);
Jesse Keating 7a3296
-	ir->raw = NULL;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 /**
Jesse Keating 7a3296
@@ -204,23 +142,103 @@ void ir_raw_event_handle(struct input_dev *input_dev)
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 EXPORT_SYMBOL_GPL(ir_raw_event_handle);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+/* used internally by the sysfs interface */
Jesse Keating 7a3296
+u64
Jesse Keating 7a3296
+ir_raw_get_allowed_protocols()
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	u64 protocols;
Jesse Keating 7a3296
+	spin_lock(&ir_raw_handler_lock);
Jesse Keating 7a3296
+	protocols = available_protocols;
Jesse Keating 7a3296
+	spin_unlock(&ir_raw_handler_lock);
Jesse Keating 7a3296
+	return protocols;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * Used to (un)register raw event clients
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+int ir_raw_event_register(struct input_dev *input_dev)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ir_input_dev *ir = input_get_drvdata(input_dev);
Jesse Keating 7a3296
+	int rc;
Jesse Keating 7a3296
+	struct ir_raw_handler *handler;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
Jesse Keating 7a3296
+	if (!ir->raw)
Jesse Keating 7a3296
+		return -ENOMEM;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ir->raw->input_dev = input_dev;
Jesse Keating 7a3296
+	INIT_WORK(&ir->raw->rx_work, ir_raw_event_work);
Jesse Keating 7a3296
+	ir->raw->enabled_protocols = ~0;
Jesse Keating 7a3296
+	rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
Jesse Keating 7a3296
+			 GFP_KERNEL);
Jesse Keating 7a3296
+	if (rc < 0) {
Jesse Keating 7a3296
+		kfree(ir->raw);
Jesse Keating 7a3296
+		ir->raw = NULL;
Jesse Keating 7a3296
+		return rc;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	spin_lock(&ir_raw_handler_lock);
Jesse Keating 7a3296
+	list_add_tail(&ir->raw->list, &ir_raw_client_list);
Jesse Keating 7a3296
+	list_for_each_entry(handler, &ir_raw_handler_list, list)
Jesse Keating 7a3296
+		if (handler->raw_register)
Jesse Keating 7a3296
+			handler->raw_register(ir->raw->input_dev);
Jesse Keating 7a3296
+	spin_unlock(&ir_raw_handler_lock);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return 0;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+void ir_raw_event_unregister(struct input_dev *input_dev)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ir_input_dev *ir = input_get_drvdata(input_dev);
Jesse Keating 7a3296
+	struct ir_raw_handler *handler;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (!ir->raw)
Jesse Keating 7a3296
+		return;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	cancel_work_sync(&ir->raw->rx_work);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	spin_lock(&ir_raw_handler_lock);
Jesse Keating 7a3296
+	list_del(&ir->raw->list);
Jesse Keating 7a3296
+	list_for_each_entry(handler, &ir_raw_handler_list, list)
Jesse Keating 7a3296
+		if (handler->raw_unregister)
Jesse Keating 7a3296
+			handler->raw_unregister(ir->raw->input_dev);
Jesse Keating 7a3296
+	spin_unlock(&ir_raw_handler_lock);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	kfifo_free(&ir->raw->kfifo);
Jesse Keating 7a3296
+	kfree(ir->raw);
Jesse Keating 7a3296
+	ir->raw = NULL;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 /*
Jesse Keating 7a3296
  * Extension interface - used to register the IR decoders
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	struct ir_raw_event_ctrl *raw;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 	spin_lock(&ir_raw_handler_lock);
Jesse Keating 7a3296
 	list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
Jesse Keating 7a3296
+	if (ir_raw_handler->raw_register)
Jesse Keating 7a3296
+		list_for_each_entry(raw, &ir_raw_client_list, list)
Jesse Keating 7a3296
+			ir_raw_handler->raw_register(raw->input_dev);
Jesse Keating 7a3296
+	available_protocols |= ir_raw_handler->protocols;
Jesse Keating 7a3296
 	spin_unlock(&ir_raw_handler_lock);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 	return 0;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 EXPORT_SYMBOL(ir_raw_handler_register);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	struct ir_raw_event_ctrl *raw;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 	spin_lock(&ir_raw_handler_lock);
Jesse Keating 7a3296
 	list_del(&ir_raw_handler->list);
Jesse Keating 7a3296
+	if (ir_raw_handler->raw_unregister)
Jesse Keating 7a3296
+		list_for_each_entry(raw, &ir_raw_client_list, list)
Jesse Keating 7a3296
+			ir_raw_handler->raw_unregister(raw->input_dev);
Jesse Keating 7a3296
+	available_protocols &= ~ir_raw_handler->protocols;
Jesse Keating 7a3296
 	spin_unlock(&ir_raw_handler_lock);
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 EXPORT_SYMBOL(ir_raw_handler_unregister);
Jesse Keating 7a3296
@@ -235,6 +253,7 @@ static void init_decoders(struct work_struct *work)
Jesse Keating 7a3296
 	load_rc6_decode();
Jesse Keating 7a3296
 	load_jvc_decode();
Jesse Keating 7a3296
 	load_sony_decode();
Jesse Keating 7a3296
+	load_lirc_codec();
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	/* If needed, we may later add some init code. In this case,
Jesse Keating 7a3296
 	   it is needed to change the CONFIG_MODULE test at ir-core.h
Jesse Keating 7a3296
diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c
Jesse Keating 7a3296
index 23cdb1b..df4770d 100644
Jesse Keating 7a3296
--- a/drivers/media/IR/ir-rc5-decoder.c
Jesse Keating 7a3296
+++ b/drivers/media/IR/ir-rc5-decoder.c
Jesse Keating 7a3296
@@ -30,10 +30,6 @@
Jesse Keating 7a3296
 #define RC5_BIT_END		(1 * RC5_UNIT)
Jesse Keating 7a3296
 #define RC5X_SPACE		(4 * RC5_UNIT)
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-/* Used to register rc5_decoder clients */
Jesse Keating 7a3296
-static LIST_HEAD(decoder_list);
Jesse Keating 7a3296
-static DEFINE_SPINLOCK(decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 enum rc5_state {
Jesse Keating 7a3296
 	STATE_INACTIVE,
Jesse Keating 7a3296
 	STATE_BIT_START,
Jesse Keating 7a3296
@@ -42,87 +38,6 @@ enum rc5_state {
Jesse Keating 7a3296
 	STATE_FINISHED,
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-struct decoder_data {
Jesse Keating 7a3296
-	struct list_head	list;
Jesse Keating 7a3296
-	struct ir_input_dev	*ir_dev;
Jesse Keating 7a3296
-	int			enabled:1;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	/* State machine control */
Jesse Keating 7a3296
-	enum rc5_state		state;
Jesse Keating 7a3296
-	u32			rc5_bits;
Jesse Keating 7a3296
-	struct ir_raw_event	prev_ev;
Jesse Keating 7a3296
-	unsigned		count;
Jesse Keating 7a3296
-	unsigned		wanted_bits;
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-/**
Jesse Keating 7a3296
- * get_decoder_data()	- gets decoder data
Jesse Keating 7a3296
- * @input_dev:	input device
Jesse Keating 7a3296
- *
Jesse Keating 7a3296
- * Returns the struct decoder_data that corresponds to a device
Jesse Keating 7a3296
- */
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static struct decoder_data *get_decoder_data(struct  ir_input_dev *ir_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct decoder_data *data = NULL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_for_each_entry(data, &decoder_list, list) {
Jesse Keating 7a3296
-		if (data->ir_dev == ir_dev)
Jesse Keating 7a3296
-			break;
Jesse Keating 7a3296
-	}
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-	return data;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static ssize_t store_enabled(struct device *d,
Jesse Keating 7a3296
-			     struct device_attribute *mattr,
Jesse Keating 7a3296
-			     const char *buf,
Jesse Keating 7a3296
-			     size_t len)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	unsigned long value;
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
Jesse Keating 7a3296
-	struct decoder_data *data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (strict_strtoul(buf, 10, &value) || value > 1)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data->enabled = value;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return len;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static ssize_t show_enabled(struct device *d,
Jesse Keating 7a3296
-			     struct device_attribute *mattr, char *buf)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
Jesse Keating 7a3296
-	struct decoder_data *data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (data->enabled)
Jesse Keating 7a3296
-		return sprintf(buf, "1\n");
Jesse Keating 7a3296
-	else
Jesse Keating 7a3296
-	return sprintf(buf, "0\n");
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static struct attribute *decoder_attributes[] = {
Jesse Keating 7a3296
-	&dev_attr_enabled.attr,
Jesse Keating 7a3296
-	NULL
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static struct attribute_group decoder_attribute_group = {
Jesse Keating 7a3296
-	.name	= "rc5_decoder",
Jesse Keating 7a3296
-	.attrs	= decoder_attributes,
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 /**
Jesse Keating 7a3296
  * ir_rc5_decode() - Decode one RC-5 pulse or space
Jesse Keating 7a3296
  * @input_dev:	the struct input_dev descriptor of the device
Jesse Keating 7a3296
@@ -132,17 +47,13 @@ static struct attribute_group decoder_attribute_group = {
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
-	struct decoder_data *data;
Jesse Keating 7a3296
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
+	struct rc5_dec *data = &ir_dev->raw->rc5;
Jesse Keating 7a3296
 	u8 toggle;
Jesse Keating 7a3296
 	u32 scancode;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data->enabled)
Jesse Keating 7a3296
-		return 0;
Jesse Keating 7a3296
+        if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5))
Jesse Keating 7a3296
+                return 0;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	if (IS_RESET(ev)) {
Jesse Keating 7a3296
 		data->state = STATE_INACTIVE;
Jesse Keating 7a3296
@@ -176,16 +87,15 @@ again:
Jesse Keating 7a3296
 		if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-		data->rc5_bits <<= 1;
Jesse Keating 7a3296
+		data->bits <<= 1;
Jesse Keating 7a3296
 		if (!ev.pulse)
Jesse Keating 7a3296
-			data->rc5_bits |= 1;
Jesse Keating 7a3296
+			data->bits |= 1;
Jesse Keating 7a3296
 		data->count++;
Jesse Keating 7a3296
-		data->prev_ev = ev;
Jesse Keating 7a3296
 		data->state = STATE_BIT_END;
Jesse Keating 7a3296
 		return 0;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	case STATE_BIT_END:
Jesse Keating 7a3296
-		if (!is_transition(&ev, &data->prev_ev))
Jesse Keating 7a3296
+		if (!is_transition(&ev, &ir_dev->raw->prev_ev))
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 		if (data->count == data->wanted_bits)
Jesse Keating 7a3296
@@ -217,11 +127,11 @@ again:
Jesse Keating 7a3296
 		if (data->wanted_bits == RC5X_NBITS) {
Jesse Keating 7a3296
 			/* RC5X */
Jesse Keating 7a3296
 			u8 xdata, command, system;
Jesse Keating 7a3296
-			xdata    = (data->rc5_bits & 0x0003F) >> 0;
Jesse Keating 7a3296
-			command  = (data->rc5_bits & 0x00FC0) >> 6;
Jesse Keating 7a3296
-			system   = (data->rc5_bits & 0x1F000) >> 12;
Jesse Keating 7a3296
-			toggle   = (data->rc5_bits & 0x20000) ? 1 : 0;
Jesse Keating 7a3296
-			command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
Jesse Keating 7a3296
+			xdata    = (data->bits & 0x0003F) >> 0;
Jesse Keating 7a3296
+			command  = (data->bits & 0x00FC0) >> 6;
Jesse Keating 7a3296
+			system   = (data->bits & 0x1F000) >> 12;
Jesse Keating 7a3296
+			toggle   = (data->bits & 0x20000) ? 1 : 0;
Jesse Keating 7a3296
+			command += (data->bits & 0x01000) ? 0 : 0x40;
Jesse Keating 7a3296
 			scancode = system << 16 | command << 8 | xdata;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 			IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
Jesse Keating 7a3296
@@ -230,10 +140,10 @@ again:
Jesse Keating 7a3296
 		} else {
Jesse Keating 7a3296
 			/* RC5 */
Jesse Keating 7a3296
 			u8 command, system;
Jesse Keating 7a3296
-			command  = (data->rc5_bits & 0x0003F) >> 0;
Jesse Keating 7a3296
-			system   = (data->rc5_bits & 0x007C0) >> 6;
Jesse Keating 7a3296
-			toggle   = (data->rc5_bits & 0x00800) ? 1 : 0;
Jesse Keating 7a3296
-			command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
Jesse Keating 7a3296
+			command  = (data->bits & 0x0003F) >> 0;
Jesse Keating 7a3296
+			system   = (data->bits & 0x007C0) >> 6;
Jesse Keating 7a3296
+			toggle   = (data->bits & 0x00800) ? 1 : 0;
Jesse Keating 7a3296
+			command += (data->bits & 0x01000) ? 0 : 0x40;
Jesse Keating 7a3296
 			scancode = system << 8 | command;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 			IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
Jesse Keating 7a3296
@@ -252,54 +162,9 @@ out:
Jesse Keating 7a3296
 	return -EINVAL;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-static int ir_rc5_register(struct input_dev *input_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
-	struct decoder_data *data;
Jesse Keating 7a3296
-	int rc;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-	if (rc < 0)
Jesse Keating 7a3296
-		return rc;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
Jesse Keating 7a3296
-	if (!data) {
Jesse Keating 7a3296
-		sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-		return -ENOMEM;
Jesse Keating 7a3296
-	}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data->ir_dev = ir_dev;
Jesse Keating 7a3296
-	data->enabled = 1;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_add_tail(&data->list, &decoder_list);
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return 0;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static int ir_rc5_unregister(struct input_dev *input_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
-	static struct decoder_data *data;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return 0;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_del(&data->list);
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return 0;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 static struct ir_raw_handler rc5_handler = {
Jesse Keating 7a3296
+	.protocols	= IR_TYPE_RC5,
Jesse Keating 7a3296
 	.decode		= ir_rc5_decode,
Jesse Keating 7a3296
-	.raw_register	= ir_rc5_register,
Jesse Keating 7a3296
-	.raw_unregister	= ir_rc5_unregister,
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 static int __init ir_rc5_decode_init(void)
Jesse Keating 7a3296
diff --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c
Jesse Keating 7a3296
index 2bf479f..f1624b8 100644
Jesse Keating 7a3296
--- a/drivers/media/IR/ir-rc6-decoder.c
Jesse Keating 7a3296
+++ b/drivers/media/IR/ir-rc6-decoder.c
Jesse Keating 7a3296
@@ -36,10 +36,6 @@
Jesse Keating 7a3296
 #define RC6_STARTBIT_MASK	0x08	/* for the header bits */
Jesse Keating 7a3296
 #define RC6_6A_MCE_TOGGLE_MASK	0x8000	/* for the body bits */
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-/* Used to register rc6_decoder clients */
Jesse Keating 7a3296
-static LIST_HEAD(decoder_list);
Jesse Keating 7a3296
-static DEFINE_SPINLOCK(decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 enum rc6_mode {
Jesse Keating 7a3296
 	RC6_MODE_0,
Jesse Keating 7a3296
 	RC6_MODE_6A,
Jesse Keating 7a3296
@@ -58,89 +54,8 @@ enum rc6_state {
Jesse Keating 7a3296
 	STATE_FINISHED,
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-struct decoder_data {
Jesse Keating 7a3296
-	struct list_head	list;
Jesse Keating 7a3296
-	struct ir_input_dev	*ir_dev;
Jesse Keating 7a3296
-	int			enabled:1;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	/* State machine control */
Jesse Keating 7a3296
-	enum rc6_state		state;
Jesse Keating 7a3296
-	u8			header;
Jesse Keating 7a3296
-	u32			body;
Jesse Keating 7a3296
-	struct ir_raw_event	prev_ev;
Jesse Keating 7a3296
-	bool			toggle;
Jesse Keating 7a3296
-	unsigned		count;
Jesse Keating 7a3296
-	unsigned		wanted_bits;
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-/**
Jesse Keating 7a3296
- * get_decoder_data()	- gets decoder data
Jesse Keating 7a3296
- * @input_dev:	input device
Jesse Keating 7a3296
- *
Jesse Keating 7a3296
- * Returns the struct decoder_data that corresponds to a device
Jesse Keating 7a3296
- */
Jesse Keating 7a3296
-static struct decoder_data *get_decoder_data(struct  ir_input_dev *ir_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct decoder_data *data = NULL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_for_each_entry(data, &decoder_list, list) {
Jesse Keating 7a3296
-		if (data->ir_dev == ir_dev)
Jesse Keating 7a3296
-			break;
Jesse Keating 7a3296
-	}
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-	return data;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static ssize_t store_enabled(struct device *d,
Jesse Keating 7a3296
-			     struct device_attribute *mattr,
Jesse Keating 7a3296
-			     const char *buf,
Jesse Keating 7a3296
-			     size_t len)
Jesse Keating 7a3296
+static enum rc6_mode rc6_mode(struct rc6_dec *data)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
-	unsigned long value;
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
Jesse Keating 7a3296
-	struct decoder_data *data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (strict_strtoul(buf, 10, &value) || value > 1)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data->enabled = value;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return len;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static ssize_t show_enabled(struct device *d,
Jesse Keating 7a3296
-			     struct device_attribute *mattr, char *buf)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
Jesse Keating 7a3296
-	struct decoder_data *data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (data->enabled)
Jesse Keating 7a3296
-		return sprintf(buf, "1\n");
Jesse Keating 7a3296
-	else
Jesse Keating 7a3296
-	return sprintf(buf, "0\n");
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static struct attribute *decoder_attributes[] = {
Jesse Keating 7a3296
-	&dev_attr_enabled.attr,
Jesse Keating 7a3296
-	NULL
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static struct attribute_group decoder_attribute_group = {
Jesse Keating 7a3296
-	.name	= "rc6_decoder",
Jesse Keating 7a3296
-	.attrs	= decoder_attributes,
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static enum rc6_mode rc6_mode(struct decoder_data *data) {
Jesse Keating 7a3296
 	switch (data->header & RC6_MODE_MASK) {
Jesse Keating 7a3296
 	case 0:
Jesse Keating 7a3296
 		return RC6_MODE_0;
Jesse Keating 7a3296
@@ -162,16 +77,12 @@ static enum rc6_mode rc6_mode(struct decoder_data *data) {
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
-	struct decoder_data *data;
Jesse Keating 7a3296
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
+	struct rc6_dec *data = &ir_dev->raw->rc6;
Jesse Keating 7a3296
 	u32 scancode;
Jesse Keating 7a3296
 	u8 toggle;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data->enabled)
Jesse Keating 7a3296
+	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
Jesse Keating 7a3296
 		return 0;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	if (IS_RESET(ev)) {
Jesse Keating 7a3296
@@ -223,12 +134,11 @@ again:
Jesse Keating 7a3296
 		if (ev.pulse)
Jesse Keating 7a3296
 			data->header |= 1;
Jesse Keating 7a3296
 		data->count++;
Jesse Keating 7a3296
-		data->prev_ev = ev;
Jesse Keating 7a3296
 		data->state = STATE_HEADER_BIT_END;
Jesse Keating 7a3296
 		return 0;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	case STATE_HEADER_BIT_END:
Jesse Keating 7a3296
-		if (!is_transition(&ev, &data->prev_ev))
Jesse Keating 7a3296
+		if (!is_transition(&ev, &ir_dev->raw->prev_ev))
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 		if (data->count == RC6_HEADER_NBITS)
Jesse Keating 7a3296
@@ -244,12 +154,11 @@ again:
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 		data->toggle = ev.pulse;
Jesse Keating 7a3296
-		data->prev_ev = ev;
Jesse Keating 7a3296
 		data->state = STATE_TOGGLE_END;
Jesse Keating 7a3296
 		return 0;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	case STATE_TOGGLE_END:
Jesse Keating 7a3296
-		if (!is_transition(&ev, &data->prev_ev) ||
Jesse Keating 7a3296
+		if (!is_transition(&ev, &ir_dev->raw->prev_ev) ||
Jesse Keating 7a3296
 		    !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -259,7 +168,6 @@ again:
Jesse Keating 7a3296
 		}
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 		data->state = STATE_BODY_BIT_START;
Jesse Keating 7a3296
-		data->prev_ev = ev;
Jesse Keating 7a3296
 		decrease_duration(&ev, RC6_TOGGLE_END);
Jesse Keating 7a3296
 		data->count = 0;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -291,13 +199,11 @@ again:
Jesse Keating 7a3296
 		if (ev.pulse)
Jesse Keating 7a3296
 			data->body |= 1;
Jesse Keating 7a3296
 		data->count++;
Jesse Keating 7a3296
-		data->prev_ev = ev;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 		data->state = STATE_BODY_BIT_END;
Jesse Keating 7a3296
 		return 0;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	case STATE_BODY_BIT_END:
Jesse Keating 7a3296
-		if (!is_transition(&ev, &data->prev_ev))
Jesse Keating 7a3296
+		if (!is_transition(&ev, &ir_dev->raw->prev_ev))
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 		if (data->count == data->wanted_bits)
Jesse Keating 7a3296
@@ -348,54 +254,9 @@ out:
Jesse Keating 7a3296
 	return -EINVAL;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-static int ir_rc6_register(struct input_dev *input_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
-	struct decoder_data *data;
Jesse Keating 7a3296
-	int rc;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-	if (rc < 0)
Jesse Keating 7a3296
-		return rc;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
Jesse Keating 7a3296
-	if (!data) {
Jesse Keating 7a3296
-		sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-		return -ENOMEM;
Jesse Keating 7a3296
-	}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data->ir_dev = ir_dev;
Jesse Keating 7a3296
-	data->enabled = 1;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_add_tail(&data->list, &decoder_list);
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return 0;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static int ir_rc6_unregister(struct input_dev *input_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
-	static struct decoder_data *data;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return 0;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_del(&data->list);
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return 0;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 static struct ir_raw_handler rc6_handler = {
Jesse Keating 7a3296
+	.protocols	= IR_TYPE_RC6,
Jesse Keating 7a3296
 	.decode		= ir_rc6_decode,
Jesse Keating 7a3296
-	.raw_register	= ir_rc6_register,
Jesse Keating 7a3296
-	.raw_unregister	= ir_rc6_unregister,
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 static int __init ir_rc6_decode_init(void)
Jesse Keating 7a3296
diff --git a/drivers/media/IR/ir-sony-decoder.c b/drivers/media/IR/ir-sony-decoder.c
Jesse Keating 7a3296
index 9f440c5..b9074f0 100644
Jesse Keating 7a3296
--- a/drivers/media/IR/ir-sony-decoder.c
Jesse Keating 7a3296
+++ b/drivers/media/IR/ir-sony-decoder.c
Jesse Keating 7a3296
@@ -23,10 +23,6 @@
Jesse Keating 7a3296
 #define SONY_BIT_SPACE		(1 * SONY_UNIT)
Jesse Keating 7a3296
 #define SONY_TRAILER_SPACE	(10 * SONY_UNIT) /* minimum */
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-/* Used to register sony_decoder clients */
Jesse Keating 7a3296
-static LIST_HEAD(decoder_list);
Jesse Keating 7a3296
-static DEFINE_SPINLOCK(decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 enum sony_state {
Jesse Keating 7a3296
 	STATE_INACTIVE,
Jesse Keating 7a3296
 	STATE_HEADER_SPACE,
Jesse Keating 7a3296
@@ -35,84 +31,6 @@ enum sony_state {
Jesse Keating 7a3296
 	STATE_FINISHED,
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-struct decoder_data {
Jesse Keating 7a3296
-	struct list_head	list;
Jesse Keating 7a3296
-	struct ir_input_dev	*ir_dev;
Jesse Keating 7a3296
-	int			enabled:1;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	/* State machine control */
Jesse Keating 7a3296
-	enum sony_state		state;
Jesse Keating 7a3296
-	u32			sony_bits;
Jesse Keating 7a3296
-	unsigned		count;
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-/**
Jesse Keating 7a3296
- * get_decoder_data()	- gets decoder data
Jesse Keating 7a3296
- * @input_dev:	input device
Jesse Keating 7a3296
- *
Jesse Keating 7a3296
- * Returns the struct decoder_data that corresponds to a device
Jesse Keating 7a3296
- */
Jesse Keating 7a3296
-static struct decoder_data *get_decoder_data(struct  ir_input_dev *ir_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct decoder_data *data = NULL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_for_each_entry(data, &decoder_list, list) {
Jesse Keating 7a3296
-		if (data->ir_dev == ir_dev)
Jesse Keating 7a3296
-			break;
Jesse Keating 7a3296
-	}
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-	return data;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static ssize_t store_enabled(struct device *d,
Jesse Keating 7a3296
-			     struct device_attribute *mattr,
Jesse Keating 7a3296
-			     const char *buf,
Jesse Keating 7a3296
-			     size_t len)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	unsigned long value;
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
Jesse Keating 7a3296
-	struct decoder_data *data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (strict_strtoul(buf, 10, &value) || value > 1)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data->enabled = value;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return len;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static ssize_t show_enabled(struct device *d,
Jesse Keating 7a3296
-			     struct device_attribute *mattr, char *buf)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
Jesse Keating 7a3296
-	struct decoder_data *data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (data->enabled)
Jesse Keating 7a3296
-		return sprintf(buf, "1\n");
Jesse Keating 7a3296
-	else
Jesse Keating 7a3296
-	return sprintf(buf, "0\n");
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static struct attribute *decoder_attributes[] = {
Jesse Keating 7a3296
-	&dev_attr_enabled.attr,
Jesse Keating 7a3296
-	NULL
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static struct attribute_group decoder_attribute_group = {
Jesse Keating 7a3296
-	.name	= "sony_decoder",
Jesse Keating 7a3296
-	.attrs	= decoder_attributes,
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 /**
Jesse Keating 7a3296
  * ir_sony_decode() - Decode one Sony pulse or space
Jesse Keating 7a3296
  * @input_dev:	the struct input_dev descriptor of the device
Jesse Keating 7a3296
@@ -122,16 +40,12 @@ static struct attribute_group decoder_attribute_group = {
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
-	struct decoder_data *data;
Jesse Keating 7a3296
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
+	struct sony_dec *data = &ir_dev->raw->sony;
Jesse Keating 7a3296
 	u32 scancode;
Jesse Keating 7a3296
 	u8 device, subdevice, function;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return -EINVAL;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (!data->enabled)
Jesse Keating 7a3296
+	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
Jesse Keating 7a3296
 		return 0;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	if (IS_RESET(ev)) {
Jesse Keating 7a3296
@@ -172,9 +86,9 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
Jesse Keating 7a3296
 		if (!ev.pulse)
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-		data->sony_bits <<= 1;
Jesse Keating 7a3296
+		data->bits <<= 1;
Jesse Keating 7a3296
 		if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2))
Jesse Keating 7a3296
-			data->sony_bits |= 1;
Jesse Keating 7a3296
+			data->bits |= 1;
Jesse Keating 7a3296
 		else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2))
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -208,19 +122,19 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 		switch (data->count) {
Jesse Keating 7a3296
 		case 12:
Jesse Keating 7a3296
-			device    = bitrev8((data->sony_bits <<  3) & 0xF8);
Jesse Keating 7a3296
+			device    = bitrev8((data->bits <<  3) & 0xF8);
Jesse Keating 7a3296
 			subdevice = 0;
Jesse Keating 7a3296
-			function  = bitrev8((data->sony_bits >>  4) & 0xFE);
Jesse Keating 7a3296
+			function  = bitrev8((data->bits >>  4) & 0xFE);
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 		case 15:
Jesse Keating 7a3296
-			device    = bitrev8((data->sony_bits >>  0) & 0xFF);
Jesse Keating 7a3296
+			device    = bitrev8((data->bits >>  0) & 0xFF);
Jesse Keating 7a3296
 			subdevice = 0;
Jesse Keating 7a3296
-			function  = bitrev8((data->sony_bits >>  7) & 0xFD);
Jesse Keating 7a3296
+			function  = bitrev8((data->bits >>  7) & 0xFD);
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 		case 20:
Jesse Keating 7a3296
-			device    = bitrev8((data->sony_bits >>  5) & 0xF8);
Jesse Keating 7a3296
-			subdevice = bitrev8((data->sony_bits >>  0) & 0xFF);
Jesse Keating 7a3296
-			function  = bitrev8((data->sony_bits >> 12) & 0xFE);
Jesse Keating 7a3296
+			device    = bitrev8((data->bits >>  5) & 0xF8);
Jesse Keating 7a3296
+			subdevice = bitrev8((data->bits >>  0) & 0xFF);
Jesse Keating 7a3296
+			function  = bitrev8((data->bits >> 12) & 0xFE);
Jesse Keating 7a3296
 			break;
Jesse Keating 7a3296
 		default:
Jesse Keating 7a3296
 			IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
Jesse Keating 7a3296
@@ -241,54 +155,9 @@ out:
Jesse Keating 7a3296
 	return -EINVAL;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-static int ir_sony_register(struct input_dev *input_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
-	struct decoder_data *data;
Jesse Keating 7a3296
-	int rc;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-	if (rc < 0)
Jesse Keating 7a3296
-		return rc;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
Jesse Keating 7a3296
-	if (!data) {
Jesse Keating 7a3296
-		sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-		return -ENOMEM;
Jesse Keating 7a3296
-	}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data->ir_dev = ir_dev;
Jesse Keating 7a3296
-	data->enabled = 1;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_add_tail(&data->list, &decoder_list);
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return 0;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static int ir_sony_unregister(struct input_dev *input_dev)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
Jesse Keating 7a3296
-	static struct decoder_data *data;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	data = get_decoder_data(ir_dev);
Jesse Keating 7a3296
-	if (!data)
Jesse Keating 7a3296
-		return 0;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	spin_lock(&decoder_lock);
Jesse Keating 7a3296
-	list_del(&data->list);
Jesse Keating 7a3296
-	spin_unlock(&decoder_lock);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	return 0;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
-
Jesse Keating 7a3296
 static struct ir_raw_handler sony_handler = {
Jesse Keating 7a3296
+	.protocols	= IR_TYPE_SONY,
Jesse Keating 7a3296
 	.decode		= ir_sony_decode,
Jesse Keating 7a3296
-	.raw_register	= ir_sony_register,
Jesse Keating 7a3296
-	.raw_unregister	= ir_sony_unregister,
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 static int __init ir_sony_decode_init(void)
Jesse Keating 7a3296
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
Jesse Keating 7a3296
index 2098dd1..a841e51 100644
Jesse Keating 7a3296
--- a/drivers/media/IR/ir-sysfs.c
Jesse Keating 7a3296
+++ b/drivers/media/IR/ir-sysfs.c
Jesse Keating 7a3296
@@ -34,122 +34,186 @@ static struct class ir_input_class = {
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 /**
Jesse Keating 7a3296
- * show_protocol() - shows the current IR protocol
Jesse Keating 7a3296
+ * show_protocols() - shows the current IR protocol(s)
Jesse Keating 7a3296
  * @d:		the device descriptor
Jesse Keating 7a3296
  * @mattr:	the device attribute struct (unused)
Jesse Keating 7a3296
  * @buf:	a pointer to the output buffer
Jesse Keating 7a3296
  *
Jesse Keating 7a3296
- * This routine is a callback routine for input read the IR protocol type.
Jesse Keating 7a3296
- * it is trigged by reading /sys/class/rc/rc?/current_protocol.
Jesse Keating 7a3296
- * It returns the protocol name, as understood by the driver.
Jesse Keating 7a3296
+ * This routine is a callback routine for input read the IR protocol type(s).
Jesse Keating 7a3296
+ * it is trigged by reading /sys/class/rc/rc?/protocols.
Jesse Keating 7a3296
+ * It returns the protocol names of supported protocols.
Jesse Keating 7a3296
+ * Enabled protocols are printed in brackets.
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
-static ssize_t show_protocol(struct device *d,
Jesse Keating 7a3296
-			     struct device_attribute *mattr, char *buf)
Jesse Keating 7a3296
+static ssize_t show_protocols(struct device *d,
Jesse Keating 7a3296
+			      struct device_attribute *mattr, char *buf)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
-	char *s;
Jesse Keating 7a3296
 	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
Jesse Keating 7a3296
-	u64 ir_type = ir_dev->rc_tab.ir_type;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	IR_dprintk(1, "Current protocol is %lld\n", (long long)ir_type);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	/* FIXME: doesn't support multiple protocols at the same time */
Jesse Keating 7a3296
-	if (ir_type == IR_TYPE_UNKNOWN)
Jesse Keating 7a3296
-		s = "Unknown";
Jesse Keating 7a3296
-	else if (ir_type == IR_TYPE_RC5)
Jesse Keating 7a3296
-		s = "rc-5";
Jesse Keating 7a3296
-	else if (ir_type == IR_TYPE_NEC)
Jesse Keating 7a3296
-		s = "nec";
Jesse Keating 7a3296
-	else if (ir_type == IR_TYPE_RC6)
Jesse Keating 7a3296
-		s = "rc6";
Jesse Keating 7a3296
-	else if (ir_type == IR_TYPE_JVC)
Jesse Keating 7a3296
-		s = "jvc";
Jesse Keating 7a3296
-	else if (ir_type == IR_TYPE_SONY)
Jesse Keating 7a3296
-		s = "sony";
Jesse Keating 7a3296
-	else
Jesse Keating 7a3296
-		s = "other";
Jesse Keating 7a3296
+	u64 allowed, enabled;
Jesse Keating 7a3296
+	char *tmp = buf;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
Jesse Keating 7a3296
+		enabled = ir_dev->rc_tab.ir_type;
Jesse Keating 7a3296
+		allowed = ir_dev->props->allowed_protos;
Jesse Keating 7a3296
+	} else {
Jesse Keating 7a3296
+		enabled = ir_dev->raw->enabled_protocols;
Jesse Keating 7a3296
+		allowed = ir_raw_get_allowed_protocols();
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	return sprintf(buf, "%s\n", s);
Jesse Keating 7a3296
+	IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
Jesse Keating 7a3296
+		   (long long)allowed,
Jesse Keating 7a3296
+		   (long long)enabled);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (allowed & enabled & IR_TYPE_UNKNOWN)
Jesse Keating 7a3296
+		tmp += sprintf(tmp, "[unknown] ");
Jesse Keating 7a3296
+	else if (allowed & IR_TYPE_UNKNOWN)
Jesse Keating 7a3296
+		tmp += sprintf(tmp, "unknown ");
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (allowed & enabled & IR_TYPE_RC5)
Jesse Keating 7a3296
+		tmp += sprintf(tmp, "[rc5] ");
Jesse Keating 7a3296
+	else if (allowed & IR_TYPE_RC5)
Jesse Keating 7a3296
+		tmp += sprintf(tmp, "rc5 ");
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (allowed & enabled & IR_TYPE_NEC)
Jesse Keating 7a3296
+		tmp += sprintf(tmp, "[nec] ");
Jesse Keating 7a3296
+	else if (allowed & IR_TYPE_NEC)
Jesse Keating 7a3296
+		tmp += sprintf(tmp, "nec ");
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (allowed & enabled & IR_TYPE_RC6)
Jesse Keating 7a3296
+		tmp += sprintf(tmp, "[rc6] ");
Jesse Keating 7a3296
+	else if (allowed & IR_TYPE_RC6)
Jesse Keating 7a3296
+		tmp += sprintf(tmp, "rc6 ");
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (allowed & enabled & IR_TYPE_JVC)
Jesse Keating 7a3296
+		tmp += sprintf(tmp, "[jvc] ");
Jesse Keating 7a3296
+	else if (allowed & IR_TYPE_JVC)
Jesse Keating 7a3296
+		tmp += sprintf(tmp, "jvc ");
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (allowed & enabled & IR_TYPE_SONY)
Jesse Keating 7a3296
+		tmp += sprintf(tmp, "[sony] ");
Jesse Keating 7a3296
+	else if (allowed & IR_TYPE_SONY)
Jesse Keating 7a3296
+		tmp += sprintf(tmp, "sony ");
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (allowed & enabled & IR_TYPE_LIRC)
Jesse Keating 7a3296
+		tmp += sprintf(tmp, "[lirc] ");
Jesse Keating 7a3296
+	else if (allowed & IR_TYPE_LIRC)
Jesse Keating 7a3296
+		tmp += sprintf(tmp, "lirc ");
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (tmp != buf)
Jesse Keating 7a3296
+		tmp--;
Jesse Keating 7a3296
+	*tmp = '\n';
Jesse Keating 7a3296
+	return tmp + 1 - buf;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 /**
Jesse Keating 7a3296
- * store_protocol() - shows the current IR protocol
Jesse Keating 7a3296
+ * store_protocols() - changes the current IR protocol(s)
Jesse Keating 7a3296
  * @d:		the device descriptor
Jesse Keating 7a3296
  * @mattr:	the device attribute struct (unused)
Jesse Keating 7a3296
  * @buf:	a pointer to the input buffer
Jesse Keating 7a3296
  * @len:	length of the input buffer
Jesse Keating 7a3296
  *
Jesse Keating 7a3296
  * This routine is a callback routine for changing the IR protocol type.
Jesse Keating 7a3296
- * it is trigged by reading /sys/class/rc/rc?/current_protocol.
Jesse Keating 7a3296
- * It changes the IR the protocol name, if the IR type is recognized
Jesse Keating 7a3296
- * by the driver.
Jesse Keating 7a3296
- * If an unknown protocol name is used, returns -EINVAL.
Jesse Keating 7a3296
+ * It is trigged by writing to /sys/class/rc/rc?/protocols.
Jesse Keating 7a3296
+ * Writing "+proto" will add a protocol to the list of enabled protocols.
Jesse Keating 7a3296
+ * Writing "-proto" will remove a protocol from the list of enabled protocols.
Jesse Keating 7a3296
+ * Writing "proto" will enable only "proto".
Jesse Keating 7a3296
+ * Returns -EINVAL if an invalid protocol combination or unknown protocol name
Jesse Keating 7a3296
+ * is used, otherwise @len.
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
-static ssize_t store_protocol(struct device *d,
Jesse Keating 7a3296
-			      struct device_attribute *mattr,
Jesse Keating 7a3296
-			      const char *data,
Jesse Keating 7a3296
-			      size_t len)
Jesse Keating 7a3296
+static ssize_t store_protocols(struct device *d,
Jesse Keating 7a3296
+			       struct device_attribute *mattr,
Jesse Keating 7a3296
+			       const char *data,
Jesse Keating 7a3296
+			       size_t len)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
 	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
Jesse Keating 7a3296
-	u64 ir_type = 0;
Jesse Keating 7a3296
-	int rc = -EINVAL;
Jesse Keating 7a3296
+	bool enable, disable;
Jesse Keating 7a3296
+	const char *tmp;
Jesse Keating 7a3296
+	u64 type;
Jesse Keating 7a3296
+	u64 mask;
Jesse Keating 7a3296
+	int rc;
Jesse Keating 7a3296
 	unsigned long flags;
Jesse Keating 7a3296
-	char *buf;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	while ((buf = strsep((char **) &data, " \n")) != NULL) {
Jesse Keating 7a3296
-		if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5"))
Jesse Keating 7a3296
-			ir_type |= IR_TYPE_RC5;
Jesse Keating 7a3296
-		if (!strcasecmp(buf, "nec"))
Jesse Keating 7a3296
-			ir_type |= IR_TYPE_NEC;
Jesse Keating 7a3296
-		if (!strcasecmp(buf, "jvc"))
Jesse Keating 7a3296
-			ir_type |= IR_TYPE_JVC;
Jesse Keating 7a3296
-		if (!strcasecmp(buf, "sony"))
Jesse Keating 7a3296
-			ir_type |= IR_TYPE_SONY;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	tmp = skip_spaces(data);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (*tmp == '+') {
Jesse Keating 7a3296
+		enable = true;
Jesse Keating 7a3296
+		disable = false;
Jesse Keating 7a3296
+		tmp++;
Jesse Keating 7a3296
+	} else if (*tmp == '-') {
Jesse Keating 7a3296
+		enable = false;
Jesse Keating 7a3296
+		disable = true;
Jesse Keating 7a3296
+		tmp++;
Jesse Keating 7a3296
+	} else {
Jesse Keating 7a3296
+		enable = false;
Jesse Keating 7a3296
+		disable = false;
Jesse Keating 7a3296
 	}
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	if (!ir_type) {
Jesse Keating 7a3296
+	if (!strncasecmp(tmp, "unknown", 7)) {
Jesse Keating 7a3296
+		tmp += 7;
Jesse Keating 7a3296
+		mask = IR_TYPE_UNKNOWN;
Jesse Keating 7a3296
+	} else if (!strncasecmp(tmp, "rc5", 3)) {
Jesse Keating 7a3296
+		tmp += 3;
Jesse Keating 7a3296
+		mask = IR_TYPE_RC5;
Jesse Keating 7a3296
+	} else if (!strncasecmp(tmp, "nec", 3)) {
Jesse Keating 7a3296
+		tmp += 3;
Jesse Keating 7a3296
+		mask = IR_TYPE_NEC;
Jesse Keating 7a3296
+	} else if (!strncasecmp(tmp, "rc6", 3)) {
Jesse Keating 7a3296
+		tmp += 3;
Jesse Keating 7a3296
+		mask = IR_TYPE_RC6;
Jesse Keating 7a3296
+	} else if (!strncasecmp(tmp, "jvc", 3)) {
Jesse Keating 7a3296
+		tmp += 3;
Jesse Keating 7a3296
+		mask = IR_TYPE_JVC;
Jesse Keating 7a3296
+	} else if (!strncasecmp(tmp, "sony", 4)) {
Jesse Keating 7a3296
+		tmp += 4;
Jesse Keating 7a3296
+		mask = IR_TYPE_SONY;
Jesse Keating 7a3296
+	} else if (!strncasecmp(tmp, "lirc", 4)) {
Jesse Keating 7a3296
+		tmp += 4;
Jesse Keating 7a3296
+		mask = IR_TYPE_LIRC;
Jesse Keating 7a3296
+	} else {
Jesse Keating 7a3296
 		IR_dprintk(1, "Unknown protocol\n");
Jesse Keating 7a3296
 		return -EINVAL;
Jesse Keating 7a3296
 	}
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	if (ir_dev->props && ir_dev->props->change_protocol)
Jesse Keating 7a3296
-		rc = ir_dev->props->change_protocol(ir_dev->props->priv,
Jesse Keating 7a3296
-						    ir_type);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-	if (rc < 0) {
Jesse Keating 7a3296
-		IR_dprintk(1, "Error setting protocol to %lld\n",
Jesse Keating 7a3296
-			   (long long)ir_type);
Jesse Keating 7a3296
+	tmp = skip_spaces(tmp);
Jesse Keating 7a3296
+	if (*tmp != '\0') {
Jesse Keating 7a3296
+		IR_dprintk(1, "Invalid trailing characters\n");
Jesse Keating 7a3296
 		return -EINVAL;
Jesse Keating 7a3296
 	}
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
Jesse Keating 7a3296
-	ir_dev->rc_tab.ir_type = ir_type;
Jesse Keating 7a3296
-	spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
Jesse Keating 7a3296
+	if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
Jesse Keating 7a3296
+		type = ir_dev->rc_tab.ir_type;
Jesse Keating 7a3296
+	else
Jesse Keating 7a3296
+		type = ir_dev->raw->enabled_protocols;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	IR_dprintk(1, "Current protocol(s) is(are) %lld\n",
Jesse Keating 7a3296
-		   (long long)ir_type);
Jesse Keating 7a3296
+	if (enable)
Jesse Keating 7a3296
+		type |= mask;
Jesse Keating 7a3296
+	else if (disable)
Jesse Keating 7a3296
+		type &= ~mask;
Jesse Keating 7a3296
+	else
Jesse Keating 7a3296
+		type = mask;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	return len;
Jesse Keating 7a3296
-}
Jesse Keating 7a3296
+	if (ir_dev->props && ir_dev->props->change_protocol) {
Jesse Keating 7a3296
+		rc = ir_dev->props->change_protocol(ir_dev->props->priv,
Jesse Keating 7a3296
+						    type);
Jesse Keating 7a3296
+		if (rc < 0) {
Jesse Keating 7a3296
+			IR_dprintk(1, "Error setting protocols to 0x%llx\n",
Jesse Keating 7a3296
+				   (long long)type);
Jesse Keating 7a3296
+			return -EINVAL;
Jesse Keating 7a3296
+		}
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-static ssize_t show_supported_protocols(struct device *d,
Jesse Keating 7a3296
-			     struct device_attribute *mattr, char *buf)
Jesse Keating 7a3296
-{
Jesse Keating 7a3296
-	char *orgbuf = buf;
Jesse Keating 7a3296
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
Jesse Keating 7a3296
+	if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
Jesse Keating 7a3296
+		spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
Jesse Keating 7a3296
+		ir_dev->rc_tab.ir_type = type;
Jesse Keating 7a3296
+		spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
Jesse Keating 7a3296
+	} else {
Jesse Keating 7a3296
+		ir_dev->raw->enabled_protocols = type;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	/* FIXME: doesn't support multiple protocols at the same time */
Jesse Keating 7a3296
-	if (ir_dev->props->allowed_protos == IR_TYPE_UNKNOWN)
Jesse Keating 7a3296
-		buf += sprintf(buf, "unknown ");
Jesse Keating 7a3296
-	if (ir_dev->props->allowed_protos & IR_TYPE_RC5)
Jesse Keating 7a3296
-		buf += sprintf(buf, "rc-5 ");
Jesse Keating 7a3296
-	if (ir_dev->props->allowed_protos & IR_TYPE_NEC)
Jesse Keating 7a3296
-		buf += sprintf(buf, "nec ");
Jesse Keating 7a3296
-	if (buf == orgbuf)
Jesse Keating 7a3296
-		buf += sprintf(buf, "other ");
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	buf += sprintf(buf - 1, "\n");
Jesse Keating 7a3296
+	IR_dprintk(1, "Current protocol(s): 0x%llx\n",
Jesse Keating 7a3296
+		   (long long)type);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	return buf - orgbuf;
Jesse Keating 7a3296
+	return len;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 #define ADD_HOTPLUG_VAR(fmt, val...)					\
Jesse Keating 7a3296
@@ -159,7 +223,7 @@ static ssize_t show_supported_protocols(struct device *d,
Jesse Keating 7a3296
 			return err;					\
Jesse Keating 7a3296
 	} while (0)
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env)
Jesse Keating 7a3296
+static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
 	struct ir_input_dev *ir_dev = dev_get_drvdata(device);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -174,34 +238,26 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env)
Jesse Keating 7a3296
 /*
Jesse Keating 7a3296
  * Static device attribute struct with the sysfs attributes for IR's
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
-static DEVICE_ATTR(protocol, S_IRUGO | S_IWUSR,
Jesse Keating 7a3296
-		   show_protocol, store_protocol);
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static DEVICE_ATTR(supported_protocols, S_IRUGO | S_IWUSR,
Jesse Keating 7a3296
-		   show_supported_protocols, NULL);
Jesse Keating 7a3296
+static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR,
Jesse Keating 7a3296
+		   show_protocols, store_protocols);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-static struct attribute *ir_hw_dev_attrs[] = {
Jesse Keating 7a3296
-	&dev_attr_protocol.attr,
Jesse Keating 7a3296
-	&dev_attr_supported_protocols.attr,
Jesse Keating 7a3296
+static struct attribute *rc_dev_attrs[] = {
Jesse Keating 7a3296
+	&dev_attr_protocols.attr,
Jesse Keating 7a3296
 	NULL,
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-static struct attribute_group ir_hw_dev_attr_grp = {
Jesse Keating 7a3296
-	.attrs	= ir_hw_dev_attrs,
Jesse Keating 7a3296
+static struct attribute_group rc_dev_attr_grp = {
Jesse Keating 7a3296
+	.attrs	= rc_dev_attrs,
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-static const struct attribute_group *ir_hw_dev_attr_groups[] = {
Jesse Keating 7a3296
-	&ir_hw_dev_attr_grp,
Jesse Keating 7a3296
+static const struct attribute_group *rc_dev_attr_groups[] = {
Jesse Keating 7a3296
+	&rc_dev_attr_grp,
Jesse Keating 7a3296
 	NULL
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 static struct device_type rc_dev_type = {
Jesse Keating 7a3296
-	.groups		= ir_hw_dev_attr_groups,
Jesse Keating 7a3296
-	.uevent		= ir_dev_uevent,
Jesse Keating 7a3296
-};
Jesse Keating 7a3296
-
Jesse Keating 7a3296
-static struct device_type ir_raw_dev_type = {
Jesse Keating 7a3296
-	.uevent		= ir_dev_uevent,
Jesse Keating 7a3296
+	.groups		= rc_dev_attr_groups,
Jesse Keating 7a3296
+	.uevent		= rc_dev_uevent,
Jesse Keating 7a3296
 };
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 /**
Jesse Keating 7a3296
@@ -221,12 +277,7 @@ int ir_register_class(struct input_dev *input_dev)
Jesse Keating 7a3296
 	if (unlikely(devno < 0))
Jesse Keating 7a3296
 		return devno;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-	if (ir_dev->props) {
Jesse Keating 7a3296
-		if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
Jesse Keating 7a3296
-			ir_dev->dev.type = &rc_dev_type;
Jesse Keating 7a3296
-	} else
Jesse Keating 7a3296
-		ir_dev->dev.type = &ir_raw_dev_type;
Jesse Keating 7a3296
-
Jesse Keating 7a3296
+	ir_dev->dev.type = &rc_dev_type;
Jesse Keating 7a3296
 	ir_dev->dev.class = &ir_input_class;
Jesse Keating 7a3296
 	ir_dev->dev.parent = input_dev->dev.parent;
Jesse Keating 7a3296
 	dev_set_name(&ir_dev->dev, "rc%d", devno);
Jesse Keating 7a3296
diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile
Jesse Keating 7a3296
index aea649f..86d3d1f 100644
Jesse Keating 7a3296
--- a/drivers/media/IR/keymaps/Makefile
Jesse Keating 7a3296
+++ b/drivers/media/IR/keymaps/Makefile
Jesse Keating 7a3296
@@ -37,6 +37,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
Jesse Keating 7a3296
 			rc-kaiomy.o \
Jesse Keating 7a3296
 			rc-kworld-315u.o \
Jesse Keating 7a3296
 			rc-kworld-plus-tv-analog.o \
Jesse Keating 7a3296
+			rc-lirc.o \
Jesse Keating 7a3296
 			rc-manli.o \
Jesse Keating 7a3296
 			rc-msi-tvanywhere.o \
Jesse Keating 7a3296
 			rc-msi-tvanywhere-plus.o \
Jesse Keating 7a3296
@@ -57,6 +58,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
Jesse Keating 7a3296
 			rc-pv951.o \
Jesse Keating 7a3296
 			rc-rc5-hauppauge-new.o \
Jesse Keating 7a3296
 			rc-rc5-tv.o \
Jesse Keating 7a3296
+			rc-rc6-mce.o \
Jesse Keating 7a3296
 			rc-real-audio-220-32-keys.o \
Jesse Keating 7a3296
 			rc-tbs-nec.o \
Jesse Keating 7a3296
 			rc-terratec-cinergy-xs.o \
Jesse Keating 7a3296
diff --git a/drivers/media/IR/keymaps/rc-lirc.c b/drivers/media/IR/keymaps/rc-lirc.c
Jesse Keating 7a3296
new file mode 100644
Jesse Keating 7a3296
index 0000000..43fcf90
Jesse Keating 7a3296
--- /dev/null
Jesse Keating 7a3296
+++ b/drivers/media/IR/keymaps/rc-lirc.c
Jesse Keating 7a3296
@@ -0,0 +1,41 @@
Jesse Keating 7a3296
+/* rc-lirc.c - Empty dummy keytable, for use when its preferred to pass
Jesse Keating 7a3296
+ * all raw IR data to the lirc userspace decoder.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This program is free software; you can redistribute it and/or modify
Jesse Keating 7a3296
+ * it under the terms of the GNU General Public License as published by
Jesse Keating 7a3296
+ * the Free Software Foundation; either version 2 of the License, or
Jesse Keating 7a3296
+ * (at your option) any later version.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#include <media ir-core.h="">
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static struct ir_scancode lirc[] = {
Jesse Keating 7a3296
+	{ },
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static struct rc_keymap lirc_map = {
Jesse Keating 7a3296
+	.map = {
Jesse Keating 7a3296
+		.scan    = lirc,
Jesse Keating 7a3296
+		.size    = ARRAY_SIZE(lirc),
Jesse Keating 7a3296
+		.ir_type = IR_TYPE_LIRC,
Jesse Keating 7a3296
+		.name    = RC_MAP_LIRC,
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static int __init init_rc_map_lirc(void)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	return ir_register_map(&lirc_map);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static void __exit exit_rc_map_lirc(void)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	ir_unregister_map(&lirc_map);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+module_init(init_rc_map_lirc)
Jesse Keating 7a3296
+module_exit(exit_rc_map_lirc)
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+MODULE_LICENSE("GPL");
Jesse Keating 7a3296
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
Jesse Keating 7a3296
diff --git a/drivers/media/IR/keymaps/rc-rc6-mce.c b/drivers/media/IR/keymaps/rc-rc6-mce.c
Jesse Keating 7a3296
new file mode 100644
Jesse Keating 7a3296
index 0000000..c6726a8
Jesse Keating 7a3296
--- /dev/null
Jesse Keating 7a3296
+++ b/drivers/media/IR/keymaps/rc-rc6-mce.c
Jesse Keating 7a3296
@@ -0,0 +1,105 @@
Jesse Keating 7a3296
+/* rc-rc6-mce.c - Keytable for Windows Media Center RC-6 remotes for use
Jesse Keating 7a3296
+ * with the Media Center Edition eHome Infrared Transceiver.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This program is free software; you can redistribute it and/or modify
Jesse Keating 7a3296
+ * it under the terms of the GNU General Public License as published by
Jesse Keating 7a3296
+ * the Free Software Foundation; either version 2 of the License, or
Jesse Keating 7a3296
+ * (at your option) any later version.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#include <media rc-map.h="">
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static struct ir_scancode rc6_mce[] = {
Jesse Keating 7a3296
+	{ 0x800f0415, KEY_REWIND },
Jesse Keating 7a3296
+	{ 0x800f0414, KEY_FASTFORWARD },
Jesse Keating 7a3296
+	{ 0x800f041b, KEY_PREVIOUS },
Jesse Keating 7a3296
+	{ 0x800f041a, KEY_NEXT },
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	{ 0x800f0416, KEY_PLAY },
Jesse Keating 7a3296
+	{ 0x800f0418, KEY_PAUSE },
Jesse Keating 7a3296
+	{ 0x800f0419, KEY_STOP },
Jesse Keating 7a3296
+	{ 0x800f0417, KEY_RECORD },
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	{ 0x800f041e, KEY_UP },
Jesse Keating 7a3296
+	{ 0x800f041f, KEY_DOWN },
Jesse Keating 7a3296
+	{ 0x800f0420, KEY_LEFT },
Jesse Keating 7a3296
+	{ 0x800f0421, KEY_RIGHT },
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	{ 0x800f040b, KEY_ENTER },
Jesse Keating 7a3296
+	{ 0x800f0422, KEY_OK },
Jesse Keating 7a3296
+	{ 0x800f0423, KEY_EXIT },
Jesse Keating 7a3296
+	{ 0x800f040a, KEY_DELETE },
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	{ 0x800f040e, KEY_MUTE },
Jesse Keating 7a3296
+	{ 0x800f0410, KEY_VOLUMEUP },
Jesse Keating 7a3296
+	{ 0x800f0411, KEY_VOLUMEDOWN },
Jesse Keating 7a3296
+	{ 0x800f0412, KEY_CHANNELUP },
Jesse Keating 7a3296
+	{ 0x800f0413, KEY_CHANNELDOWN },
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	{ 0x800f0401, KEY_NUMERIC_1 },
Jesse Keating 7a3296
+	{ 0x800f0402, KEY_NUMERIC_2 },
Jesse Keating 7a3296
+	{ 0x800f0403, KEY_NUMERIC_3 },
Jesse Keating 7a3296
+	{ 0x800f0404, KEY_NUMERIC_4 },
Jesse Keating 7a3296
+	{ 0x800f0405, KEY_NUMERIC_5 },
Jesse Keating 7a3296
+	{ 0x800f0406, KEY_NUMERIC_6 },
Jesse Keating 7a3296
+	{ 0x800f0407, KEY_NUMERIC_7 },
Jesse Keating 7a3296
+	{ 0x800f0408, KEY_NUMERIC_8 },
Jesse Keating 7a3296
+	{ 0x800f0409, KEY_NUMERIC_9 },
Jesse Keating 7a3296
+	{ 0x800f0400, KEY_NUMERIC_0 },
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	{ 0x800f041d, KEY_NUMERIC_STAR },
Jesse Keating 7a3296
+	{ 0x800f041c, KEY_NUMERIC_POUND },
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	{ 0x800f0446, KEY_TV },
Jesse Keating 7a3296
+	{ 0x800f0447, KEY_AUDIO }, /* My Music */
Jesse Keating 7a3296
+	{ 0x800f0448, KEY_PVR }, /* RecordedTV */
Jesse Keating 7a3296
+	{ 0x800f0449, KEY_CAMERA },
Jesse Keating 7a3296
+	{ 0x800f044a, KEY_VIDEO },
Jesse Keating 7a3296
+	{ 0x800f0424, KEY_DVD },
Jesse Keating 7a3296
+	{ 0x800f0425, KEY_TUNER }, /* LiveTV */
Jesse Keating 7a3296
+	{ 0x800f0450, KEY_RADIO },
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	{ 0x800f044c, KEY_LANGUAGE },
Jesse Keating 7a3296
+	{ 0x800f0427, KEY_ZOOM }, /* Aspect */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	{ 0x800f045b, KEY_RED },
Jesse Keating 7a3296
+	{ 0x800f045c, KEY_GREEN },
Jesse Keating 7a3296
+	{ 0x800f045d, KEY_YELLOW },
Jesse Keating 7a3296
+	{ 0x800f045e, KEY_BLUE },
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	{ 0x800f040f, KEY_INFO },
Jesse Keating 7a3296
+	{ 0x800f0426, KEY_EPG }, /* Guide */
Jesse Keating 7a3296
+	{ 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */
Jesse Keating 7a3296
+	{ 0x800f044d, KEY_TITLE },
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	{ 0x800f040c, KEY_POWER },
Jesse Keating 7a3296
+	{ 0x800f040d, KEY_PROG1 }, /* Windows MCE button */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static struct rc_keymap rc6_mce_map = {
Jesse Keating 7a3296
+	.map = {
Jesse Keating 7a3296
+		.scan    = rc6_mce,
Jesse Keating 7a3296
+		.size    = ARRAY_SIZE(rc6_mce),
Jesse Keating 7a3296
+		.ir_type = IR_TYPE_RC6,
Jesse Keating 7a3296
+		.name    = RC_MAP_RC6_MCE,
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static int __init init_rc_map_rc6_mce(void)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	return ir_register_map(&rc6_mce_map);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static void __exit exit_rc_map_rc6_mce(void)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	ir_unregister_map(&rc6_mce_map);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+module_init(init_rc_map_rc6_mce)
Jesse Keating 7a3296
+module_exit(exit_rc_map_rc6_mce)
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+MODULE_LICENSE("GPL");
Jesse Keating 7a3296
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
Jesse Keating 7a3296
diff --git a/drivers/media/IR/lirc_dev.c b/drivers/media/IR/lirc_dev.c
Jesse Keating 7a3296
new file mode 100644
Jesse Keating 7a3296
index 0000000..899891b
Jesse Keating 7a3296
--- /dev/null
Jesse Keating 7a3296
+++ b/drivers/media/IR/lirc_dev.c
Jesse Keating 7a3296
@@ -0,0 +1,764 @@
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * LIRC base driver
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * by Artur Lipowski <alipowski@interia.pl>
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ *  This program is free software; you can redistribute it and/or modify
Jesse Keating 7a3296
+ *  it under the terms of the GNU General Public License as published by
Jesse Keating 7a3296
+ *  the Free Software Foundation; either version 2 of the License, or
Jesse Keating 7a3296
+ *  (at your option) any later version.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ *  This program is distributed in the hope that it will be useful,
Jesse Keating 7a3296
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Jesse Keating 7a3296
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Jesse Keating 7a3296
+ *  GNU General Public License for more details.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ *  You should have received a copy of the GNU General Public License
Jesse Keating 7a3296
+ *  along with this program; if not, write to the Free Software
Jesse Keating 7a3296
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#include <linux module.h="">
Jesse Keating 7a3296
+#include <linux kernel.h="">
Jesse Keating 7a3296
+#include <linux sched.h="">
Jesse Keating 7a3296
+#include <linux errno.h="">
Jesse Keating 7a3296
+#include <linux ioctl.h="">
Jesse Keating 7a3296
+#include <linux fs.h="">
Jesse Keating 7a3296
+#include <linux poll.h="">
Jesse Keating 7a3296
+#include <linux completion.h="">
Jesse Keating 7a3296
+#include <linux errno.h="">
Jesse Keating 7a3296
+#include <linux mutex.h="">
Jesse Keating 7a3296
+#include <linux wait.h="">
Jesse Keating 7a3296
+#include <linux unistd.h="">
Jesse Keating 7a3296
+#include <linux kthread.h="">
Jesse Keating 7a3296
+#include <linux bitops.h="">
Jesse Keating 7a3296
+#include <linux device.h="">
Jesse Keating 7a3296
+#include <linux cdev.h="">
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#include <media lirc.h="">
Jesse Keating 7a3296
+#include <media lirc_dev.h="">
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static int debug;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#define IRCTL_DEV_NAME	"BaseRemoteCtl"
Jesse Keating 7a3296
+#define NOPLUG		-1
Jesse Keating 7a3296
+#define LOGHEAD		"lirc_dev (%s[%d]): "
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static dev_t lirc_base_dev;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+struct irctl {
Jesse Keating 7a3296
+	struct lirc_driver d;
Jesse Keating 7a3296
+	int attached;
Jesse Keating 7a3296
+	int open;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	struct mutex irctl_lock;
Jesse Keating 7a3296
+	struct lirc_buffer *buf;
Jesse Keating 7a3296
+	unsigned int chunk_size;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	struct task_struct *task;
Jesse Keating 7a3296
+	long jiffies_to_wait;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	struct cdev cdev;
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static DEFINE_MUTEX(lirc_dev_lock);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static struct irctl *irctls[MAX_IRCTL_DEVICES];
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/* Only used for sysfs but defined to void otherwise */
Jesse Keating 7a3296
+static struct class *lirc_class;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*  helper function
Jesse Keating 7a3296
+ *  initializes the irctl structure
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static void init_irctl(struct irctl *ir)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	dev_dbg(ir->d.dev, LOGHEAD "initializing irctl\n",
Jesse Keating 7a3296
+		ir->d.name, ir->d.minor);
Jesse Keating 7a3296
+	mutex_init(&ir->irctl_lock);
Jesse Keating 7a3296
+	ir->d.minor = NOPLUG;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static void cleanup(struct irctl *ir)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (ir->buf != ir->d.rbuf) {
Jesse Keating 7a3296
+		lirc_buffer_free(ir->buf);
Jesse Keating 7a3296
+		kfree(ir->buf);
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+	ir->buf = NULL;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*  helper function
Jesse Keating 7a3296
+ *  reads key codes from driver and puts them into buffer
Jesse Keating 7a3296
+ *  returns 0 on success
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static int add_to_buf(struct irctl *ir)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	if (ir->d.add_to_buf) {
Jesse Keating 7a3296
+		int res = -ENODATA;
Jesse Keating 7a3296
+		int got_data = 0;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		/*
Jesse Keating 7a3296
+		 * service the device as long as it is returning
Jesse Keating 7a3296
+		 * data and we have space
Jesse Keating 7a3296
+		 */
Jesse Keating 7a3296
+get_data:
Jesse Keating 7a3296
+		res = ir->d.add_to_buf(ir->d.data, ir->buf);
Jesse Keating 7a3296
+		if (res == 0) {
Jesse Keating 7a3296
+			got_data++;
Jesse Keating 7a3296
+			goto get_data;
Jesse Keating 7a3296
+		}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (res == -ENODEV)
Jesse Keating 7a3296
+			kthread_stop(ir->task);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		return got_data ? 0 : res;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return 0;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/* main function of the polling thread
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static int lirc_thread(void *irctl)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct irctl *ir = irctl;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	dev_dbg(ir->d.dev, LOGHEAD "poll thread started\n",
Jesse Keating 7a3296
+		ir->d.name, ir->d.minor);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	do {
Jesse Keating 7a3296
+		if (ir->open) {
Jesse Keating 7a3296
+			if (ir->jiffies_to_wait) {
Jesse Keating 7a3296
+				set_current_state(TASK_INTERRUPTIBLE);
Jesse Keating 7a3296
+				schedule_timeout(ir->jiffies_to_wait);
Jesse Keating 7a3296
+			}
Jesse Keating 7a3296
+			if (kthread_should_stop())
Jesse Keating 7a3296
+				break;
Jesse Keating 7a3296
+			if (!add_to_buf(ir))
Jesse Keating 7a3296
+				wake_up_interruptible(&ir->buf->wait_poll);
Jesse Keating 7a3296
+		} else {
Jesse Keating 7a3296
+			set_current_state(TASK_INTERRUPTIBLE);
Jesse Keating 7a3296
+			schedule();
Jesse Keating 7a3296
+		}
Jesse Keating 7a3296
+	} while (!kthread_should_stop());
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	dev_dbg(ir->d.dev, LOGHEAD "poll thread ended\n",
Jesse Keating 7a3296