mirror of https://gitee.com/openkylin/linux.git
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (505 commits) [media] af9015: Fix max I2C message size when used with tda18271 [media] IR: initialize ir_raw_event in few more drivers [media] Guard a divide in v4l1 compat layer [media] imon: fix nomouse modprobe option [media] imon: remove redundant change_protocol call [media] imon: fix my egregious brown paper bag w/rdev/idev split [media] cafe_ccic: Configure ov7670 correctly [media] ov7670: allow configuration of image size, clock speed, and I/O method [media] af9015: support for DigitalNow TinyTwin v3 [1f4d:9016] [media] af9015: map DigitalNow TinyTwin v2 remote [media] DigitalNow TinyTwin remote controller [media] af9015: RC fixes and improvements videodev2.h.xml: Update to reflect the latest changes at videodev2.h [media] v4l: document new Bayer and monochrome pixel formats [media] DocBook/v4l: Add missing formats used on gspca cpia1 and sn9c2028 [media] firedtv: add parameter to fake ca_system_ids in CA_INFO [media] tm6000: fix a macro coding style issue tm6000: Remove some ugly debug code [media] Nova-S-Plus audio line input [media] [RFC,1/1] V4L2: Use new CAP bits in existing RDS capable drivers ...
This commit is contained in:
commit
0851668fdd
|
@ -250,6 +250,9 @@
|
|||
<!ENTITY sub-yuv422p SYSTEM "v4l/pixfmt-yuv422p.xml">
|
||||
<!ENTITY sub-yuyv SYSTEM "v4l/pixfmt-yuyv.xml">
|
||||
<!ENTITY sub-yvyu SYSTEM "v4l/pixfmt-yvyu.xml">
|
||||
<!ENTITY sub-srggb10 SYSTEM "v4l/pixfmt-srggb10.xml">
|
||||
<!ENTITY sub-srggb8 SYSTEM "v4l/pixfmt-srggb8.xml">
|
||||
<!ENTITY sub-y10 SYSTEM "v4l/pixfmt-y10.xml">
|
||||
<!ENTITY sub-pixfmt SYSTEM "v4l/pixfmt.xml">
|
||||
<!ENTITY sub-cropcap SYSTEM "v4l/vidioc-cropcap.xml">
|
||||
<!ENTITY sub-dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">
|
||||
|
@ -347,6 +350,9 @@
|
|||
<!ENTITY yuv422p SYSTEM "v4l/pixfmt-yuv422p.xml">
|
||||
<!ENTITY yuyv SYSTEM "v4l/pixfmt-yuyv.xml">
|
||||
<!ENTITY yvyu SYSTEM "v4l/pixfmt-yvyu.xml">
|
||||
<!ENTITY srggb10 SYSTEM "v4l/pixfmt-srggb10.xml">
|
||||
<!ENTITY srggb8 SYSTEM "v4l/pixfmt-srggb8.xml">
|
||||
<!ENTITY y10 SYSTEM "v4l/pixfmt-y10.xml">
|
||||
<!ENTITY cropcap SYSTEM "v4l/vidioc-cropcap.xml">
|
||||
<!ENTITY dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">
|
||||
<!ENTITY encoder-cmd SYSTEM "v4l/vidioc-encoder-cmd.xml">
|
||||
|
|
|
@ -21,11 +21,15 @@ API.</para>
|
|||
<title>Opening and Closing Devices</title>
|
||||
|
||||
<para>For compatibility reasons the character device file names
|
||||
recommended for V4L2 video capture, overlay, radio, teletext and raw
|
||||
recommended for V4L2 video capture, overlay, radio and raw
|
||||
vbi capture devices did not change from those used by V4L. They are
|
||||
listed in <xref linkend="devices" /> and below in <xref
|
||||
linkend="v4l-dev" />.</para>
|
||||
|
||||
<para>The teletext devices (minor range 192-223) have been removed in
|
||||
V4L2 and no longer exist. There is no hardware available anymore for handling
|
||||
pure teletext. Instead raw or sliced VBI is used.</para>
|
||||
|
||||
<para>The V4L <filename>videodev</filename> module automatically
|
||||
assigns minor numbers to drivers in load order, depending on the
|
||||
registered device type. We recommend that V4L2 drivers by default
|
||||
|
@ -65,13 +69,6 @@ not compatible with V4L or V4L2.</para> </footnote>,
|
|||
<filename>/dev/radio63</filename></para></entry>
|
||||
<entry>64-127</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Teletext decoder</entry>
|
||||
<entry><para><filename>/dev/vtx</filename>,
|
||||
<filename>/dev/vtx0</filename> to
|
||||
<filename>/dev/vtx31</filename></para></entry>
|
||||
<entry>192-223</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Raw VBI capture</entry>
|
||||
<entry><para><filename>/dev/vbi</filename>,
|
||||
|
@ -2345,6 +2342,17 @@ more information.</para>
|
|||
</listitem>
|
||||
</orderedlist>
|
||||
</section>
|
||||
<section>
|
||||
<title>V4L2 in Linux 2.6.37</title>
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>Remove the vtx (videotext/teletext) API. This API was no longer
|
||||
used and no hardware exists to verify the API. Nor were any userspace applications found
|
||||
that used it. It was originally scheduled for removal in 2.6.35.
|
||||
</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
</section>
|
||||
|
||||
<section id="other">
|
||||
<title>Relation of V4L2 to other Linux multimedia APIs</title>
|
||||
|
|
|
@ -311,11 +311,18 @@ minimum value disables backlight compensation.</entry>
|
|||
bits 8-15 Green color information, bits 16-23 Blue color
|
||||
information and bits 24-31 must be zero.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CID_ILLUMINATORS_1</constant>
|
||||
<constant>V4L2_CID_ILLUMINATORS_2</constant></entry>
|
||||
<entry>boolean</entry>
|
||||
<entry>Switch on or off the illuminator 1 or 2 of the device
|
||||
(usually a microscope).</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CID_LASTP1</constant></entry>
|
||||
<entry></entry>
|
||||
<entry>End of the predefined control IDs (currently
|
||||
<constant>V4L2_CID_BG_COLOR</constant> + 1).</entry>
|
||||
<constant>V4L2_CID_ILLUMINATORS_2</constant> + 1).</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CID_PRIVATE_BASE</constant></entry>
|
||||
|
@ -357,9 +364,6 @@ enumerate_menu (void)
|
|||
querymenu.index++) {
|
||||
if (0 == ioctl (fd, &VIDIOC-QUERYMENU;, &querymenu)) {
|
||||
printf (" %s\n", querymenu.name);
|
||||
} else {
|
||||
perror ("VIDIOC_QUERYMENU");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,15 +3,16 @@
|
|||
<para>The Radio Data System transmits supplementary
|
||||
information in binary format, for example the station name or travel
|
||||
information, on an inaudible audio subcarrier of a radio program. This
|
||||
interface is aimed at devices capable of receiving and decoding RDS
|
||||
interface is aimed at devices capable of receiving and/or transmitting RDS
|
||||
information.</para>
|
||||
|
||||
<para>For more information see the core RDS standard <xref linkend="en50067" />
|
||||
and the RBDS standard <xref linkend="nrsc4" />.</para>
|
||||
|
||||
<para>Note that the RBDS standard as is used in the USA is almost identical
|
||||
to the RDS standard. Any RDS decoder can also handle RBDS. Only some of the fields
|
||||
have slightly different meanings. See the RBDS standard for more information.</para>
|
||||
to the RDS standard. Any RDS decoder/encoder can also handle RBDS. Only some of the
|
||||
fields have slightly different meanings. See the RBDS standard for more
|
||||
information.</para>
|
||||
|
||||
<para>The RBDS standard also specifies support for MMBS (Modified Mobile Search).
|
||||
This is a proprietary format which seems to be discontinued. The RDS interface does not
|
||||
|
@ -21,16 +22,25 @@ be needed, then please contact the linux-media mailing list: &v4l-ml;.</para>
|
|||
<section>
|
||||
<title>Querying Capabilities</title>
|
||||
|
||||
<para>Devices supporting the RDS capturing API
|
||||
set the <constant>V4L2_CAP_RDS_CAPTURE</constant> flag in
|
||||
<para>Devices supporting the RDS capturing API set
|
||||
the <constant>V4L2_CAP_RDS_CAPTURE</constant> flag in
|
||||
the <structfield>capabilities</structfield> field of &v4l2-capability;
|
||||
returned by the &VIDIOC-QUERYCAP; ioctl.
|
||||
Any tuner that supports RDS will set the
|
||||
<constant>V4L2_TUNER_CAP_RDS</constant> flag in the <structfield>capability</structfield>
|
||||
field of &v4l2-tuner;.
|
||||
Whether an RDS signal is present can be detected by looking at
|
||||
the <structfield>rxsubchans</structfield> field of &v4l2-tuner;: the
|
||||
<constant>V4L2_TUNER_SUB_RDS</constant> will be set if RDS data was detected.</para>
|
||||
returned by the &VIDIOC-QUERYCAP; ioctl. Any tuner that supports RDS
|
||||
will set the <constant>V4L2_TUNER_CAP_RDS</constant> flag in
|
||||
the <structfield>capability</structfield> field of &v4l2-tuner;. If
|
||||
the driver only passes RDS blocks without interpreting the data
|
||||
the <constant>V4L2_TUNER_SUB_RDS_BLOCK_IO</constant> flag has to be
|
||||
set, see <link linkend="reading-rds-data">Reading RDS data</link>.
|
||||
For future use the
|
||||
flag <constant>V4L2_TUNER_SUB_RDS_CONTROLS</constant> has also been
|
||||
defined. However, a driver for a radio tuner with this capability does
|
||||
not yet exist, so if you are planning to write such a driver you
|
||||
should discuss this on the linux-media mailing list: &v4l-ml;.</para>
|
||||
|
||||
<para> Whether an RDS signal is present can be detected by looking
|
||||
at the <structfield>rxsubchans</structfield> field of &v4l2-tuner;:
|
||||
the <constant>V4L2_TUNER_SUB_RDS</constant> will be set if RDS data
|
||||
was detected.</para>
|
||||
|
||||
<para>Devices supporting the RDS output API
|
||||
set the <constant>V4L2_CAP_RDS_OUTPUT</constant> flag in
|
||||
|
@ -40,16 +50,31 @@ Any modulator that supports RDS will set the
|
|||
<constant>V4L2_TUNER_CAP_RDS</constant> flag in the <structfield>capability</structfield>
|
||||
field of &v4l2-modulator;.
|
||||
In order to enable the RDS transmission one must set the <constant>V4L2_TUNER_SUB_RDS</constant>
|
||||
bit in the <structfield>txsubchans</structfield> field of &v4l2-modulator;.</para>
|
||||
|
||||
bit in the <structfield>txsubchans</structfield> field of &v4l2-modulator;.
|
||||
If the driver only passes RDS blocks without interpreting the data
|
||||
the <constant>V4L2_TUNER_SUB_RDS_BLOCK_IO</constant> flag has to be set. If the
|
||||
tuner is capable of handling RDS entities like program identification codes and radio
|
||||
text, the flag <constant>V4L2_TUNER_SUB_RDS_CONTROLS</constant> should be set,
|
||||
see <link linkend="writing-rds-data">Writing RDS data</link> and
|
||||
<link linkend="fm-tx-controls">FM Transmitter Control Reference</link>.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<section id="reading-rds-data">
|
||||
<title>Reading RDS data</title>
|
||||
|
||||
<para>RDS data can be read from the radio device
|
||||
with the &func-read; function. The data is packed in groups of three bytes,
|
||||
with the &func-read; function. The data is packed in groups of three bytes.</para>
|
||||
</section>
|
||||
|
||||
<section id="writing-rds-data">
|
||||
<title>Writing RDS data</title>
|
||||
|
||||
<para>RDS data can be written to the radio device
|
||||
with the &func-write; function. The data is packed in groups of three bytes,
|
||||
as follows:</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<table frame="none" pgwide="1" id="v4l2-rds-data">
|
||||
<title>struct
|
||||
<structname>v4l2_rds_data</structname></title>
|
||||
|
@ -111,48 +136,57 @@ as follows:</para>
|
|||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>V4L2_RDS_BLOCK_MSK</entry>
|
||||
<entry> </entry>
|
||||
<entry>7</entry>
|
||||
<entry>Mask for bits 0-2 to get the block ID.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>V4L2_RDS_BLOCK_A</entry>
|
||||
<entry> </entry>
|
||||
<entry>0</entry>
|
||||
<entry>Block A.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>V4L2_RDS_BLOCK_B</entry>
|
||||
<entry> </entry>
|
||||
<entry>1</entry>
|
||||
<entry>Block B.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>V4L2_RDS_BLOCK_C</entry>
|
||||
<entry> </entry>
|
||||
<entry>2</entry>
|
||||
<entry>Block C.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>V4L2_RDS_BLOCK_D</entry>
|
||||
<entry> </entry>
|
||||
<entry>3</entry>
|
||||
<entry>Block D.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>V4L2_RDS_BLOCK_C_ALT</entry>
|
||||
<entry> </entry>
|
||||
<entry>4</entry>
|
||||
<entry>Block C'.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>V4L2_RDS_BLOCK_INVALID</entry>
|
||||
<entry>read-only</entry>
|
||||
<entry>7</entry>
|
||||
<entry>An invalid block.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>V4L2_RDS_BLOCK_CORRECTED</entry>
|
||||
<entry>read-only</entry>
|
||||
<entry>0x40</entry>
|
||||
<entry>A bit error was detected but corrected.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>V4L2_RDS_BLOCK_ERROR</entry>
|
||||
<entry>read-only</entry>
|
||||
<entry>0x80</entry>
|
||||
<entry>An incorrectable error occurred.</entry>
|
||||
<entry>An uncorrectable error occurred.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
|
|
|
@ -1,35 +1,32 @@
|
|||
<title>Teletext Interface</title>
|
||||
|
||||
<para>This interface aims at devices receiving and demodulating
|
||||
<para>This interface was aimed at devices receiving and demodulating
|
||||
Teletext data [<xref linkend="ets300706" />, <xref linkend="itu653" />], evaluating the
|
||||
Teletext packages and storing formatted pages in cache memory. Such
|
||||
devices are usually implemented as microcontrollers with serial
|
||||
interface (I<superscript>2</superscript>C) and can be found on older
|
||||
interface (I<superscript>2</superscript>C) and could be found on old
|
||||
TV cards, dedicated Teletext decoding cards and home-brew devices
|
||||
connected to the PC parallel port.</para>
|
||||
|
||||
<para>The Teletext API was designed by Martin Buck. It is defined in
|
||||
<para>The Teletext API was designed by Martin Buck. It was defined in
|
||||
the kernel header file <filename>linux/videotext.h</filename>, the
|
||||
specification is available from <ulink url="ftp://ftp.gwdg.de/pub/linux/misc/videotext/">
|
||||
ftp://ftp.gwdg.de/pub/linux/misc/videotext/</ulink>. (Videotext is the name of
|
||||
the German public television Teletext service.) Conventional character
|
||||
device file names are <filename>/dev/vtx</filename> and
|
||||
<filename>/dev/vttuner</filename>, with device number 83, 0 and 83, 16
|
||||
respectively. A similar interface exists for the Philips SAA5249
|
||||
Teletext decoder [specification?] with character device file names
|
||||
<filename>/dev/tlkN</filename>, device number 102, N.</para>
|
||||
the German public television Teletext service.)</para>
|
||||
|
||||
<para>Eventually the Teletext API was integrated into the V4L API
|
||||
with character device file names <filename>/dev/vtx0</filename> to
|
||||
<filename>/dev/vtx31</filename>, device major number 81, minor numbers
|
||||
192 to 223. For reference the V4L Teletext API specification is
|
||||
reproduced here in full: "Teletext interfaces talk the existing VTX
|
||||
API." Teletext devices with major number 83 and 102 will be removed in
|
||||
Linux 2.6.</para>
|
||||
192 to 223.</para>
|
||||
|
||||
<para>There are no plans to replace the Teletext API or to integrate
|
||||
it into V4L2. Please write to the linux-media mailing list: &v4l-ml;
|
||||
when the need arises.</para>
|
||||
<para>However, teletext decoders were quickly replaced by more
|
||||
generic VBI demodulators and those dedicated teletext decoders no longer exist.
|
||||
For many years the vtx devices were still around, even though nobody used
|
||||
them. So the decision was made to finally remove support for the Teletext API in
|
||||
kernel 2.6.37.</para>
|
||||
|
||||
<para>Modern devices all use the <link linkend="raw-vbi">raw</link> or
|
||||
<link linkend="sliced">sliced</link> VBI API.</para>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
|
|
|
@ -739,7 +739,7 @@ defined in error. Drivers may interpret them as in <xref
|
|||
<entry>b<subscript>1</subscript></entry>
|
||||
<entry>b<subscript>0</subscript></entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-BGR666">
|
||||
<row><!-- id="V4L2-PIX-FMT-BGR666" -->
|
||||
<entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
|
||||
<entry>'BGRH'</entry>
|
||||
<entry></entry>
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
<refentry>
|
||||
<refmeta>
|
||||
<refentrytitle>V4L2_PIX_FMT_SRGGB10 ('RG10'),
|
||||
V4L2_PIX_FMT_SGRBG10 ('BA10'),
|
||||
V4L2_PIX_FMT_SGBRG10 ('GB10'),
|
||||
V4L2_PIX_FMT_SBGGR10 ('BG10'),
|
||||
</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname id="V4L2-PIX-FMT-SRGGB10"><constant>V4L2_PIX_FMT_SRGGB10</constant></refname>
|
||||
<refname id="V4L2-PIX-FMT-SGRBG10"><constant>V4L2_PIX_FMT_SGRBG10</constant></refname>
|
||||
<refname id="V4L2-PIX-FMT-SGBRG10"><constant>V4L2_PIX_FMT_SGBRG10</constant></refname>
|
||||
<refname id="V4L2-PIX-FMT-SBGGR10"><constant>V4L2_PIX_FMT_SBGGR10</constant></refname>
|
||||
<refpurpose>10-bit Bayer formats expanded to 16 bits</refpurpose>
|
||||
</refnamediv>
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>The following four pixel formats are raw sRGB / Bayer formats with
|
||||
10 bits per colour. Each colour component is stored in a 16-bit word, with 6
|
||||
unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
|
||||
and n/2 blue or red samples, with alternating red and blue rows. Bytes are
|
||||
stored in memory in little endian order. They are conventionally described
|
||||
as GRGR... BGBG..., RGRG... GBGB..., etc. Below is an example of one of these
|
||||
formats</para>
|
||||
|
||||
<example>
|
||||
<title><constant>V4L2_PIX_FMT_SBGGR10</constant> 4 × 4
|
||||
pixel image</title>
|
||||
|
||||
<formalpara>
|
||||
<title>Byte Order.</title>
|
||||
<para>Each cell is one byte, high 6 bits in high bytes are 0.
|
||||
<informaltable frame="none">
|
||||
<tgroup cols="5" align="center">
|
||||
<colspec align="left" colwidth="2*" />
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>start + 0:</entry>
|
||||
<entry>B<subscript>00low</subscript></entry>
|
||||
<entry>B<subscript>00high</subscript></entry>
|
||||
<entry>G<subscript>01low</subscript></entry>
|
||||
<entry>G<subscript>01high</subscript></entry>
|
||||
<entry>B<subscript>02low</subscript></entry>
|
||||
<entry>B<subscript>02high</subscript></entry>
|
||||
<entry>G<subscript>03low</subscript></entry>
|
||||
<entry>G<subscript>03high</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 8:</entry>
|
||||
<entry>G<subscript>10low</subscript></entry>
|
||||
<entry>G<subscript>10high</subscript></entry>
|
||||
<entry>R<subscript>11low</subscript></entry>
|
||||
<entry>R<subscript>11high</subscript></entry>
|
||||
<entry>G<subscript>12low</subscript></entry>
|
||||
<entry>G<subscript>12high</subscript></entry>
|
||||
<entry>R<subscript>13low</subscript></entry>
|
||||
<entry>R<subscript>13high</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 16:</entry>
|
||||
<entry>B<subscript>20low</subscript></entry>
|
||||
<entry>B<subscript>20high</subscript></entry>
|
||||
<entry>G<subscript>21low</subscript></entry>
|
||||
<entry>G<subscript>21high</subscript></entry>
|
||||
<entry>B<subscript>22low</subscript></entry>
|
||||
<entry>B<subscript>22high</subscript></entry>
|
||||
<entry>G<subscript>23low</subscript></entry>
|
||||
<entry>G<subscript>23high</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 24:</entry>
|
||||
<entry>G<subscript>30low</subscript></entry>
|
||||
<entry>G<subscript>30high</subscript></entry>
|
||||
<entry>R<subscript>31low</subscript></entry>
|
||||
<entry>R<subscript>31high</subscript></entry>
|
||||
<entry>G<subscript>32low</subscript></entry>
|
||||
<entry>G<subscript>32high</subscript></entry>
|
||||
<entry>R<subscript>33low</subscript></entry>
|
||||
<entry>R<subscript>33high</subscript></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</formalpara>
|
||||
</example>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -0,0 +1,67 @@
|
|||
<refentry id="V4L2-PIX-FMT-SRGGB8">
|
||||
<refmeta>
|
||||
<refentrytitle>V4L2_PIX_FMT_SRGGB8 ('RGGB')</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname><constant>V4L2_PIX_FMT_SRGGB8</constant></refname>
|
||||
<refpurpose>Bayer RGB format</refpurpose>
|
||||
</refnamediv>
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>This is commonly the native format of digital cameras,
|
||||
reflecting the arrangement of sensors on the CCD device. Only one red,
|
||||
green or blue value is given for each pixel. Missing components must
|
||||
be interpolated from neighbouring pixels. From left to right the first
|
||||
row consists of a red and green value, the second row of a green and
|
||||
blue value. This scheme repeats to the right and down for every two
|
||||
columns and rows.</para>
|
||||
|
||||
<example>
|
||||
<title><constant>V4L2_PIX_FMT_SRGGB8</constant> 4 × 4
|
||||
pixel image</title>
|
||||
|
||||
<formalpara>
|
||||
<title>Byte Order.</title>
|
||||
<para>Each cell is one byte.
|
||||
<informaltable frame="none">
|
||||
<tgroup cols="5" align="center">
|
||||
<colspec align="left" colwidth="2*" />
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>start + 0:</entry>
|
||||
<entry>R<subscript>00</subscript></entry>
|
||||
<entry>G<subscript>01</subscript></entry>
|
||||
<entry>R<subscript>02</subscript></entry>
|
||||
<entry>G<subscript>03</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 4:</entry>
|
||||
<entry>G<subscript>10</subscript></entry>
|
||||
<entry>B<subscript>11</subscript></entry>
|
||||
<entry>G<subscript>12</subscript></entry>
|
||||
<entry>B<subscript>13</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 8:</entry>
|
||||
<entry>R<subscript>20</subscript></entry>
|
||||
<entry>G<subscript>21</subscript></entry>
|
||||
<entry>R<subscript>22</subscript></entry>
|
||||
<entry>G<subscript>23</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 12:</entry>
|
||||
<entry>G<subscript>30</subscript></entry>
|
||||
<entry>B<subscript>31</subscript></entry>
|
||||
<entry>G<subscript>32</subscript></entry>
|
||||
<entry>B<subscript>33</subscript></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</formalpara>
|
||||
</example>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -0,0 +1,79 @@
|
|||
<refentry id="V4L2-PIX-FMT-Y10">
|
||||
<refmeta>
|
||||
<refentrytitle>V4L2_PIX_FMT_Y10 ('Y10 ')</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname><constant>V4L2_PIX_FMT_Y10</constant></refname>
|
||||
<refpurpose>Grey-scale image</refpurpose>
|
||||
</refnamediv>
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>This is a grey-scale image with a depth of 10 bits per pixel. Pixels
|
||||
are stored in 16-bit words with unused high bits padded with 0. The least
|
||||
significant byte is stored at lower memory addresses (little-endian).</para>
|
||||
|
||||
<example>
|
||||
<title><constant>V4L2_PIX_FMT_Y10</constant> 4 × 4
|
||||
pixel image</title>
|
||||
|
||||
<formalpara>
|
||||
<title>Byte Order.</title>
|
||||
<para>Each cell is one byte.
|
||||
<informaltable frame="none">
|
||||
<tgroup cols="9" align="center">
|
||||
<colspec align="left" colwidth="2*" />
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>start + 0:</entry>
|
||||
<entry>Y'<subscript>00low</subscript></entry>
|
||||
<entry>Y'<subscript>00high</subscript></entry>
|
||||
<entry>Y'<subscript>01low</subscript></entry>
|
||||
<entry>Y'<subscript>01high</subscript></entry>
|
||||
<entry>Y'<subscript>02low</subscript></entry>
|
||||
<entry>Y'<subscript>02high</subscript></entry>
|
||||
<entry>Y'<subscript>03low</subscript></entry>
|
||||
<entry>Y'<subscript>03high</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 8:</entry>
|
||||
<entry>Y'<subscript>10low</subscript></entry>
|
||||
<entry>Y'<subscript>10high</subscript></entry>
|
||||
<entry>Y'<subscript>11low</subscript></entry>
|
||||
<entry>Y'<subscript>11high</subscript></entry>
|
||||
<entry>Y'<subscript>12low</subscript></entry>
|
||||
<entry>Y'<subscript>12high</subscript></entry>
|
||||
<entry>Y'<subscript>13low</subscript></entry>
|
||||
<entry>Y'<subscript>13high</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 16:</entry>
|
||||
<entry>Y'<subscript>20low</subscript></entry>
|
||||
<entry>Y'<subscript>20high</subscript></entry>
|
||||
<entry>Y'<subscript>21low</subscript></entry>
|
||||
<entry>Y'<subscript>21high</subscript></entry>
|
||||
<entry>Y'<subscript>22low</subscript></entry>
|
||||
<entry>Y'<subscript>22high</subscript></entry>
|
||||
<entry>Y'<subscript>23low</subscript></entry>
|
||||
<entry>Y'<subscript>23high</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 24:</entry>
|
||||
<entry>Y'<subscript>30low</subscript></entry>
|
||||
<entry>Y'<subscript>30high</subscript></entry>
|
||||
<entry>Y'<subscript>31low</subscript></entry>
|
||||
<entry>Y'<subscript>31high</subscript></entry>
|
||||
<entry>Y'<subscript>32low</subscript></entry>
|
||||
<entry>Y'<subscript>32high</subscript></entry>
|
||||
<entry>Y'<subscript>33low</subscript></entry>
|
||||
<entry>Y'<subscript>33high</subscript></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</formalpara>
|
||||
</example>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -566,7 +566,9 @@ access the palette, this must be done with ioctls of the Linux framebuffer API.<
|
|||
&sub-sbggr8;
|
||||
&sub-sgbrg8;
|
||||
&sub-sgrbg8;
|
||||
&sub-srggb8;
|
||||
&sub-sbggr16;
|
||||
&sub-srggb10;
|
||||
</section>
|
||||
|
||||
<section id="yuv-formats">
|
||||
|
@ -589,6 +591,7 @@ information.</para>
|
|||
|
||||
&sub-packed-yuv;
|
||||
&sub-grey;
|
||||
&sub-y10;
|
||||
&sub-y16;
|
||||
&sub-yuyv;
|
||||
&sub-uyvy;
|
||||
|
@ -685,6 +688,11 @@ http://www.ivtvdriver.org/</ulink></para><para>The format is documented in the
|
|||
kernel sources in the file <filename>Documentation/video4linux/cx2341x/README.hm12</filename>
|
||||
</para></entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-CPIA1">
|
||||
<entry><constant>V4L2_PIX_FMT_CPIA1</constant></entry>
|
||||
<entry>'CPIA'</entry>
|
||||
<entry>YUV format used by the gspca cpia1 driver.</entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-SPCA501">
|
||||
<entry><constant>V4L2_PIX_FMT_SPCA501</constant></entry>
|
||||
<entry>'S501'</entry>
|
||||
|
@ -705,11 +713,6 @@ kernel sources in the file <filename>Documentation/video4linux/cx2341x/README.hm
|
|||
<entry>'S561'</entry>
|
||||
<entry>Compressed GBRG Bayer format used by the gspca driver.</entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-SGRBG10">
|
||||
<entry><constant>V4L2_PIX_FMT_SGRBG10</constant></entry>
|
||||
<entry>'DA10'</entry>
|
||||
<entry>10 bit raw Bayer, expanded to 16 bits.</entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-SGRBG10DPCM8">
|
||||
<entry><constant>V4L2_PIX_FMT_SGRBG10DPCM8</constant></entry>
|
||||
<entry>'DB10'</entry>
|
||||
|
@ -770,6 +773,11 @@ kernel sources in the file <filename>Documentation/video4linux/cx2341x/README.hm
|
|||
<entry>'S920'</entry>
|
||||
<entry>YUV 4:2:0 format of the gspca sn9c20x driver.</entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-SN9C2028">
|
||||
<entry><constant>V4L2_PIX_FMT_SN9C2028</constant></entry>
|
||||
<entry>'SONX'</entry>
|
||||
<entry>Compressed GBRG bayer format of the gspca sn9c2028 driver.</entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-STV0680">
|
||||
<entry><constant>V4L2_PIX_FMT_STV0680</constant></entry>
|
||||
<entry>'S680'</entry>
|
||||
|
@ -787,6 +795,20 @@ http://www.thedirks.org/winnov/</ulink></para></entry>
|
|||
<entry>'TM60'</entry>
|
||||
<entry><para>Used by Trident tm6000</para></entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-CIT-YYVYUY">
|
||||
<entry><constant>V4L2_PIX_FMT_CIT_YYVYUY</constant></entry>
|
||||
<entry>'CITV'</entry>
|
||||
<entry><para>Used by xirlink CIT, found at IBM webcams.</para>
|
||||
<para>Uses one line of Y then 1 line of VYUY</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-KONICA420">
|
||||
<entry><constant>V4L2_PIX_FMT_KONICA420</constant></entry>
|
||||
<entry>'KONI'</entry>
|
||||
<entry><para>Used by Konica webcams.</para>
|
||||
<para>YUV420 planar in blocks of 256 pixels.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-YYUV">
|
||||
<entry><constant>V4L2_PIX_FMT_YYUV</constant></entry>
|
||||
<entry>'YYUV'</entry>
|
||||
|
|
|
@ -99,6 +99,7 @@ Remote Controller chapter.</contrib>
|
|||
<year>2007</year>
|
||||
<year>2008</year>
|
||||
<year>2009</year>
|
||||
<year>2010</year>
|
||||
<holder>Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin
|
||||
Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab</holder>
|
||||
</copyright>
|
||||
|
@ -110,9 +111,16 @@ Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab</holder>
|
|||
<!-- Put document revisions here, newest first. -->
|
||||
<!-- API revisions (changes and additions of defines, enums,
|
||||
structs, ioctls) must be noted in more detail in the history chapter
|
||||
(compat.sgml), along with the possible impact on existing drivers and
|
||||
(compat.xml), along with the possible impact on existing drivers and
|
||||
applications. -->
|
||||
|
||||
<revision>
|
||||
<revnumber>2.6.37</revnumber>
|
||||
<date>2010-08-06</date>
|
||||
<authorinitials>hv</authorinitials>
|
||||
<revremark>Removed obsolete vtx (videotext) API.</revremark>
|
||||
</revision>
|
||||
|
||||
<revision>
|
||||
<revnumber>2.6.33</revnumber>
|
||||
<date>2009-12-03</date>
|
||||
|
|
|
@ -154,23 +154,13 @@ enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> {
|
|||
V4L2_BUF_TYPE_VBI_OUTPUT = 5,
|
||||
V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6,
|
||||
V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7,
|
||||
#if 1 /*KEEP*/
|
||||
#if 1
|
||||
/* Experimental */
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8,
|
||||
#endif
|
||||
V4L2_BUF_TYPE_PRIVATE = 0x80,
|
||||
};
|
||||
|
||||
enum <link linkend="v4l2-ctrl-type">v4l2_ctrl_type</link> {
|
||||
V4L2_CTRL_TYPE_INTEGER = 1,
|
||||
V4L2_CTRL_TYPE_BOOLEAN = 2,
|
||||
V4L2_CTRL_TYPE_MENU = 3,
|
||||
V4L2_CTRL_TYPE_BUTTON = 4,
|
||||
V4L2_CTRL_TYPE_INTEGER64 = 5,
|
||||
V4L2_CTRL_TYPE_CTRL_CLASS = 6,
|
||||
V4L2_CTRL_TYPE_STRING = 7,
|
||||
};
|
||||
|
||||
enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link> {
|
||||
V4L2_TUNER_RADIO = 1,
|
||||
V4L2_TUNER_ANALOG_TV = 2,
|
||||
|
@ -288,6 +278,7 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
|
|||
#define <link linkend="V4L2-PIX-FMT-RGB565">V4L2_PIX_FMT_RGB565</link> v4l2_fourcc('R', 'G', 'B', 'P') /* 16 RGB-5-6-5 */
|
||||
#define <link linkend="V4L2-PIX-FMT-RGB555X">V4L2_PIX_FMT_RGB555X</link> v4l2_fourcc('R', 'G', 'B', 'Q') /* 16 RGB-5-5-5 BE */
|
||||
#define <link linkend="V4L2-PIX-FMT-RGB565X">V4L2_PIX_FMT_RGB565X</link> v4l2_fourcc('R', 'G', 'B', 'R') /* 16 RGB-5-6-5 BE */
|
||||
#define <link linkend="V4L2-PIX-FMT-BGR666">V4L2_PIX_FMT_BGR666</link> v4l2_fourcc('B', 'G', 'R', 'H') /* 18 BGR-6-6-6 */
|
||||
#define <link linkend="V4L2-PIX-FMT-BGR24">V4L2_PIX_FMT_BGR24</link> v4l2_fourcc('B', 'G', 'R', '3') /* 24 BGR-8-8-8 */
|
||||
#define <link linkend="V4L2-PIX-FMT-RGB24">V4L2_PIX_FMT_RGB24</link> v4l2_fourcc('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */
|
||||
#define <link linkend="V4L2-PIX-FMT-BGR32">V4L2_PIX_FMT_BGR32</link> v4l2_fourcc('B', 'G', 'R', '4') /* 32 BGR-8-8-8-8 */
|
||||
|
@ -295,6 +286,9 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
|
|||
|
||||
/* Grey formats */
|
||||
#define <link linkend="V4L2-PIX-FMT-GREY">V4L2_PIX_FMT_GREY</link> v4l2_fourcc('G', 'R', 'E', 'Y') /* 8 Greyscale */
|
||||
#define <link linkend="V4L2-PIX-FMT-Y4">V4L2_PIX_FMT_Y4</link> v4l2_fourcc('Y', '0', '4', ' ') /* 4 Greyscale */
|
||||
#define <link linkend="V4L2-PIX-FMT-Y6">V4L2_PIX_FMT_Y6</link> v4l2_fourcc('Y', '0', '6', ' ') /* 6 Greyscale */
|
||||
#define <link linkend="V4L2-PIX-FMT-Y10">V4L2_PIX_FMT_Y10</link> v4l2_fourcc('Y', '1', '0', ' ') /* 10 Greyscale */
|
||||
#define <link linkend="V4L2-PIX-FMT-Y16">V4L2_PIX_FMT_Y16</link> v4l2_fourcc('Y', '1', '6', ' ') /* 16 Greyscale */
|
||||
|
||||
/* Palette formats */
|
||||
|
@ -330,7 +324,11 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
|
|||
#define <link linkend="V4L2-PIX-FMT-SBGGR8">V4L2_PIX_FMT_SBGGR8</link> v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */
|
||||
#define <link linkend="V4L2-PIX-FMT-SGBRG8">V4L2_PIX_FMT_SGBRG8</link> v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */
|
||||
#define <link linkend="V4L2-PIX-FMT-SGRBG8">V4L2_PIX_FMT_SGRBG8</link> v4l2_fourcc('G', 'R', 'B', 'G') /* 8 GRGR.. BGBG.. */
|
||||
#define <link linkend="V4L2-PIX-FMT-SGRBG10">V4L2_PIX_FMT_SGRBG10</link> v4l2_fourcc('B', 'A', '1', '0') /* 10bit raw bayer */
|
||||
#define <link linkend="V4L2-PIX-FMT-SRGGB8">V4L2_PIX_FMT_SRGGB8</link> v4l2_fourcc('R', 'G', 'G', 'B') /* 8 RGRG.. GBGB.. */
|
||||
#define <link linkend="V4L2-PIX-FMT-SBGGR10">V4L2_PIX_FMT_SBGGR10</link> v4l2_fourcc('B', 'G', '1', '0') /* 10 BGBG.. GRGR.. */
|
||||
#define <link linkend="V4L2-PIX-FMT-SGBRG10">V4L2_PIX_FMT_SGBRG10</link> v4l2_fourcc('G', 'B', '1', '0') /* 10 GBGB.. RGRG.. */
|
||||
#define <link linkend="V4L2-PIX-FMT-SGRBG10">V4L2_PIX_FMT_SGRBG10</link> v4l2_fourcc('B', 'A', '1', '0') /* 10 GRGR.. BGBG.. */
|
||||
#define <link linkend="V4L2-PIX-FMT-SRGGB10">V4L2_PIX_FMT_SRGGB10</link> v4l2_fourcc('R', 'G', '1', '0') /* 10 RGRG.. GBGB.. */
|
||||
/* 10bit raw bayer DPCM compressed to 8 bits */
|
||||
#define <link linkend="V4L2-PIX-FMT-SGRBG10DPCM8">V4L2_PIX_FMT_SGRBG10DPCM8</link> v4l2_fourcc('B', 'D', '1', '0')
|
||||
/*
|
||||
|
@ -346,6 +344,7 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
|
|||
#define <link linkend="V4L2-PIX-FMT-MPEG">V4L2_PIX_FMT_MPEG</link> v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 */
|
||||
|
||||
/* Vendor-specific formats */
|
||||
#define <link linkend="V4L2-PIX-FMT-CPIA1">V4L2_PIX_FMT_CPIA1</link> v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
|
||||
#define <link linkend="V4L2-PIX-FMT-WNVA">V4L2_PIX_FMT_WNVA</link> v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */
|
||||
#define <link linkend="V4L2-PIX-FMT-SN9C10X">V4L2_PIX_FMT_SN9C10X</link> v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */
|
||||
#define <link linkend="V4L2-PIX-FMT-SN9C20X-I420">V4L2_PIX_FMT_SN9C20X_I420</link> v4l2_fourcc('S', '9', '2', '0') /* SN9C20x YUV 4:2:0 */
|
||||
|
@ -358,12 +357,15 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
|
|||
#define <link linkend="V4L2-PIX-FMT-SPCA561">V4L2_PIX_FMT_SPCA561</link> v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
|
||||
#define <link linkend="V4L2-PIX-FMT-PAC207">V4L2_PIX_FMT_PAC207</link> v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
|
||||
#define <link linkend="V4L2-PIX-FMT-MR97310A">V4L2_PIX_FMT_MR97310A</link> v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */
|
||||
#define <link linkend="V4L2-PIX-FMT-SN9C2028">V4L2_PIX_FMT_SN9C2028</link> v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */
|
||||
#define <link linkend="V4L2-PIX-FMT-SQ905C">V4L2_PIX_FMT_SQ905C</link> v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */
|
||||
#define <link linkend="V4L2-PIX-FMT-PJPG">V4L2_PIX_FMT_PJPG</link> v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
|
||||
#define <link linkend="V4L2-PIX-FMT-OV511">V4L2_PIX_FMT_OV511</link> v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */
|
||||
#define <link linkend="V4L2-PIX-FMT-OV518">V4L2_PIX_FMT_OV518</link> v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */
|
||||
#define <link linkend="V4L2-PIX-FMT-TM6000">V4L2_PIX_FMT_TM6000</link> v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */
|
||||
#define <link linkend="V4L2-PIX-FMT-STV0680">V4L2_PIX_FMT_STV0680</link> v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */
|
||||
#define <link linkend="V4L2-PIX-FMT-TM6000">V4L2_PIX_FMT_TM6000</link> v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */
|
||||
#define <link linkend="V4L2-PIX-FMT-CIT-YYVYUY">V4L2_PIX_FMT_CIT_YYVYUY</link> v4l2_fourcc('C', 'I', 'T', 'V') /* one line of Y then 1 line of VYUY */
|
||||
#define <link linkend="V4L2-PIX-FMT-KONICA420">V4L2_PIX_FMT_KONICA420</link> v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */
|
||||
|
||||
/*
|
||||
* F O R M A T E N U M E R A T I O N
|
||||
|
@ -380,7 +382,7 @@ struct <link linkend="v4l2-fmtdesc">v4l2_fmtdesc</link> {
|
|||
#define V4L2_FMT_FLAG_COMPRESSED 0x0001
|
||||
#define V4L2_FMT_FLAG_EMULATED 0x0002
|
||||
|
||||
#if 1 /*KEEP*/
|
||||
#if 1
|
||||
/* Experimental Frame Size and frame rate enumeration */
|
||||
/*
|
||||
* F R A M E S I Z E E N U M E R A T I O N
|
||||
|
@ -544,6 +546,8 @@ struct <link linkend="v4l2-buffer">v4l2_buffer</link> {
|
|||
#define V4L2_BUF_FLAG_KEYFRAME 0x0008 /* Image is a keyframe (I-frame) */
|
||||
#define V4L2_BUF_FLAG_PFRAME 0x0010 /* Image is a P-frame */
|
||||
#define V4L2_BUF_FLAG_BFRAME 0x0020 /* Image is a B-frame */
|
||||
/* Buffer is ready, but the data contained within is corrupted. */
|
||||
#define V4L2_BUF_FLAG_ERROR 0x0040
|
||||
#define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */
|
||||
#define V4L2_BUF_FLAG_INPUT 0x0200 /* input field is valid */
|
||||
|
||||
|
@ -934,6 +938,16 @@ struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link> {
|
|||
#define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL)
|
||||
#define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000)
|
||||
|
||||
enum <link linkend="v4l2-ctrl-type">v4l2_ctrl_type</link> {
|
||||
V4L2_CTRL_TYPE_INTEGER = 1,
|
||||
V4L2_CTRL_TYPE_BOOLEAN = 2,
|
||||
V4L2_CTRL_TYPE_MENU = 3,
|
||||
V4L2_CTRL_TYPE_BUTTON = 4,
|
||||
V4L2_CTRL_TYPE_INTEGER64 = 5,
|
||||
V4L2_CTRL_TYPE_CTRL_CLASS = 6,
|
||||
V4L2_CTRL_TYPE_STRING = 7,
|
||||
};
|
||||
|
||||
/* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
|
||||
struct <link linkend="v4l2-queryctrl">v4l2_queryctrl</link> {
|
||||
__u32 id;
|
||||
|
@ -1018,21 +1032,27 @@ enum <link linkend="v4l2-colorfx">v4l2_colorfx</link> {
|
|||
V4L2_COLORFX_NONE = 0,
|
||||
V4L2_COLORFX_BW = 1,
|
||||
V4L2_COLORFX_SEPIA = 2,
|
||||
V4L2_COLORFX_NEGATIVE = 3,
|
||||
V4L2_COLORFX_EMBOSS = 4,
|
||||
V4L2_COLORFX_SKETCH = 5,
|
||||
V4L2_COLORFX_SKY_BLUE = 6,
|
||||
V4L2_COLORFX_NEGATIVE = 3,
|
||||
V4L2_COLORFX_EMBOSS = 4,
|
||||
V4L2_COLORFX_SKETCH = 5,
|
||||
V4L2_COLORFX_SKY_BLUE = 6,
|
||||
V4L2_COLORFX_GRASS_GREEN = 7,
|
||||
V4L2_COLORFX_SKIN_WHITEN = 8,
|
||||
V4L2_COLORFX_VIVID = 9.
|
||||
V4L2_COLORFX_VIVID = 9,
|
||||
};
|
||||
#define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32)
|
||||
#define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33)
|
||||
|
||||
#define V4L2_CID_ROTATE (V4L2_CID_BASE+34)
|
||||
#define V4L2_CID_BG_COLOR (V4L2_CID_BASE+35)
|
||||
|
||||
#define V4L2_CID_CHROMA_GAIN (V4L2_CID_BASE+36)
|
||||
|
||||
#define V4L2_CID_ILLUMINATORS_1 (V4L2_CID_BASE+37)
|
||||
#define V4L2_CID_ILLUMINATORS_2 (V4L2_CID_BASE+38)
|
||||
|
||||
/* last CID + 1 */
|
||||
#define V4L2_CID_LASTP1 (V4L2_CID_BASE+36)
|
||||
#define V4L2_CID_LASTP1 (V4L2_CID_BASE+39)
|
||||
|
||||
/* MPEG-class control IDs defined by V4L2 */
|
||||
#define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900)
|
||||
|
@ -1349,6 +1369,8 @@ struct <link linkend="v4l2-modulator">v4l2_modulator</link> {
|
|||
#define V4L2_TUNER_CAP_SAP 0x0020
|
||||
#define V4L2_TUNER_CAP_LANG1 0x0040
|
||||
#define V4L2_TUNER_CAP_RDS 0x0080
|
||||
#define V4L2_TUNER_CAP_RDS_BLOCK_IO 0x0100
|
||||
#define V4L2_TUNER_CAP_RDS_CONTROLS 0x0200
|
||||
|
||||
/* Flags for the 'rxsubchans' field */
|
||||
#define V4L2_TUNER_SUB_MONO 0x0001
|
||||
|
@ -1378,7 +1400,8 @@ struct <link linkend="v4l2-hw-freq-seek">v4l2_hw_freq_seek</link> {
|
|||
enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link> type;
|
||||
__u32 seek_upward;
|
||||
__u32 wrap_around;
|
||||
__u32 reserved[8];
|
||||
__u32 spacing;
|
||||
__u32 reserved[7];
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1433,7 +1456,7 @@ struct <link linkend="v4l2-audioout">v4l2_audioout</link> {
|
|||
*
|
||||
* NOTE: EXPERIMENTAL API
|
||||
*/
|
||||
#if 1 /*KEEP*/
|
||||
#if 1
|
||||
#define V4L2_ENC_IDX_FRAME_I (0)
|
||||
#define V4L2_ENC_IDX_FRAME_P (1)
|
||||
#define V4L2_ENC_IDX_FRAME_B (2)
|
||||
|
@ -1625,6 +1648,38 @@ struct <link linkend="v4l2-streamparm">v4l2_streamparm</link> {
|
|||
} parm;
|
||||
};
|
||||
|
||||
/*
|
||||
* E V E N T S
|
||||
*/
|
||||
|
||||
#define V4L2_EVENT_ALL 0
|
||||
#define V4L2_EVENT_VSYNC 1
|
||||
#define V4L2_EVENT_EOS 2
|
||||
#define V4L2_EVENT_PRIVATE_START 0x08000000
|
||||
|
||||
/* Payload for V4L2_EVENT_VSYNC */
|
||||
struct <link linkend="v4l2-event-vsync">v4l2_event_vsync</link> {
|
||||
/* Can be V4L2_FIELD_ANY, _NONE, _TOP or _BOTTOM */
|
||||
__u8 field;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct <link linkend="v4l2-event">v4l2_event</link> {
|
||||
__u32 type;
|
||||
union {
|
||||
struct <link linkend="v4l2-event-vsync">v4l2_event_vsync</link> vsync;
|
||||
__u8 data[64];
|
||||
} u;
|
||||
__u32 pending;
|
||||
__u32 sequence;
|
||||
struct timespec timestamp;
|
||||
__u32 reserved[9];
|
||||
};
|
||||
|
||||
struct <link linkend="v4l2-event-subscription">v4l2_event_subscription</link> {
|
||||
__u32 type;
|
||||
__u32 reserved[7];
|
||||
};
|
||||
|
||||
/*
|
||||
* A D V A N C E D D E B U G G I N G
|
||||
*
|
||||
|
@ -1720,7 +1775,7 @@ struct <link linkend="v4l2-dbg-chip-ident">v4l2_dbg_chip_ident</link> {
|
|||
#define VIDIOC_G_EXT_CTRLS _IOWR('V', 71, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
|
||||
#define VIDIOC_S_EXT_CTRLS _IOWR('V', 72, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
|
||||
#define VIDIOC_TRY_EXT_CTRLS _IOWR('V', 73, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
|
||||
#if 1 /*KEEP*/
|
||||
#if 1
|
||||
#define VIDIOC_ENUM_FRAMESIZES _IOWR('V', 74, struct <link linkend="v4l2-frmsizeenum">v4l2_frmsizeenum</link>)
|
||||
#define VIDIOC_ENUM_FRAMEINTERVALS _IOWR('V', 75, struct <link linkend="v4l2-frmivalenum">v4l2_frmivalenum</link>)
|
||||
#define VIDIOC_G_ENC_INDEX _IOR('V', 76, struct <link linkend="v4l2-enc-idx">v4l2_enc_idx</link>)
|
||||
|
@ -1728,7 +1783,7 @@ struct <link linkend="v4l2-dbg-chip-ident">v4l2_dbg_chip_ident</link> {
|
|||
#define VIDIOC_TRY_ENCODER_CMD _IOWR('V', 78, struct <link linkend="v4l2-encoder-cmd">v4l2_encoder_cmd</link>)
|
||||
#endif
|
||||
|
||||
#if 1 /*KEEP*/
|
||||
#if 1
|
||||
/* Experimental, meant for debugging, testing and internal use.
|
||||
Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined.
|
||||
You must be root to use these ioctls. Never use these in applications! */
|
||||
|
@ -1747,6 +1802,9 @@ struct <link linkend="v4l2-dbg-chip-ident">v4l2_dbg_chip_ident</link> {
|
|||
#define VIDIOC_QUERY_DV_PRESET _IOR('V', 86, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
|
||||
#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link>)
|
||||
#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link>)
|
||||
#define VIDIOC_DQEVENT _IOR('V', 89, struct <link linkend="v4l2-event">v4l2_event</link>)
|
||||
#define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct <link linkend="v4l2-event-subscription">v4l2_event_subscription</link>)
|
||||
#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct <link linkend="v4l2-event-subscription">v4l2_event_subscription</link>)
|
||||
|
||||
/* Reminder: when adding new ioctls please add support for them to
|
||||
drivers/media/video/v4l2-compat-ioctl32.c as well! */
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>&v4l2-dv-preset;
|
||||
*<parameter>argp</parameter></paramdef>
|
||||
<paramdef>struct v4l2_dv_preset *<parameter>argp</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>&v4l2-dv-timings;
|
||||
*<parameter>argp</parameter></paramdef>
|
||||
<paramdef>struct v4l2_dv_timings *<parameter>argp</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
|
|
@ -16,7 +16,7 @@ input</refpurpose>
|
|||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>&v4l2-dv-preset; *<parameter>argp</parameter></paramdef>
|
||||
<paramdef>struct v4l2_dv_preset *<parameter>argp</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
|
|
@ -184,7 +184,7 @@ data.</entry>
|
|||
<row>
|
||||
<entry><constant>V4L2_CAP_RDS_CAPTURE</constant></entry>
|
||||
<entry>0x00000100</entry>
|
||||
<entry>The device supports the <link linkend="rds">RDS</link> interface.</entry>
|
||||
<entry>The device supports the <link linkend="rds">RDS</link> capture interface.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CAP_VIDEO_OUTPUT_OVERLAY</constant></entry>
|
||||
|
@ -205,6 +205,11 @@ driver capabilities.</para></footnote></entry>
|
|||
<entry>The device supports the &VIDIOC-S-HW-FREQ-SEEK; ioctl for
|
||||
hardware frequency seeking.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CAP_RDS_OUTPUT</constant></entry>
|
||||
<entry>0x00000800</entry>
|
||||
<entry>The device supports the <link linkend="rds">RDS</link> output interface.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CAP_TUNER</constant></entry>
|
||||
<entry>0x00010000</entry>
|
||||
|
|
|
@ -103,8 +103,12 @@ structure. The driver fills the rest of the structure or returns an
|
|||
<structfield>index</structfield> is invalid. Menu items are enumerated
|
||||
by calling <constant>VIDIOC_QUERYMENU</constant> with successive
|
||||
<structfield>index</structfield> values from &v4l2-queryctrl;
|
||||
<structfield>minimum</structfield> (0) to
|
||||
<structfield>maximum</structfield>, inclusive.</para>
|
||||
<structfield>minimum</structfield> to
|
||||
<structfield>maximum</structfield>, inclusive. Note that it is possible
|
||||
for <constant>VIDIOC_QUERYMENU</constant> to return an &EINVAL; for some
|
||||
indices between <structfield>minimum</structfield> and <structfield>maximum</structfield>.
|
||||
In that case that particular menu item is not supported by this driver. Also note that
|
||||
the <structfield>minimum</structfield> value is not necessarily 0.</para>
|
||||
|
||||
<para>See also the examples in <xref linkend="control" />.</para>
|
||||
|
||||
|
@ -139,7 +143,7 @@ string. This information is intended for the user.</entry>
|
|||
<entry><structfield>minimum</structfield></entry>
|
||||
<entry>Minimum value, inclusive. This field gives a lower
|
||||
bound for <constant>V4L2_CTRL_TYPE_INTEGER</constant> controls and the
|
||||
lowest valid index (always 0) for <constant>V4L2_CTRL_TYPE_MENU</constant> controls.
|
||||
lowest valid index for <constant>V4L2_CTRL_TYPE_MENU</constant> controls.
|
||||
For <constant>V4L2_CTRL_TYPE_STRING</constant> controls the minimum value
|
||||
gives the minimum length of the string. This length <emphasis>does not include the terminating
|
||||
zero</emphasis>. It may not be valid for any other type of control, including
|
||||
|
@ -279,7 +283,7 @@ values which are actually different on the hardware.</entry>
|
|||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CTRL_TYPE_MENU</constant></entry>
|
||||
<entry>0</entry>
|
||||
<entry>≥ 0</entry>
|
||||
<entry>1</entry>
|
||||
<entry>N-1</entry>
|
||||
<entry>The control has a menu of N choices. The names of
|
||||
|
@ -405,8 +409,10 @@ writing a value will cause the device to carry out a given action
|
|||
<term><errorcode>EINVAL</errorcode></term>
|
||||
<listitem>
|
||||
<para>The &v4l2-queryctrl; <structfield>id</structfield>
|
||||
is invalid. The &v4l2-querymenu; <structfield>id</structfield> or
|
||||
<structfield>index</structfield> is invalid.</para>
|
||||
is invalid. The &v4l2-querymenu; <structfield>id</structfield> is
|
||||
invalid or <structfield>index</structfield> is out of range (less than
|
||||
<structfield>minimum</structfield> or greater than <structfield>maximum</structfield>)
|
||||
or this particular menu item is not supported by the driver.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
|
|
|
@ -51,7 +51,8 @@
|
|||
|
||||
<para>Start a hardware frequency seek from the current frequency.
|
||||
To do this applications initialize the <structfield>tuner</structfield>,
|
||||
<structfield>type</structfield>, <structfield>seek_upward</structfield> and
|
||||
<structfield>type</structfield>, <structfield>seek_upward</structfield>,
|
||||
<structfield>spacing</structfield> and
|
||||
<structfield>wrap_around</structfield> fields, and zero out the
|
||||
<structfield>reserved</structfield> array of a &v4l2-hw-freq-seek; and
|
||||
call the <constant>VIDIOC_S_HW_FREQ_SEEK</constant> ioctl with a pointer
|
||||
|
@ -89,7 +90,12 @@ field and the &v4l2-tuner; <structfield>index</structfield> field.</entry>
|
|||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>reserved</structfield>[8]</entry>
|
||||
<entry><structfield>spacing</structfield></entry>
|
||||
<entry>If non-zero, defines the hardware seek resolution in Hz. The driver selects the nearest value that is supported by the device. If spacing is zero a reasonable default value is used.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>reserved</structfield>[7]</entry>
|
||||
<entry>Reserved for future extensions. Drivers and
|
||||
applications must set the array to zero.</entry>
|
||||
</row>
|
||||
|
|
|
@ -1496,9 +1496,6 @@ Your cooperation is appreciated.
|
|||
64 = /dev/radio0 Radio device
|
||||
...
|
||||
127 = /dev/radio63 Radio device
|
||||
192 = /dev/vtx0 Teletext device
|
||||
...
|
||||
223 = /dev/vtx31 Teletext device
|
||||
224 = /dev/vbi0 Vertical blank interrupt
|
||||
...
|
||||
255 = /dev/vbi31 Vertical blank interrupt
|
||||
|
|
|
@ -26,7 +26,8 @@ use IO::Handle;
|
|||
"dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004",
|
||||
"or51211", "or51132_qam", "or51132_vsb", "bluebird",
|
||||
"opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718",
|
||||
"af9015", "ngene", "az6027");
|
||||
"af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395",
|
||||
"lme2510c_s7395_old");
|
||||
|
||||
# Check args
|
||||
syntax() if (scalar(@ARGV) != 1);
|
||||
|
@ -584,6 +585,49 @@ sub az6027{
|
|||
|
||||
$firmware;
|
||||
}
|
||||
|
||||
sub lme2510_lg {
|
||||
my $sourcefile = "LMEBDA_DVBS.sys";
|
||||
my $hash = "fc6017ad01e79890a97ec53bea157ed2";
|
||||
my $outfile = "dvb-usb-lme2510-lg.fw";
|
||||
my $hasho = "caa065d5fdbd2c09ad57b399bbf55cad";
|
||||
|
||||
checkstandard();
|
||||
|
||||
verify($sourcefile, $hash);
|
||||
extract($sourcefile, 4168, 3841, $outfile);
|
||||
verify($outfile, $hasho);
|
||||
$outfile;
|
||||
}
|
||||
|
||||
sub lme2510c_s7395 {
|
||||
my $sourcefile = "US2A0D.sys";
|
||||
my $hash = "b0155a8083fb822a3bd47bc360e74601";
|
||||
my $outfile = "dvb-usb-lme2510c-s7395.fw";
|
||||
my $hasho = "3a3cf1aeebd17b6ddc04cebe131e94cf";
|
||||
|
||||
checkstandard();
|
||||
|
||||
verify($sourcefile, $hash);
|
||||
extract($sourcefile, 37248, 3720, $outfile);
|
||||
verify($outfile, $hasho);
|
||||
$outfile;
|
||||
}
|
||||
|
||||
sub lme2510c_s7395_old {
|
||||
my $sourcefile = "LMEBDA_DVBS7395C.sys";
|
||||
my $hash = "7572ae0eb9cdf91baabd7c0ba9e09b31";
|
||||
my $outfile = "dvb-usb-lme2510c-s7395.fw";
|
||||
my $hasho = "90430c5b435eb5c6f88fd44a9d950674";
|
||||
|
||||
checkstandard();
|
||||
|
||||
verify($sourcefile, $hash);
|
||||
extract($sourcefile, 4208, 3881, $outfile);
|
||||
verify($outfile, $hasho);
|
||||
$outfile;
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Utilities
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
To extract firmware for the DM04/QQBOX you need to copy the
|
||||
following file(s) to this directory.
|
||||
|
||||
for DM04+/QQBOX LME2510C (Sharp 7395 Tuner)
|
||||
-------------------------------------------
|
||||
|
||||
The Sharp 7395 driver can be found in windows/system32/driver
|
||||
|
||||
US2A0D.sys (dated 17 Mar 2009)
|
||||
|
||||
|
||||
and run
|
||||
./get_dvb_firmware lme2510c_s7395
|
||||
|
||||
will produce
|
||||
dvb-usb-lme2510c-s7395.fw
|
||||
|
||||
An alternative but older firmware can be found on the driver
|
||||
disk DVB-S_EN_3.5A in BDADriver/driver
|
||||
|
||||
LMEBDA_DVBS7395C.sys (dated 18 Jan 2008)
|
||||
|
||||
and run
|
||||
./get_dvb_firmware lme2510c_s7395_old
|
||||
|
||||
will produce
|
||||
dvb-usb-lme2510c-s7395.fw
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
The LG firmware can be found on the driver
|
||||
disk DM04+_5.1A[LG] in BDADriver/driver
|
||||
|
||||
for DM04 LME2510 (LG Tuner)
|
||||
---------------------------
|
||||
|
||||
LMEBDA_DVBS.sys (dated 13 Nov 2007)
|
||||
|
||||
and run
|
||||
./get_dvb_firmware lme2510_lg
|
||||
|
||||
will produce
|
||||
dvb-usb-lme2510-lg.fw
|
||||
|
||||
|
||||
Other LG firmware can be extracted manually from US280D.sys
|
||||
only found in windows/system32/driver.
|
||||
|
||||
dd if=US280D.sys ibs=1 skip=42616 count=3668 of=dvb-usb-lme2510-lg.fw
|
||||
|
||||
for DM04 LME2510C (LG Tuner)
|
||||
---------------------------
|
||||
|
||||
dd if=US280D.sys ibs=1 skip=35200 count=3850 of=dvb-usb-lme2510c-lg.fw
|
||||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Copy the firmware file(s) to /lib/firmware
|
|
@ -98,7 +98,7 @@ Who: Pavel Machek <pavel@ucw.cz>
|
|||
---------------------------
|
||||
|
||||
What: Video4Linux API 1 ioctls and from Video devices.
|
||||
When: July 2009
|
||||
When: kernel 2.6.38
|
||||
Files: include/linux/videodev.h
|
||||
Check: include/linux/videodev.h
|
||||
Why: V4L1 AP1 was replaced by V4L2 API during migration from 2.4 to 2.6
|
||||
|
@ -116,6 +116,21 @@ Who: Mauro Carvalho Chehab <mchehab@infradead.org>
|
|||
|
||||
---------------------------
|
||||
|
||||
What: Video4Linux obsolete drivers using V4L1 API
|
||||
When: kernel 2.6.38
|
||||
Files: drivers/staging/cpia/* drivers/staging/stradis/*
|
||||
Check: drivers/staging/cpia/cpia.c drivers/staging/stradis/stradis.c
|
||||
Why: There are some drivers still using V4L1 API, despite all efforts we've done
|
||||
to migrate. Those drivers are for obsolete hardware that the old maintainer
|
||||
didn't care (or not have the hardware anymore), and that no other developer
|
||||
could find any hardware to buy. They probably have no practical usage today,
|
||||
and people with such old hardware could probably keep using an older version
|
||||
of the kernel. Those drivers will be moved to staging on 2.6.37 and, if nobody
|
||||
care enough to port and test them with V4L2 API, they'll be removed on 2.6.38.
|
||||
Who: Mauro Carvalho Chehab <mchehab@infradead.org>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: sys_sysctl
|
||||
When: September 2010
|
||||
Option: CONFIG_SYSCTL_SYSCALL
|
||||
|
@ -470,29 +485,6 @@ When: April 2011
|
|||
Why: Superseded by xt_CT
|
||||
Who: Netfilter developer team <netfilter-devel@vger.kernel.org>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: video4linux /dev/vtx teletext API support
|
||||
When: 2.6.35
|
||||
Files: drivers/media/video/saa5246a.c drivers/media/video/saa5249.c
|
||||
include/linux/videotext.h
|
||||
Why: The vtx device nodes have been superseded by vbi device nodes
|
||||
for many years. No applications exist that use the vtx support.
|
||||
Of the two i2c drivers that actually support this API the saa5249
|
||||
has been impossible to use for a year now and no known hardware
|
||||
that supports this device exists. The saa5246a is theoretically
|
||||
supported by the old mxb boards, but it never actually worked.
|
||||
|
||||
In summary: there is no hardware that can use this API and there
|
||||
are no applications actually implementing this API.
|
||||
|
||||
The vtx support still reserves minors 192-223 and we would really
|
||||
like to reuse those for upcoming new functionality. In the unlikely
|
||||
event that new hardware appears that wants to use the functionality
|
||||
provided by the vtx API, then that functionality should be build
|
||||
around the sliced VBI API instead.
|
||||
Who: Hans Verkuil <hverkuil@xs4all.nl>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: IRQF_DISABLED
|
||||
|
|
|
@ -278,7 +278,6 @@ Code Seq#(hex) Include File Comments
|
|||
<mailto:oe@port.de>
|
||||
'z' 10-4F drivers/s390/crypto/zcrypt_api.h conflict!
|
||||
0x80 00-1F linux/fb.h
|
||||
0x81 00-1F linux/videotext.h
|
||||
0x88 00-3F media/ovcamchip.h
|
||||
0x89 00-06 arch/x86/include/asm/sockios.h
|
||||
0x89 0B-DF linux/sockios.h
|
||||
|
|
|
@ -83,3 +83,4 @@
|
|||
82 -> WinFast DTV2000 H rev. J [107d:6f2b]
|
||||
83 -> Prof 7301 DVB-S/S2 [b034:3034]
|
||||
84 -> Samsung SMT 7020 DVB-S [18ac:dc00,18ac:dccd]
|
||||
85 -> Twinhan VP-1027 DVB-S [1822:0023]
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
30 -> Videology 20K14XUSB USB2.0 (em2820/em2840)
|
||||
31 -> Usbgear VD204v9 (em2821)
|
||||
32 -> Supercomp USB 2.0 TV (em2821)
|
||||
33 -> Elgato Video Capture (em2860) [0fd9:0033]
|
||||
34 -> Terratec Cinergy A Hybrid XS (em2860) [0ccd:004f]
|
||||
35 -> Typhoon DVD Maker (em2860)
|
||||
36 -> NetGMBH Cam (em2860)
|
||||
|
@ -45,7 +46,7 @@
|
|||
45 -> Pinnacle PCTV DVB-T (em2870)
|
||||
46 -> Compro, VideoMate U3 (em2870) [185b:2870]
|
||||
47 -> KWorld DVB-T 305U (em2880) [eb1a:e305]
|
||||
48 -> KWorld DVB-T 310U (em2880) [eb1a:e310]
|
||||
48 -> KWorld DVB-T 310U (em2880)
|
||||
49 -> MSI DigiVox A/D (em2880) [eb1a:e310]
|
||||
50 -> MSI DigiVox A/D II (em2880) [eb1a:e320]
|
||||
51 -> Terratec Hybrid XS Secam (em2880) [0ccd:004c]
|
||||
|
|
|
@ -126,7 +126,7 @@
|
|||
125 -> Beholder BeholdTV 409 [0000:4090]
|
||||
126 -> Beholder BeholdTV 505 FM [5ace:5050]
|
||||
127 -> Beholder BeholdTV 507 FM / BeholdTV 509 FM [5ace:5070,5ace:5090]
|
||||
128 -> Beholder BeholdTV Columbus TVFM [0000:5201]
|
||||
128 -> Beholder BeholdTV Columbus TV/FM [0000:5201]
|
||||
129 -> Beholder BeholdTV 607 FM [5ace:6070]
|
||||
130 -> Beholder BeholdTV M6 [5ace:6190]
|
||||
131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022]
|
||||
|
|
|
@ -19,7 +19,6 @@ function makedev () {
|
|||
echo "*** new device names ***"
|
||||
makedev video 0
|
||||
makedev radio 64
|
||||
makedev vtx 192
|
||||
makedev vbi 224
|
||||
|
||||
#echo "*** old device names (for compatibility only) ***"
|
||||
|
|
|
@ -302,12 +302,14 @@ sonixj 0c45:60fb Surfer NoName
|
|||
sonixj 0c45:60fc LG-LIC300
|
||||
sonixj 0c45:60fe Microdia Audio
|
||||
sonixj 0c45:6100 PC Camera (SN9C128)
|
||||
sonixj 0c45:6102 PC Camera (SN9C128)
|
||||
sonixj 0c45:610a PC Camera (SN9C128)
|
||||
sonixj 0c45:610b PC Camera (SN9C128)
|
||||
sonixj 0c45:610c PC Camera (SN9C128)
|
||||
sonixj 0c45:610e PC Camera (SN9C128)
|
||||
sonixj 0c45:6128 Microdia/Sonix SNP325
|
||||
sonixj 0c45:612a Avant Camera
|
||||
sonixj 0c45:612b Speed-Link REFLECT2
|
||||
sonixj 0c45:612c Typhoon Rasy Cam 1.3MPix
|
||||
sonixj 0c45:6130 Sonix Pccam
|
||||
sonixj 0c45:6138 Sn9c120 Mo4000
|
||||
|
|
|
@ -44,8 +44,8 @@ All drivers have the following structure:
|
|||
|
||||
2) A way of initializing and commanding sub-devices (if any).
|
||||
|
||||
3) Creating V4L2 device nodes (/dev/videoX, /dev/vbiX, /dev/radioX and
|
||||
/dev/vtxX) and keeping track of device-node specific data.
|
||||
3) Creating V4L2 device nodes (/dev/videoX, /dev/vbiX and /dev/radioX)
|
||||
and keeping track of device-node specific data.
|
||||
|
||||
4) Filehandle-specific structs containing per-filehandle data;
|
||||
|
||||
|
@ -192,6 +192,11 @@ You also need a way to go from the low-level struct to v4l2_subdev. For the
|
|||
common i2c_client struct the i2c_set_clientdata() call is used to store a
|
||||
v4l2_subdev pointer, for other busses you may have to use other methods.
|
||||
|
||||
Bridges might also need to store per-subdev private data, such as a pointer to
|
||||
bridge-specific per-subdev private data. The v4l2_subdev structure provides
|
||||
host private data for that purpose that can be accessed with
|
||||
v4l2_get_subdev_hostdata() and v4l2_set_subdev_hostdata().
|
||||
|
||||
From the bridge driver perspective you load the sub-device module and somehow
|
||||
obtain the v4l2_subdev pointer. For i2c devices this is easy: you call
|
||||
i2c_get_clientdata(). For other busses something similar needs to be done.
|
||||
|
@ -448,6 +453,10 @@ You should also set these fields:
|
|||
- ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance
|
||||
(highly recommended to use this and it might become compulsory in the
|
||||
future!), then set this to your v4l2_ioctl_ops struct.
|
||||
- lock: leave to NULL if you want to do all the locking in the driver.
|
||||
Otherwise you give it a pointer to a struct mutex_lock and before any
|
||||
of the v4l2_file_operations is called this lock will be taken by the
|
||||
core and released afterwards.
|
||||
- parent: you only set this if v4l2_device was registered with NULL as
|
||||
the parent device struct. This only happens in cases where one hardware
|
||||
device has multiple PCI devices that all share the same v4l2_device core.
|
||||
|
@ -464,6 +473,22 @@ If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or
|
|||
The v4l2_file_operations struct is a subset of file_operations. The main
|
||||
difference is that the inode argument is omitted since it is never used.
|
||||
|
||||
v4l2_file_operations and locking
|
||||
--------------------------------
|
||||
|
||||
You can set a pointer to a mutex_lock in struct video_device. Usually this
|
||||
will be either a top-level mutex or a mutex per device node. If you want
|
||||
finer-grained locking then you have to set it to NULL and do you own locking.
|
||||
|
||||
If a lock is specified then all file operations will be serialized on that
|
||||
lock. If you use videobuf then you must pass the same lock to the videobuf
|
||||
queue initialize function: if videobuf has to wait for a frame to arrive, then
|
||||
it will temporarily unlock the lock and relock it afterwards. If your driver
|
||||
also waits in the code, then you should do the same to allow other processes
|
||||
to access the device node while the first process is waiting for something.
|
||||
|
||||
The implementation of a hotplug disconnect should also take the lock before
|
||||
calling v4l2_device_disconnect.
|
||||
|
||||
video_device registration
|
||||
-------------------------
|
||||
|
@ -483,7 +508,6 @@ types exist:
|
|||
VFL_TYPE_GRABBER: videoX for video input/output devices
|
||||
VFL_TYPE_VBI: vbiX for vertical blank data (i.e. closed captions, teletext)
|
||||
VFL_TYPE_RADIO: radioX for radio tuners
|
||||
VFL_TYPE_VTX: vtxX for teletext devices (deprecated, don't use)
|
||||
|
||||
The last argument gives you a certain amount of control over the device
|
||||
device node number used (i.e. the X in videoX). Normally you will pass -1
|
||||
|
@ -547,9 +571,8 @@ from /dev).
|
|||
|
||||
After video_unregister_device() returns no new opens can be done. However,
|
||||
in the case of USB devices some application might still have one of these
|
||||
device nodes open. So after the unregister all file operations will return
|
||||
an error as well, except for the ioctl and unlocked_ioctl file operations:
|
||||
those will still be passed on since some buffer ioctls may still be needed.
|
||||
device nodes open. So after the unregister all file operations (except
|
||||
release, of course) will return an error as well.
|
||||
|
||||
When the last user of the video device node exits, then the vdev->release()
|
||||
callback is called and you can do the final cleanup there.
|
||||
|
|
|
@ -311,7 +311,6 @@ static struct soc_camera_link iclink_mt9v022 = {
|
|||
.bus_id = 0, /* Must match with the camera ID */
|
||||
.board_info = &pcm037_i2c_camera[1],
|
||||
.i2c_adapter_id = 2,
|
||||
.module_name = "mt9v022",
|
||||
};
|
||||
|
||||
static struct soc_camera_link iclink_mt9t031 = {
|
||||
|
@ -319,7 +318,6 @@ static struct soc_camera_link iclink_mt9t031 = {
|
|||
.power = pcm037_camera_power,
|
||||
.board_info = &pcm037_i2c_camera[0],
|
||||
.i2c_adapter_id = 2,
|
||||
.module_name = "mt9t031",
|
||||
};
|
||||
|
||||
static struct i2c_board_info pcm037_i2c_devices[] = {
|
||||
|
|
|
@ -179,7 +179,6 @@ static struct soc_camera_link base_iclink = {
|
|||
.reset = marxbot_basecam_reset,
|
||||
.board_info = &marxbot_i2c_devices[0],
|
||||
.i2c_adapter_id = 0,
|
||||
.module_name = "mt9t031",
|
||||
};
|
||||
|
||||
static struct platform_device marxbot_camera[] = {
|
||||
|
|
|
@ -88,7 +88,6 @@ static struct soc_camera_link base_iclink = {
|
|||
.reset = smartbot_cam_reset,
|
||||
.board_info = &smartbot_i2c_devices[0],
|
||||
.i2c_adapter_id = 0,
|
||||
.module_name = "mt9t031",
|
||||
};
|
||||
|
||||
static struct platform_device smartbot_camera[] = {
|
||||
|
|
|
@ -1015,7 +1015,6 @@ static struct soc_camera_link iclink = {
|
|||
.power = em_x270_sensor_power,
|
||||
.board_info = &em_x270_i2c_cam_info[0],
|
||||
.i2c_adapter_id = 0,
|
||||
.module_name = "mt9m111",
|
||||
};
|
||||
|
||||
static struct platform_device em_x270_camera = {
|
||||
|
|
|
@ -755,7 +755,6 @@ static struct soc_camera_link a780_iclink = {
|
|||
.flags = SOCAM_SENSOR_INVERT_PCLK,
|
||||
.i2c_adapter_id = 0,
|
||||
.board_info = &a780_camera_i2c_board_info,
|
||||
.module_name = "mt9m111",
|
||||
.power = a780_camera_power,
|
||||
.reset = a780_camera_reset,
|
||||
};
|
||||
|
@ -1024,7 +1023,6 @@ static struct soc_camera_link a910_iclink = {
|
|||
.bus_id = 0,
|
||||
.i2c_adapter_id = 0,
|
||||
.board_info = &a910_camera_i2c_board_info,
|
||||
.module_name = "mt9m111",
|
||||
.power = a910_camera_power,
|
||||
.reset = a910_camera_reset,
|
||||
};
|
||||
|
|
|
@ -711,7 +711,6 @@ static struct soc_camera_link iclink = {
|
|||
.bus_id = 0, /* Match id in pxa27x_device_camera in device.c */
|
||||
.board_info = &mioa701_i2c_devices[0],
|
||||
.i2c_adapter_id = 0,
|
||||
.module_name = "mt9m111",
|
||||
};
|
||||
|
||||
struct i2c_pxa_platform_data i2c_pdata = {
|
||||
|
|
|
@ -453,7 +453,6 @@ static struct soc_camera_link iclink[] = {
|
|||
.query_bus_param = pcm990_camera_query_bus_param,
|
||||
.set_bus_param = pcm990_camera_set_bus_param,
|
||||
.free_bus = pcm990_camera_free_bus,
|
||||
.module_name = "mt9v022",
|
||||
}, {
|
||||
.bus_id = 0, /* Must match with the camera ID */
|
||||
.board_info = &pcm990_camera_i2c[1],
|
||||
|
@ -461,7 +460,6 @@ static struct soc_camera_link iclink[] = {
|
|||
.query_bus_param = pcm990_camera_query_bus_param,
|
||||
.set_bus_param = pcm990_camera_set_bus_param,
|
||||
.free_bus = pcm990_camera_free_bus,
|
||||
.module_name = "mt9m001",
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -481,7 +481,6 @@ static struct soc_camera_link ov7725_link = {
|
|||
.power = ov7725_power,
|
||||
.board_info = &ap325rxa_i2c_camera[0],
|
||||
.i2c_adapter_id = 0,
|
||||
.module_name = "ov772x",
|
||||
.priv = &ov7725_info,
|
||||
};
|
||||
|
||||
|
|
|
@ -620,7 +620,6 @@ static struct soc_camera_link tw9910_link = {
|
|||
.bus_id = 1,
|
||||
.power = tw9910_power,
|
||||
.board_info = &i2c_camera[0],
|
||||
.module_name = "tw9910",
|
||||
.priv = &tw9910_info,
|
||||
};
|
||||
|
||||
|
@ -644,7 +643,6 @@ static struct soc_camera_link mt9t112_link1 = {
|
|||
.power = mt9t112_power1,
|
||||
.bus_id = 0,
|
||||
.board_info = &i2c_camera[1],
|
||||
.module_name = "mt9t112",
|
||||
.priv = &mt9t112_info1,
|
||||
};
|
||||
|
||||
|
@ -667,7 +665,6 @@ static struct soc_camera_link mt9t112_link2 = {
|
|||
.power = mt9t112_power2,
|
||||
.bus_id = 1,
|
||||
.board_info = &i2c_camera[2],
|
||||
.module_name = "mt9t112",
|
||||
.priv = &mt9t112_info2,
|
||||
};
|
||||
|
||||
|
@ -793,7 +790,6 @@ static struct sh_vou_pdata sh_vou_pdata = {
|
|||
.flags = SH_VOU_HSYNC_LOW | SH_VOU_VSYNC_LOW,
|
||||
.board_info = &ak8813,
|
||||
.i2c_adap = 0,
|
||||
.module_name = "ak881x",
|
||||
};
|
||||
|
||||
static struct resource sh_vou_resources[] = {
|
||||
|
|
|
@ -333,7 +333,6 @@ static struct soc_camera_link rj54n1_link = {
|
|||
.power = camera_power,
|
||||
.board_info = &kfr2r09_i2c_camera,
|
||||
.i2c_adapter_id = 1,
|
||||
.module_name = "rj54n1cb0c",
|
||||
.priv = &rj54n1_priv,
|
||||
};
|
||||
|
||||
|
|
|
@ -450,7 +450,6 @@ static struct soc_camera_link ov7725_link = {
|
|||
.power = ov7725_power,
|
||||
.board_info = &migor_i2c_camera[0],
|
||||
.i2c_adapter_id = 0,
|
||||
.module_name = "ov772x",
|
||||
.priv = &ov7725_info,
|
||||
};
|
||||
|
||||
|
@ -463,7 +462,6 @@ static struct soc_camera_link tw9910_link = {
|
|||
.power = tw9910_power,
|
||||
.board_info = &migor_i2c_camera[1],
|
||||
.i2c_adapter_id = 0,
|
||||
.module_name = "tw9910",
|
||||
.priv = &tw9910_info,
|
||||
};
|
||||
|
||||
|
|
|
@ -550,7 +550,6 @@ static struct sh_vou_pdata sh_vou_pdata = {
|
|||
.flags = SH_VOU_HSYNC_LOW | SH_VOU_VSYNC_LOW,
|
||||
.board_info = &ak8813,
|
||||
.i2c_adap = 0,
|
||||
.module_name = "ak881x",
|
||||
};
|
||||
|
||||
static struct resource sh_vou_resources[] = {
|
||||
|
|
|
@ -79,6 +79,18 @@ config IR_SONY_DECODER
|
|||
Enable this option if you have an infrared remote control which
|
||||
uses the Sony protocol, and you need software decoding support.
|
||||
|
||||
config IR_RC5_SZ_DECODER
|
||||
tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol"
|
||||
depends on IR_CORE
|
||||
select BITREVERSE
|
||||
default y
|
||||
|
||||
---help---
|
||||
Enable this option if you have IR with RC-5 (streamzap) protocol,
|
||||
and if the IR is decoded in software. (The Streamzap PC Remote
|
||||
uses an IR protocol that is almost standard RC-5, but not quite,
|
||||
as it uses an additional bit).
|
||||
|
||||
config IR_LIRC_CODEC
|
||||
tristate "Enable IR to LIRC bridge"
|
||||
depends on IR_CORE
|
||||
|
@ -89,6 +101,20 @@ config IR_LIRC_CODEC
|
|||
Enable this option to pass raw IR to and from userspace via
|
||||
the LIRC interface.
|
||||
|
||||
config IR_ENE
|
||||
tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)"
|
||||
depends on PNP
|
||||
depends on IR_CORE
|
||||
---help---
|
||||
Say Y here to enable support for integrated infrared receiver
|
||||
/transceiver made by ENE.
|
||||
|
||||
You can see if you have it by looking at lspnp output.
|
||||
Output should include ENE0100 ENE0200 or something similar.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ene_ir.
|
||||
|
||||
config IR_IMON
|
||||
tristate "SoundGraph iMON Receiver and Display"
|
||||
depends on USB_ARCH_HAS_HCD
|
||||
|
@ -113,19 +139,18 @@ config IR_MCEUSB
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called mceusb.
|
||||
|
||||
config IR_ENE
|
||||
tristate "ENE eHome Receiver/Transciever (pnp id: ENE0100/ENE02xxx)"
|
||||
config IR_NUVOTON
|
||||
tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
|
||||
depends on PNP
|
||||
depends on IR_CORE
|
||||
---help---
|
||||
Say Y here to enable support for integrated infrared receiver
|
||||
/transciever made by ENE.
|
||||
|
||||
You can see if you have it by looking at lspnp output.
|
||||
Output should include ENE0100 ENE0200 or something similiar.
|
||||
/transciever made by Nuvoton (formerly Winbond). This chip is
|
||||
found in the ASRock ION 330HT, as well as assorted Intel
|
||||
DP55-series motherboards (and of course, possibly others).
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ene_ir.
|
||||
module will be called nuvoton-cir.
|
||||
|
||||
config IR_STREAMZAP
|
||||
tristate "Streamzap PC Remote IR Receiver"
|
||||
|
|
|
@ -11,10 +11,12 @@ obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
|
|||
obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
|
||||
obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
|
||||
obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
|
||||
obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
|
||||
obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
|
||||
|
||||
# stand-alone IR receivers/transmitters
|
||||
obj-$(CONFIG_IR_IMON) += imon.o
|
||||
obj-$(CONFIG_IR_MCEUSB) += mceusb.o
|
||||
obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
|
||||
obj-$(CONFIG_IR_ENE) += ene_ir.o
|
||||
obj-$(CONFIG_IR_STREAMZAP) += streamzap.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* driver for ENE KB3926 B/C/D CIR (also known as ENE0XXX)
|
||||
* driver for ENE KB3926 B/C/D/E/F CIR (also known as ENE0XXX)
|
||||
*
|
||||
* Copyright (C) 2010 Maxim Levitsky <maximlevitsky@gmail.com>
|
||||
*
|
||||
|
@ -26,43 +26,50 @@
|
|||
#define ENE_ADDR_HI 1 /* hi byte of register address */
|
||||
#define ENE_ADDR_LO 2 /* low byte of register address */
|
||||
#define ENE_IO 3 /* read/write window */
|
||||
#define ENE_MAX_IO 4
|
||||
#define ENE_IO_SIZE 4
|
||||
|
||||
/* 8 bytes of samples, divided in 2 halfs*/
|
||||
#define ENE_SAMPLE_BUFFER 0xF8F0 /* regular sample buffer */
|
||||
#define ENE_SAMPLE_SPC_MASK 0x80 /* sample is space */
|
||||
#define ENE_SAMPLE_VALUE_MASK 0x7F
|
||||
#define ENE_SAMPLE_OVERFLOW 0x7F
|
||||
#define ENE_SAMPLES_SIZE 4
|
||||
/* 8 bytes of samples, divided in 2 packets*/
|
||||
#define ENE_FW_SAMPLE_BUFFER 0xF8F0 /* sample buffer */
|
||||
#define ENE_FW_SAMPLE_SPACE 0x80 /* sample is space */
|
||||
#define ENE_FW_PACKET_SIZE 4
|
||||
|
||||
/* fan input sample buffer */
|
||||
#define ENE_SAMPLE_BUFFER_FAN 0xF8FB /* this buffer holds high byte of */
|
||||
/* each sample of normal buffer */
|
||||
#define ENE_FAN_SMPL_PULS_MSK 0x8000 /* this bit of combined sample */
|
||||
/* if set, says that sample is pulse */
|
||||
#define ENE_FAN_VALUE_MASK 0x0FFF /* mask for valid bits of the value */
|
||||
|
||||
/* first firmware register */
|
||||
#define ENE_FW1 0xF8F8
|
||||
/* first firmware flag register */
|
||||
#define ENE_FW1 0xF8F8 /* flagr */
|
||||
#define ENE_FW1_ENABLE 0x01 /* enable fw processing */
|
||||
#define ENE_FW1_TXIRQ 0x02 /* TX interrupt pending */
|
||||
#define ENE_FW1_HAS_EXTRA_BUF 0x04 /* fw uses extra buffer*/
|
||||
#define ENE_FW1_EXTRA_BUF_HND 0x08 /* extra buffer handshake bit*/
|
||||
#define ENE_FW1_LED_ON 0x10 /* turn on a led */
|
||||
|
||||
#define ENE_FW1_WPATTERN 0x20 /* enable wake pattern */
|
||||
#define ENE_FW1_WAKE 0x40 /* enable wake from S3 */
|
||||
#define ENE_FW1_IRQ 0x80 /* enable interrupt */
|
||||
|
||||
/* second firmware register */
|
||||
#define ENE_FW2 0xF8F9
|
||||
#define ENE_FW2_BUF_HIGH 0x01 /* which half of the buffer to read */
|
||||
#define ENE_FW2_IRQ_CLR 0x04 /* clear this on IRQ */
|
||||
#define ENE_FW2_GP40_AS_LEARN 0x08 /* normal input is used as */
|
||||
/* learning input */
|
||||
#define ENE_FW2_FAN_AS_NRML_IN 0x40 /* fan is used as normal input */
|
||||
/* second firmware flag register */
|
||||
#define ENE_FW2 0xF8F9 /* flagw */
|
||||
#define ENE_FW2_BUF_WPTR 0x01 /* which half of the buffer to read */
|
||||
#define ENE_FW2_RXIRQ 0x04 /* RX IRQ pending*/
|
||||
#define ENE_FW2_GP0A 0x08 /* Use GPIO0A for demodulated input */
|
||||
#define ENE_FW2_EMMITER1_CONN 0x10 /* TX emmiter 1 connected */
|
||||
#define ENE_FW2_EMMITER2_CONN 0x20 /* TX emmiter 2 connected */
|
||||
|
||||
#define ENE_FW2_FAN_INPUT 0x40 /* fan input used for demodulated data*/
|
||||
#define ENE_FW2_LEARNING 0x80 /* hardware supports learning and TX */
|
||||
|
||||
/* firmware RX pointer for new style buffer */
|
||||
#define ENE_FW_RX_POINTER 0xF8FA
|
||||
|
||||
/* high parts of samples for fan input (8 samples)*/
|
||||
#define ENE_FW_SMPL_BUF_FAN 0xF8FB
|
||||
#define ENE_FW_SMPL_BUF_FAN_PLS 0x8000 /* combined sample is pulse */
|
||||
#define ENE_FW_SMPL_BUF_FAN_MSK 0x0FFF /* combined sample maximum value */
|
||||
#define ENE_FW_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */
|
||||
|
||||
/* transmitter ports */
|
||||
#define ENE_TX_PORT2 0xFC01 /* this enables one or both */
|
||||
#define ENE_TX_PORT2_EN 0x20 /* TX ports */
|
||||
#define ENE_TX_PORT1 0xFC08
|
||||
#define ENE_TX_PORT1_EN 0x02
|
||||
#define ENE_GPIOFS1 0xFC01
|
||||
#define ENE_GPIOFS1_GPIO0D 0x20 /* enable tx output on GPIO0D */
|
||||
#define ENE_GPIOFS8 0xFC08
|
||||
#define ENE_GPIOFS8_GPIO41 0x02 /* enable tx output on GPIO40 */
|
||||
|
||||
/* IRQ registers block (for revision B) */
|
||||
#define ENEB_IRQ 0xFD09 /* IRQ number */
|
||||
|
@ -70,98 +77,100 @@
|
|||
#define ENEB_IRQ_STATUS 0xFD80 /* irq status */
|
||||
#define ENEB_IRQ_STATUS_IR 0x20 /* IR irq */
|
||||
|
||||
/* fan as input settings - only if learning capable */
|
||||
/* fan as input settings */
|
||||
#define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */
|
||||
#define ENE_FAN_AS_IN1_EN 0xCD
|
||||
#define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */
|
||||
#define ENE_FAN_AS_IN2_EN 0x03
|
||||
#define ENE_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */
|
||||
|
||||
/* IRQ registers block (for revision C,D) */
|
||||
#define ENEC_IRQ 0xFE9B /* new irq settings register */
|
||||
#define ENEC_IRQ_MASK 0x0F /* irq number mask */
|
||||
#define ENEC_IRQ_UNK_EN 0x10 /* always enabled */
|
||||
#define ENEC_IRQ_STATUS 0x20 /* irq status and ACK */
|
||||
#define ENE_IRQ 0xFE9B /* new irq settings register */
|
||||
#define ENE_IRQ_MASK 0x0F /* irq number mask */
|
||||
#define ENE_IRQ_UNK_EN 0x10 /* always enabled */
|
||||
#define ENE_IRQ_STATUS 0x20 /* irq status and ACK */
|
||||
|
||||
/* CIR block settings */
|
||||
#define ENE_CIR_CONF1 0xFEC0
|
||||
#define ENE_CIR_CONF1_TX_CLEAR 0x01 /* clear that on revC */
|
||||
/* while transmitting */
|
||||
#define ENE_CIR_CONF1_RX_ON 0x07 /* normal receiver enabled */
|
||||
#define ENE_CIR_CONF1_LEARN1 0x08 /* enabled on learning mode */
|
||||
#define ENE_CIR_CONF1_TX_ON 0x30 /* enabled on transmit */
|
||||
#define ENE_CIR_CONF1_TX_CARR 0x80 /* send TX carrier or not */
|
||||
/* CIR Config register #1 */
|
||||
#define ENE_CIRCFG 0xFEC0
|
||||
#define ENE_CIRCFG_RX_EN 0x01 /* RX enable */
|
||||
#define ENE_CIRCFG_RX_IRQ 0x02 /* Enable hardware interrupt */
|
||||
#define ENE_CIRCFG_REV_POL 0x04 /* Input polarity reversed */
|
||||
#define ENE_CIRCFG_CARR_DEMOD 0x08 /* Enable carrier demodulator */
|
||||
|
||||
#define ENE_CIR_CONF2 0xFEC1 /* unknown setting = 0 */
|
||||
#define ENE_CIR_CONF2_LEARN2 0x10 /* set on enable learning */
|
||||
#define ENE_CIR_CONF2_GPIO40DIS 0x20 /* disable input via gpio40 */
|
||||
#define ENE_CIRCFG_TX_EN 0x10 /* TX enable */
|
||||
#define ENE_CIRCFG_TX_IRQ 0x20 /* Send interrupt on TX done */
|
||||
#define ENE_CIRCFG_TX_POL_REV 0x40 /* TX polarity reversed */
|
||||
#define ENE_CIRCFG_TX_CARR 0x80 /* send TX carrier or not */
|
||||
|
||||
#define ENE_CIR_SAMPLE_PERIOD 0xFEC8 /* sample period in us */
|
||||
#define ENE_CIR_SAMPLE_OVERFLOW 0x80 /* interrupt on overflows if set */
|
||||
/* CIR config register #2 */
|
||||
#define ENE_CIRCFG2 0xFEC1
|
||||
#define ENE_CIRCFG2_RLC 0x00
|
||||
#define ENE_CIRCFG2_RC5 0x01
|
||||
#define ENE_CIRCFG2_RC6 0x02
|
||||
#define ENE_CIRCFG2_NEC 0x03
|
||||
#define ENE_CIRCFG2_CARR_DETECT 0x10 /* Enable carrier detection */
|
||||
#define ENE_CIRCFG2_GPIO0A 0x20 /* Use GPIO0A instead of GPIO40 for input */
|
||||
#define ENE_CIRCFG2_FAST_SAMPL1 0x40 /* Fast leading pulse detection for RC6 */
|
||||
#define ENE_CIRCFG2_FAST_SAMPL2 0x80 /* Fast data detection for RC6 */
|
||||
|
||||
/* Knobs for protocol decoding - will document when/if will use them */
|
||||
#define ENE_CIRPF 0xFEC2
|
||||
#define ENE_CIRHIGH 0xFEC3
|
||||
#define ENE_CIRBIT 0xFEC4
|
||||
#define ENE_CIRSTART 0xFEC5
|
||||
#define ENE_CIRSTART2 0xFEC6
|
||||
|
||||
/* Actual register which contains RLC RX data - read by firmware */
|
||||
#define ENE_CIRDAT_IN 0xFEC7
|
||||
|
||||
|
||||
/* Two byte tx buffer */
|
||||
#define ENE_TX_INPUT1 0xFEC9
|
||||
#define ENE_TX_INPUT2 0xFECA
|
||||
#define ENE_TX_PULSE_MASK 0x80 /* Transmitted sample is pulse */
|
||||
#define ENE_TX_SMLP_MASK 0x7F
|
||||
#define ENE_TX_SMPL_PERIOD 50 /* transmit sample period - fixed */
|
||||
/* RLC configuration - sample period (1us resulution) + idle mode */
|
||||
#define ENE_CIRRLC_CFG 0xFEC8
|
||||
#define ENE_CIRRLC_CFG_OVERFLOW 0x80 /* interrupt on overflows if set */
|
||||
#define ENE_DEFAULT_SAMPLE_PERIOD 50
|
||||
|
||||
/* Two byte RLC TX buffer */
|
||||
#define ENE_CIRRLC_OUT0 0xFEC9
|
||||
#define ENE_CIRRLC_OUT1 0xFECA
|
||||
#define ENE_CIRRLC_OUT_PULSE 0x80 /* Transmitted sample is pulse */
|
||||
#define ENE_CIRRLC_OUT_MASK 0x7F
|
||||
|
||||
|
||||
/* Unknown TX setting - TX sample period ??? */
|
||||
#define ENE_TX_UNK1 0xFECB /* set to 0x63 */
|
||||
/* Carrier detect setting
|
||||
* Low nibble - number of carrier pulses to average
|
||||
* High nibble - number of initial carrier pulses to discard
|
||||
*/
|
||||
#define ENE_CIRCAR_PULS 0xFECB
|
||||
|
||||
/* Current received carrier period */
|
||||
#define ENE_RX_CARRIER 0xFECC /* RX period (500 ns) */
|
||||
#define ENE_RX_CARRIER_VALID 0x80 /* Register content valid */
|
||||
/* detected RX carrier period (resolution: 500 ns) */
|
||||
#define ENE_CIRCAR_PRD 0xFECC
|
||||
#define ENE_CIRCAR_PRD_VALID 0x80 /* data valid content valid */
|
||||
|
||||
/* detected RX carrier pulse width (resolution: 500 ns) */
|
||||
#define ENE_CIRCAR_HPRD 0xFECD
|
||||
|
||||
/* TX period (1/carrier) */
|
||||
#define ENE_TX_PERIOD 0xFECE /* TX period (500 ns) */
|
||||
#define ENE_TX_PERIOD_UNKBIT 0x80 /* This bit set on transmit*/
|
||||
#define ENE_TX_PERIOD_PULSE 0xFECF /* TX pulse period (500 ns)*/
|
||||
/* TX period (resolution: 500 ns, minimum 2)*/
|
||||
#define ENE_CIRMOD_PRD 0xFECE
|
||||
#define ENE_CIRMOD_PRD_POL 0x80 /* TX carrier polarity*/
|
||||
|
||||
#define ENE_CIRMOD_PRD_MAX 0x7F /* 15.87 kHz */
|
||||
#define ENE_CIRMOD_PRD_MIN 0x02 /* 1 Mhz */
|
||||
|
||||
/* TX pulse width (resolution: 500 ns)*/
|
||||
#define ENE_CIRMOD_HPRD 0xFECF
|
||||
|
||||
/* Hardware versions */
|
||||
#define ENE_HW_VERSION 0xFF00 /* hardware revision */
|
||||
#define ENE_ECHV 0xFF00 /* hardware revision */
|
||||
#define ENE_PLLFRH 0xFF16
|
||||
#define ENE_PLLFRL 0xFF17
|
||||
#define ENE_DEFAULT_PLL_FREQ 1000
|
||||
|
||||
#define ENE_HW_UNK 0xFF1D
|
||||
#define ENE_HW_UNK_CLR 0x04
|
||||
#define ENE_HW_VER_MAJOR 0xFF1E /* chip version */
|
||||
#define ENE_HW_VER_MINOR 0xFF1F
|
||||
#define ENE_ECSTS 0xFF1D
|
||||
#define ENE_ECSTS_RSRVD 0x04
|
||||
|
||||
#define ENE_ECVER_MAJOR 0xFF1E /* chip version */
|
||||
#define ENE_ECVER_MINOR 0xFF1F
|
||||
#define ENE_HW_VER_OLD 0xFD00
|
||||
|
||||
/* Normal/Learning carrier ranges - only valid if we have learning input*/
|
||||
/* TODO: test */
|
||||
#define ENE_NORMAL_RX_LOW 34
|
||||
#define ENE_NORMAL_RX_HI 38
|
||||
|
||||
/* Tx carrier range */
|
||||
/* Hardware might be able to do more, but this range is enough for
|
||||
all purposes */
|
||||
#define ENE_TX_PERIOD_MAX 32 /* corresponds to 29.4 kHz */
|
||||
#define ENE_TX_PERIOD_MIN 16 /* corrsponds to 62.5 kHz */
|
||||
|
||||
|
||||
|
||||
/* Minimal and maximal gaps */
|
||||
|
||||
/* Normal case:
|
||||
Minimal gap is 0x7F * sample period
|
||||
Maximum gap depends on hardware.
|
||||
For KB3926B, it is unlimited, for newer models its around
|
||||
250000, after which HW stops sending samples, and that is
|
||||
not possible to change */
|
||||
|
||||
/* Fan case:
|
||||
Both minimal and maximal gaps are same, and equal to 0xFFF * 0x61
|
||||
And there is nothing to change this setting
|
||||
*/
|
||||
|
||||
#define ENE_MAXGAP 250000
|
||||
#define ENE_MINGAP (127 * sample_period)
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#define ENE_DRIVER_NAME "ene_ir"
|
||||
|
@ -171,46 +180,60 @@
|
|||
|
||||
#define ENE_HW_B 1 /* 3926B */
|
||||
#define ENE_HW_C 2 /* 3926C */
|
||||
#define ENE_HW_D 3 /* 3926D */
|
||||
#define ENE_HW_D 3 /* 3926D or later */
|
||||
|
||||
#define ene_printk(level, text, ...) \
|
||||
printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__)
|
||||
printk(level ENE_DRIVER_NAME ": " text "\n", ## __VA_ARGS__)
|
||||
|
||||
#define ene_dbg(text, ...) \
|
||||
if (debug) \
|
||||
printk(KERN_DEBUG \
|
||||
ENE_DRIVER_NAME ": " text "\n" , ## __VA_ARGS__)
|
||||
#define ene_notice(text, ...) ene_printk(KERN_NOTICE, text, ## __VA_ARGS__)
|
||||
#define ene_warn(text, ...) ene_printk(KERN_WARNING, text, ## __VA_ARGS__)
|
||||
|
||||
#define ene_dbg_verbose(text, ...) \
|
||||
if (debug > 1) \
|
||||
printk(KERN_DEBUG \
|
||||
ENE_DRIVER_NAME ": " text "\n" , ## __VA_ARGS__)
|
||||
|
||||
#define __dbg(level, format, ...) \
|
||||
do { \
|
||||
if (debug >= level) \
|
||||
printk(KERN_DEBUG ENE_DRIVER_NAME \
|
||||
": " format "\n", ## __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define dbg(format, ...) __dbg(1, format, ## __VA_ARGS__)
|
||||
#define dbg_verbose(format, ...) __dbg(2, format, ## __VA_ARGS__)
|
||||
#define dbg_regs(format, ...) __dbg(3, format, ## __VA_ARGS__)
|
||||
|
||||
#define MS_TO_NS(msec) ((msec) * 1000)
|
||||
|
||||
struct ene_device {
|
||||
struct pnp_dev *pnp_dev;
|
||||
struct input_dev *idev;
|
||||
struct ir_dev_props *props;
|
||||
int in_use;
|
||||
|
||||
/* hw IO settings */
|
||||
unsigned long hw_io;
|
||||
long hw_io;
|
||||
int irq;
|
||||
spinlock_t hw_lock;
|
||||
|
||||
/* HW features */
|
||||
int hw_revision; /* hardware revision */
|
||||
bool hw_learning_and_tx_capable; /* learning capable */
|
||||
bool hw_gpio40_learning; /* gpio40 is learning */
|
||||
bool hw_fan_as_normal_input; /* fan input is used as */
|
||||
/* regular input */
|
||||
bool hw_use_gpio_0a; /* gpio0a is demodulated input*/
|
||||
bool hw_extra_buffer; /* hardware has 'extra buffer' */
|
||||
bool hw_fan_input; /* fan input is IR data source */
|
||||
bool hw_learning_and_tx_capable; /* learning & tx capable */
|
||||
int pll_freq;
|
||||
int buffer_len;
|
||||
|
||||
/* Extra RX buffer location */
|
||||
int extra_buf1_address;
|
||||
int extra_buf1_len;
|
||||
int extra_buf2_address;
|
||||
int extra_buf2_len;
|
||||
|
||||
/* HW state*/
|
||||
int rx_pointer; /* hw pointer to rx buffer */
|
||||
int r_pointer; /* pointer to next sample to read */
|
||||
int w_pointer; /* pointer to next sample hw will write */
|
||||
bool rx_fan_input_inuse; /* is fan input in use for rx*/
|
||||
int tx_reg; /* current reg used for TX */
|
||||
u8 saved_conf1; /* saved FEC0 reg */
|
||||
|
||||
/* TX sample handling */
|
||||
unsigned int tx_sample; /* current sample for TX */
|
||||
bool tx_sample_pulse; /* current sample is pulse */
|
||||
|
||||
|
@ -229,7 +252,11 @@ struct ene_device {
|
|||
int transmitter_mask;
|
||||
|
||||
/* RX settings */
|
||||
bool learning_enabled; /* learning input enabled */
|
||||
bool learning_mode_enabled; /* learning input enabled */
|
||||
bool carrier_detect_enabled; /* carrier detect enabled */
|
||||
int rx_period_adjust;
|
||||
bool rx_enabled;
|
||||
};
|
||||
|
||||
static int ene_irq_status(struct ene_device *dev);
|
||||
static void ene_rx_read_hw_pointer(struct ene_device *dev);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,6 +17,7 @@
|
|||
#define _IR_RAW_EVENT
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <media/ir-core.h>
|
||||
|
||||
struct ir_raw_handler {
|
||||
|
@ -33,6 +34,7 @@ struct ir_raw_handler {
|
|||
struct ir_raw_event_ctrl {
|
||||
struct list_head list; /* to keep track of raw clients */
|
||||
struct task_struct *thread;
|
||||
spinlock_t lock;
|
||||
struct kfifo kfifo; /* fifo for the pulse/space durations */
|
||||
ktime_t last_event; /* when last event occurred */
|
||||
enum raw_event_type last_type; /* last event type */
|
||||
|
@ -76,10 +78,22 @@ struct ir_raw_event_ctrl {
|
|||
bool first;
|
||||
bool toggle;
|
||||
} jvc;
|
||||
struct rc5_sz_dec {
|
||||
int state;
|
||||
u32 bits;
|
||||
unsigned count;
|
||||
unsigned wanted_bits;
|
||||
} rc5_sz;
|
||||
struct lirc_codec {
|
||||
struct ir_input_dev *ir_dev;
|
||||
struct lirc_driver *drv;
|
||||
int carrier_low;
|
||||
|
||||
ktime_t gap_start;
|
||||
u64 gap_duration;
|
||||
bool gap;
|
||||
bool send_timeout_reports;
|
||||
|
||||
} lirc;
|
||||
};
|
||||
|
||||
|
@ -107,13 +121,19 @@ static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration)
|
|||
ev->duration -= duration;
|
||||
}
|
||||
|
||||
/* Returns true if event is normal pulse/space event */
|
||||
static inline bool is_timing_event(struct ir_raw_event ev)
|
||||
{
|
||||
return !ev.carrier_report && !ev.reset;
|
||||
}
|
||||
|
||||
#define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000)
|
||||
#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space")
|
||||
#define IS_RESET(ev) (ev.duration == 0)
|
||||
/*
|
||||
* Routines from ir-sysfs.c - Meant to be called only internally inside
|
||||
* ir-core
|
||||
*/
|
||||
int ir_register_input(struct input_dev *input_dev);
|
||||
|
||||
int ir_register_class(struct input_dev *input_dev);
|
||||
void ir_unregister_class(struct input_dev *input_dev);
|
||||
|
|
|
@ -50,8 +50,9 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
data->state = STATE_INACTIVE;
|
||||
if (!is_timing_event(ev)) {
|
||||
if (ev.reset)
|
||||
data->state = STATE_INACTIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -435,7 +435,7 @@ EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
|
|||
* This routine is used to signal that a key has been released on the
|
||||
* remote control. It reports a keyup input event via input_report_key().
|
||||
*/
|
||||
static void ir_keyup(struct ir_input_dev *ir)
|
||||
void ir_keyup(struct ir_input_dev *ir)
|
||||
{
|
||||
if (!ir->keypressed)
|
||||
return;
|
||||
|
@ -445,6 +445,7 @@ static void ir_keyup(struct ir_input_dev *ir)
|
|||
input_sync(ir->input_dev);
|
||||
ir->keypressed = false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_keyup);
|
||||
|
||||
/**
|
||||
* ir_timer_keyup() - generates a keyup event after a timeout
|
||||
|
@ -640,6 +641,10 @@ int __ir_input_register(struct input_dev *input_dev,
|
|||
goto out_event;
|
||||
}
|
||||
|
||||
rc = ir_register_input(input_dev);
|
||||
if (rc < 0)
|
||||
goto out_event;
|
||||
|
||||
IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
|
||||
driver_name, rc_tab->name,
|
||||
(ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct lirc_codec *lirc = &ir_dev->raw->lirc;
|
||||
int sample;
|
||||
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
|
||||
|
@ -40,21 +41,57 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
|
||||
return -EINVAL;
|
||||
|
||||
if (IS_RESET(ev))
|
||||
/* Packet start */
|
||||
if (ev.reset)
|
||||
return 0;
|
||||
|
||||
IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
|
||||
TO_US(ev.duration), TO_STR(ev.pulse));
|
||||
/* Carrier reports */
|
||||
if (ev.carrier_report) {
|
||||
sample = LIRC_FREQUENCY(ev.carrier);
|
||||
|
||||
sample = ev.duration / 1000;
|
||||
if (ev.pulse)
|
||||
sample |= PULSE_BIT;
|
||||
/* Packet end */
|
||||
} else if (ev.timeout) {
|
||||
|
||||
if (lirc->gap)
|
||||
return 0;
|
||||
|
||||
lirc->gap_start = ktime_get();
|
||||
lirc->gap = true;
|
||||
lirc->gap_duration = ev.duration;
|
||||
|
||||
if (!lirc->send_timeout_reports)
|
||||
return 0;
|
||||
|
||||
sample = LIRC_TIMEOUT(ev.duration / 1000);
|
||||
|
||||
/* Normal sample */
|
||||
} else {
|
||||
|
||||
if (lirc->gap) {
|
||||
int gap_sample;
|
||||
|
||||
lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
|
||||
lirc->gap_start));
|
||||
|
||||
/* Convert to ms and cap by LIRC_VALUE_MASK */
|
||||
do_div(lirc->gap_duration, 1000);
|
||||
lirc->gap_duration = min(lirc->gap_duration,
|
||||
(u64)LIRC_VALUE_MASK);
|
||||
|
||||
gap_sample = LIRC_SPACE(lirc->gap_duration);
|
||||
lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
|
||||
(unsigned char *) &gap_sample);
|
||||
lirc->gap = false;
|
||||
}
|
||||
|
||||
sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) :
|
||||
LIRC_SPACE(ev.duration / 1000);
|
||||
}
|
||||
|
||||
lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
|
||||
(unsigned char *) &sample);
|
||||
wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -102,7 +139,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
|
|||
struct ir_input_dev *ir_dev;
|
||||
int ret = 0;
|
||||
void *drv_data;
|
||||
unsigned long val = 0;
|
||||
__u32 val = 0, tmp;
|
||||
|
||||
lirc = lirc_get_pdata(filep);
|
||||
if (!lirc)
|
||||
|
@ -115,7 +152,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
|
|||
drv_data = ir_dev->props->priv;
|
||||
|
||||
if (_IOC_DIR(cmd) & _IOC_WRITE) {
|
||||
ret = get_user(val, (unsigned long *)arg);
|
||||
ret = get_user(val, (__u32 *)arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -130,22 +167,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
|
|||
case LIRC_SET_SEND_MODE:
|
||||
if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
|
||||
return -EINVAL;
|
||||
break;
|
||||
return 0;
|
||||
|
||||
/* TX settings */
|
||||
case LIRC_SET_TRANSMITTER_MASK:
|
||||
if (ir_dev->props->s_tx_mask)
|
||||
ret = ir_dev->props->s_tx_mask(drv_data, (u32)val);
|
||||
else
|
||||
if (!ir_dev->props->s_tx_mask)
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
return ir_dev->props->s_tx_mask(drv_data, val);
|
||||
|
||||
case LIRC_SET_SEND_CARRIER:
|
||||
if (ir_dev->props->s_tx_carrier)
|
||||
ir_dev->props->s_tx_carrier(drv_data, (u32)val);
|
||||
else
|
||||
if (!ir_dev->props->s_tx_carrier)
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
return ir_dev->props->s_tx_carrier(drv_data, val);
|
||||
|
||||
case LIRC_SET_SEND_DUTY_CYCLE:
|
||||
if (!ir_dev->props->s_tx_duty_cycle)
|
||||
|
@ -154,39 +189,42 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
|
|||
if (val <= 0 || val >= 100)
|
||||
return -EINVAL;
|
||||
|
||||
ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val);
|
||||
break;
|
||||
return ir_dev->props->s_tx_duty_cycle(drv_data, val);
|
||||
|
||||
/* RX settings */
|
||||
case LIRC_SET_REC_CARRIER:
|
||||
if (ir_dev->props->s_rx_carrier_range)
|
||||
ret = ir_dev->props->s_rx_carrier_range(
|
||||
ir_dev->props->priv,
|
||||
ir_dev->raw->lirc.carrier_low, val);
|
||||
else
|
||||
if (!ir_dev->props->s_rx_carrier_range)
|
||||
return -ENOSYS;
|
||||
|
||||
if (!ret)
|
||||
ir_dev->raw->lirc.carrier_low = 0;
|
||||
break;
|
||||
if (val <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
return ir_dev->props->s_rx_carrier_range(drv_data,
|
||||
ir_dev->raw->lirc.carrier_low, val);
|
||||
|
||||
case LIRC_SET_REC_CARRIER_RANGE:
|
||||
if (val >= 0)
|
||||
ir_dev->raw->lirc.carrier_low = val;
|
||||
break;
|
||||
if (val <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
ir_dev->raw->lirc.carrier_low = val;
|
||||
return 0;
|
||||
|
||||
case LIRC_GET_REC_RESOLUTION:
|
||||
val = ir_dev->props->rx_resolution;
|
||||
break;
|
||||
|
||||
case LIRC_SET_WIDEBAND_RECEIVER:
|
||||
if (ir_dev->props->s_learning_mode)
|
||||
return ir_dev->props->s_learning_mode(
|
||||
ir_dev->props->priv, !!val);
|
||||
else
|
||||
if (!ir_dev->props->s_learning_mode)
|
||||
return -ENOSYS;
|
||||
|
||||
return ir_dev->props->s_learning_mode(drv_data, !!val);
|
||||
|
||||
case LIRC_SET_MEASURE_CARRIER_MODE:
|
||||
if (!ir_dev->props->s_carrier_report)
|
||||
return -ENOSYS;
|
||||
|
||||
return ir_dev->props->s_carrier_report(drv_data, !!val);
|
||||
|
||||
/* Generic timeout support */
|
||||
case LIRC_GET_MIN_TIMEOUT:
|
||||
if (!ir_dev->props->max_timeout)
|
||||
|
@ -201,10 +239,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
|
|||
break;
|
||||
|
||||
case LIRC_SET_REC_TIMEOUT:
|
||||
if (val < ir_dev->props->min_timeout ||
|
||||
val > ir_dev->props->max_timeout)
|
||||
return -EINVAL;
|
||||
ir_dev->props->timeout = val * 1000;
|
||||
if (!ir_dev->props->max_timeout)
|
||||
return -ENOSYS;
|
||||
|
||||
tmp = val * 1000;
|
||||
|
||||
if (tmp < ir_dev->props->min_timeout ||
|
||||
tmp > ir_dev->props->max_timeout)
|
||||
return -EINVAL;
|
||||
|
||||
ir_dev->props->timeout = tmp;
|
||||
break;
|
||||
|
||||
case LIRC_SET_REC_TIMEOUT_REPORTS:
|
||||
lirc->send_timeout_reports = !!val;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -212,7 +260,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
|
|||
}
|
||||
|
||||
if (_IOC_DIR(cmd) & _IOC_READ)
|
||||
ret = put_user(val, (unsigned long *)arg);
|
||||
ret = put_user(val, (__u32 *)arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -231,6 +279,9 @@ static struct file_operations lirc_fops = {
|
|||
.owner = THIS_MODULE,
|
||||
.write = ir_lirc_transmit_ir,
|
||||
.unlocked_ioctl = ir_lirc_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = ir_lirc_ioctl,
|
||||
#endif
|
||||
.read = lirc_dev_fop_read,
|
||||
.poll = lirc_dev_fop_poll,
|
||||
.open = lirc_dev_fop_open,
|
||||
|
@ -278,6 +329,10 @@ static int ir_lirc_register(struct input_dev *input_dev)
|
|||
if (ir_dev->props->s_learning_mode)
|
||||
features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
|
||||
|
||||
if (ir_dev->props->s_carrier_report)
|
||||
features |= LIRC_CAN_MEASURE_CARRIER;
|
||||
|
||||
|
||||
if (ir_dev->props->max_timeout)
|
||||
features |= LIRC_CAN_SET_REC_TIMEOUT;
|
||||
|
||||
|
|
|
@ -54,8 +54,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
data->state = STATE_INACTIVE;
|
||||
if (!is_timing_event(ev)) {
|
||||
if (ev.reset)
|
||||
data->state = STATE_INACTIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,22 +39,34 @@ static int ir_raw_event_thread(void *data)
|
|||
struct ir_raw_event ev;
|
||||
struct ir_raw_handler *handler;
|
||||
struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
|
||||
int retval;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
try_to_freeze();
|
||||
|
||||
mutex_lock(&ir_raw_handler_lock);
|
||||
spin_lock_irq(&raw->lock);
|
||||
retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev));
|
||||
|
||||
while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
handler->decode(raw->input_dev, ev);
|
||||
raw->prev_ev = ev;
|
||||
if (!retval) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
if (kthread_should_stop())
|
||||
set_current_state(TASK_RUNNING);
|
||||
|
||||
spin_unlock_irq(&raw->lock);
|
||||
schedule();
|
||||
continue;
|
||||
}
|
||||
|
||||
mutex_unlock(&ir_raw_handler_lock);
|
||||
spin_unlock_irq(&raw->lock);
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
|
||||
BUG_ON(retval != sizeof(ev));
|
||||
|
||||
mutex_lock(&ir_raw_handler_lock);
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
handler->decode(raw->input_dev, ev);
|
||||
raw->prev_ev = ev;
|
||||
mutex_unlock(&ir_raw_handler_lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -77,7 +89,7 @@ int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev)
|
|||
if (!ir->raw)
|
||||
return -EINVAL;
|
||||
|
||||
IR_dprintk(2, "sample: (05%dus %s)\n",
|
||||
IR_dprintk(2, "sample: (%05dus %s)\n",
|
||||
TO_US(ev->duration), TO_STR(ev->pulse));
|
||||
|
||||
if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
|
||||
|
@ -162,7 +174,7 @@ int ir_raw_event_store_with_filter(struct input_dev *input_dev,
|
|||
if (ir->idle && !ev->pulse)
|
||||
return 0;
|
||||
else if (ir->idle)
|
||||
ir_raw_event_set_idle(input_dev, 0);
|
||||
ir_raw_event_set_idle(input_dev, false);
|
||||
|
||||
if (!raw->this_ev.duration) {
|
||||
raw->this_ev = *ev;
|
||||
|
@ -175,48 +187,35 @@ int ir_raw_event_store_with_filter(struct input_dev *input_dev,
|
|||
|
||||
/* Enter idle mode if nessesary */
|
||||
if (!ev->pulse && ir->props->timeout &&
|
||||
raw->this_ev.duration >= ir->props->timeout)
|
||||
ir_raw_event_set_idle(input_dev, 1);
|
||||
raw->this_ev.duration >= ir->props->timeout) {
|
||||
ir_raw_event_set_idle(input_dev, true);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
|
||||
|
||||
void ir_raw_event_set_idle(struct input_dev *input_dev, int idle)
|
||||
/**
|
||||
* ir_raw_event_set_idle() - hint the ir core if device is receiving
|
||||
* IR data or not
|
||||
* @input_dev: the struct input_dev device descriptor
|
||||
* @idle: the hint value
|
||||
*/
|
||||
void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle)
|
||||
{
|
||||
struct ir_input_dev *ir = input_get_drvdata(input_dev);
|
||||
struct ir_raw_event_ctrl *raw = ir->raw;
|
||||
ktime_t now;
|
||||
u64 delta;
|
||||
|
||||
if (!ir->props)
|
||||
if (!ir->props || !ir->raw)
|
||||
return;
|
||||
|
||||
if (!ir->raw)
|
||||
goto out;
|
||||
IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave");
|
||||
|
||||
if (idle) {
|
||||
IR_dprintk(2, "enter idle mode\n");
|
||||
raw->last_event = ktime_get();
|
||||
} else {
|
||||
IR_dprintk(2, "exit idle mode\n");
|
||||
|
||||
now = ktime_get();
|
||||
delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event));
|
||||
|
||||
WARN_ON(raw->this_ev.pulse);
|
||||
|
||||
raw->this_ev.duration =
|
||||
min(raw->this_ev.duration + delta,
|
||||
(u64)IR_MAX_DURATION);
|
||||
|
||||
raw->this_ev.timeout = true;
|
||||
ir_raw_event_store(input_dev, &raw->this_ev);
|
||||
|
||||
if (raw->this_ev.duration == IR_MAX_DURATION)
|
||||
ir_raw_event_reset(input_dev);
|
||||
|
||||
raw->this_ev.duration = 0;
|
||||
init_ir_raw_event(&raw->this_ev);
|
||||
}
|
||||
out:
|
||||
|
||||
if (ir->props->s_idle)
|
||||
ir->props->s_idle(ir->props->priv, idle);
|
||||
ir->idle = idle;
|
||||
|
@ -232,11 +231,14 @@ EXPORT_SYMBOL_GPL(ir_raw_event_set_idle);
|
|||
void ir_raw_event_handle(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir = input_get_drvdata(input_dev);
|
||||
unsigned long flags;
|
||||
|
||||
if (!ir->raw)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&ir->raw->lock, flags);
|
||||
wake_up_process(ir->raw->thread);
|
||||
spin_unlock_irqrestore(&ir->raw->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_raw_event_handle);
|
||||
|
||||
|
@ -275,6 +277,7 @@ int ir_raw_event_register(struct input_dev *input_dev)
|
|||
return rc;
|
||||
}
|
||||
|
||||
spin_lock_init(&ir->raw->lock);
|
||||
ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw,
|
||||
"rc%u", (unsigned int)ir->devno);
|
||||
|
||||
|
|
|
@ -55,8 +55,9 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
data->state = STATE_INACTIVE;
|
||||
if (!is_timing_event(ev)) {
|
||||
if (ev.reset)
|
||||
data->state = STATE_INACTIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
/* ir-rc5-sz-decoder.c - handle RC5 Streamzap IR Pulse/Space protocol
|
||||
*
|
||||
* Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
* Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code handles the 15 bit RC5-ish protocol used by the Streamzap
|
||||
* PC Remote.
|
||||
* It considers a carrier of 36 kHz, with a total of 15 bits, where
|
||||
* the first two bits are start bits, and a third one is a filing bit
|
||||
*/
|
||||
|
||||
#include "ir-core-priv.h"
|
||||
|
||||
#define RC5_SZ_NBITS 15
|
||||
#define RC5_UNIT 888888 /* ns */
|
||||
#define RC5_BIT_START (1 * RC5_UNIT)
|
||||
#define RC5_BIT_END (1 * RC5_UNIT)
|
||||
|
||||
enum rc5_sz_state {
|
||||
STATE_INACTIVE,
|
||||
STATE_BIT_START,
|
||||
STATE_BIT_END,
|
||||
STATE_FINISHED,
|
||||
};
|
||||
|
||||
/**
|
||||
* ir_rc5_sz_decode() - Decode one RC-5 Streamzap pulse or space
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
* @ev: the struct ir_raw_event descriptor of the pulse/space
|
||||
*
|
||||
* This function returns -EINVAL if the pulse violates the state machine
|
||||
*/
|
||||
static int ir_rc5_sz_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct rc5_sz_dec *data = &ir_dev->raw->rc5_sz;
|
||||
u8 toggle, command, system;
|
||||
u32 scancode;
|
||||
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5_SZ))
|
||||
return 0;
|
||||
|
||||
if (!is_timing_event(ev)) {
|
||||
if (ev.reset)
|
||||
data->state = STATE_INACTIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
|
||||
goto out;
|
||||
|
||||
again:
|
||||
IR_dprintk(2, "RC5-sz decode started at state %i (%uus %s)\n",
|
||||
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
|
||||
|
||||
if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
|
||||
return 0;
|
||||
|
||||
switch (data->state) {
|
||||
|
||||
case STATE_INACTIVE:
|
||||
if (!ev.pulse)
|
||||
break;
|
||||
|
||||
data->state = STATE_BIT_START;
|
||||
data->count = 1;
|
||||
data->wanted_bits = RC5_SZ_NBITS;
|
||||
decrease_duration(&ev, RC5_BIT_START);
|
||||
goto again;
|
||||
|
||||
case STATE_BIT_START:
|
||||
if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
|
||||
break;
|
||||
|
||||
data->bits <<= 1;
|
||||
if (!ev.pulse)
|
||||
data->bits |= 1;
|
||||
data->count++;
|
||||
data->state = STATE_BIT_END;
|
||||
return 0;
|
||||
|
||||
case STATE_BIT_END:
|
||||
if (!is_transition(&ev, &ir_dev->raw->prev_ev))
|
||||
break;
|
||||
|
||||
if (data->count == data->wanted_bits)
|
||||
data->state = STATE_FINISHED;
|
||||
else
|
||||
data->state = STATE_BIT_START;
|
||||
|
||||
decrease_duration(&ev, RC5_BIT_END);
|
||||
goto again;
|
||||
|
||||
case STATE_FINISHED:
|
||||
if (ev.pulse)
|
||||
break;
|
||||
|
||||
/* RC5-sz */
|
||||
command = (data->bits & 0x0003F) >> 0;
|
||||
system = (data->bits & 0x02FC0) >> 6;
|
||||
toggle = (data->bits & 0x01000) ? 1 : 0;
|
||||
scancode = system << 6 | command;
|
||||
|
||||
IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n",
|
||||
scancode, toggle);
|
||||
|
||||
ir_keydown(input_dev, scancode, toggle);
|
||||
data->state = STATE_INACTIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
out:
|
||||
IR_dprintk(1, "RC5-sz decode failed at state %i (%uus %s)\n",
|
||||
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
|
||||
data->state = STATE_INACTIVE;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler rc5_sz_handler = {
|
||||
.protocols = IR_TYPE_RC5_SZ,
|
||||
.decode = ir_rc5_sz_decode,
|
||||
};
|
||||
|
||||
static int __init ir_rc5_sz_decode_init(void)
|
||||
{
|
||||
ir_raw_handler_register(&rc5_sz_handler);
|
||||
|
||||
printk(KERN_INFO "IR RC5 (streamzap) protocol handler initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ir_rc5_sz_decode_exit(void)
|
||||
{
|
||||
ir_raw_handler_unregister(&rc5_sz_handler);
|
||||
}
|
||||
|
||||
module_init(ir_rc5_sz_decode_init);
|
||||
module_exit(ir_rc5_sz_decode_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
|
||||
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
|
||||
MODULE_DESCRIPTION("RC5 (streamzap) IR protocol decoder");
|
|
@ -85,8 +85,9 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
data->state = STATE_INACTIVE;
|
||||
if (!is_timing_event(ev)) {
|
||||
if (ev.reset)
|
||||
data->state = STATE_INACTIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,8 +48,9 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
data->state = STATE_INACTIVE;
|
||||
if (!is_timing_event(ev)) {
|
||||
if (ev.reset)
|
||||
data->state = STATE_INACTIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ static struct {
|
|||
{ IR_TYPE_RC6, "rc-6" },
|
||||
{ IR_TYPE_JVC, "jvc" },
|
||||
{ IR_TYPE_SONY, "sony" },
|
||||
{ IR_TYPE_RC5_SZ, "rc-5-sz" },
|
||||
{ IR_TYPE_LIRC, "lirc" },
|
||||
};
|
||||
|
||||
|
@ -67,6 +68,10 @@ static ssize_t show_protocols(struct device *d,
|
|||
char *tmp = buf;
|
||||
int i;
|
||||
|
||||
/* Device is being removed */
|
||||
if (!ir_dev)
|
||||
return -EINVAL;
|
||||
|
||||
if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
|
||||
enabled = ir_dev->rc_tab.ir_type;
|
||||
allowed = ir_dev->props->allowed_protos;
|
||||
|
@ -122,6 +127,10 @@ static ssize_t store_protocols(struct device *d,
|
|||
int rc, i, count = 0;
|
||||
unsigned long flags;
|
||||
|
||||
/* Device is being removed */
|
||||
if (!ir_dev)
|
||||
return -EINVAL;
|
||||
|
||||
if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
|
||||
type = ir_dev->rc_tab.ir_type;
|
||||
else if (ir_dev->raw)
|
||||
|
@ -256,8 +265,6 @@ static struct device_type rc_dev_type = {
|
|||
*/
|
||||
int ir_register_class(struct input_dev *input_dev)
|
||||
{
|
||||
int rc;
|
||||
const char *path;
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
int devno = find_first_zero_bit(&ir_core_dev_number,
|
||||
IRRCV_NUM_DEVICES);
|
||||
|
@ -266,17 +273,28 @@ int ir_register_class(struct input_dev *input_dev)
|
|||
return devno;
|
||||
|
||||
ir_dev->dev.type = &rc_dev_type;
|
||||
ir_dev->devno = devno;
|
||||
|
||||
ir_dev->dev.class = &ir_input_class;
|
||||
ir_dev->dev.parent = input_dev->dev.parent;
|
||||
input_dev->dev.parent = &ir_dev->dev;
|
||||
dev_set_name(&ir_dev->dev, "rc%d", devno);
|
||||
dev_set_drvdata(&ir_dev->dev, ir_dev);
|
||||
rc = device_register(&ir_dev->dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
return device_register(&ir_dev->dev);
|
||||
};
|
||||
|
||||
/**
|
||||
* ir_register_input - registers ir input device with input subsystem
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
*/
|
||||
|
||||
int ir_register_input(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
int rc;
|
||||
const char *path;
|
||||
|
||||
|
||||
input_dev->dev.parent = &ir_dev->dev;
|
||||
rc = input_register_device(input_dev);
|
||||
if (rc < 0) {
|
||||
device_del(&ir_dev->dev);
|
||||
|
@ -292,11 +310,9 @@ int ir_register_class(struct input_dev *input_dev)
|
|||
path ? path : "N/A");
|
||||
kfree(path);
|
||||
|
||||
ir_dev->devno = devno;
|
||||
set_bit(devno, &ir_core_dev_number);
|
||||
|
||||
set_bit(ir_dev->devno, &ir_core_dev_number);
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_unregister_class() - removes the sysfs for sysfs for
|
||||
|
@ -309,6 +325,7 @@ void ir_unregister_class(struct input_dev *input_dev)
|
|||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
|
||||
input_set_drvdata(input_dev, NULL);
|
||||
clear_bit(ir_dev->devno, &ir_core_dev_number);
|
||||
input_unregister_device(input_dev);
|
||||
device_del(&ir_dev->dev);
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
|
||||
rc-alink-dtu-m.o \
|
||||
rc-anysee.o \
|
||||
rc-apac-viewcomp.o \
|
||||
rc-asus-pc39.o \
|
||||
rc-ati-tv-wonder-hd-600.o \
|
||||
|
@ -8,7 +10,9 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
|
|||
rc-avermedia-dvbt.o \
|
||||
rc-avermedia-m135a.o \
|
||||
rc-avermedia-m733a-rm-k6.o \
|
||||
rc-avermedia-rm-ks.o \
|
||||
rc-avertv-303.o \
|
||||
rc-azurewave-ad-tu700.o \
|
||||
rc-behold.o \
|
||||
rc-behold-columbus.o \
|
||||
rc-budget-ci-old.o \
|
||||
|
@ -16,6 +20,8 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
|
|||
rc-cinergy.o \
|
||||
rc-dib0700-nec.o \
|
||||
rc-dib0700-rc5.o \
|
||||
rc-digitalnow-tinytwin.o \
|
||||
rc-digittrade.o \
|
||||
rc-dm1105-nec.o \
|
||||
rc-dntv-live-dvb-t.o \
|
||||
rc-dntv-live-dvbt-pro.o \
|
||||
|
@ -38,8 +44,12 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
|
|||
rc-kaiomy.o \
|
||||
rc-kworld-315u.o \
|
||||
rc-kworld-plus-tv-analog.o \
|
||||
rc-leadtek-y04g0051.o \
|
||||
rc-lirc.o \
|
||||
rc-lme2510.o \
|
||||
rc-manli.o \
|
||||
rc-msi-digivox-ii.o \
|
||||
rc-msi-digivox-iii.o \
|
||||
rc-msi-tvanywhere.o \
|
||||
rc-msi-tvanywhere-plus.o \
|
||||
rc-nebula.o \
|
||||
|
@ -58,14 +68,18 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
|
|||
rc-purpletv.o \
|
||||
rc-pv951.o \
|
||||
rc-rc5-hauppauge-new.o \
|
||||
rc-rc5-streamzap.o \
|
||||
rc-rc5-tv.o \
|
||||
rc-rc6-mce.o \
|
||||
rc-real-audio-220-32-keys.o \
|
||||
rc-streamzap.o \
|
||||
rc-tbs-nec.o \
|
||||
rc-terratec-cinergy-xs.o \
|
||||
rc-terratec-slim.o \
|
||||
rc-tevii-nec.o \
|
||||
rc-total-media-in-hand.o \
|
||||
rc-trekstor.o \
|
||||
rc-tt-1500.o \
|
||||
rc-twinhan1027.o \
|
||||
rc-videomate-s350.o \
|
||||
rc-videomate-tv-pvr.o \
|
||||
rc-winfast.o \
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* A-Link DTU(m) remote controller keytable
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
/* A-Link DTU(m) slim remote, 6 rows, 3 columns. */
|
||||
static struct ir_scancode alink_dtu_m[] = {
|
||||
{ 0x0800, KEY_VOLUMEUP },
|
||||
{ 0x0801, KEY_1 },
|
||||
{ 0x0802, KEY_3 },
|
||||
{ 0x0803, KEY_7 },
|
||||
{ 0x0804, KEY_9 },
|
||||
{ 0x0805, KEY_NEW }, /* symbol: PIP */
|
||||
{ 0x0806, KEY_0 },
|
||||
{ 0x0807, KEY_CHANNEL }, /* JUMP */
|
||||
{ 0x080d, KEY_5 },
|
||||
{ 0x080f, KEY_2 },
|
||||
{ 0x0812, KEY_POWER2 },
|
||||
{ 0x0814, KEY_CHANNELUP },
|
||||
{ 0x0816, KEY_VOLUMEDOWN },
|
||||
{ 0x0818, KEY_6 },
|
||||
{ 0x081a, KEY_MUTE },
|
||||
{ 0x081b, KEY_8 },
|
||||
{ 0x081c, KEY_4 },
|
||||
{ 0x081d, KEY_CHANNELDOWN },
|
||||
};
|
||||
|
||||
static struct rc_keymap alink_dtu_m_map = {
|
||||
.map = {
|
||||
.scan = alink_dtu_m,
|
||||
.size = ARRAY_SIZE(alink_dtu_m),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
.name = RC_MAP_ALINK_DTU_M,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_alink_dtu_m(void)
|
||||
{
|
||||
return ir_register_map(&alink_dtu_m_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_alink_dtu_m(void)
|
||||
{
|
||||
ir_unregister_map(&alink_dtu_m_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_alink_dtu_m)
|
||||
module_exit(exit_rc_map_alink_dtu_m)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Anysee remote controller keytable
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
static struct ir_scancode anysee[] = {
|
||||
{ 0x0800, KEY_0 },
|
||||
{ 0x0801, KEY_1 },
|
||||
{ 0x0802, KEY_2 },
|
||||
{ 0x0803, KEY_3 },
|
||||
{ 0x0804, KEY_4 },
|
||||
{ 0x0805, KEY_5 },
|
||||
{ 0x0806, KEY_6 },
|
||||
{ 0x0807, KEY_7 },
|
||||
{ 0x0808, KEY_8 },
|
||||
{ 0x0809, KEY_9 },
|
||||
{ 0x080a, KEY_POWER2 }, /* [red power button] */
|
||||
{ 0x080b, KEY_VIDEO }, /* [*] MODE */
|
||||
{ 0x080c, KEY_CHANNEL }, /* [symbol counterclockwise arrow] */
|
||||
{ 0x080d, KEY_NEXT }, /* [>>|] */
|
||||
{ 0x080e, KEY_MENU }, /* MENU */
|
||||
{ 0x080f, KEY_EPG }, /* [EPG] */
|
||||
{ 0x0810, KEY_CLEAR }, /* EXIT */
|
||||
{ 0x0811, KEY_CHANNELUP },
|
||||
{ 0x0812, KEY_VOLUMEDOWN },
|
||||
{ 0x0813, KEY_VOLUMEUP },
|
||||
{ 0x0814, KEY_CHANNELDOWN },
|
||||
{ 0x0815, KEY_OK },
|
||||
{ 0x0816, KEY_RADIO }, /* [symbol TV/radio] */
|
||||
{ 0x0817, KEY_INFO }, /* [i] */
|
||||
{ 0x0818, KEY_PREVIOUS }, /* [|<<] */
|
||||
{ 0x0819, KEY_FAVORITES }, /* FAV. */
|
||||
{ 0x081a, KEY_SUBTITLE }, /* Subtitle */
|
||||
{ 0x081b, KEY_CAMERA }, /* [symbol camera] */
|
||||
{ 0x081c, KEY_YELLOW },
|
||||
{ 0x081d, KEY_RED },
|
||||
{ 0x081e, KEY_LANGUAGE }, /* [symbol Second Audio Program] */
|
||||
{ 0x081f, KEY_GREEN },
|
||||
{ 0x0820, KEY_SLEEP }, /* Sleep */
|
||||
{ 0x0821, KEY_SCREEN }, /* 16:9 / 4:3 */
|
||||
{ 0x0822, KEY_ZOOM }, /* SIZE */
|
||||
{ 0x0824, KEY_FN }, /* [F1] */
|
||||
{ 0x0825, KEY_FN }, /* [F2] */
|
||||
{ 0x0842, KEY_MUTE }, /* symbol mute */
|
||||
{ 0x0844, KEY_BLUE },
|
||||
{ 0x0847, KEY_TEXT }, /* TEXT */
|
||||
{ 0x0848, KEY_STOP },
|
||||
{ 0x0849, KEY_RECORD },
|
||||
{ 0x0850, KEY_PLAY },
|
||||
{ 0x0851, KEY_PAUSE },
|
||||
};
|
||||
|
||||
static struct rc_keymap anysee_map = {
|
||||
.map = {
|
||||
.scan = anysee,
|
||||
.size = ARRAY_SIZE(anysee),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
.name = RC_MAP_ANYSEE,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_anysee(void)
|
||||
{
|
||||
return ir_register_map(&anysee_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_anysee(void)
|
||||
{
|
||||
ir_unregister_map(&anysee_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_anysee)
|
||||
module_exit(exit_rc_map_anysee)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
|
@ -20,56 +20,56 @@
|
|||
|
||||
static struct ir_scancode asus_pc39[] = {
|
||||
/* Keys 0 to 9 */
|
||||
{ 0x15, KEY_0 },
|
||||
{ 0x29, KEY_1 },
|
||||
{ 0x2d, KEY_2 },
|
||||
{ 0x2b, KEY_3 },
|
||||
{ 0x09, KEY_4 },
|
||||
{ 0x0d, KEY_5 },
|
||||
{ 0x0b, KEY_6 },
|
||||
{ 0x31, KEY_7 },
|
||||
{ 0x35, KEY_8 },
|
||||
{ 0x33, KEY_9 },
|
||||
{ 0x082a, KEY_0 },
|
||||
{ 0x0816, KEY_1 },
|
||||
{ 0x0812, KEY_2 },
|
||||
{ 0x0814, KEY_3 },
|
||||
{ 0x0836, KEY_4 },
|
||||
{ 0x0832, KEY_5 },
|
||||
{ 0x0834, KEY_6 },
|
||||
{ 0x080e, KEY_7 },
|
||||
{ 0x080a, KEY_8 },
|
||||
{ 0x080c, KEY_9 },
|
||||
|
||||
{ 0x3e, KEY_RADIO }, /* radio */
|
||||
{ 0x03, KEY_MENU }, /* dvd/menu */
|
||||
{ 0x2a, KEY_VOLUMEUP },
|
||||
{ 0x19, KEY_VOLUMEDOWN },
|
||||
{ 0x37, KEY_UP },
|
||||
{ 0x3b, KEY_DOWN },
|
||||
{ 0x27, KEY_LEFT },
|
||||
{ 0x2f, KEY_RIGHT },
|
||||
{ 0x25, KEY_VIDEO }, /* video */
|
||||
{ 0x39, KEY_AUDIO }, /* music */
|
||||
{ 0x0801, KEY_RADIO }, /* radio */
|
||||
{ 0x083c, KEY_MENU }, /* dvd/menu */
|
||||
{ 0x0815, KEY_VOLUMEUP },
|
||||
{ 0x0826, KEY_VOLUMEDOWN },
|
||||
{ 0x0808, KEY_UP },
|
||||
{ 0x0804, KEY_DOWN },
|
||||
{ 0x0818, KEY_LEFT },
|
||||
{ 0x0810, KEY_RIGHT },
|
||||
{ 0x081a, KEY_VIDEO }, /* video */
|
||||
{ 0x0806, KEY_AUDIO }, /* music */
|
||||
|
||||
{ 0x21, KEY_TV }, /* tv */
|
||||
{ 0x1d, KEY_EXIT }, /* back */
|
||||
{ 0x0a, KEY_CHANNELUP }, /* channel / program + */
|
||||
{ 0x1b, KEY_CHANNELDOWN }, /* channel / program - */
|
||||
{ 0x1a, KEY_ENTER }, /* enter */
|
||||
{ 0x081e, KEY_TV }, /* tv */
|
||||
{ 0x0822, KEY_EXIT }, /* back */
|
||||
{ 0x0835, KEY_CHANNELUP }, /* channel / program + */
|
||||
{ 0x0824, KEY_CHANNELDOWN }, /* channel / program - */
|
||||
{ 0x0825, KEY_ENTER }, /* enter */
|
||||
|
||||
{ 0x06, KEY_PAUSE }, /* play/pause */
|
||||
{ 0x1e, KEY_PREVIOUS }, /* rew */
|
||||
{ 0x26, KEY_NEXT }, /* forward */
|
||||
{ 0x0e, KEY_REWIND }, /* backward << */
|
||||
{ 0x3a, KEY_FASTFORWARD }, /* forward >> */
|
||||
{ 0x36, KEY_STOP },
|
||||
{ 0x2e, KEY_RECORD }, /* recording */
|
||||
{ 0x16, KEY_POWER }, /* the button that reads "close" */
|
||||
{ 0x0839, KEY_PAUSE }, /* play/pause */
|
||||
{ 0x0821, KEY_PREVIOUS }, /* rew */
|
||||
{ 0x0819, KEY_NEXT }, /* forward */
|
||||
{ 0x0831, KEY_REWIND }, /* backward << */
|
||||
{ 0x0805, KEY_FASTFORWARD }, /* forward >> */
|
||||
{ 0x0809, KEY_STOP },
|
||||
{ 0x0811, KEY_RECORD }, /* recording */
|
||||
{ 0x0829, KEY_POWER }, /* the button that reads "close" */
|
||||
|
||||
{ 0x11, KEY_ZOOM }, /* full screen */
|
||||
{ 0x13, KEY_MACRO }, /* recall */
|
||||
{ 0x23, KEY_HOME }, /* home */
|
||||
{ 0x05, KEY_PVR }, /* picture */
|
||||
{ 0x3d, KEY_MUTE }, /* mute */
|
||||
{ 0x01, KEY_DVD }, /* dvd */
|
||||
{ 0x082e, KEY_ZOOM }, /* full screen */
|
||||
{ 0x082c, KEY_MACRO }, /* recall */
|
||||
{ 0x081c, KEY_HOME }, /* home */
|
||||
{ 0x083a, KEY_PVR }, /* picture */
|
||||
{ 0x0802, KEY_MUTE }, /* mute */
|
||||
{ 0x083e, KEY_DVD }, /* dvd */
|
||||
};
|
||||
|
||||
static struct rc_keymap asus_pc39_map = {
|
||||
.map = {
|
||||
.scan = asus_pc39,
|
||||
.size = ARRAY_SIZE(asus_pc39),
|
||||
.ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
|
||||
.ir_type = IR_TYPE_RC5,
|
||||
.name = RC_MAP_ASUS_PC39,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* AverMedia RM-KS remote controller keytable
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
/* Initial keytable is from Jose Alberto Reguero <jareguero@telefonica.net>
|
||||
and Felipe Morales Moreno <felipe.morales.moreno@gmail.com> */
|
||||
/* FIXME: mappings are not 100% correct? */
|
||||
static struct ir_scancode avermedia_rm_ks[] = {
|
||||
{ 0x0501, KEY_POWER2 },
|
||||
{ 0x0502, KEY_CHANNELUP },
|
||||
{ 0x0503, KEY_CHANNELDOWN },
|
||||
{ 0x0504, KEY_VOLUMEUP },
|
||||
{ 0x0505, KEY_VOLUMEDOWN },
|
||||
{ 0x0506, KEY_MUTE },
|
||||
{ 0x0507, KEY_RIGHT },
|
||||
{ 0x0508, KEY_PROG1 },
|
||||
{ 0x0509, KEY_1 },
|
||||
{ 0x050a, KEY_2 },
|
||||
{ 0x050b, KEY_3 },
|
||||
{ 0x050c, KEY_4 },
|
||||
{ 0x050d, KEY_5 },
|
||||
{ 0x050e, KEY_6 },
|
||||
{ 0x050f, KEY_7 },
|
||||
{ 0x0510, KEY_8 },
|
||||
{ 0x0511, KEY_9 },
|
||||
{ 0x0512, KEY_0 },
|
||||
{ 0x0513, KEY_AUDIO },
|
||||
{ 0x0515, KEY_EPG },
|
||||
{ 0x0516, KEY_PLAY },
|
||||
{ 0x0517, KEY_RECORD },
|
||||
{ 0x0518, KEY_STOP },
|
||||
{ 0x051c, KEY_BACK },
|
||||
{ 0x051d, KEY_FORWARD },
|
||||
{ 0x054d, KEY_LEFT },
|
||||
{ 0x0556, KEY_ZOOM },
|
||||
};
|
||||
|
||||
static struct rc_keymap avermedia_rm_ks_map = {
|
||||
.map = {
|
||||
.scan = avermedia_rm_ks,
|
||||
.size = ARRAY_SIZE(avermedia_rm_ks),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
.name = RC_MAP_AVERMEDIA_RM_KS,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_avermedia_rm_ks(void)
|
||||
{
|
||||
return ir_register_map(&avermedia_rm_ks_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_avermedia_rm_ks(void)
|
||||
{
|
||||
ir_unregister_map(&avermedia_rm_ks_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_avermedia_rm_ks)
|
||||
module_exit(exit_rc_map_avermedia_rm_ks)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* TwinHan AzureWave AD-TU700(704J) remote controller keytable
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
static struct ir_scancode azurewave_ad_tu700[] = {
|
||||
{ 0x0000, KEY_TAB }, /* Tab */
|
||||
{ 0x0001, KEY_2 },
|
||||
{ 0x0002, KEY_CHANNELDOWN },
|
||||
{ 0x0003, KEY_1 },
|
||||
{ 0x0004, KEY_MENU }, /* Record List */
|
||||
{ 0x0005, KEY_CHANNELUP },
|
||||
{ 0x0006, KEY_3 },
|
||||
{ 0x0007, KEY_SLEEP }, /* Hibernate */
|
||||
{ 0x0008, KEY_VIDEO }, /* A/V */
|
||||
{ 0x0009, KEY_4 },
|
||||
{ 0x000a, KEY_VOLUMEDOWN },
|
||||
{ 0x000c, KEY_CANCEL }, /* Cancel */
|
||||
{ 0x000d, KEY_7 },
|
||||
{ 0x000e, KEY_AGAIN }, /* Recall */
|
||||
{ 0x000f, KEY_TEXT }, /* Teletext */
|
||||
{ 0x0010, KEY_MUTE },
|
||||
{ 0x0011, KEY_RECORD },
|
||||
{ 0x0012, KEY_FASTFORWARD }, /* FF >> */
|
||||
{ 0x0013, KEY_BACK }, /* Back */
|
||||
{ 0x0014, KEY_PLAY },
|
||||
{ 0x0015, KEY_0 },
|
||||
{ 0x0016, KEY_POWER2 }, /* [red power button] */
|
||||
{ 0x0017, KEY_FAVORITES }, /* Favorite List */
|
||||
{ 0x0018, KEY_RED },
|
||||
{ 0x0019, KEY_8 },
|
||||
{ 0x001a, KEY_STOP },
|
||||
{ 0x001b, KEY_9 },
|
||||
{ 0x001c, KEY_EPG }, /* Info/EPG */
|
||||
{ 0x001d, KEY_5 },
|
||||
{ 0x001e, KEY_VOLUMEUP },
|
||||
{ 0x001f, KEY_6 },
|
||||
{ 0x0040, KEY_REWIND }, /* FR << */
|
||||
{ 0x0041, KEY_PREVIOUS }, /* Replay */
|
||||
{ 0x0042, KEY_NEXT }, /* Skip */
|
||||
{ 0x0043, KEY_SUBTITLE }, /* Subtitle / CC */
|
||||
{ 0x0045, KEY_KPPLUS }, /* Zoom+ */
|
||||
{ 0x0046, KEY_KPMINUS }, /* Zoom- */
|
||||
{ 0x0047, KEY_NEW }, /* PIP */
|
||||
{ 0x0048, KEY_INFO }, /* Preview */
|
||||
{ 0x0049, KEY_MODE }, /* L/R */
|
||||
{ 0x004a, KEY_CLEAR }, /* Clear */
|
||||
{ 0x004b, KEY_UP }, /* up arrow */
|
||||
{ 0x004c, KEY_PAUSE },
|
||||
{ 0x004d, KEY_ZOOM }, /* Full Screen */
|
||||
{ 0x004e, KEY_LEFT }, /* left arrow */
|
||||
{ 0x004f, KEY_OK }, /* Enter / ok */
|
||||
{ 0x0050, KEY_LANGUAGE }, /* SAP */
|
||||
{ 0x0051, KEY_DOWN }, /* down arrow */
|
||||
{ 0x0052, KEY_RIGHT }, /* right arrow */
|
||||
{ 0x0053, KEY_GREEN },
|
||||
{ 0x0054, KEY_CAMERA }, /* Capture */
|
||||
{ 0x005e, KEY_YELLOW },
|
||||
{ 0x005f, KEY_BLUE },
|
||||
};
|
||||
|
||||
static struct rc_keymap azurewave_ad_tu700_map = {
|
||||
.map = {
|
||||
.scan = azurewave_ad_tu700,
|
||||
.size = ARRAY_SIZE(azurewave_ad_tu700),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
.name = RC_MAP_AZUREWAVE_AD_TU700,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_azurewave_ad_tu700(void)
|
||||
{
|
||||
return ir_register_map(&azurewave_ad_tu700_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_azurewave_ad_tu700(void)
|
||||
{
|
||||
ir_unregister_map(&azurewave_ad_tu700_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_azurewave_ad_tu700)
|
||||
module_exit(exit_rc_map_azurewave_ad_tu700)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* DigitalNow TinyTwin remote controller keytable
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
static struct ir_scancode digitalnow_tinytwin[] = {
|
||||
{ 0x0000, KEY_MUTE }, /* [symbol speaker] */
|
||||
{ 0x0001, KEY_VOLUMEUP },
|
||||
{ 0x0002, KEY_POWER2 }, /* TV [power button] */
|
||||
{ 0x0003, KEY_2 },
|
||||
{ 0x0004, KEY_3 },
|
||||
{ 0x0005, KEY_4 },
|
||||
{ 0x0006, KEY_6 },
|
||||
{ 0x0007, KEY_7 },
|
||||
{ 0x0008, KEY_8 },
|
||||
{ 0x0009, KEY_NUMERIC_STAR }, /* [*] */
|
||||
{ 0x000a, KEY_0 },
|
||||
{ 0x000b, KEY_NUMERIC_POUND }, /* [#] */
|
||||
{ 0x000c, KEY_RIGHT }, /* [right arrow] */
|
||||
{ 0x000d, KEY_HOMEPAGE }, /* [symbol home] Start */
|
||||
{ 0x000e, KEY_RED }, /* [red] Videos */
|
||||
{ 0x0010, KEY_POWER }, /* PC [power button] */
|
||||
{ 0x0011, KEY_YELLOW }, /* [yellow] Pictures */
|
||||
{ 0x0012, KEY_DOWN }, /* [down arrow] */
|
||||
{ 0x0013, KEY_GREEN }, /* [green] Music */
|
||||
{ 0x0014, KEY_CYCLEWINDOWS }, /* BACK */
|
||||
{ 0x0015, KEY_FAVORITES }, /* MORE */
|
||||
{ 0x0016, KEY_UP }, /* [up arrow] */
|
||||
{ 0x0017, KEY_LEFT }, /* [left arrow] */
|
||||
{ 0x0018, KEY_OK }, /* OK */
|
||||
{ 0x0019, KEY_BLUE }, /* [blue] MyTV */
|
||||
{ 0x001a, KEY_REWIND }, /* REW [<<] */
|
||||
{ 0x001b, KEY_PLAY }, /* PLAY */
|
||||
{ 0x001c, KEY_5 },
|
||||
{ 0x001d, KEY_9 },
|
||||
{ 0x001e, KEY_VOLUMEDOWN },
|
||||
{ 0x001f, KEY_1 },
|
||||
{ 0x0040, KEY_STOP }, /* STOP */
|
||||
{ 0x0042, KEY_PAUSE }, /* PAUSE */
|
||||
{ 0x0043, KEY_SCREEN }, /* Aspect */
|
||||
{ 0x0044, KEY_FORWARD }, /* FWD [>>] */
|
||||
{ 0x0045, KEY_NEXT }, /* SKIP */
|
||||
{ 0x0048, KEY_RECORD }, /* RECORD */
|
||||
{ 0x0049, KEY_VIDEO }, /* RTV */
|
||||
{ 0x004a, KEY_EPG }, /* Guide */
|
||||
{ 0x004b, KEY_CHANNELUP },
|
||||
{ 0x004c, KEY_HELP }, /* Help */
|
||||
{ 0x004d, KEY_RADIO }, /* Radio */
|
||||
{ 0x004f, KEY_CHANNELDOWN },
|
||||
{ 0x0050, KEY_DVD }, /* DVD */
|
||||
{ 0x0051, KEY_AUDIO }, /* Audio */
|
||||
{ 0x0052, KEY_TITLE }, /* Title */
|
||||
{ 0x0053, KEY_NEW }, /* [symbol PIP?] */
|
||||
{ 0x0057, KEY_MENU }, /* Mouse */
|
||||
{ 0x005a, KEY_PREVIOUS }, /* REPLAY */
|
||||
};
|
||||
|
||||
static struct rc_keymap digitalnow_tinytwin_map = {
|
||||
.map = {
|
||||
.scan = digitalnow_tinytwin,
|
||||
.size = ARRAY_SIZE(digitalnow_tinytwin),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
.name = RC_MAP_DIGITALNOW_TINYTWIN,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_digitalnow_tinytwin(void)
|
||||
{
|
||||
return ir_register_map(&digitalnow_tinytwin_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_digitalnow_tinytwin(void)
|
||||
{
|
||||
ir_unregister_map(&digitalnow_tinytwin_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_digitalnow_tinytwin)
|
||||
module_exit(exit_rc_map_digitalnow_tinytwin)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Digittrade DVB-T USB Stick remote controller keytable
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
/* Digittrade DVB-T USB Stick remote controller. */
|
||||
/* Imported from af9015.h.
|
||||
Initial keytable was from Alain Kalker <miki@dds.nl> */
|
||||
|
||||
/* Digittrade DVB-T USB Stick */
|
||||
static struct ir_scancode digittrade[] = {
|
||||
{ 0x0000, KEY_9 },
|
||||
{ 0x0001, KEY_EPG }, /* EPG */
|
||||
{ 0x0002, KEY_VOLUMEDOWN }, /* Vol Dn */
|
||||
{ 0x0003, KEY_TEXT }, /* TELETEXT */
|
||||
{ 0x0004, KEY_8 },
|
||||
{ 0x0005, KEY_MUTE }, /* MUTE */
|
||||
{ 0x0006, KEY_POWER2 }, /* POWER */
|
||||
{ 0x0009, KEY_ZOOM }, /* FULLSCREEN */
|
||||
{ 0x000a, KEY_RECORD }, /* RECORD */
|
||||
{ 0x000d, KEY_SUBTITLE }, /* SUBTITLE */
|
||||
{ 0x000e, KEY_STOP }, /* STOP */
|
||||
{ 0x0010, KEY_OK }, /* RETURN */
|
||||
{ 0x0011, KEY_2 },
|
||||
{ 0x0012, KEY_4 },
|
||||
{ 0x0015, KEY_3 },
|
||||
{ 0x0016, KEY_5 },
|
||||
{ 0x0017, KEY_CHANNELDOWN }, /* Ch Dn */
|
||||
{ 0x0019, KEY_CHANNELUP }, /* CH Up */
|
||||
{ 0x001a, KEY_PAUSE }, /* PAUSE */
|
||||
{ 0x001b, KEY_1 },
|
||||
{ 0x001d, KEY_AUDIO }, /* DUAL SOUND */
|
||||
{ 0x001e, KEY_PLAY }, /* PLAY */
|
||||
{ 0x001f, KEY_CAMERA }, /* SNAPSHOT */
|
||||
{ 0x0040, KEY_VOLUMEUP }, /* Vol Up */
|
||||
{ 0x0048, KEY_7 },
|
||||
{ 0x004c, KEY_6 },
|
||||
{ 0x004d, KEY_PLAYPAUSE }, /* TIMESHIFT */
|
||||
{ 0x0054, KEY_0 },
|
||||
};
|
||||
|
||||
static struct rc_keymap digittrade_map = {
|
||||
.map = {
|
||||
.scan = digittrade,
|
||||
.size = ARRAY_SIZE(digittrade),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
.name = RC_MAP_DIGITTRADE,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_digittrade(void)
|
||||
{
|
||||
return ir_register_map(&digittrade_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_digittrade(void)
|
||||
{
|
||||
ir_unregister_map(&digittrade_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_digittrade)
|
||||
module_exit(exit_rc_map_digittrade)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* LeadTek Y04G0051 remote controller keytable
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
static struct ir_scancode leadtek_y04g0051[] = {
|
||||
{ 0x0300, KEY_POWER2 },
|
||||
{ 0x0303, KEY_SCREEN },
|
||||
{ 0x0304, KEY_RIGHT },
|
||||
{ 0x0305, KEY_1 },
|
||||
{ 0x0306, KEY_2 },
|
||||
{ 0x0307, KEY_3 },
|
||||
{ 0x0308, KEY_LEFT },
|
||||
{ 0x0309, KEY_4 },
|
||||
{ 0x030a, KEY_5 },
|
||||
{ 0x030b, KEY_6 },
|
||||
{ 0x030c, KEY_UP },
|
||||
{ 0x030d, KEY_7 },
|
||||
{ 0x030e, KEY_8 },
|
||||
{ 0x030f, KEY_9 },
|
||||
{ 0x0310, KEY_DOWN },
|
||||
{ 0x0311, KEY_AGAIN },
|
||||
{ 0x0312, KEY_0 },
|
||||
{ 0x0313, KEY_OK }, /* 1st ok */
|
||||
{ 0x0314, KEY_MUTE },
|
||||
{ 0x0316, KEY_OK }, /* 2nd ok */
|
||||
{ 0x031e, KEY_VIDEO }, /* 2nd video */
|
||||
{ 0x031b, KEY_AUDIO },
|
||||
{ 0x031f, KEY_TEXT },
|
||||
{ 0x0340, KEY_SLEEP },
|
||||
{ 0x0341, KEY_DOT },
|
||||
{ 0x0342, KEY_REWIND },
|
||||
{ 0x0343, KEY_PLAY },
|
||||
{ 0x0344, KEY_FASTFORWARD },
|
||||
{ 0x0345, KEY_TIME },
|
||||
{ 0x0346, KEY_STOP }, /* 2nd stop */
|
||||
{ 0x0347, KEY_RECORD },
|
||||
{ 0x0348, KEY_CAMERA },
|
||||
{ 0x0349, KEY_ESC },
|
||||
{ 0x034a, KEY_NEW },
|
||||
{ 0x034b, KEY_RED },
|
||||
{ 0x034c, KEY_GREEN },
|
||||
{ 0x034d, KEY_YELLOW },
|
||||
{ 0x034e, KEY_BLUE },
|
||||
{ 0x034f, KEY_MENU },
|
||||
{ 0x0350, KEY_STOP }, /* 1st stop */
|
||||
{ 0x0351, KEY_CHANNEL },
|
||||
{ 0x0352, KEY_VIDEO }, /* 1st video */
|
||||
{ 0x0353, KEY_EPG },
|
||||
{ 0x0354, KEY_PREVIOUS },
|
||||
{ 0x0355, KEY_NEXT },
|
||||
{ 0x0356, KEY_TV },
|
||||
{ 0x035a, KEY_VOLUMEDOWN },
|
||||
{ 0x035b, KEY_CHANNELUP },
|
||||
{ 0x035e, KEY_VOLUMEUP },
|
||||
{ 0x035f, KEY_CHANNELDOWN },
|
||||
};
|
||||
|
||||
static struct rc_keymap leadtek_y04g0051_map = {
|
||||
.map = {
|
||||
.scan = leadtek_y04g0051,
|
||||
.size = ARRAY_SIZE(leadtek_y04g0051),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
.name = RC_MAP_LEADTEK_Y04G0051,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_leadtek_y04g0051(void)
|
||||
{
|
||||
return ir_register_map(&leadtek_y04g0051_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_leadtek_y04g0051(void)
|
||||
{
|
||||
ir_unregister_map(&leadtek_y04g0051_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_leadtek_y04g0051)
|
||||
module_exit(exit_rc_map_leadtek_y04g0051)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
|
@ -0,0 +1,68 @@
|
|||
/* LME2510 remote control
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2010 Malcolm Priestley (tvboxspy@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
|
||||
static struct ir_scancode lme2510_rc[] = {
|
||||
{ 0xba45, KEY_0 },
|
||||
{ 0xa05f, KEY_1 },
|
||||
{ 0xaf50, KEY_2 },
|
||||
{ 0xa25d, KEY_3 },
|
||||
{ 0xbe41, KEY_4 },
|
||||
{ 0xf50a, KEY_5 },
|
||||
{ 0xbd42, KEY_6 },
|
||||
{ 0xb847, KEY_7 },
|
||||
{ 0xb649, KEY_8 },
|
||||
{ 0xfa05, KEY_9 },
|
||||
{ 0xbc43, KEY_POWER },
|
||||
{ 0xb946, KEY_SUBTITLE },
|
||||
{ 0xf906, KEY_PAUSE },
|
||||
{ 0xfc03, KEY_MEDIA_REPEAT},
|
||||
{ 0xfd02, KEY_PAUSE },
|
||||
{ 0xa15e, KEY_VOLUMEUP },
|
||||
{ 0xa35c, KEY_VOLUMEDOWN },
|
||||
{ 0xf609, KEY_CHANNELUP },
|
||||
{ 0xe51a, KEY_CHANNELDOWN },
|
||||
{ 0xe11e, KEY_PLAY },
|
||||
{ 0xe41b, KEY_ZOOM },
|
||||
{ 0xa659, KEY_MUTE },
|
||||
{ 0xa55a, KEY_TV },
|
||||
{ 0xe718, KEY_RECORD },
|
||||
{ 0xf807, KEY_EPG },
|
||||
{ 0xfe01, KEY_STOP },
|
||||
|
||||
};
|
||||
|
||||
static struct rc_keymap lme2510_map = {
|
||||
.map = {
|
||||
.scan = lme2510_rc,
|
||||
.size = ARRAY_SIZE(lme2510_rc),
|
||||
.ir_type = IR_TYPE_UNKNOWN,
|
||||
.name = RC_MAP_LME2510,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_lme2510_map(void)
|
||||
{
|
||||
return ir_register_map(&lme2510_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_lme2510_map(void)
|
||||
{
|
||||
ir_unregister_map(&lme2510_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_lme2510_map)
|
||||
module_exit(exit_rc_lme2510_map)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* MSI DIGIVOX mini II remote controller keytable
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
static struct ir_scancode msi_digivox_ii[] = {
|
||||
{ 0x0002, KEY_2 },
|
||||
{ 0x0003, KEY_UP }, /* up */
|
||||
{ 0x0004, KEY_3 },
|
||||
{ 0x0005, KEY_CHANNELDOWN },
|
||||
{ 0x0008, KEY_5 },
|
||||
{ 0x0009, KEY_0 },
|
||||
{ 0x000b, KEY_8 },
|
||||
{ 0x000d, KEY_DOWN }, /* down */
|
||||
{ 0x0010, KEY_9 },
|
||||
{ 0x0011, KEY_7 },
|
||||
{ 0x0014, KEY_VOLUMEUP },
|
||||
{ 0x0015, KEY_CHANNELUP },
|
||||
{ 0x0016, KEY_OK },
|
||||
{ 0x0017, KEY_POWER2 },
|
||||
{ 0x001a, KEY_1 },
|
||||
{ 0x001c, KEY_4 },
|
||||
{ 0x001d, KEY_6 },
|
||||
{ 0x001f, KEY_VOLUMEDOWN },
|
||||
};
|
||||
|
||||
static struct rc_keymap msi_digivox_ii_map = {
|
||||
.map = {
|
||||
.scan = msi_digivox_ii,
|
||||
.size = ARRAY_SIZE(msi_digivox_ii),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
.name = RC_MAP_MSI_DIGIVOX_II,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_msi_digivox_ii(void)
|
||||
{
|
||||
return ir_register_map(&msi_digivox_ii_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_msi_digivox_ii(void)
|
||||
{
|
||||
ir_unregister_map(&msi_digivox_ii_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_msi_digivox_ii)
|
||||
module_exit(exit_rc_map_msi_digivox_ii)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* MSI DIGIVOX mini III remote controller keytable
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
/* MSI DIGIVOX mini III */
|
||||
/* Uses NEC extended 0x61d6. */
|
||||
/* This remote seems to be same as rc-kworld-315u.c. Anyhow, add new remote
|
||||
since rc-kworld-315u.c lacks NEC extended address byte. */
|
||||
static struct ir_scancode msi_digivox_iii[] = {
|
||||
{ 0x61d601, KEY_VIDEO }, /* Source */
|
||||
{ 0x61d602, KEY_3 },
|
||||
{ 0x61d603, KEY_POWER }, /* ShutDown */
|
||||
{ 0x61d604, KEY_1 },
|
||||
{ 0x61d605, KEY_5 },
|
||||
{ 0x61d606, KEY_6 },
|
||||
{ 0x61d607, KEY_CHANNELDOWN }, /* CH- */
|
||||
{ 0x61d608, KEY_2 },
|
||||
{ 0x61d609, KEY_CHANNELUP }, /* CH+ */
|
||||
{ 0x61d60a, KEY_9 },
|
||||
{ 0x61d60b, KEY_ZOOM }, /* Zoom */
|
||||
{ 0x61d60c, KEY_7 },
|
||||
{ 0x61d60d, KEY_8 },
|
||||
{ 0x61d60e, KEY_VOLUMEUP }, /* Vol+ */
|
||||
{ 0x61d60f, KEY_4 },
|
||||
{ 0x61d610, KEY_ESC }, /* [back up arrow] */
|
||||
{ 0x61d611, KEY_0 },
|
||||
{ 0x61d612, KEY_OK }, /* [enter arrow] */
|
||||
{ 0x61d613, KEY_VOLUMEDOWN }, /* Vol- */
|
||||
{ 0x61d614, KEY_RECORD }, /* Rec */
|
||||
{ 0x61d615, KEY_STOP }, /* Stop */
|
||||
{ 0x61d616, KEY_PLAY }, /* Play */
|
||||
{ 0x61d617, KEY_MUTE }, /* Mute */
|
||||
{ 0x61d618, KEY_UP },
|
||||
{ 0x61d619, KEY_DOWN },
|
||||
{ 0x61d61a, KEY_LEFT },
|
||||
{ 0x61d61b, KEY_RIGHT },
|
||||
{ 0x61d61c, KEY_RED },
|
||||
{ 0x61d61d, KEY_GREEN },
|
||||
{ 0x61d61e, KEY_YELLOW },
|
||||
{ 0x61d61f, KEY_BLUE },
|
||||
{ 0x61d643, KEY_POWER2 }, /* [red power button] */
|
||||
};
|
||||
|
||||
static struct rc_keymap msi_digivox_iii_map = {
|
||||
.map = {
|
||||
.scan = msi_digivox_iii,
|
||||
.size = ARRAY_SIZE(msi_digivox_iii),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
.name = RC_MAP_MSI_DIGIVOX_III,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_msi_digivox_iii(void)
|
||||
{
|
||||
return ir_register_map(&msi_digivox_iii_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_msi_digivox_iii(void)
|
||||
{
|
||||
ir_unregister_map(&msi_digivox_iii_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_msi_digivox_iii)
|
||||
module_exit(exit_rc_map_msi_digivox_iii)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
|
@ -1,81 +0,0 @@
|
|||
/* rc-rc5-streamzap.c - Keytable for Streamzap PC Remote, for use
|
||||
* with the Streamzap PC Remote IR Receiver.
|
||||
*
|
||||
* Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
static struct ir_scancode rc5_streamzap[] = {
|
||||
/*
|
||||
* FIXME: The Streamzap remote isn't actually true RC-5, it has an extra
|
||||
* bit in it, which presently throws the in-kernel RC-5 decoder for a loop.
|
||||
* We either have to enhance the decoder to support it, add a new decoder,
|
||||
* or just rely on lirc userspace decoding.
|
||||
*/
|
||||
{ 0x00, KEY_NUMERIC_0 },
|
||||
{ 0x01, KEY_NUMERIC_1 },
|
||||
{ 0x02, KEY_NUMERIC_2 },
|
||||
{ 0x03, KEY_NUMERIC_3 },
|
||||
{ 0x04, KEY_NUMERIC_4 },
|
||||
{ 0x05, KEY_NUMERIC_5 },
|
||||
{ 0x06, KEY_NUMERIC_6 },
|
||||
{ 0x07, KEY_NUMERIC_7 },
|
||||
{ 0x08, KEY_NUMERIC_8 },
|
||||
{ 0x0a, KEY_POWER },
|
||||
{ 0x0b, KEY_MUTE },
|
||||
{ 0x0c, KEY_CHANNELUP },
|
||||
{ 0x0d, KEY_VOLUMEUP },
|
||||
{ 0x0e, KEY_CHANNELDOWN },
|
||||
{ 0x0f, KEY_VOLUMEDOWN },
|
||||
{ 0x10, KEY_UP },
|
||||
{ 0x11, KEY_LEFT },
|
||||
{ 0x12, KEY_OK },
|
||||
{ 0x13, KEY_RIGHT },
|
||||
{ 0x14, KEY_DOWN },
|
||||
{ 0x15, KEY_MENU },
|
||||
{ 0x16, KEY_EXIT },
|
||||
{ 0x17, KEY_PLAY },
|
||||
{ 0x18, KEY_PAUSE },
|
||||
{ 0x19, KEY_STOP },
|
||||
{ 0x1a, KEY_BACK },
|
||||
{ 0x1b, KEY_FORWARD },
|
||||
{ 0x1c, KEY_RECORD },
|
||||
{ 0x1d, KEY_REWIND },
|
||||
{ 0x1e, KEY_FASTFORWARD },
|
||||
{ 0x20, KEY_RED },
|
||||
{ 0x21, KEY_GREEN },
|
||||
{ 0x22, KEY_YELLOW },
|
||||
{ 0x23, KEY_BLUE },
|
||||
|
||||
};
|
||||
|
||||
static struct rc_keymap rc5_streamzap_map = {
|
||||
.map = {
|
||||
.scan = rc5_streamzap,
|
||||
.size = ARRAY_SIZE(rc5_streamzap),
|
||||
.ir_type = IR_TYPE_RC5,
|
||||
.name = RC_MAP_RC5_STREAMZAP,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_rc5_streamzap(void)
|
||||
{
|
||||
return ir_register_map(&rc5_streamzap_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_rc5_streamzap(void)
|
||||
{
|
||||
ir_unregister_map(&rc5_streamzap_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_rc5_streamzap)
|
||||
module_exit(exit_rc_map_rc5_streamzap)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
|
|
@ -12,35 +12,8 @@
|
|||
#include <media/rc-map.h>
|
||||
|
||||
static struct ir_scancode rc6_mce[] = {
|
||||
{ 0x800f0415, KEY_REWIND },
|
||||
{ 0x800f0414, KEY_FASTFORWARD },
|
||||
{ 0x800f041b, KEY_PREVIOUS },
|
||||
{ 0x800f041a, KEY_NEXT },
|
||||
|
||||
{ 0x800f0416, KEY_PLAY },
|
||||
{ 0x800f0418, KEY_PAUSE },
|
||||
{ 0x800f046e, KEY_PLAYPAUSE },
|
||||
{ 0x800f0419, KEY_STOP },
|
||||
{ 0x800f0417, KEY_RECORD },
|
||||
|
||||
{ 0x800f041e, KEY_UP },
|
||||
{ 0x800f041f, KEY_DOWN },
|
||||
{ 0x800f0420, KEY_LEFT },
|
||||
{ 0x800f0421, KEY_RIGHT },
|
||||
|
||||
{ 0x800f040b, KEY_ENTER },
|
||||
{ 0x800f0422, KEY_OK },
|
||||
{ 0x800f0423, KEY_EXIT },
|
||||
{ 0x800f040a, KEY_DELETE },
|
||||
|
||||
{ 0x800f040e, KEY_MUTE },
|
||||
{ 0x800f0410, KEY_VOLUMEUP },
|
||||
{ 0x800f0411, KEY_VOLUMEDOWN },
|
||||
{ 0x800f0412, KEY_CHANNELUP },
|
||||
{ 0x800f0413, KEY_CHANNELDOWN },
|
||||
{ 0x800f043a, KEY_BRIGHTNESSUP },
|
||||
{ 0x800f0480, KEY_BRIGHTNESSDOWN },
|
||||
|
||||
{ 0x800f0400, KEY_NUMERIC_0 },
|
||||
{ 0x800f0401, KEY_NUMERIC_1 },
|
||||
{ 0x800f0402, KEY_NUMERIC_2 },
|
||||
{ 0x800f0403, KEY_NUMERIC_3 },
|
||||
|
@ -50,38 +23,67 @@ static struct ir_scancode rc6_mce[] = {
|
|||
{ 0x800f0407, KEY_NUMERIC_7 },
|
||||
{ 0x800f0408, KEY_NUMERIC_8 },
|
||||
{ 0x800f0409, KEY_NUMERIC_9 },
|
||||
{ 0x800f0400, KEY_NUMERIC_0 },
|
||||
|
||||
{ 0x800f041d, KEY_NUMERIC_STAR },
|
||||
{ 0x800f040a, KEY_DELETE },
|
||||
{ 0x800f040b, KEY_ENTER },
|
||||
{ 0x800f040c, KEY_POWER },
|
||||
{ 0x800f040d, KEY_PROG1 }, /* Windows MCE button */
|
||||
{ 0x800f040e, KEY_MUTE },
|
||||
{ 0x800f040f, KEY_INFO },
|
||||
|
||||
{ 0x800f0410, KEY_VOLUMEUP },
|
||||
{ 0x800f0411, KEY_VOLUMEDOWN },
|
||||
{ 0x800f0412, KEY_CHANNELUP },
|
||||
{ 0x800f0413, KEY_CHANNELDOWN },
|
||||
|
||||
{ 0x800f0414, KEY_FASTFORWARD },
|
||||
{ 0x800f0415, KEY_REWIND },
|
||||
{ 0x800f0416, KEY_PLAY },
|
||||
{ 0x800f0417, KEY_RECORD },
|
||||
{ 0x800f0418, KEY_PAUSE },
|
||||
{ 0x800f046e, KEY_PLAYPAUSE },
|
||||
{ 0x800f0419, KEY_STOP },
|
||||
{ 0x800f041a, KEY_NEXT },
|
||||
{ 0x800f041b, KEY_PREVIOUS },
|
||||
{ 0x800f041c, KEY_NUMERIC_POUND },
|
||||
{ 0x800f041d, KEY_NUMERIC_STAR },
|
||||
|
||||
{ 0x800f041e, KEY_UP },
|
||||
{ 0x800f041f, KEY_DOWN },
|
||||
{ 0x800f0420, KEY_LEFT },
|
||||
{ 0x800f0421, KEY_RIGHT },
|
||||
|
||||
{ 0x800f0422, KEY_OK },
|
||||
{ 0x800f0423, KEY_EXIT },
|
||||
{ 0x800f0424, KEY_DVD },
|
||||
{ 0x800f0425, KEY_TUNER }, /* LiveTV */
|
||||
{ 0x800f0426, KEY_EPG }, /* Guide */
|
||||
{ 0x800f0427, KEY_ZOOM }, /* Aspect */
|
||||
|
||||
{ 0x800f043a, KEY_BRIGHTNESSUP },
|
||||
|
||||
{ 0x800f0446, KEY_TV },
|
||||
{ 0x800f0447, KEY_AUDIO }, /* My Music */
|
||||
{ 0x800f0448, KEY_PVR }, /* RecordedTV */
|
||||
{ 0x800f0447, KEY_AUDIO }, /* My Music */
|
||||
{ 0x800f0448, KEY_PVR }, /* RecordedTV */
|
||||
{ 0x800f0449, KEY_CAMERA },
|
||||
{ 0x800f044a, KEY_VIDEO },
|
||||
{ 0x800f0424, KEY_DVD },
|
||||
{ 0x800f0425, KEY_TUNER }, /* LiveTV */
|
||||
{ 0x800f044c, KEY_LANGUAGE },
|
||||
{ 0x800f044d, KEY_TITLE },
|
||||
{ 0x800f044e, KEY_PRINT }, /* Print - HP OEM version of remote */
|
||||
|
||||
{ 0x800f0450, KEY_RADIO },
|
||||
|
||||
{ 0x800f044c, KEY_LANGUAGE },
|
||||
{ 0x800f0427, KEY_ZOOM }, /* Aspect */
|
||||
|
||||
{ 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */
|
||||
{ 0x800f045b, KEY_RED },
|
||||
{ 0x800f045c, KEY_GREEN },
|
||||
{ 0x800f045d, KEY_YELLOW },
|
||||
{ 0x800f045e, KEY_BLUE },
|
||||
|
||||
{ 0x800f040f, KEY_INFO },
|
||||
{ 0x800f0426, KEY_EPG }, /* Guide */
|
||||
{ 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */
|
||||
{ 0x800f044d, KEY_TITLE },
|
||||
|
||||
{ 0x800f044e, KEY_PRINT }, /* Print - HP OEM version of remote */
|
||||
|
||||
{ 0x800f040c, KEY_POWER },
|
||||
{ 0x800f040d, KEY_PROG1 }, /* Windows MCE button */
|
||||
{ 0x800f046e, KEY_PLAYPAUSE },
|
||||
{ 0x800f046f, KEY_MEDIA }, /* Start media application (NEW) */
|
||||
|
||||
{ 0x800f0480, KEY_BRIGHTNESSDOWN },
|
||||
{ 0x800f0481, KEY_PLAYPAUSE },
|
||||
};
|
||||
|
||||
static struct rc_keymap rc6_mce_map = {
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/* rc-streamzap.c - Keytable for Streamzap PC Remote, for use
|
||||
* with the Streamzap PC Remote IR Receiver.
|
||||
*
|
||||
* Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
static struct ir_scancode streamzap[] = {
|
||||
/*
|
||||
* The Streamzap remote is almost, but not quite, RC-5, as it has an extra
|
||||
* bit in it, which throws the in-kernel RC-5 decoder for a loop. Currently,
|
||||
* an additional RC-5-sz decoder is being deployed to support it, but it
|
||||
* may be possible to merge it back with the standard RC-5 decoder.
|
||||
*/
|
||||
{ 0x28c0, KEY_NUMERIC_0 },
|
||||
{ 0x28c1, KEY_NUMERIC_1 },
|
||||
{ 0x28c2, KEY_NUMERIC_2 },
|
||||
{ 0x28c3, KEY_NUMERIC_3 },
|
||||
{ 0x28c4, KEY_NUMERIC_4 },
|
||||
{ 0x28c5, KEY_NUMERIC_5 },
|
||||
{ 0x28c6, KEY_NUMERIC_6 },
|
||||
{ 0x28c7, KEY_NUMERIC_7 },
|
||||
{ 0x28c8, KEY_NUMERIC_8 },
|
||||
{ 0x28c9, KEY_NUMERIC_9 },
|
||||
{ 0x28ca, KEY_POWER },
|
||||
{ 0x28cb, KEY_MUTE },
|
||||
{ 0x28cc, KEY_CHANNELUP },
|
||||
{ 0x28cd, KEY_VOLUMEUP },
|
||||
{ 0x28ce, KEY_CHANNELDOWN },
|
||||
{ 0x28cf, KEY_VOLUMEDOWN },
|
||||
{ 0x28d0, KEY_UP },
|
||||
{ 0x28d1, KEY_LEFT },
|
||||
{ 0x28d2, KEY_OK },
|
||||
{ 0x28d3, KEY_RIGHT },
|
||||
{ 0x28d4, KEY_DOWN },
|
||||
{ 0x28d5, KEY_MENU },
|
||||
{ 0x28d6, KEY_EXIT },
|
||||
{ 0x28d7, KEY_PLAY },
|
||||
{ 0x28d8, KEY_PAUSE },
|
||||
{ 0x28d9, KEY_STOP },
|
||||
{ 0x28da, KEY_BACK },
|
||||
{ 0x28db, KEY_FORWARD },
|
||||
{ 0x28dc, KEY_RECORD },
|
||||
{ 0x28dd, KEY_REWIND },
|
||||
{ 0x28de, KEY_FASTFORWARD },
|
||||
{ 0x28e0, KEY_RED },
|
||||
{ 0x28e1, KEY_GREEN },
|
||||
{ 0x28e2, KEY_YELLOW },
|
||||
{ 0x28e3, KEY_BLUE },
|
||||
|
||||
};
|
||||
|
||||
static struct rc_keymap streamzap_map = {
|
||||
.map = {
|
||||
.scan = streamzap,
|
||||
.size = ARRAY_SIZE(streamzap),
|
||||
.ir_type = IR_TYPE_RC5_SZ,
|
||||
.name = RC_MAP_STREAMZAP,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_streamzap(void)
|
||||
{
|
||||
return ir_register_map(&streamzap_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_streamzap(void)
|
||||
{
|
||||
ir_unregister_map(&streamzap_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_streamzap)
|
||||
module_exit(exit_rc_map_streamzap)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* TerraTec remote controller keytable
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
/* TerraTec slim remote, 7 rows, 4 columns. */
|
||||
/* Uses NEC extended 0x02bd. */
|
||||
static struct ir_scancode terratec_slim[] = {
|
||||
{ 0x02bd00, KEY_1 },
|
||||
{ 0x02bd01, KEY_2 },
|
||||
{ 0x02bd02, KEY_3 },
|
||||
{ 0x02bd03, KEY_4 },
|
||||
{ 0x02bd04, KEY_5 },
|
||||
{ 0x02bd05, KEY_6 },
|
||||
{ 0x02bd06, KEY_7 },
|
||||
{ 0x02bd07, KEY_8 },
|
||||
{ 0x02bd08, KEY_9 },
|
||||
{ 0x02bd09, KEY_0 },
|
||||
{ 0x02bd0a, KEY_MUTE },
|
||||
{ 0x02bd0b, KEY_NEW }, /* symbol: PIP */
|
||||
{ 0x02bd0e, KEY_VOLUMEDOWN },
|
||||
{ 0x02bd0f, KEY_PLAYPAUSE },
|
||||
{ 0x02bd10, KEY_RIGHT },
|
||||
{ 0x02bd11, KEY_LEFT },
|
||||
{ 0x02bd12, KEY_UP },
|
||||
{ 0x02bd13, KEY_DOWN },
|
||||
{ 0x02bd15, KEY_OK },
|
||||
{ 0x02bd16, KEY_STOP },
|
||||
{ 0x02bd17, KEY_CAMERA }, /* snapshot */
|
||||
{ 0x02bd18, KEY_CHANNELUP },
|
||||
{ 0x02bd19, KEY_RECORD },
|
||||
{ 0x02bd1a, KEY_CHANNELDOWN },
|
||||
{ 0x02bd1c, KEY_ESC },
|
||||
{ 0x02bd1f, KEY_VOLUMEUP },
|
||||
{ 0x02bd44, KEY_EPG },
|
||||
{ 0x02bd45, KEY_POWER2 }, /* [red power button] */
|
||||
};
|
||||
|
||||
static struct rc_keymap terratec_slim_map = {
|
||||
.map = {
|
||||
.scan = terratec_slim,
|
||||
.size = ARRAY_SIZE(terratec_slim),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
.name = RC_MAP_TERRATEC_SLIM,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_terratec_slim(void)
|
||||
{
|
||||
return ir_register_map(&terratec_slim_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_terratec_slim(void)
|
||||
{
|
||||
ir_unregister_map(&terratec_slim_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_terratec_slim)
|
||||
module_exit(exit_rc_map_terratec_slim)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Total Media In Hand remote controller keytable
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
/* Uses NEC extended 0x02bd */
|
||||
static struct ir_scancode total_media_in_hand[] = {
|
||||
{ 0x02bd00, KEY_1 },
|
||||
{ 0x02bd01, KEY_2 },
|
||||
{ 0x02bd02, KEY_3 },
|
||||
{ 0x02bd03, KEY_4 },
|
||||
{ 0x02bd04, KEY_5 },
|
||||
{ 0x02bd05, KEY_6 },
|
||||
{ 0x02bd06, KEY_7 },
|
||||
{ 0x02bd07, KEY_8 },
|
||||
{ 0x02bd08, KEY_9 },
|
||||
{ 0x02bd09, KEY_0 },
|
||||
{ 0x02bd0a, KEY_MUTE },
|
||||
{ 0x02bd0b, KEY_CYCLEWINDOWS }, /* yellow, [min / max] */
|
||||
{ 0x02bd0c, KEY_VIDEO }, /* TV / AV */
|
||||
{ 0x02bd0e, KEY_VOLUMEDOWN },
|
||||
{ 0x02bd0f, KEY_TIME }, /* TimeShift */
|
||||
{ 0x02bd10, KEY_RIGHT }, /* right arrow */
|
||||
{ 0x02bd11, KEY_LEFT }, /* left arrow */
|
||||
{ 0x02bd12, KEY_UP }, /* up arrow */
|
||||
{ 0x02bd13, KEY_DOWN }, /* down arrow */
|
||||
{ 0x02bd14, KEY_POWER2 }, /* [red] */
|
||||
{ 0x02bd15, KEY_OK }, /* OK */
|
||||
{ 0x02bd16, KEY_STOP },
|
||||
{ 0x02bd17, KEY_CAMERA }, /* Snapshot */
|
||||
{ 0x02bd18, KEY_CHANNELUP },
|
||||
{ 0x02bd19, KEY_RECORD },
|
||||
{ 0x02bd1a, KEY_CHANNELDOWN },
|
||||
{ 0x02bd1c, KEY_ESC }, /* Esc */
|
||||
{ 0x02bd1e, KEY_PLAY },
|
||||
{ 0x02bd1f, KEY_VOLUMEUP },
|
||||
{ 0x02bd40, KEY_PAUSE },
|
||||
{ 0x02bd41, KEY_FASTFORWARD }, /* FF >> */
|
||||
{ 0x02bd42, KEY_REWIND }, /* FR << */
|
||||
{ 0x02bd43, KEY_ZOOM }, /* [window + mouse pointer] */
|
||||
{ 0x02bd44, KEY_SHUFFLE }, /* Shuffle */
|
||||
{ 0x02bd45, KEY_INFO }, /* [red (I)] */
|
||||
};
|
||||
|
||||
static struct rc_keymap total_media_in_hand_map = {
|
||||
.map = {
|
||||
.scan = total_media_in_hand,
|
||||
.size = ARRAY_SIZE(total_media_in_hand),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
.name = RC_MAP_TOTAL_MEDIA_IN_HAND,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_total_media_in_hand(void)
|
||||
{
|
||||
return ir_register_map(&total_media_in_hand_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_total_media_in_hand(void)
|
||||
{
|
||||
ir_unregister_map(&total_media_in_hand_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_total_media_in_hand)
|
||||
module_exit(exit_rc_map_total_media_in_hand)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* TrekStor remote controller keytable
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
/* TrekStor DVB-T USB Stick remote controller. */
|
||||
/* Imported from af9015.h.
|
||||
Initial keytable was from Marc Schneider <macke@macke.org> */
|
||||
static struct ir_scancode trekstor[] = {
|
||||
{ 0x0084, KEY_0 },
|
||||
{ 0x0085, KEY_MUTE }, /* Mute */
|
||||
{ 0x0086, KEY_HOMEPAGE }, /* Home */
|
||||
{ 0x0087, KEY_UP }, /* Up */
|
||||
{ 0x0088, KEY_OK }, /* OK */
|
||||
{ 0x0089, KEY_RIGHT }, /* Right */
|
||||
{ 0x008a, KEY_FASTFORWARD }, /* Fast forward */
|
||||
{ 0x008b, KEY_VOLUMEUP }, /* Volume + */
|
||||
{ 0x008c, KEY_DOWN }, /* Down */
|
||||
{ 0x008d, KEY_PLAY }, /* Play/Pause */
|
||||
{ 0x008e, KEY_STOP }, /* Stop */
|
||||
{ 0x008f, KEY_EPG }, /* Info/EPG */
|
||||
{ 0x0090, KEY_7 },
|
||||
{ 0x0091, KEY_4 },
|
||||
{ 0x0092, KEY_1 },
|
||||
{ 0x0093, KEY_CHANNELDOWN }, /* Channel - */
|
||||
{ 0x0094, KEY_8 },
|
||||
{ 0x0095, KEY_5 },
|
||||
{ 0x0096, KEY_2 },
|
||||
{ 0x0097, KEY_CHANNELUP }, /* Channel + */
|
||||
{ 0x0098, KEY_9 },
|
||||
{ 0x0099, KEY_6 },
|
||||
{ 0x009a, KEY_3 },
|
||||
{ 0x009b, KEY_VOLUMEDOWN }, /* Volume - */
|
||||
{ 0x009c, KEY_TV }, /* TV */
|
||||
{ 0x009d, KEY_RECORD }, /* Record */
|
||||
{ 0x009e, KEY_REWIND }, /* Rewind */
|
||||
{ 0x009f, KEY_LEFT }, /* Left */
|
||||
};
|
||||
|
||||
static struct rc_keymap trekstor_map = {
|
||||
.map = {
|
||||
.scan = trekstor,
|
||||
.size = ARRAY_SIZE(trekstor),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
.name = RC_MAP_TREKSTOR,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_trekstor(void)
|
||||
{
|
||||
return ir_register_map(&trekstor_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_trekstor(void)
|
||||
{
|
||||
ir_unregister_map(&trekstor_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_trekstor)
|
||||
module_exit(exit_rc_map_trekstor)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
|
@ -0,0 +1,87 @@
|
|||
#include <media/rc-map.h>
|
||||
|
||||
static struct ir_scancode twinhan_vp1027[] = {
|
||||
{ 0x16, KEY_POWER2 },
|
||||
{ 0x17, KEY_FAVORITES },
|
||||
{ 0x0f, KEY_TEXT },
|
||||
{ 0x48, KEY_INFO},
|
||||
{ 0x1c, KEY_EPG },
|
||||
{ 0x04, KEY_LIST },
|
||||
|
||||
{ 0x03, KEY_1 },
|
||||
{ 0x01, KEY_2 },
|
||||
{ 0x06, KEY_3 },
|
||||
{ 0x09, KEY_4 },
|
||||
{ 0x1d, KEY_5 },
|
||||
{ 0x1f, KEY_6 },
|
||||
{ 0x0d, KEY_7 },
|
||||
{ 0x19, KEY_8 },
|
||||
{ 0x1b, KEY_9 },
|
||||
{ 0x15, KEY_0 },
|
||||
|
||||
{ 0x0c, KEY_CANCEL },
|
||||
{ 0x4a, KEY_CLEAR },
|
||||
{ 0x13, KEY_BACKSPACE },
|
||||
{ 0x00, KEY_TAB },
|
||||
|
||||
{ 0x4b, KEY_UP },
|
||||
{ 0x51, KEY_DOWN },
|
||||
{ 0x4e, KEY_LEFT },
|
||||
{ 0x52, KEY_RIGHT },
|
||||
{ 0x4f, KEY_ENTER },
|
||||
|
||||
{ 0x1e, KEY_VOLUMEUP },
|
||||
{ 0x0a, KEY_VOLUMEDOWN },
|
||||
{ 0x02, KEY_CHANNELDOWN },
|
||||
{ 0x05, KEY_CHANNELUP },
|
||||
{ 0x11, KEY_RECORD },
|
||||
|
||||
{ 0x14, KEY_PLAY },
|
||||
{ 0x4c, KEY_PAUSE },
|
||||
{ 0x1a, KEY_STOP },
|
||||
{ 0x40, KEY_REWIND },
|
||||
{ 0x12, KEY_FASTFORWARD },
|
||||
{ 0x41, KEY_PREVIOUSSONG },
|
||||
{ 0x42, KEY_NEXTSONG },
|
||||
{ 0x54, KEY_SAVE },
|
||||
{ 0x50, KEY_LANGUAGE },
|
||||
{ 0x47, KEY_MEDIA },
|
||||
{ 0x4d, KEY_SCREEN },
|
||||
{ 0x43, KEY_SUBTITLE },
|
||||
{ 0x10, KEY_MUTE },
|
||||
{ 0x49, KEY_AUDIO },
|
||||
{ 0x07, KEY_SLEEP },
|
||||
{ 0x08, KEY_VIDEO },
|
||||
{ 0x0e, KEY_AGAIN },
|
||||
{ 0x45, KEY_EQUAL },
|
||||
{ 0x46, KEY_MINUS },
|
||||
{ 0x18, KEY_RED },
|
||||
{ 0x53, KEY_GREEN },
|
||||
{ 0x5e, KEY_YELLOW },
|
||||
{ 0x5f, KEY_BLUE },
|
||||
};
|
||||
|
||||
static struct rc_keymap twinhan_vp1027_map = {
|
||||
.map = {
|
||||
.scan = twinhan_vp1027,
|
||||
.size = ARRAY_SIZE(twinhan_vp1027),
|
||||
.ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
|
||||
.name = RC_MAP_TWINHAN_VP1027_DVBS,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_twinhan_vp1027(void)
|
||||
{
|
||||
return ir_register_map(&twinhan_vp1027_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_twinhan_vp1027(void)
|
||||
{
|
||||
ir_unregister_map(&twinhan_vp1027_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_twinhan_vp1027)
|
||||
module_exit(exit_rc_map_twinhan_vp1027)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Sergey Ivanov <123kash@gmail.com>");
|
|
@ -57,13 +57,12 @@ struct irctl {
|
|||
|
||||
struct task_struct *task;
|
||||
long jiffies_to_wait;
|
||||
|
||||
struct cdev cdev;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(lirc_dev_lock);
|
||||
|
||||
static struct irctl *irctls[MAX_IRCTL_DEVICES];
|
||||
static struct cdev cdevs[MAX_IRCTL_DEVICES];
|
||||
|
||||
/* Only used for sysfs but defined to void otherwise */
|
||||
static struct class *lirc_class;
|
||||
|
@ -71,15 +70,13 @@ static struct class *lirc_class;
|
|||
/* helper function
|
||||
* initializes the irctl structure
|
||||
*/
|
||||
static void init_irctl(struct irctl *ir)
|
||||
static void lirc_irctl_init(struct irctl *ir)
|
||||
{
|
||||
dev_dbg(ir->d.dev, LOGHEAD "initializing irctl\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
mutex_init(&ir->irctl_lock);
|
||||
ir->d.minor = NOPLUG;
|
||||
}
|
||||
|
||||
static void cleanup(struct irctl *ir)
|
||||
static void lirc_irctl_cleanup(struct irctl *ir)
|
||||
{
|
||||
dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
|
||||
|
||||
|
@ -96,7 +93,7 @@ static void cleanup(struct irctl *ir)
|
|||
* reads key codes from driver and puts them into buffer
|
||||
* returns 0 on success
|
||||
*/
|
||||
static int add_to_buf(struct irctl *ir)
|
||||
static int lirc_add_to_buf(struct irctl *ir)
|
||||
{
|
||||
if (ir->d.add_to_buf) {
|
||||
int res = -ENODATA;
|
||||
|
@ -139,7 +136,7 @@ static int lirc_thread(void *irctl)
|
|||
}
|
||||
if (kthread_should_stop())
|
||||
break;
|
||||
if (!add_to_buf(ir))
|
||||
if (!lirc_add_to_buf(ir))
|
||||
wake_up_interruptible(&ir->buf->wait_poll);
|
||||
} else {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
@ -154,12 +151,15 @@ static int lirc_thread(void *irctl)
|
|||
}
|
||||
|
||||
|
||||
static struct file_operations fops = {
|
||||
static struct file_operations lirc_dev_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = lirc_dev_fop_read,
|
||||
.write = lirc_dev_fop_write,
|
||||
.poll = lirc_dev_fop_poll,
|
||||
.unlocked_ioctl = lirc_dev_fop_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = lirc_dev_fop_ioctl,
|
||||
#endif
|
||||
.open = lirc_dev_fop_open,
|
||||
.release = lirc_dev_fop_close,
|
||||
.llseek = noop_llseek,
|
||||
|
@ -169,19 +169,20 @@ static int lirc_cdev_add(struct irctl *ir)
|
|||
{
|
||||
int retval;
|
||||
struct lirc_driver *d = &ir->d;
|
||||
struct cdev *cdev = &cdevs[d->minor];
|
||||
|
||||
if (d->fops) {
|
||||
cdev_init(&ir->cdev, d->fops);
|
||||
ir->cdev.owner = d->owner;
|
||||
cdev_init(cdev, d->fops);
|
||||
cdev->owner = d->owner;
|
||||
} else {
|
||||
cdev_init(&ir->cdev, &fops);
|
||||
ir->cdev.owner = THIS_MODULE;
|
||||
cdev_init(cdev, &lirc_dev_fops);
|
||||
cdev->owner = THIS_MODULE;
|
||||
}
|
||||
kobject_set_name(&ir->cdev.kobj, "lirc%d", d->minor);
|
||||
kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
|
||||
|
||||
retval = cdev_add(&ir->cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
|
||||
retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
|
||||
if (retval)
|
||||
kobject_put(&ir->cdev.kobj);
|
||||
kobject_put(&cdev->kobj);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -202,6 +203,12 @@ int lirc_register_driver(struct lirc_driver *d)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!d->dev) {
|
||||
printk(KERN_ERR "%s: dev pointer not filled in!\n", __func__);
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (MAX_IRCTL_DEVICES <= d->minor) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"\"minor\" must be between 0 and %d (%d)!\n",
|
||||
|
@ -277,7 +284,7 @@ int lirc_register_driver(struct lirc_driver *d)
|
|||
err = -ENOMEM;
|
||||
goto out_lock;
|
||||
}
|
||||
init_irctl(ir);
|
||||
lirc_irctl_init(ir);
|
||||
irctls[minor] = ir;
|
||||
d->minor = minor;
|
||||
|
||||
|
@ -316,7 +323,6 @@ int lirc_register_driver(struct lirc_driver *d)
|
|||
d->features = LIRC_CAN_REC_LIRCCODE;
|
||||
|
||||
ir->d = *d;
|
||||
ir->d.minor = minor;
|
||||
|
||||
device_create(lirc_class, ir->d.dev,
|
||||
MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL,
|
||||
|
@ -357,21 +363,28 @@ EXPORT_SYMBOL(lirc_register_driver);
|
|||
int lirc_unregister_driver(int minor)
|
||||
{
|
||||
struct irctl *ir;
|
||||
struct cdev *cdev;
|
||||
|
||||
if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
|
||||
printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
|
||||
"\"minor (%d)\" must be between 0 and %d!\n",
|
||||
minor, MAX_IRCTL_DEVICES-1);
|
||||
printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between "
|
||||
"0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1);
|
||||
return -EBADRQC;
|
||||
}
|
||||
|
||||
ir = irctls[minor];
|
||||
if (!ir) {
|
||||
printk(KERN_ERR "lirc_dev: %s: failed to get irctl struct "
|
||||
"for minor %d!\n", __func__, minor);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
cdev = &cdevs[minor];
|
||||
|
||||
mutex_lock(&lirc_dev_lock);
|
||||
|
||||
if (ir->d.minor != minor) {
|
||||
printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
|
||||
"minor (%d) device not registered!", minor);
|
||||
printk(KERN_ERR "lirc_dev: %s: minor (%d) device not "
|
||||
"registered!\n", __func__, minor);
|
||||
mutex_unlock(&lirc_dev_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -390,12 +403,11 @@ int lirc_unregister_driver(int minor)
|
|||
wake_up_interruptible(&ir->buf->wait_poll);
|
||||
mutex_lock(&ir->irctl_lock);
|
||||
ir->d.set_use_dec(ir->d.data);
|
||||
module_put(ir->d.owner);
|
||||
module_put(cdev->owner);
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
cdev_del(&ir->cdev);
|
||||
} else {
|
||||
cleanup(ir);
|
||||
cdev_del(&ir->cdev);
|
||||
lirc_irctl_cleanup(ir);
|
||||
cdev_del(cdev);
|
||||
kfree(ir);
|
||||
irctls[minor] = NULL;
|
||||
}
|
||||
|
@ -409,6 +421,7 @@ EXPORT_SYMBOL(lirc_unregister_driver);
|
|||
int lirc_dev_fop_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct irctl *ir;
|
||||
struct cdev *cdev;
|
||||
int retval = 0;
|
||||
|
||||
if (iminor(inode) >= MAX_IRCTL_DEVICES) {
|
||||
|
@ -425,7 +438,6 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
|
|||
retval = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
file->private_data = ir;
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
|
@ -439,13 +451,14 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (try_module_get(ir->d.owner)) {
|
||||
++ir->open;
|
||||
cdev = &cdevs[iminor(inode)];
|
||||
if (try_module_get(cdev->owner)) {
|
||||
ir->open++;
|
||||
retval = ir->d.set_use_inc(ir->d.data);
|
||||
|
||||
if (retval) {
|
||||
module_put(ir->d.owner);
|
||||
--ir->open;
|
||||
module_put(cdev->owner);
|
||||
ir->open--;
|
||||
} else {
|
||||
lirc_buffer_clear(ir->buf);
|
||||
}
|
||||
|
@ -469,17 +482,24 @@ EXPORT_SYMBOL(lirc_dev_fop_open);
|
|||
int lirc_dev_fop_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct irctl *ir = irctls[iminor(inode)];
|
||||
struct cdev *cdev = &cdevs[iminor(inode)];
|
||||
|
||||
if (!ir) {
|
||||
printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
WARN_ON(mutex_lock_killable(&lirc_dev_lock));
|
||||
|
||||
--ir->open;
|
||||
ir->open--;
|
||||
if (ir->attached) {
|
||||
ir->d.set_use_dec(ir->d.data);
|
||||
module_put(ir->d.owner);
|
||||
module_put(cdev->owner);
|
||||
} else {
|
||||
cleanup(ir);
|
||||
lirc_irctl_cleanup(ir);
|
||||
cdev_del(cdev);
|
||||
irctls[ir->d.minor] = NULL;
|
||||
kfree(ir);
|
||||
}
|
||||
|
@ -495,6 +515,11 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
|
|||
struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
|
||||
unsigned int ret;
|
||||
|
||||
if (!ir) {
|
||||
printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
|
||||
return POLLERR;
|
||||
}
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
if (!ir->attached) {
|
||||
|
@ -521,9 +546,14 @@ EXPORT_SYMBOL(lirc_dev_fop_poll);
|
|||
|
||||
long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned long mode;
|
||||
__u32 mode;
|
||||
int result = 0;
|
||||
struct irctl *ir = file->private_data;
|
||||
struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
|
||||
|
||||
if (!ir) {
|
||||
printk(KERN_ERR "lirc_dev: %s: no irctl found!\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
|
||||
ir->d.name, ir->d.minor, cmd);
|
||||
|
@ -538,7 +568,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
|
||||
switch (cmd) {
|
||||
case LIRC_GET_FEATURES:
|
||||
result = put_user(ir->d.features, (unsigned long *)arg);
|
||||
result = put_user(ir->d.features, (__u32 *)arg);
|
||||
break;
|
||||
case LIRC_GET_REC_MODE:
|
||||
if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
|
||||
|
@ -548,7 +578,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
|
||||
result = put_user(LIRC_REC2MODE
|
||||
(ir->d.features & LIRC_CAN_REC_MASK),
|
||||
(unsigned long *)arg);
|
||||
(__u32 *)arg);
|
||||
break;
|
||||
case LIRC_SET_REC_MODE:
|
||||
if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
|
||||
|
@ -556,7 +586,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
break;
|
||||
}
|
||||
|
||||
result = get_user(mode, (unsigned long *)arg);
|
||||
result = get_user(mode, (__u32 *)arg);
|
||||
if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
|
||||
result = -EINVAL;
|
||||
/*
|
||||
|
@ -565,7 +595,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
*/
|
||||
break;
|
||||
case LIRC_GET_LENGTH:
|
||||
result = put_user(ir->d.code_length, (unsigned long *)arg);
|
||||
result = put_user(ir->d.code_length, (__u32 *)arg);
|
||||
break;
|
||||
case LIRC_GET_MIN_TIMEOUT:
|
||||
if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
|
||||
|
@ -574,7 +604,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
break;
|
||||
}
|
||||
|
||||
result = put_user(ir->d.min_timeout, (unsigned long *)arg);
|
||||
result = put_user(ir->d.min_timeout, (__u32 *)arg);
|
||||
break;
|
||||
case LIRC_GET_MAX_TIMEOUT:
|
||||
if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
|
||||
|
@ -583,7 +613,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
break;
|
||||
}
|
||||
|
||||
result = put_user(ir->d.max_timeout, (unsigned long *)arg);
|
||||
result = put_user(ir->d.max_timeout, (__u32 *)arg);
|
||||
break;
|
||||
default:
|
||||
result = -EINVAL;
|
||||
|
@ -604,12 +634,21 @@ ssize_t lirc_dev_fop_read(struct file *file,
|
|||
loff_t *ppos)
|
||||
{
|
||||
struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
|
||||
unsigned char buf[ir->chunk_size];
|
||||
unsigned char *buf;
|
||||
int ret = 0, written = 0;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
if (!ir) {
|
||||
printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
buf = kzalloc(ir->chunk_size, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (mutex_lock_interruptible(&ir->irctl_lock))
|
||||
return -ERESTARTSYS;
|
||||
if (!ir->attached) {
|
||||
|
@ -681,6 +720,7 @@ ssize_t lirc_dev_fop_read(struct file *file,
|
|||
mutex_unlock(&ir->irctl_lock);
|
||||
|
||||
out_unlocked:
|
||||
kfree(buf);
|
||||
dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
|
||||
ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret);
|
||||
|
||||
|
@ -709,6 +749,11 @@ ssize_t lirc_dev_fop_write(struct file *file, const char *buffer,
|
|||
{
|
||||
struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
|
||||
|
||||
if (!ir) {
|
||||
printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
if (!ir->attached)
|
||||
|
|
|
@ -46,24 +46,58 @@
|
|||
"device driver"
|
||||
#define DRIVER_NAME "mceusb"
|
||||
|
||||
#define USB_BUFLEN 32 /* USB reception buffer length */
|
||||
#define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */
|
||||
#define MCE_G1_INIT_MSGS 40 /* Init messages on gen1 hw to throw out */
|
||||
#define USB_BUFLEN 32 /* USB reception buffer length */
|
||||
#define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */
|
||||
#define MCE_G1_INIT_MSGS 40 /* Init messages on gen1 hw to throw out */
|
||||
|
||||
/* MCE constants */
|
||||
#define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */
|
||||
#define MCE_TIME_UNIT 50 /* Approx 50us resolution */
|
||||
#define MCE_CODE_LENGTH 5 /* Normal length of packet (with header) */
|
||||
#define MCE_PACKET_SIZE 4 /* Normal length of packet (without header) */
|
||||
#define MCE_PACKET_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */
|
||||
#define MCE_CONTROL_HEADER 0x9F /* MCE status header */
|
||||
#define MCE_TX_HEADER_LENGTH 3 /* # of bytes in the initializing tx header */
|
||||
#define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */
|
||||
#define MCE_DEFAULT_TX_MASK 0x03 /* Val opts: TX1=0x01, TX2=0x02, ALL=0x03 */
|
||||
#define MCE_PULSE_BIT 0x80 /* Pulse bit, MSB set == PULSE else SPACE */
|
||||
#define MCE_PULSE_MASK 0x7F /* Pulse mask */
|
||||
#define MCE_MAX_PULSE_LENGTH 0x7F /* Longest transmittable pulse symbol */
|
||||
#define MCE_PACKET_LENGTH_MASK 0x1F /* Packet length mask */
|
||||
#define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */
|
||||
#define MCE_TIME_UNIT 50 /* Approx 50us resolution */
|
||||
#define MCE_CODE_LENGTH 5 /* Normal length of packet (with header) */
|
||||
#define MCE_PACKET_SIZE 4 /* Normal length of packet (without header) */
|
||||
#define MCE_IRDATA_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */
|
||||
#define MCE_IRDATA_TRAILER 0x80 /* End of IR data */
|
||||
#define MCE_TX_HEADER_LENGTH 3 /* # of bytes in the initializing tx header */
|
||||
#define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */
|
||||
#define MCE_DEFAULT_TX_MASK 0x03 /* Vals: TX1=0x01, TX2=0x02, ALL=0x03 */
|
||||
#define MCE_PULSE_BIT 0x80 /* Pulse bit, MSB set == PULSE else SPACE */
|
||||
#define MCE_PULSE_MASK 0x7f /* Pulse mask */
|
||||
#define MCE_MAX_PULSE_LENGTH 0x7f /* Longest transmittable pulse symbol */
|
||||
|
||||
#define MCE_HW_CMD_HEADER 0xff /* MCE hardware command header */
|
||||
#define MCE_COMMAND_HEADER 0x9f /* MCE command header */
|
||||
#define MCE_COMMAND_MASK 0xe0 /* Mask out command bits */
|
||||
#define MCE_COMMAND_NULL 0x00 /* These show up various places... */
|
||||
/* if buf[i] & MCE_COMMAND_MASK == 0x80 and buf[i] != MCE_COMMAND_HEADER,
|
||||
* then we're looking at a raw IR data sample */
|
||||
#define MCE_COMMAND_IRDATA 0x80
|
||||
#define MCE_PACKET_LENGTH_MASK 0x1f /* Packet length mask */
|
||||
|
||||
/* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */
|
||||
#define MCE_CMD_PING 0x03 /* Ping device */
|
||||
#define MCE_CMD_UNKNOWN 0x04 /* Unknown */
|
||||
#define MCE_CMD_UNKNOWN2 0x05 /* Unknown */
|
||||
#define MCE_CMD_S_CARRIER 0x06 /* Set TX carrier frequency */
|
||||
#define MCE_CMD_G_CARRIER 0x07 /* Get TX carrier frequency */
|
||||
#define MCE_CMD_S_TXMASK 0x08 /* Set TX port bitmask */
|
||||
#define MCE_CMD_UNKNOWN3 0x09 /* Unknown */
|
||||
#define MCE_CMD_UNKNOWN4 0x0a /* Unknown */
|
||||
#define MCE_CMD_G_REVISION 0x0b /* Get hw/sw revision */
|
||||
#define MCE_CMD_S_TIMEOUT 0x0c /* Set RX timeout value */
|
||||
#define MCE_CMD_G_TIMEOUT 0x0d /* Get RX timeout value */
|
||||
#define MCE_CMD_UNKNOWN5 0x0e /* Unknown */
|
||||
#define MCE_CMD_UNKNOWN6 0x0f /* Unknown */
|
||||
#define MCE_CMD_G_RXPORTSTS 0x11 /* Get RX port status */
|
||||
#define MCE_CMD_G_TXMASK 0x13 /* Set TX port bitmask */
|
||||
#define MCE_CMD_S_RXSENSOR 0x14 /* Set RX sensor (std/learning) */
|
||||
#define MCE_CMD_G_RXSENSOR 0x15 /* Get RX sensor (std/learning) */
|
||||
#define MCE_CMD_TX_PORTS 0x16 /* Get number of TX ports */
|
||||
#define MCE_CMD_G_WAKESRC 0x17 /* Get wake source */
|
||||
#define MCE_CMD_UNKNOWN7 0x18 /* Unknown */
|
||||
#define MCE_CMD_UNKNOWN8 0x19 /* Unknown */
|
||||
#define MCE_CMD_UNKNOWN9 0x1b /* Unknown */
|
||||
#define MCE_CMD_DEVICE_RESET 0xaa /* Reset the hardware */
|
||||
#define MCE_RSP_CMD_INVALID 0xfe /* Invalid command issued */
|
||||
|
||||
|
||||
/* module parameters */
|
||||
|
@ -104,14 +138,64 @@ static int debug;
|
|||
#define VENDOR_NORTHSTAR 0x04eb
|
||||
#define VENDOR_REALTEK 0x0bda
|
||||
#define VENDOR_TIVO 0x105a
|
||||
#define VENDOR_CONEXANT 0x0572
|
||||
|
||||
enum mceusb_model_type {
|
||||
MCE_GEN2 = 0, /* Most boards */
|
||||
MCE_GEN1,
|
||||
MCE_GEN3,
|
||||
MCE_GEN2_TX_INV,
|
||||
POLARIS_EVK,
|
||||
};
|
||||
|
||||
struct mceusb_model {
|
||||
u32 mce_gen1:1;
|
||||
u32 mce_gen2:1;
|
||||
u32 mce_gen3:1;
|
||||
u32 tx_mask_inverted:1;
|
||||
u32 is_polaris:1;
|
||||
|
||||
const char *rc_map; /* Allow specify a per-board map */
|
||||
const char *name; /* per-board name */
|
||||
};
|
||||
|
||||
static const struct mceusb_model mceusb_model[] = {
|
||||
[MCE_GEN1] = {
|
||||
.mce_gen1 = 1,
|
||||
.tx_mask_inverted = 1,
|
||||
},
|
||||
[MCE_GEN2] = {
|
||||
.mce_gen2 = 1,
|
||||
},
|
||||
[MCE_GEN2_TX_INV] = {
|
||||
.mce_gen2 = 1,
|
||||
.tx_mask_inverted = 1,
|
||||
},
|
||||
[MCE_GEN3] = {
|
||||
.mce_gen3 = 1,
|
||||
.tx_mask_inverted = 1,
|
||||
},
|
||||
[POLARIS_EVK] = {
|
||||
.is_polaris = 1,
|
||||
/*
|
||||
* In fact, the EVK is shipped without
|
||||
* remotes, but we should have something handy,
|
||||
* to allow testing it
|
||||
*/
|
||||
.rc_map = RC_MAP_RC5_HAUPPAUGE_NEW,
|
||||
.name = "cx231xx MCE IR",
|
||||
},
|
||||
};
|
||||
|
||||
static struct usb_device_id mceusb_dev_table[] = {
|
||||
/* Original Microsoft MCE IR Transceiver (often HP-branded) */
|
||||
{ USB_DEVICE(VENDOR_MICROSOFT, 0x006d) },
|
||||
{ USB_DEVICE(VENDOR_MICROSOFT, 0x006d),
|
||||
.driver_info = MCE_GEN1 },
|
||||
/* Philips Infrared Transceiver - Sahara branded */
|
||||
{ USB_DEVICE(VENDOR_PHILIPS, 0x0608) },
|
||||
/* Philips Infrared Transceiver - HP branded */
|
||||
{ USB_DEVICE(VENDOR_PHILIPS, 0x060c) },
|
||||
{ USB_DEVICE(VENDOR_PHILIPS, 0x060c),
|
||||
.driver_info = MCE_GEN2_TX_INV },
|
||||
/* Philips SRM5100 */
|
||||
{ USB_DEVICE(VENDOR_PHILIPS, 0x060d) },
|
||||
/* Philips Infrared Transceiver - Omaura */
|
||||
|
@ -127,11 +211,14 @@ static struct usb_device_id mceusb_dev_table[] = {
|
|||
/* Realtek MCE IR Receiver */
|
||||
{ USB_DEVICE(VENDOR_REALTEK, 0x0161) },
|
||||
/* SMK/Toshiba G83C0004D410 */
|
||||
{ USB_DEVICE(VENDOR_SMK, 0x031d) },
|
||||
{ USB_DEVICE(VENDOR_SMK, 0x031d),
|
||||
.driver_info = MCE_GEN2_TX_INV },
|
||||
/* SMK eHome Infrared Transceiver (Sony VAIO) */
|
||||
{ USB_DEVICE(VENDOR_SMK, 0x0322) },
|
||||
{ USB_DEVICE(VENDOR_SMK, 0x0322),
|
||||
.driver_info = MCE_GEN2_TX_INV },
|
||||
/* bundled with Hauppauge PVR-150 */
|
||||
{ USB_DEVICE(VENDOR_SMK, 0x0334) },
|
||||
{ USB_DEVICE(VENDOR_SMK, 0x0334),
|
||||
.driver_info = MCE_GEN2_TX_INV },
|
||||
/* SMK eHome Infrared Transceiver */
|
||||
{ USB_DEVICE(VENDOR_SMK, 0x0338) },
|
||||
/* Tatung eHome Infrared Transceiver */
|
||||
|
@ -145,17 +232,23 @@ static struct usb_device_id mceusb_dev_table[] = {
|
|||
/* Mitsumi */
|
||||
{ USB_DEVICE(VENDOR_MITSUMI, 0x2501) },
|
||||
/* Topseed eHome Infrared Transceiver */
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0001) },
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0001),
|
||||
.driver_info = MCE_GEN2_TX_INV },
|
||||
/* Topseed HP eHome Infrared Transceiver */
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0006) },
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0006),
|
||||
.driver_info = MCE_GEN2_TX_INV },
|
||||
/* Topseed eHome Infrared Transceiver */
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0007) },
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0007),
|
||||
.driver_info = MCE_GEN2_TX_INV },
|
||||
/* Topseed eHome Infrared Transceiver */
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0008),
|
||||
.driver_info = MCE_GEN3 },
|
||||
/* Topseed eHome Infrared Transceiver */
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x000a) },
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x000a),
|
||||
.driver_info = MCE_GEN2_TX_INV },
|
||||
/* Topseed eHome Infrared Transceiver */
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0011) },
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0011),
|
||||
.driver_info = MCE_GEN2_TX_INV },
|
||||
/* Ricavision internal Infrared Transceiver */
|
||||
{ USB_DEVICE(VENDOR_RICAVISION, 0x0010) },
|
||||
/* Itron ione Libra Q-11 */
|
||||
|
@ -185,7 +278,8 @@ static struct usb_device_id mceusb_dev_table[] = {
|
|||
/* Fintek eHome Infrared Transceiver (in the AOpen MP45) */
|
||||
{ USB_DEVICE(VENDOR_FINTEK, 0x0702) },
|
||||
/* Pinnacle Remote Kit */
|
||||
{ USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
|
||||
{ USB_DEVICE(VENDOR_PINNACLE, 0x0225),
|
||||
.driver_info = MCE_GEN3 },
|
||||
/* Elitegroup Computer Systems IR */
|
||||
{ USB_DEVICE(VENDOR_ECS, 0x0f38) },
|
||||
/* Wistron Corp. eHome Infrared Receiver */
|
||||
|
@ -198,37 +292,13 @@ static struct usb_device_id mceusb_dev_table[] = {
|
|||
{ USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) },
|
||||
/* TiVo PC IR Receiver */
|
||||
{ USB_DEVICE(VENDOR_TIVO, 0x2000) },
|
||||
/* Conexant SDK */
|
||||
{ USB_DEVICE(VENDOR_CONEXANT, 0x58a1),
|
||||
.driver_info = POLARIS_EVK },
|
||||
/* Terminating entry */
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct usb_device_id gen3_list[] = {
|
||||
{ USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct usb_device_id microsoft_gen1_list[] = {
|
||||
{ USB_DEVICE(VENDOR_MICROSOFT, 0x006d) },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct usb_device_id std_tx_mask_list[] = {
|
||||
{ USB_DEVICE(VENDOR_MICROSOFT, 0x006d) },
|
||||
{ USB_DEVICE(VENDOR_PHILIPS, 0x060c) },
|
||||
{ USB_DEVICE(VENDOR_SMK, 0x031d) },
|
||||
{ USB_DEVICE(VENDOR_SMK, 0x0322) },
|
||||
{ USB_DEVICE(VENDOR_SMK, 0x0334) },
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0001) },
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0006) },
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0007) },
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x000a) },
|
||||
{ USB_DEVICE(VENDOR_TOPSEED, 0x0011) },
|
||||
{ USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
|
||||
{}
|
||||
};
|
||||
|
||||
/* data structure for each usb transceiver */
|
||||
struct mceusb_dev {
|
||||
/* ir-core bits */
|
||||
|
@ -248,8 +318,15 @@ struct mceusb_dev {
|
|||
/* buffers and dma */
|
||||
unsigned char *buf_in;
|
||||
unsigned int len_in;
|
||||
u8 cmd; /* MCE command type */
|
||||
u8 rem; /* Remaining IR data bytes in packet */
|
||||
|
||||
enum {
|
||||
CMD_HEADER = 0,
|
||||
SUBCMD,
|
||||
CMD_DATA,
|
||||
PARSE_IRDATA,
|
||||
} parser_state;
|
||||
u8 cmd, rem; /* Remaining IR data bytes in packet */
|
||||
|
||||
dma_addr_t dma_in;
|
||||
dma_addr_t dma_out;
|
||||
|
||||
|
@ -257,7 +334,6 @@ struct mceusb_dev {
|
|||
u32 connected:1;
|
||||
u32 tx_mask_inverted:1;
|
||||
u32 microsoft_gen1:1;
|
||||
u32 reserved:29;
|
||||
} flags;
|
||||
|
||||
/* transmit support */
|
||||
|
@ -267,6 +343,7 @@ struct mceusb_dev {
|
|||
|
||||
char name[128];
|
||||
char phys[64];
|
||||
enum mceusb_model_type model;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -291,43 +368,81 @@ struct mceusb_dev {
|
|||
* - SET_RX_TIMEOUT sets the receiver timeout
|
||||
* - SET_RX_SENSOR sets which receiver sensor to use
|
||||
*/
|
||||
static char DEVICE_RESET[] = {0x00, 0xff, 0xaa};
|
||||
static char GET_REVISION[] = {0xff, 0x0b};
|
||||
static char GET_UNKNOWN[] = {0xff, 0x18};
|
||||
static char GET_UNKNOWN2[] = {0x9f, 0x05};
|
||||
static char GET_CARRIER_FREQ[] = {0x9f, 0x07};
|
||||
static char GET_RX_TIMEOUT[] = {0x9f, 0x0d};
|
||||
static char GET_TX_BITMASK[] = {0x9f, 0x13};
|
||||
static char GET_RX_SENSOR[] = {0x9f, 0x15};
|
||||
static char DEVICE_RESET[] = {MCE_COMMAND_NULL, MCE_HW_CMD_HEADER,
|
||||
MCE_CMD_DEVICE_RESET};
|
||||
static char GET_REVISION[] = {MCE_HW_CMD_HEADER, MCE_CMD_G_REVISION};
|
||||
static char GET_UNKNOWN[] = {MCE_HW_CMD_HEADER, MCE_CMD_UNKNOWN7};
|
||||
static char GET_UNKNOWN2[] = {MCE_COMMAND_HEADER, MCE_CMD_UNKNOWN2};
|
||||
static char GET_CARRIER_FREQ[] = {MCE_COMMAND_HEADER, MCE_CMD_G_CARRIER};
|
||||
static char GET_RX_TIMEOUT[] = {MCE_COMMAND_HEADER, MCE_CMD_G_TIMEOUT};
|
||||
static char GET_TX_BITMASK[] = {MCE_COMMAND_HEADER, MCE_CMD_G_TXMASK};
|
||||
static char GET_RX_SENSOR[] = {MCE_COMMAND_HEADER, MCE_CMD_G_RXSENSOR};
|
||||
/* sub in desired values in lower byte or bytes for full command */
|
||||
/* FIXME: make use of these for transmit.
|
||||
static char SET_CARRIER_FREQ[] = {0x9f, 0x06, 0x00, 0x00};
|
||||
static char SET_TX_BITMASK[] = {0x9f, 0x08, 0x00};
|
||||
static char SET_RX_TIMEOUT[] = {0x9f, 0x0c, 0x00, 0x00};
|
||||
static char SET_RX_SENSOR[] = {0x9f, 0x14, 0x00};
|
||||
static char SET_CARRIER_FREQ[] = {MCE_COMMAND_HEADER,
|
||||
MCE_CMD_S_CARRIER, 0x00, 0x00};
|
||||
static char SET_TX_BITMASK[] = {MCE_COMMAND_HEADER, MCE_CMD_S_TXMASK, 0x00};
|
||||
static char SET_RX_TIMEOUT[] = {MCE_COMMAND_HEADER,
|
||||
MCE_CMD_S_TIMEOUT, 0x00, 0x00};
|
||||
static char SET_RX_SENSOR[] = {MCE_COMMAND_HEADER,
|
||||
MCE_CMD_S_RXSENSOR, 0x00};
|
||||
*/
|
||||
|
||||
static int mceusb_cmdsize(u8 cmd, u8 subcmd)
|
||||
{
|
||||
int datasize = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case MCE_COMMAND_NULL:
|
||||
if (subcmd == MCE_HW_CMD_HEADER)
|
||||
datasize = 1;
|
||||
break;
|
||||
case MCE_HW_CMD_HEADER:
|
||||
switch (subcmd) {
|
||||
case MCE_CMD_G_REVISION:
|
||||
datasize = 2;
|
||||
break;
|
||||
}
|
||||
case MCE_COMMAND_HEADER:
|
||||
switch (subcmd) {
|
||||
case MCE_CMD_UNKNOWN:
|
||||
case MCE_CMD_S_CARRIER:
|
||||
case MCE_CMD_S_TIMEOUT:
|
||||
case MCE_CMD_G_RXSENSOR:
|
||||
datasize = 2;
|
||||
break;
|
||||
case MCE_CMD_S_TXMASK:
|
||||
case MCE_CMD_S_RXSENSOR:
|
||||
datasize = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return datasize;
|
||||
}
|
||||
|
||||
static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
|
||||
int len, bool out)
|
||||
int offset, int len, bool out)
|
||||
{
|
||||
char codes[USB_BUFLEN * 3 + 1];
|
||||
char inout[9];
|
||||
int i;
|
||||
u8 cmd, subcmd, data1, data2;
|
||||
struct device *dev = ir->dev;
|
||||
int idx = 0;
|
||||
int i, start, skip = 0;
|
||||
|
||||
if (!debug)
|
||||
return;
|
||||
|
||||
/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
|
||||
if (ir->flags.microsoft_gen1 && !out)
|
||||
idx = 2;
|
||||
skip = 2;
|
||||
|
||||
if (len <= idx)
|
||||
if (len <= skip)
|
||||
return;
|
||||
|
||||
for (i = 0; i < len && i < USB_BUFLEN; i++)
|
||||
snprintf(codes + i * 3, 4, "%02x ", buf[i] & 0xFF);
|
||||
snprintf(codes + i * 3, 4, "%02x ", buf[i + offset] & 0xff);
|
||||
|
||||
dev_info(dev, "%sx data: %s (length=%d)\n",
|
||||
dev_info(dev, "%sx data: %s(length=%d)\n",
|
||||
(out ? "t" : "r"), codes, len);
|
||||
|
||||
if (out)
|
||||
|
@ -335,91 +450,93 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
|
|||
else
|
||||
strcpy(inout, "Got\0");
|
||||
|
||||
cmd = buf[idx] & 0xff;
|
||||
subcmd = buf[idx + 1] & 0xff;
|
||||
data1 = buf[idx + 2] & 0xff;
|
||||
data2 = buf[idx + 3] & 0xff;
|
||||
start = offset + skip;
|
||||
cmd = buf[start] & 0xff;
|
||||
subcmd = buf[start + 1] & 0xff;
|
||||
data1 = buf[start + 2] & 0xff;
|
||||
data2 = buf[start + 3] & 0xff;
|
||||
|
||||
switch (cmd) {
|
||||
case 0x00:
|
||||
if (subcmd == 0xff && data1 == 0xaa)
|
||||
case MCE_COMMAND_NULL:
|
||||
if ((subcmd == MCE_HW_CMD_HEADER) &&
|
||||
(data1 == MCE_CMD_DEVICE_RESET))
|
||||
dev_info(dev, "Device reset requested\n");
|
||||
else
|
||||
dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
|
||||
cmd, subcmd);
|
||||
break;
|
||||
case 0xff:
|
||||
case MCE_HW_CMD_HEADER:
|
||||
switch (subcmd) {
|
||||
case 0x0b:
|
||||
case MCE_CMD_G_REVISION:
|
||||
if (len == 2)
|
||||
dev_info(dev, "Get hw/sw rev?\n");
|
||||
else
|
||||
dev_info(dev, "hw/sw rev 0x%02x 0x%02x "
|
||||
"0x%02x 0x%02x\n", data1, data2,
|
||||
buf[idx + 4], buf[idx + 5]);
|
||||
buf[start + 4], buf[start + 5]);
|
||||
break;
|
||||
case 0xaa:
|
||||
case MCE_CMD_DEVICE_RESET:
|
||||
dev_info(dev, "Device reset requested\n");
|
||||
break;
|
||||
case 0xfe:
|
||||
case MCE_RSP_CMD_INVALID:
|
||||
dev_info(dev, "Previous command not supported\n");
|
||||
break;
|
||||
case 0x18:
|
||||
case 0x1b:
|
||||
case MCE_CMD_UNKNOWN7:
|
||||
case MCE_CMD_UNKNOWN9:
|
||||
default:
|
||||
dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
|
||||
cmd, subcmd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x9f:
|
||||
case MCE_COMMAND_HEADER:
|
||||
switch (subcmd) {
|
||||
case 0x03:
|
||||
case MCE_CMD_PING:
|
||||
dev_info(dev, "Ping\n");
|
||||
break;
|
||||
case 0x04:
|
||||
case MCE_CMD_UNKNOWN:
|
||||
dev_info(dev, "Resp to 9f 05 of 0x%02x 0x%02x\n",
|
||||
data1, data2);
|
||||
break;
|
||||
case 0x06:
|
||||
case MCE_CMD_S_CARRIER:
|
||||
dev_info(dev, "%s carrier mode and freq of "
|
||||
"0x%02x 0x%02x\n", inout, data1, data2);
|
||||
break;
|
||||
case 0x07:
|
||||
case MCE_CMD_G_CARRIER:
|
||||
dev_info(dev, "Get carrier mode and freq\n");
|
||||
break;
|
||||
case 0x08:
|
||||
case MCE_CMD_S_TXMASK:
|
||||
dev_info(dev, "%s transmit blaster mask of 0x%02x\n",
|
||||
inout, data1);
|
||||
break;
|
||||
case 0x0c:
|
||||
case MCE_CMD_S_TIMEOUT:
|
||||
/* value is in units of 50us, so x*50/100 or x/2 ms */
|
||||
dev_info(dev, "%s receive timeout of %d ms\n",
|
||||
inout, ((data1 << 8) | data2) / 2);
|
||||
break;
|
||||
case 0x0d:
|
||||
case MCE_CMD_G_TIMEOUT:
|
||||
dev_info(dev, "Get receive timeout\n");
|
||||
break;
|
||||
case 0x13:
|
||||
case MCE_CMD_G_TXMASK:
|
||||
dev_info(dev, "Get transmit blaster mask\n");
|
||||
break;
|
||||
case 0x14:
|
||||
case MCE_CMD_S_RXSENSOR:
|
||||
dev_info(dev, "%s %s-range receive sensor in use\n",
|
||||
inout, data1 == 0x02 ? "short" : "long");
|
||||
break;
|
||||
case 0x15:
|
||||
case MCE_CMD_G_RXSENSOR:
|
||||
if (len == 2)
|
||||
dev_info(dev, "Get receive sensor\n");
|
||||
else
|
||||
dev_info(dev, "Received pulse count is %d\n",
|
||||
((data1 << 8) | data2));
|
||||
break;
|
||||
case 0xfe:
|
||||
case MCE_RSP_CMD_INVALID:
|
||||
dev_info(dev, "Error! Hardware is likely wedged...\n");
|
||||
break;
|
||||
case 0x05:
|
||||
case 0x09:
|
||||
case 0x0f:
|
||||
case MCE_CMD_UNKNOWN2:
|
||||
case MCE_CMD_UNKNOWN3:
|
||||
case MCE_CMD_UNKNOWN5:
|
||||
default:
|
||||
dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
|
||||
cmd, subcmd);
|
||||
|
@ -429,6 +546,12 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd == MCE_IRDATA_TRAILER)
|
||||
dev_info(dev, "End of raw IR data\n");
|
||||
else if ((cmd != MCE_COMMAND_HEADER) &&
|
||||
((cmd & MCE_COMMAND_MASK) == MCE_COMMAND_IRDATA))
|
||||
dev_info(dev, "Raw IR data, %d pulse/space samples\n", ir->rem);
|
||||
}
|
||||
|
||||
static void mce_async_callback(struct urb *urb, struct pt_regs *regs)
|
||||
|
@ -446,9 +569,7 @@ static void mce_async_callback(struct urb *urb, struct pt_regs *regs)
|
|||
dev_dbg(ir->dev, "callback called (status=%d len=%d)\n",
|
||||
urb->status, len);
|
||||
|
||||
if (debug)
|
||||
mceusb_dev_printdata(ir, urb->transfer_buffer,
|
||||
len, true);
|
||||
mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -536,8 +657,8 @@ static int mceusb_tx_ir(void *priv, int *txbuf, u32 n)
|
|||
return -ENOMEM;
|
||||
|
||||
/* MCE tx init header */
|
||||
cmdbuf[cmdcount++] = MCE_CONTROL_HEADER;
|
||||
cmdbuf[cmdcount++] = 0x08;
|
||||
cmdbuf[cmdcount++] = MCE_COMMAND_HEADER;
|
||||
cmdbuf[cmdcount++] = MCE_CMD_S_TXMASK;
|
||||
cmdbuf[cmdcount++] = ir->tx_mask;
|
||||
|
||||
/* Generate mce packet data */
|
||||
|
@ -551,7 +672,7 @@ static int mceusb_tx_ir(void *priv, int *txbuf, u32 n)
|
|||
if ((cmdcount < MCE_CMDBUF_SIZE) &&
|
||||
(cmdcount - MCE_TX_HEADER_LENGTH) %
|
||||
MCE_CODE_LENGTH == 0)
|
||||
cmdbuf[cmdcount++] = MCE_PACKET_HEADER;
|
||||
cmdbuf[cmdcount++] = MCE_IRDATA_HEADER;
|
||||
|
||||
/* Insert mce packet data */
|
||||
if (cmdcount < MCE_CMDBUF_SIZE)
|
||||
|
@ -570,7 +691,8 @@ static int mceusb_tx_ir(void *priv, int *txbuf, u32 n)
|
|||
|
||||
/* Fix packet length in last header */
|
||||
cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] =
|
||||
0x80 + (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH - 1;
|
||||
MCE_COMMAND_IRDATA + (cmdcount - MCE_TX_HEADER_LENGTH) %
|
||||
MCE_CODE_LENGTH - 1;
|
||||
|
||||
/* Check if we have room for the empty packet at the end */
|
||||
if (cmdcount >= MCE_CMDBUF_SIZE) {
|
||||
|
@ -579,7 +701,7 @@ static int mceusb_tx_ir(void *priv, int *txbuf, u32 n)
|
|||
}
|
||||
|
||||
/* All mce commands end with an empty packet (0x80) */
|
||||
cmdbuf[cmdcount++] = 0x80;
|
||||
cmdbuf[cmdcount++] = MCE_IRDATA_TRAILER;
|
||||
|
||||
/* Transmit the command to the mce device */
|
||||
mce_async_out(ir, cmdbuf, cmdcount);
|
||||
|
@ -608,7 +730,8 @@ static int mceusb_set_tx_mask(void *priv, u32 mask)
|
|||
struct mceusb_dev *ir = priv;
|
||||
|
||||
if (ir->flags.tx_mask_inverted)
|
||||
ir->tx_mask = (mask != 0x03 ? mask ^ 0x03 : mask) << 1;
|
||||
ir->tx_mask = (mask != MCE_DEFAULT_TX_MASK ?
|
||||
mask ^ MCE_DEFAULT_TX_MASK : mask) << 1;
|
||||
else
|
||||
ir->tx_mask = mask;
|
||||
|
||||
|
@ -621,7 +744,8 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)
|
|||
struct mceusb_dev *ir = priv;
|
||||
int clk = 10000000;
|
||||
int prescaler = 0, divisor = 0;
|
||||
unsigned char cmdbuf[4] = { 0x9f, 0x06, 0x00, 0x00 };
|
||||
unsigned char cmdbuf[4] = { MCE_COMMAND_HEADER,
|
||||
MCE_CMD_S_CARRIER, 0x00, 0x00 };
|
||||
|
||||
/* Carrier has changed */
|
||||
if (ir->carrier != carrier) {
|
||||
|
@ -629,7 +753,7 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)
|
|||
if (carrier == 0) {
|
||||
ir->carrier = carrier;
|
||||
cmdbuf[2] = 0x01;
|
||||
cmdbuf[3] = 0x80;
|
||||
cmdbuf[3] = MCE_IRDATA_TRAILER;
|
||||
dev_dbg(ir->dev, "%s: disabling carrier "
|
||||
"modulation\n", __func__);
|
||||
mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
|
||||
|
@ -638,7 +762,7 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)
|
|||
|
||||
for (prescaler = 0; prescaler < 4; ++prescaler) {
|
||||
divisor = (clk >> (2 * prescaler)) / carrier;
|
||||
if (divisor <= 0xFF) {
|
||||
if (divisor <= 0xff) {
|
||||
ir->carrier = carrier;
|
||||
cmdbuf[2] = prescaler;
|
||||
cmdbuf[3] = divisor;
|
||||
|
@ -660,47 +784,36 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)
|
|||
|
||||
static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
|
||||
{
|
||||
struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
|
||||
int i, start_index = 0;
|
||||
u8 hdr = MCE_CONTROL_HEADER;
|
||||
DEFINE_IR_RAW_EVENT(rawir);
|
||||
int i = 0;
|
||||
|
||||
/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
|
||||
if (ir->flags.microsoft_gen1)
|
||||
start_index = 2;
|
||||
i = 2;
|
||||
|
||||
for (i = start_index; i < buf_len;) {
|
||||
if (ir->rem == 0) {
|
||||
/* decode mce packets of the form (84),AA,BB,CC,DD */
|
||||
/* IR data packets can span USB messages - rem */
|
||||
hdr = ir->buf_in[i];
|
||||
ir->rem = (hdr & MCE_PACKET_LENGTH_MASK);
|
||||
ir->cmd = (hdr & ~MCE_PACKET_LENGTH_MASK);
|
||||
dev_dbg(ir->dev, "New data. rem: 0x%02x, cmd: 0x%02x\n",
|
||||
ir->rem, ir->cmd);
|
||||
i++;
|
||||
}
|
||||
|
||||
/* don't process MCE commands */
|
||||
if (hdr == MCE_CONTROL_HEADER || hdr == 0xff) {
|
||||
ir->rem = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (; (ir->rem > 0) && (i < buf_len); i++) {
|
||||
for (; i < buf_len; i++) {
|
||||
switch (ir->parser_state) {
|
||||
case SUBCMD:
|
||||
ir->rem = mceusb_cmdsize(ir->cmd, ir->buf_in[i]);
|
||||
mceusb_dev_printdata(ir, ir->buf_in, i - 1,
|
||||
ir->rem + 2, false);
|
||||
ir->parser_state = CMD_DATA;
|
||||
break;
|
||||
case PARSE_IRDATA:
|
||||
ir->rem--;
|
||||
|
||||
rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);
|
||||
rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
|
||||
* MCE_TIME_UNIT * 1000;
|
||||
|
||||
if ((ir->buf_in[i] & MCE_PULSE_MASK) == 0x7f) {
|
||||
if (ir->rawir.pulse == rawir.pulse)
|
||||
if (ir->rawir.pulse == rawir.pulse) {
|
||||
ir->rawir.duration += rawir.duration;
|
||||
else {
|
||||
} else {
|
||||
ir->rawir.duration = rawir.duration;
|
||||
ir->rawir.pulse = rawir.pulse;
|
||||
}
|
||||
continue;
|
||||
if (ir->rem)
|
||||
break;
|
||||
}
|
||||
rawir.duration += ir->rawir.duration;
|
||||
ir->rawir.duration = 0;
|
||||
|
@ -711,14 +824,40 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
|
|||
rawir.duration);
|
||||
|
||||
ir_raw_event_store(ir->idev, &rawir);
|
||||
break;
|
||||
case CMD_DATA:
|
||||
ir->rem--;
|
||||
break;
|
||||
case CMD_HEADER:
|
||||
/* decode mce packets of the form (84),AA,BB,CC,DD */
|
||||
/* IR data packets can span USB messages - rem */
|
||||
ir->cmd = ir->buf_in[i];
|
||||
if ((ir->cmd == MCE_COMMAND_HEADER) ||
|
||||
((ir->cmd & MCE_COMMAND_MASK) !=
|
||||
MCE_COMMAND_IRDATA)) {
|
||||
ir->parser_state = SUBCMD;
|
||||
continue;
|
||||
}
|
||||
ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK);
|
||||
mceusb_dev_printdata(ir, ir->buf_in, i, ir->rem + 1, false);
|
||||
if (ir->rem) {
|
||||
ir->parser_state = PARSE_IRDATA;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* a package with len=0 (e. g. 0x80) means end of
|
||||
* data. We could use it to do the call to
|
||||
* ir_raw_event_handle(). For now, we don't need to
|
||||
* use it.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if (ir->buf_in[i] == 0x80 || ir->buf_in[i] == 0x9f)
|
||||
ir->rem = 0;
|
||||
|
||||
dev_dbg(ir->dev, "calling ir_raw_event_handle\n");
|
||||
ir_raw_event_handle(ir->idev);
|
||||
if (ir->parser_state != CMD_HEADER && !ir->rem)
|
||||
ir->parser_state = CMD_HEADER;
|
||||
}
|
||||
dev_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n");
|
||||
ir_raw_event_handle(ir->idev);
|
||||
}
|
||||
|
||||
static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
|
||||
|
@ -737,9 +876,6 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
|
|||
|
||||
buf_len = urb->actual_length;
|
||||
|
||||
if (debug)
|
||||
mceusb_dev_printdata(ir, urb->transfer_buffer, buf_len, false);
|
||||
|
||||
if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
|
||||
ir->send_flags = SEND_FLAG_COMPLETE;
|
||||
dev_dbg(ir->dev, "setup answer received %d bytes\n",
|
||||
|
@ -760,6 +896,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
|
|||
|
||||
case -EPIPE:
|
||||
default:
|
||||
dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -865,6 +1002,8 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
|
|||
struct input_dev *idev;
|
||||
struct ir_dev_props *props;
|
||||
struct device *dev = ir->dev;
|
||||
const char *rc_map = RC_MAP_RC6_MCE;
|
||||
const char *name = "Media Center Ed. eHome Infrared Remote Transceiver";
|
||||
int ret = -ENODEV;
|
||||
|
||||
idev = input_allocate_device();
|
||||
|
@ -880,8 +1019,11 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
|
|||
goto props_alloc_failed;
|
||||
}
|
||||
|
||||
snprintf(ir->name, sizeof(ir->name), "Media Center Ed. eHome "
|
||||
"Infrared Remote Transceiver (%04x:%04x)",
|
||||
if (mceusb_model[ir->model].name)
|
||||
name = mceusb_model[ir->model].name;
|
||||
|
||||
snprintf(ir->name, sizeof(ir->name), "%s (%04x:%04x)",
|
||||
name,
|
||||
le16_to_cpu(ir->usbdev->descriptor.idVendor),
|
||||
le16_to_cpu(ir->usbdev->descriptor.idProduct));
|
||||
|
||||
|
@ -899,7 +1041,10 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
|
|||
|
||||
ir->props = props;
|
||||
|
||||
ret = ir_input_register(idev, RC_MAP_RC6_MCE, props, DRIVER_NAME);
|
||||
if (mceusb_model[ir->model].rc_map)
|
||||
rc_map = mceusb_model[ir->model].rc_map;
|
||||
|
||||
ret = ir_input_register(idev, rc_map, props, DRIVER_NAME);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "remote input device register failed\n");
|
||||
goto irdev_failed;
|
||||
|
@ -926,17 +1071,26 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
|
|||
struct mceusb_dev *ir = NULL;
|
||||
int pipe, maxp, i;
|
||||
char buf[63], name[128] = "";
|
||||
enum mceusb_model_type model = id->driver_info;
|
||||
bool is_gen3;
|
||||
bool is_microsoft_gen1;
|
||||
bool tx_mask_inverted;
|
||||
bool is_polaris;
|
||||
|
||||
dev_dbg(&intf->dev, ": %s called\n", __func__);
|
||||
|
||||
idesc = intf->cur_altsetting;
|
||||
|
||||
is_gen3 = usb_match_id(intf, gen3_list) ? 1 : 0;
|
||||
is_microsoft_gen1 = usb_match_id(intf, microsoft_gen1_list) ? 1 : 0;
|
||||
tx_mask_inverted = usb_match_id(intf, std_tx_mask_list) ? 0 : 1;
|
||||
is_gen3 = mceusb_model[model].mce_gen3;
|
||||
is_microsoft_gen1 = mceusb_model[model].mce_gen1;
|
||||
tx_mask_inverted = mceusb_model[model].tx_mask_inverted;
|
||||
is_polaris = mceusb_model[model].is_polaris;
|
||||
|
||||
if (is_polaris) {
|
||||
/* Interface 0 is IR */
|
||||
if (idesc->desc.bInterfaceNumber)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* step through the endpoints to find first bulk in and out endpoint */
|
||||
for (i = 0; i < idesc->desc.bNumEndpoints; ++i) {
|
||||
|
@ -997,6 +1151,9 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
|
|||
ir->len_in = maxp;
|
||||
ir->flags.microsoft_gen1 = is_microsoft_gen1;
|
||||
ir->flags.tx_mask_inverted = tx_mask_inverted;
|
||||
ir->model = model;
|
||||
|
||||
init_ir_raw_event(&ir->rawir);
|
||||
|
||||
/* Saving usb interface data for use by the transmitter routine */
|
||||
ir->usb_ep_in = ep_in;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
* Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR
|
||||
*
|
||||
* Copyright (C) 2010 Jarod Wilson <jarod@redhat.com>
|
||||
* Copyright (C) 2009 Nuvoton PS Team
|
||||
*
|
||||
* Special thanks to Nuvoton for providing hardware, spec sheets and
|
||||
* sample code upon which portions of this driver are based. Indirect
|
||||
* thanks also to Maxim Levitsky, whose ene_ir driver this driver is
|
||||
* modeled after.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
/* platform driver name to register */
|
||||
#define NVT_DRIVER_NAME "nuvoton-cir"
|
||||
|
||||
/* debugging module parameter */
|
||||
static int debug;
|
||||
|
||||
|
||||
#define nvt_pr(level, text, ...) \
|
||||
printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__)
|
||||
|
||||
#define nvt_dbg(text, ...) \
|
||||
if (debug) \
|
||||
printk(KERN_DEBUG \
|
||||
KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
|
||||
|
||||
#define nvt_dbg_verbose(text, ...) \
|
||||
if (debug > 1) \
|
||||
printk(KERN_DEBUG \
|
||||
KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
|
||||
|
||||
#define nvt_dbg_wake(text, ...) \
|
||||
if (debug > 2) \
|
||||
printk(KERN_DEBUG \
|
||||
KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
|
||||
|
||||
|
||||
/*
|
||||
* Original lirc driver said min value of 76, and recommended value of 256
|
||||
* for the buffer length, but then used 2048. Never mind that the size of the
|
||||
* RX FIFO is 32 bytes... So I'm using 32 for RX and 256 for TX atm, but I'm
|
||||
* not sure if maybe that TX value is off by a factor of 8 (bits vs. bytes),
|
||||
* and I don't have TX-capable hardware to test/debug on...
|
||||
*/
|
||||
#define TX_BUF_LEN 256
|
||||
#define RX_BUF_LEN 32
|
||||
|
||||
struct nvt_dev {
|
||||
struct pnp_dev *pdev;
|
||||
struct input_dev *rdev;
|
||||
struct ir_dev_props *props;
|
||||
struct ir_raw_event rawir;
|
||||
|
||||
spinlock_t nvt_lock;
|
||||
bool in_use;
|
||||
|
||||
/* for rx */
|
||||
u8 buf[RX_BUF_LEN];
|
||||
unsigned int pkts;
|
||||
|
||||
struct {
|
||||
spinlock_t lock;
|
||||
u8 buf[TX_BUF_LEN];
|
||||
unsigned int buf_count;
|
||||
unsigned int cur_buf_num;
|
||||
wait_queue_head_t queue;
|
||||
u8 tx_state;
|
||||
} tx;
|
||||
|
||||
/* EFER Config register index/data pair */
|
||||
u8 cr_efir;
|
||||
u8 cr_efdr;
|
||||
|
||||
/* hardware I/O settings */
|
||||
unsigned long cir_addr;
|
||||
unsigned long cir_wake_addr;
|
||||
int cir_irq;
|
||||
int cir_wake_irq;
|
||||
|
||||
/* hardware id */
|
||||
u8 chip_major;
|
||||
u8 chip_minor;
|
||||
|
||||
/* hardware features */
|
||||
bool hw_learning_capable;
|
||||
bool hw_tx_capable;
|
||||
|
||||
/* rx settings */
|
||||
bool learning_enabled;
|
||||
bool carrier_detect_enabled;
|
||||
|
||||
/* track cir wake state */
|
||||
u8 wake_state;
|
||||
/* for study */
|
||||
u8 study_state;
|
||||
/* carrier period = 1 / frequency */
|
||||
u32 carrier;
|
||||
};
|
||||
|
||||
/* study states */
|
||||
#define ST_STUDY_NONE 0x0
|
||||
#define ST_STUDY_START 0x1
|
||||
#define ST_STUDY_CARRIER 0x2
|
||||
#define ST_STUDY_ALL_RECV 0x4
|
||||
|
||||
/* wake states */
|
||||
#define ST_WAKE_NONE 0x0
|
||||
#define ST_WAKE_START 0x1
|
||||
#define ST_WAKE_FINISH 0x2
|
||||
|
||||
/* receive states */
|
||||
#define ST_RX_WAIT_7F 0x1
|
||||
#define ST_RX_WAIT_HEAD 0x2
|
||||
#define ST_RX_WAIT_SILENT_END 0x4
|
||||
|
||||
/* send states */
|
||||
#define ST_TX_NONE 0x0
|
||||
#define ST_TX_REQUEST 0x2
|
||||
#define ST_TX_REPLY 0x4
|
||||
|
||||
/* buffer packet constants */
|
||||
#define BUF_PULSE_BIT 0x80
|
||||
#define BUF_LEN_MASK 0x7f
|
||||
#define BUF_REPEAT_BYTE 0x70
|
||||
#define BUF_REPEAT_MASK 0xf0
|
||||
|
||||
/* CIR settings */
|
||||
|
||||
/* total length of CIR and CIR WAKE */
|
||||
#define CIR_IOREG_LENGTH 0x0f
|
||||
|
||||
/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */
|
||||
#define CIR_RX_LIMIT_COUNT 0x7d0
|
||||
|
||||
/* CIR Regs */
|
||||
#define CIR_IRCON 0x00
|
||||
#define CIR_IRSTS 0x01
|
||||
#define CIR_IREN 0x02
|
||||
#define CIR_RXFCONT 0x03
|
||||
#define CIR_CP 0x04
|
||||
#define CIR_CC 0x05
|
||||
#define CIR_SLCH 0x06
|
||||
#define CIR_SLCL 0x07
|
||||
#define CIR_FIFOCON 0x08
|
||||
#define CIR_IRFIFOSTS 0x09
|
||||
#define CIR_SRXFIFO 0x0a
|
||||
#define CIR_TXFCONT 0x0b
|
||||
#define CIR_STXFIFO 0x0c
|
||||
#define CIR_FCCH 0x0d
|
||||
#define CIR_FCCL 0x0e
|
||||
#define CIR_IRFSM 0x0f
|
||||
|
||||
/* CIR IRCON settings */
|
||||
#define CIR_IRCON_RECV 0x80
|
||||
#define CIR_IRCON_WIREN 0x40
|
||||
#define CIR_IRCON_TXEN 0x20
|
||||
#define CIR_IRCON_RXEN 0x10
|
||||
#define CIR_IRCON_WRXINV 0x08
|
||||
#define CIR_IRCON_RXINV 0x04
|
||||
|
||||
#define CIR_IRCON_SAMPLE_PERIOD_SEL_1 0x00
|
||||
#define CIR_IRCON_SAMPLE_PERIOD_SEL_25 0x01
|
||||
#define CIR_IRCON_SAMPLE_PERIOD_SEL_50 0x02
|
||||
#define CIR_IRCON_SAMPLE_PERIOD_SEL_100 0x03
|
||||
|
||||
/* FIXME: make this a runtime option */
|
||||
/* select sample period as 50us */
|
||||
#define CIR_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50
|
||||
|
||||
/* CIR IRSTS settings */
|
||||
#define CIR_IRSTS_RDR 0x80
|
||||
#define CIR_IRSTS_RTR 0x40
|
||||
#define CIR_IRSTS_PE 0x20
|
||||
#define CIR_IRSTS_RFO 0x10
|
||||
#define CIR_IRSTS_TE 0x08
|
||||
#define CIR_IRSTS_TTR 0x04
|
||||
#define CIR_IRSTS_TFU 0x02
|
||||
#define CIR_IRSTS_GH 0x01
|
||||
|
||||
/* CIR IREN settings */
|
||||
#define CIR_IREN_RDR 0x80
|
||||
#define CIR_IREN_RTR 0x40
|
||||
#define CIR_IREN_PE 0x20
|
||||
#define CIR_IREN_RFO 0x10
|
||||
#define CIR_IREN_TE 0x08
|
||||
#define CIR_IREN_TTR 0x04
|
||||
#define CIR_IREN_TFU 0x02
|
||||
#define CIR_IREN_GH 0x01
|
||||
|
||||
/* CIR FIFOCON settings */
|
||||
#define CIR_FIFOCON_TXFIFOCLR 0x80
|
||||
|
||||
#define CIR_FIFOCON_TX_TRIGGER_LEV_31 0x00
|
||||
#define CIR_FIFOCON_TX_TRIGGER_LEV_24 0x10
|
||||
#define CIR_FIFOCON_TX_TRIGGER_LEV_16 0x20
|
||||
#define CIR_FIFOCON_TX_TRIGGER_LEV_8 0x30
|
||||
|
||||
/* FIXME: make this a runtime option */
|
||||
/* select TX trigger level as 16 */
|
||||
#define CIR_FIFOCON_TX_TRIGGER_LEV CIR_FIFOCON_TX_TRIGGER_LEV_16
|
||||
|
||||
#define CIR_FIFOCON_RXFIFOCLR 0x08
|
||||
|
||||
#define CIR_FIFOCON_RX_TRIGGER_LEV_1 0x00
|
||||
#define CIR_FIFOCON_RX_TRIGGER_LEV_8 0x01
|
||||
#define CIR_FIFOCON_RX_TRIGGER_LEV_16 0x02
|
||||
#define CIR_FIFOCON_RX_TRIGGER_LEV_24 0x03
|
||||
|
||||
/* FIXME: make this a runtime option */
|
||||
/* select RX trigger level as 24 */
|
||||
#define CIR_FIFOCON_RX_TRIGGER_LEV CIR_FIFOCON_RX_TRIGGER_LEV_24
|
||||
|
||||
/* CIR IRFIFOSTS settings */
|
||||
#define CIR_IRFIFOSTS_IR_PENDING 0x80
|
||||
#define CIR_IRFIFOSTS_RX_GS 0x40
|
||||
#define CIR_IRFIFOSTS_RX_FTA 0x20
|
||||
#define CIR_IRFIFOSTS_RX_EMPTY 0x10
|
||||
#define CIR_IRFIFOSTS_RX_FULL 0x08
|
||||
#define CIR_IRFIFOSTS_TX_FTA 0x04
|
||||
#define CIR_IRFIFOSTS_TX_EMPTY 0x02
|
||||
#define CIR_IRFIFOSTS_TX_FULL 0x01
|
||||
|
||||
|
||||
/* CIR WAKE UP Regs */
|
||||
#define CIR_WAKE_IRCON 0x00
|
||||
#define CIR_WAKE_IRSTS 0x01
|
||||
#define CIR_WAKE_IREN 0x02
|
||||
#define CIR_WAKE_FIFO_CMP_DEEP 0x03
|
||||
#define CIR_WAKE_FIFO_CMP_TOL 0x04
|
||||
#define CIR_WAKE_FIFO_COUNT 0x05
|
||||
#define CIR_WAKE_SLCH 0x06
|
||||
#define CIR_WAKE_SLCL 0x07
|
||||
#define CIR_WAKE_FIFOCON 0x08
|
||||
#define CIR_WAKE_SRXFSTS 0x09
|
||||
#define CIR_WAKE_SAMPLE_RX_FIFO 0x0a
|
||||
#define CIR_WAKE_WR_FIFO_DATA 0x0b
|
||||
#define CIR_WAKE_RD_FIFO_ONLY 0x0c
|
||||
#define CIR_WAKE_RD_FIFO_ONLY_IDX 0x0d
|
||||
#define CIR_WAKE_FIFO_IGNORE 0x0e
|
||||
#define CIR_WAKE_IRFSM 0x0f
|
||||
|
||||
/* CIR WAKE UP IRCON settings */
|
||||
#define CIR_WAKE_IRCON_DEC_RST 0x80
|
||||
#define CIR_WAKE_IRCON_MODE1 0x40
|
||||
#define CIR_WAKE_IRCON_MODE0 0x20
|
||||
#define CIR_WAKE_IRCON_RXEN 0x10
|
||||
#define CIR_WAKE_IRCON_R 0x08
|
||||
#define CIR_WAKE_IRCON_RXINV 0x04
|
||||
|
||||
/* FIXME/jarod: make this a runtime option */
|
||||
/* select a same sample period like cir register */
|
||||
#define CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50
|
||||
|
||||
/* CIR WAKE IRSTS Bits */
|
||||
#define CIR_WAKE_IRSTS_RDR 0x80
|
||||
#define CIR_WAKE_IRSTS_RTR 0x40
|
||||
#define CIR_WAKE_IRSTS_PE 0x20
|
||||
#define CIR_WAKE_IRSTS_RFO 0x10
|
||||
#define CIR_WAKE_IRSTS_GH 0x08
|
||||
#define CIR_WAKE_IRSTS_IR_PENDING 0x01
|
||||
|
||||
/* CIR WAKE UP IREN Bits */
|
||||
#define CIR_WAKE_IREN_RDR 0x80
|
||||
#define CIR_WAKE_IREN_RTR 0x40
|
||||
#define CIR_WAKE_IREN_PE 0x20
|
||||
#define CIR_WAKE_IREN_RFO 0x10
|
||||
#define CIR_WAKE_IREN_TE 0x08
|
||||
#define CIR_WAKE_IREN_TTR 0x04
|
||||
#define CIR_WAKE_IREN_TFU 0x02
|
||||
#define CIR_WAKE_IREN_GH 0x01
|
||||
|
||||
/* CIR WAKE FIFOCON settings */
|
||||
#define CIR_WAKE_FIFOCON_RXFIFOCLR 0x08
|
||||
|
||||
#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67 0x00
|
||||
#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_66 0x01
|
||||
#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_65 0x02
|
||||
#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_64 0x03
|
||||
|
||||
/* FIXME: make this a runtime option */
|
||||
/* select WAKE UP RX trigger level as 67 */
|
||||
#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67
|
||||
|
||||
/* CIR WAKE SRXFSTS settings */
|
||||
#define CIR_WAKE_IRFIFOSTS_RX_GS 0x80
|
||||
#define CIR_WAKE_IRFIFOSTS_RX_FTA 0x40
|
||||
#define CIR_WAKE_IRFIFOSTS_RX_EMPTY 0x20
|
||||
#define CIR_WAKE_IRFIFOSTS_RX_FULL 0x10
|
||||
|
||||
/* CIR Wake FIFO buffer is 67 bytes long */
|
||||
#define CIR_WAKE_FIFO_LEN 67
|
||||
/* CIR Wake byte comparison tolerance */
|
||||
#define CIR_WAKE_CMP_TOLERANCE 5
|
||||
|
||||
/*
|
||||
* Extended Function Enable Registers:
|
||||
* Extended Function Index Register
|
||||
* Extended Function Data Register
|
||||
*/
|
||||
#define CR_EFIR 0x2e
|
||||
#define CR_EFDR 0x2f
|
||||
|
||||
/* Possible alternate EFER values, depends on how the chip is wired */
|
||||
#define CR_EFIR2 0x4e
|
||||
#define CR_EFDR2 0x4f
|
||||
|
||||
/* Extended Function Mode enable/disable magic values */
|
||||
#define EFER_EFM_ENABLE 0x87
|
||||
#define EFER_EFM_DISABLE 0xaa
|
||||
|
||||
/* Chip IDs found in CR_CHIP_ID_{HI,LO} */
|
||||
#define CHIP_ID_HIGH 0xb4
|
||||
#define CHIP_ID_LOW 0x72
|
||||
#define CHIP_ID_LOW2 0x73
|
||||
|
||||
/* Config regs we need to care about */
|
||||
#define CR_SOFTWARE_RESET 0x02
|
||||
#define CR_LOGICAL_DEV_SEL 0x07
|
||||
#define CR_CHIP_ID_HI 0x20
|
||||
#define CR_CHIP_ID_LO 0x21
|
||||
#define CR_DEV_POWER_DOWN 0x22 /* bit 2 is CIR power, default power on */
|
||||
#define CR_OUTPUT_PIN_SEL 0x27
|
||||
#define CR_LOGICAL_DEV_EN 0x30 /* valid for all logical devices */
|
||||
/* next three regs valid for both the CIR and CIR_WAKE logical devices */
|
||||
#define CR_CIR_BASE_ADDR_HI 0x60
|
||||
#define CR_CIR_BASE_ADDR_LO 0x61
|
||||
#define CR_CIR_IRQ_RSRC 0x70
|
||||
/* next three regs valid only for ACPI logical dev */
|
||||
#define CR_ACPI_CIR_WAKE 0xe0
|
||||
#define CR_ACPI_IRQ_EVENTS 0xf6
|
||||
#define CR_ACPI_IRQ_EVENTS2 0xf7
|
||||
|
||||
/* Logical devices that we need to care about */
|
||||
#define LOGICAL_DEV_LPT 0x01
|
||||
#define LOGICAL_DEV_CIR 0x06
|
||||
#define LOGICAL_DEV_ACPI 0x0a
|
||||
#define LOGICAL_DEV_CIR_WAKE 0x0e
|
||||
|
||||
#define LOGICAL_DEV_DISABLE 0x00
|
||||
#define LOGICAL_DEV_ENABLE 0x01
|
||||
|
||||
#define CIR_WAKE_ENABLE_BIT 0x08
|
||||
#define CIR_INTR_MOUSE_IRQ_BIT 0x80
|
||||
#define PME_INTR_CIR_PASS_BIT 0x08
|
||||
|
||||
#define OUTPUT_PIN_SEL_MASK 0xbc
|
||||
#define OUTPUT_ENABLE_CIR 0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */
|
||||
#define OUTPUT_ENABLE_CIRWB 0x40 /* enable wide-band sensor */
|
||||
|
||||
/* MCE CIR signal length, related on sample period */
|
||||
|
||||
/* MCE CIR controller signal length: about 43ms
|
||||
* 43ms / 50us (sample period) * 0.85 (inaccuracy)
|
||||
*/
|
||||
#define CONTROLLER_BUF_LEN_MIN 830
|
||||
|
||||
/* MCE CIR keyboard signal length: about 26ms
|
||||
* 26ms / 50us (sample period) * 0.85 (inaccuracy)
|
||||
*/
|
||||
#define KEYBOARD_BUF_LEN_MAX 650
|
||||
#define KEYBOARD_BUF_LEN_MIN 610
|
||||
|
||||
/* MCE CIR mouse signal length: about 24ms
|
||||
* 24ms / 50us (sample period) * 0.85 (inaccuracy)
|
||||
*/
|
||||
#define MOUSE_BUF_LEN_MIN 565
|
||||
|
||||
#define CIR_SAMPLE_PERIOD 50
|
||||
#define CIR_SAMPLE_LOW_INACCURACY 0.85
|
||||
|
||||
/* MAX silence time that driver will sent to lirc */
|
||||
#define MAX_SILENCE_TIME 60000
|
||||
|
||||
#if CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_100
|
||||
#define SAMPLE_PERIOD 100
|
||||
|
||||
#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_50
|
||||
#define SAMPLE_PERIOD 50
|
||||
|
||||
#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_25
|
||||
#define SAMPLE_PERIOD 25
|
||||
|
||||
#else
|
||||
#define SAMPLE_PERIOD 1
|
||||
#endif
|
||||
|
||||
/* as VISTA MCE definition, valid carrier value */
|
||||
#define MAX_CARRIER 60000
|
||||
#define MIN_CARRIER 30000
|
|
@ -38,7 +38,7 @@
|
|||
#include <linux/input.h>
|
||||
#include <media/ir-core.h>
|
||||
|
||||
#define DRIVER_VERSION "1.60"
|
||||
#define DRIVER_VERSION "1.61"
|
||||
#define DRIVER_NAME "streamzap"
|
||||
#define DRIVER_DESC "Streamzap Remote Control driver"
|
||||
|
||||
|
@ -61,14 +61,21 @@ static struct usb_device_id streamzap_table[] = {
|
|||
|
||||
MODULE_DEVICE_TABLE(usb, streamzap_table);
|
||||
|
||||
#define STREAMZAP_PULSE_MASK 0xf0
|
||||
#define STREAMZAP_SPACE_MASK 0x0f
|
||||
#define STREAMZAP_TIMEOUT 0xff
|
||||
#define STREAMZAP_RESOLUTION 256
|
||||
#define SZ_PULSE_MASK 0xf0
|
||||
#define SZ_SPACE_MASK 0x0f
|
||||
#define SZ_TIMEOUT 0xff
|
||||
#define SZ_RESOLUTION 256
|
||||
|
||||
/* number of samples buffered */
|
||||
#define SZ_BUF_LEN 128
|
||||
|
||||
/* from ir-rc5-sz-decoder.c */
|
||||
#ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE
|
||||
#define load_rc5_sz_decode() request_module("ir-rc5-sz-decoder")
|
||||
#else
|
||||
#define load_rc5_sz_decode() 0
|
||||
#endif
|
||||
|
||||
enum StreamzapDecoderState {
|
||||
PulseSpace,
|
||||
FullPulse,
|
||||
|
@ -81,7 +88,6 @@ struct streamzap_ir {
|
|||
|
||||
/* ir-core */
|
||||
struct ir_dev_props *props;
|
||||
struct ir_raw_event rawir;
|
||||
|
||||
/* core device info */
|
||||
struct device *dev;
|
||||
|
@ -98,17 +104,6 @@ struct streamzap_ir {
|
|||
dma_addr_t dma_in;
|
||||
unsigned int buf_in_len;
|
||||
|
||||
/* timer used to support delay buffering */
|
||||
struct timer_list delay_timer;
|
||||
bool timer_running;
|
||||
spinlock_t timer_lock;
|
||||
struct timer_list flush_timer;
|
||||
bool flush;
|
||||
|
||||
/* delay buffer */
|
||||
struct kfifo fifo;
|
||||
bool fifo_initialized;
|
||||
|
||||
/* track what state we're in */
|
||||
enum StreamzapDecoderState decoder_state;
|
||||
/* tracks whether we are currently receiving some signal */
|
||||
|
@ -118,7 +113,7 @@ struct streamzap_ir {
|
|||
/* start time of signal; necessary for gap tracking */
|
||||
struct timeval signal_last;
|
||||
struct timeval signal_start;
|
||||
/* bool timeout_enabled; */
|
||||
bool timeout_enabled;
|
||||
|
||||
char name[128];
|
||||
char phys[64];
|
||||
|
@ -143,122 +138,16 @@ static struct usb_driver streamzap_driver = {
|
|||
.id_table = streamzap_table,
|
||||
};
|
||||
|
||||
static void streamzap_stop_timer(struct streamzap_ir *sz)
|
||||
static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sz->timer_lock, flags);
|
||||
if (sz->timer_running) {
|
||||
sz->timer_running = false;
|
||||
spin_unlock_irqrestore(&sz->timer_lock, flags);
|
||||
del_timer_sync(&sz->delay_timer);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&sz->timer_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void streamzap_flush_timeout(unsigned long arg)
|
||||
{
|
||||
struct streamzap_ir *sz = (struct streamzap_ir *)arg;
|
||||
|
||||
dev_info(sz->dev, "%s: callback firing\n", __func__);
|
||||
|
||||
/* finally start accepting data */
|
||||
sz->flush = false;
|
||||
}
|
||||
|
||||
static void streamzap_delay_timeout(unsigned long arg)
|
||||
{
|
||||
struct streamzap_ir *sz = (struct streamzap_ir *)arg;
|
||||
struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
|
||||
unsigned long flags;
|
||||
int len, ret;
|
||||
static unsigned long delay;
|
||||
bool wake = false;
|
||||
|
||||
/* deliver data every 10 ms */
|
||||
delay = msecs_to_jiffies(10);
|
||||
|
||||
spin_lock_irqsave(&sz->timer_lock, flags);
|
||||
|
||||
if (kfifo_len(&sz->fifo) > 0) {
|
||||
ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
|
||||
if (ret != sizeof(rawir))
|
||||
dev_err(sz->dev, "Problem w/kfifo_out...\n");
|
||||
ir_raw_event_store(sz->idev, &rawir);
|
||||
wake = true;
|
||||
}
|
||||
|
||||
len = kfifo_len(&sz->fifo);
|
||||
if (len > 0) {
|
||||
while ((len < SZ_BUF_LEN / 2) &&
|
||||
(len < SZ_BUF_LEN * sizeof(int))) {
|
||||
ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
|
||||
if (ret != sizeof(rawir))
|
||||
dev_err(sz->dev, "Problem w/kfifo_out...\n");
|
||||
ir_raw_event_store(sz->idev, &rawir);
|
||||
wake = true;
|
||||
len = kfifo_len(&sz->fifo);
|
||||
}
|
||||
if (sz->timer_running)
|
||||
mod_timer(&sz->delay_timer, jiffies + delay);
|
||||
|
||||
} else {
|
||||
sz->timer_running = false;
|
||||
}
|
||||
|
||||
if (wake)
|
||||
ir_raw_event_handle(sz->idev);
|
||||
|
||||
spin_unlock_irqrestore(&sz->timer_lock, flags);
|
||||
}
|
||||
|
||||
static void streamzap_flush_delay_buffer(struct streamzap_ir *sz)
|
||||
{
|
||||
struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
|
||||
bool wake = false;
|
||||
int ret;
|
||||
|
||||
while (kfifo_len(&sz->fifo) > 0) {
|
||||
ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
|
||||
if (ret != sizeof(rawir))
|
||||
dev_err(sz->dev, "Problem w/kfifo_out...\n");
|
||||
ir_raw_event_store(sz->idev, &rawir);
|
||||
wake = true;
|
||||
}
|
||||
|
||||
if (wake)
|
||||
ir_raw_event_handle(sz->idev);
|
||||
}
|
||||
|
||||
static void sz_push(struct streamzap_ir *sz)
|
||||
{
|
||||
struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&sz->timer_lock, flags);
|
||||
if (kfifo_len(&sz->fifo) >= sizeof(int) * SZ_BUF_LEN) {
|
||||
ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
|
||||
if (ret != sizeof(rawir))
|
||||
dev_err(sz->dev, "Problem w/kfifo_out...\n");
|
||||
ir_raw_event_store(sz->idev, &rawir);
|
||||
}
|
||||
|
||||
kfifo_in(&sz->fifo, &sz->rawir, sizeof(rawir));
|
||||
|
||||
if (!sz->timer_running) {
|
||||
sz->delay_timer.expires = jiffies + (HZ / 10);
|
||||
add_timer(&sz->delay_timer);
|
||||
sz->timer_running = true;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&sz->timer_lock, flags);
|
||||
ir_raw_event_store(sz->idev, &rawir);
|
||||
}
|
||||
|
||||
static void sz_push_full_pulse(struct streamzap_ir *sz,
|
||||
unsigned char value)
|
||||
{
|
||||
DEFINE_IR_RAW_EVENT(rawir);
|
||||
|
||||
if (sz->idle) {
|
||||
long deltv;
|
||||
|
||||
|
@ -266,57 +155,59 @@ static void sz_push_full_pulse(struct streamzap_ir *sz,
|
|||
do_gettimeofday(&sz->signal_start);
|
||||
|
||||
deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec;
|
||||
sz->rawir.pulse = false;
|
||||
rawir.pulse = false;
|
||||
if (deltv > 15) {
|
||||
/* really long time */
|
||||
sz->rawir.duration = IR_MAX_DURATION;
|
||||
rawir.duration = IR_MAX_DURATION;
|
||||
} else {
|
||||
sz->rawir.duration = (int)(deltv * 1000000 +
|
||||
rawir.duration = (int)(deltv * 1000000 +
|
||||
sz->signal_start.tv_usec -
|
||||
sz->signal_last.tv_usec);
|
||||
sz->rawir.duration -= sz->sum;
|
||||
sz->rawir.duration *= 1000;
|
||||
sz->rawir.duration &= IR_MAX_DURATION;
|
||||
rawir.duration -= sz->sum;
|
||||
rawir.duration *= 1000;
|
||||
rawir.duration &= IR_MAX_DURATION;
|
||||
}
|
||||
dev_dbg(sz->dev, "ls %u\n", sz->rawir.duration);
|
||||
sz_push(sz);
|
||||
dev_dbg(sz->dev, "ls %u\n", rawir.duration);
|
||||
sz_push(sz, rawir);
|
||||
|
||||
sz->idle = 0;
|
||||
sz->idle = false;
|
||||
sz->sum = 0;
|
||||
}
|
||||
|
||||
sz->rawir.pulse = true;
|
||||
sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION;
|
||||
sz->rawir.duration += STREAMZAP_RESOLUTION / 2;
|
||||
sz->sum += sz->rawir.duration;
|
||||
sz->rawir.duration *= 1000;
|
||||
sz->rawir.duration &= IR_MAX_DURATION;
|
||||
dev_dbg(sz->dev, "p %u\n", sz->rawir.duration);
|
||||
sz_push(sz);
|
||||
rawir.pulse = true;
|
||||
rawir.duration = ((int) value) * SZ_RESOLUTION;
|
||||
rawir.duration += SZ_RESOLUTION / 2;
|
||||
sz->sum += rawir.duration;
|
||||
rawir.duration *= 1000;
|
||||
rawir.duration &= IR_MAX_DURATION;
|
||||
dev_dbg(sz->dev, "p %u\n", rawir.duration);
|
||||
sz_push(sz, rawir);
|
||||
}
|
||||
|
||||
static void sz_push_half_pulse(struct streamzap_ir *sz,
|
||||
unsigned char value)
|
||||
{
|
||||
sz_push_full_pulse(sz, (value & STREAMZAP_PULSE_MASK) >> 4);
|
||||
sz_push_full_pulse(sz, (value & SZ_PULSE_MASK) >> 4);
|
||||
}
|
||||
|
||||
static void sz_push_full_space(struct streamzap_ir *sz,
|
||||
unsigned char value)
|
||||
{
|
||||
sz->rawir.pulse = false;
|
||||
sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION;
|
||||
sz->rawir.duration += STREAMZAP_RESOLUTION / 2;
|
||||
sz->sum += sz->rawir.duration;
|
||||
sz->rawir.duration *= 1000;
|
||||
dev_dbg(sz->dev, "s %u\n", sz->rawir.duration);
|
||||
sz_push(sz);
|
||||
DEFINE_IR_RAW_EVENT(rawir);
|
||||
|
||||
rawir.pulse = false;
|
||||
rawir.duration = ((int) value) * SZ_RESOLUTION;
|
||||
rawir.duration += SZ_RESOLUTION / 2;
|
||||
sz->sum += rawir.duration;
|
||||
rawir.duration *= 1000;
|
||||
dev_dbg(sz->dev, "s %u\n", rawir.duration);
|
||||
sz_push(sz, rawir);
|
||||
}
|
||||
|
||||
static void sz_push_half_space(struct streamzap_ir *sz,
|
||||
unsigned long value)
|
||||
{
|
||||
sz_push_full_space(sz, value & STREAMZAP_SPACE_MASK);
|
||||
sz_push_full_space(sz, value & SZ_SPACE_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -330,10 +221,8 @@ static void streamzap_callback(struct urb *urb)
|
|||
struct streamzap_ir *sz;
|
||||
unsigned int i;
|
||||
int len;
|
||||
#if 0
|
||||
static int timeout = (((STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION) &
|
||||
static int timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) &
|
||||
IR_MAX_DURATION) | 0x03000000);
|
||||
#endif
|
||||
|
||||
if (!urb)
|
||||
return;
|
||||
|
@ -356,57 +245,53 @@ static void streamzap_callback(struct urb *urb)
|
|||
}
|
||||
|
||||
dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
|
||||
if (!sz->flush) {
|
||||
for (i = 0; i < urb->actual_length; i++) {
|
||||
dev_dbg(sz->dev, "%d: %x\n", i,
|
||||
(unsigned char)sz->buf_in[i]);
|
||||
switch (sz->decoder_state) {
|
||||
case PulseSpace:
|
||||
if ((sz->buf_in[i] & STREAMZAP_PULSE_MASK) ==
|
||||
STREAMZAP_PULSE_MASK) {
|
||||
sz->decoder_state = FullPulse;
|
||||
continue;
|
||||
} else if ((sz->buf_in[i] & STREAMZAP_SPACE_MASK)
|
||||
== STREAMZAP_SPACE_MASK) {
|
||||
sz_push_half_pulse(sz, sz->buf_in[i]);
|
||||
sz->decoder_state = FullSpace;
|
||||
continue;
|
||||
} else {
|
||||
sz_push_half_pulse(sz, sz->buf_in[i]);
|
||||
sz_push_half_space(sz, sz->buf_in[i]);
|
||||
}
|
||||
break;
|
||||
case FullPulse:
|
||||
sz_push_full_pulse(sz, sz->buf_in[i]);
|
||||
sz->decoder_state = IgnorePulse;
|
||||
break;
|
||||
case FullSpace:
|
||||
if (sz->buf_in[i] == STREAMZAP_TIMEOUT) {
|
||||
sz->idle = 1;
|
||||
streamzap_stop_timer(sz);
|
||||
#if 0
|
||||
if (sz->timeout_enabled) {
|
||||
sz->rawir.pulse = false;
|
||||
sz->rawir.duration = timeout;
|
||||
sz->rawir.duration *= 1000;
|
||||
sz_push(sz);
|
||||
}
|
||||
#endif
|
||||
streamzap_flush_delay_buffer(sz);
|
||||
} else
|
||||
sz_push_full_space(sz, sz->buf_in[i]);
|
||||
sz->decoder_state = PulseSpace;
|
||||
break;
|
||||
case IgnorePulse:
|
||||
if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) ==
|
||||
STREAMZAP_SPACE_MASK) {
|
||||
sz->decoder_state = FullSpace;
|
||||
continue;
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
dev_dbg(sz->dev, "sz idx %d: %x\n",
|
||||
i, (unsigned char)sz->buf_in[i]);
|
||||
switch (sz->decoder_state) {
|
||||
case PulseSpace:
|
||||
if ((sz->buf_in[i] & SZ_PULSE_MASK) ==
|
||||
SZ_PULSE_MASK) {
|
||||
sz->decoder_state = FullPulse;
|
||||
continue;
|
||||
} else if ((sz->buf_in[i] & SZ_SPACE_MASK)
|
||||
== SZ_SPACE_MASK) {
|
||||
sz_push_half_pulse(sz, sz->buf_in[i]);
|
||||
sz->decoder_state = FullSpace;
|
||||
continue;
|
||||
} else {
|
||||
sz_push_half_pulse(sz, sz->buf_in[i]);
|
||||
sz_push_half_space(sz, sz->buf_in[i]);
|
||||
sz->decoder_state = PulseSpace;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FullPulse:
|
||||
sz_push_full_pulse(sz, sz->buf_in[i]);
|
||||
sz->decoder_state = IgnorePulse;
|
||||
break;
|
||||
case FullSpace:
|
||||
if (sz->buf_in[i] == SZ_TIMEOUT) {
|
||||
DEFINE_IR_RAW_EVENT(rawir);
|
||||
|
||||
rawir.pulse = false;
|
||||
rawir.duration = timeout;
|
||||
sz->idle = true;
|
||||
if (sz->timeout_enabled)
|
||||
sz_push(sz, rawir);
|
||||
ir_raw_event_handle(sz->idev);
|
||||
} else {
|
||||
sz_push_full_space(sz, sz->buf_in[i]);
|
||||
}
|
||||
sz->decoder_state = PulseSpace;
|
||||
break;
|
||||
case IgnorePulse:
|
||||
if ((sz->buf_in[i] & SZ_SPACE_MASK) ==
|
||||
SZ_SPACE_MASK) {
|
||||
sz->decoder_state = FullSpace;
|
||||
continue;
|
||||
}
|
||||
sz_push_half_space(sz, sz->buf_in[i]);
|
||||
sz->decoder_state = PulseSpace;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -446,12 +331,11 @@ static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz)
|
|||
|
||||
props->priv = sz;
|
||||
props->driver_type = RC_DRIVER_IR_RAW;
|
||||
/* FIXME: not sure about supported protocols, check on this */
|
||||
props->allowed_protos = IR_TYPE_RC5 | IR_TYPE_RC6;
|
||||
props->allowed_protos = IR_TYPE_ALL;
|
||||
|
||||
sz->props = props;
|
||||
|
||||
ret = ir_input_register(idev, RC_MAP_RC5_STREAMZAP, props, DRIVER_NAME);
|
||||
ret = ir_input_register(idev, RC_MAP_STREAMZAP, props, DRIVER_NAME);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "remote input device register failed\n");
|
||||
goto irdev_failed;
|
||||
|
@ -467,29 +351,6 @@ static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int streamzap_delay_buf_init(struct streamzap_ir *sz)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = kfifo_alloc(&sz->fifo, sizeof(int) * SZ_BUF_LEN,
|
||||
GFP_KERNEL);
|
||||
if (ret == 0)
|
||||
sz->fifo_initialized = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void streamzap_start_flush_timer(struct streamzap_ir *sz)
|
||||
{
|
||||
sz->flush_timer.expires = jiffies + HZ;
|
||||
sz->flush = true;
|
||||
add_timer(&sz->flush_timer);
|
||||
|
||||
sz->urb_in->dev = sz->usbdev;
|
||||
if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
|
||||
dev_err(sz->dev, "urb submit failed\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* streamzap_probe
|
||||
*
|
||||
|
@ -575,35 +436,21 @@ static int __devinit streamzap_probe(struct usb_interface *intf,
|
|||
snprintf(name + strlen(name), sizeof(name) - strlen(name),
|
||||
" %s", buf);
|
||||
|
||||
retval = streamzap_delay_buf_init(sz);
|
||||
if (retval) {
|
||||
dev_err(&intf->dev, "%s: delay buffer init failed\n", __func__);
|
||||
goto free_urb_in;
|
||||
}
|
||||
|
||||
sz->idev = streamzap_init_input_dev(sz);
|
||||
if (!sz->idev)
|
||||
goto input_dev_fail;
|
||||
|
||||
sz->idle = true;
|
||||
sz->decoder_state = PulseSpace;
|
||||
/* FIXME: don't yet have a way to set this */
|
||||
sz->timeout_enabled = true;
|
||||
#if 0
|
||||
/* not yet supported, depends on patches from maxim */
|
||||
/* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */
|
||||
sz->timeout_enabled = false;
|
||||
sz->min_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000;
|
||||
sz->max_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000;
|
||||
sz->min_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000;
|
||||
sz->max_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000;
|
||||
#endif
|
||||
|
||||
init_timer(&sz->delay_timer);
|
||||
sz->delay_timer.function = streamzap_delay_timeout;
|
||||
sz->delay_timer.data = (unsigned long)sz;
|
||||
spin_lock_init(&sz->timer_lock);
|
||||
|
||||
init_timer(&sz->flush_timer);
|
||||
sz->flush_timer.function = streamzap_flush_timeout;
|
||||
sz->flush_timer.data = (unsigned long)sz;
|
||||
|
||||
do_gettimeofday(&sz->signal_start);
|
||||
|
||||
/* Complete final initialisations */
|
||||
|
@ -615,16 +462,18 @@ static int __devinit streamzap_probe(struct usb_interface *intf,
|
|||
|
||||
usb_set_intfdata(intf, sz);
|
||||
|
||||
streamzap_start_flush_timer(sz);
|
||||
if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
|
||||
dev_err(sz->dev, "urb submit failed\n");
|
||||
|
||||
dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
|
||||
usbdev->bus->busnum, usbdev->devnum);
|
||||
|
||||
/* Load the streamzap not-quite-rc5 decoder too */
|
||||
load_rc5_sz_decode();
|
||||
|
||||
return 0;
|
||||
|
||||
input_dev_fail:
|
||||
kfifo_free(&sz->fifo);
|
||||
free_urb_in:
|
||||
usb_free_urb(sz->urb_in);
|
||||
free_buf_in:
|
||||
usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in);
|
||||
|
@ -654,13 +503,6 @@ static void streamzap_disconnect(struct usb_interface *interface)
|
|||
if (!sz)
|
||||
return;
|
||||
|
||||
if (sz->flush) {
|
||||
sz->flush = false;
|
||||
del_timer_sync(&sz->flush_timer);
|
||||
}
|
||||
|
||||
streamzap_stop_timer(sz);
|
||||
|
||||
sz->usbdev = NULL;
|
||||
ir_input_unregister(sz->idev);
|
||||
usb_kill_urb(sz->urb_in);
|
||||
|
@ -674,13 +516,6 @@ static int streamzap_suspend(struct usb_interface *intf, pm_message_t message)
|
|||
{
|
||||
struct streamzap_ir *sz = usb_get_intfdata(intf);
|
||||
|
||||
if (sz->flush) {
|
||||
sz->flush = false;
|
||||
del_timer_sync(&sz->flush_timer);
|
||||
}
|
||||
|
||||
streamzap_stop_timer(sz);
|
||||
|
||||
usb_kill_urb(sz->urb_in);
|
||||
|
||||
return 0;
|
||||
|
@ -690,13 +525,6 @@ static int streamzap_resume(struct usb_interface *intf)
|
|||
{
|
||||
struct streamzap_ir *sz = usb_get_intfdata(intf);
|
||||
|
||||
if (sz->fifo_initialized)
|
||||
kfifo_reset(&sz->fifo);
|
||||
|
||||
sz->flush_timer.expires = jiffies + HZ;
|
||||
sz->flush = true;
|
||||
add_timer(&sz->flush_timer);
|
||||
|
||||
if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) {
|
||||
dev_err(sz->dev, "Error sumbiting urb\n");
|
||||
return -EIO;
|
||||
|
|
|
@ -56,7 +56,7 @@ void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
|
|||
|
||||
BUG_ON(in_interrupt());
|
||||
|
||||
videobuf_waiton(&buf->vb,0,0);
|
||||
videobuf_waiton(q, &buf->vb, 0, 0);
|
||||
videobuf_dma_unmap(q->dev, dma);
|
||||
videobuf_dma_free(dma);
|
||||
buf->vb.state = VIDEOBUF_NEEDS_INIT;
|
||||
|
|
|
@ -414,7 +414,6 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c
|
|||
i2c_adapter->dev.parent = &dev->pci->dev;
|
||||
i2c_adapter->algo = &saa7146_algo;
|
||||
i2c_adapter->algo_data = NULL;
|
||||
i2c_adapter->id = I2C_HW_SAA7146;
|
||||
i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
|
||||
i2c_adapter->retries = SAA7146_I2C_RETRIES;
|
||||
}
|
||||
|
|
|
@ -412,7 +412,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
|
|||
V4L2_BUF_TYPE_VBI_CAPTURE,
|
||||
V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
|
||||
sizeof(struct saa7146_buf),
|
||||
file);
|
||||
file, NULL);
|
||||
|
||||
init_timer(&fh->vbi_read_timeout);
|
||||
fh->vbi_read_timeout.function = vbi_read_timeout;
|
||||
|
|
|
@ -1386,7 +1386,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
|
|||
V4L2_BUF_TYPE_VIDEO_CAPTURE,
|
||||
V4L2_FIELD_INTERLACED,
|
||||
sizeof(struct saa7146_buf),
|
||||
file);
|
||||
file, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -179,4 +179,11 @@ config MEDIA_TUNER_MAX2165
|
|||
help
|
||||
A driver for the silicon tuner MAX2165 from Maxim.
|
||||
|
||||
config MEDIA_TUNER_TDA18218
|
||||
tristate "NXP TDA18218 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
NXP TDA18218 silicon tuner driver.
|
||||
|
||||
endif # MEDIA_TUNER_CUSTOMISE
|
||||
|
|
|
@ -24,6 +24,7 @@ obj-$(CONFIG_MEDIA_TUNER_MXL5005S) += mxl5005s.o
|
|||
obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o
|
||||
obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o
|
||||
obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o
|
||||
obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
|
||||
|
|
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
* NXP TDA18218HN silicon tuner driver
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "tda18218.h"
|
||||
#include "tda18218_priv.h"
|
||||
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
|
||||
|
||||
/* write multiple registers */
|
||||
static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
|
||||
{
|
||||
int ret;
|
||||
u8 buf[1+len], quotient, remainder, i, msg_len, msg_len_max;
|
||||
struct i2c_msg msg[1] = {
|
||||
{
|
||||
.addr = priv->cfg->i2c_address,
|
||||
.flags = 0,
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
|
||||
msg_len_max = priv->cfg->i2c_wr_max - 1;
|
||||
quotient = len / msg_len_max;
|
||||
remainder = len % msg_len_max;
|
||||
msg_len = msg_len_max;
|
||||
for (i = 0; (i <= quotient && remainder); i++) {
|
||||
if (i == quotient) /* set len of the last msg */
|
||||
msg_len = remainder;
|
||||
|
||||
msg[0].len = msg_len + 1;
|
||||
buf[0] = reg + i * msg_len_max;
|
||||
memcpy(&buf[1], &val[i * msg_len_max], msg_len);
|
||||
|
||||
ret = i2c_transfer(priv->i2c, msg, 1);
|
||||
if (ret != 1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == 1) {
|
||||
ret = 0;
|
||||
} else {
|
||||
warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
|
||||
ret = -EREMOTEIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* read multiple registers */
|
||||
static int tda18218_rd_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
|
||||
{
|
||||
int ret;
|
||||
u8 buf[reg+len]; /* we must start read always from reg 0x00 */
|
||||
struct i2c_msg msg[2] = {
|
||||
{
|
||||
.addr = priv->cfg->i2c_address,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = "\x00",
|
||||
}, {
|
||||
.addr = priv->cfg->i2c_address,
|
||||
.flags = I2C_M_RD,
|
||||
.len = sizeof(buf),
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
|
||||
ret = i2c_transfer(priv->i2c, msg, 2);
|
||||
if (ret == 2) {
|
||||
memcpy(val, &buf[reg], len);
|
||||
ret = 0;
|
||||
} else {
|
||||
warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
|
||||
ret = -EREMOTEIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* write single register */
|
||||
static int tda18218_wr_reg(struct tda18218_priv *priv, u8 reg, u8 val)
|
||||
{
|
||||
return tda18218_wr_regs(priv, reg, &val, 1);
|
||||
}
|
||||
|
||||
/* read single register */
|
||||
|
||||
static int tda18218_rd_reg(struct tda18218_priv *priv, u8 reg, u8 *val)
|
||||
{
|
||||
return tda18218_rd_regs(priv, reg, val, 1);
|
||||
}
|
||||
|
||||
static int tda18218_set_params(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct tda18218_priv *priv = fe->tuner_priv;
|
||||
int ret;
|
||||
u8 buf[3], i, BP_Filter, LP_Fc;
|
||||
u32 LO_Frac;
|
||||
/* TODO: find out correct AGC algorithm */
|
||||
u8 agc[][2] = {
|
||||
{ R20_AGC11, 0x60 },
|
||||
{ R23_AGC21, 0x02 },
|
||||
{ R20_AGC11, 0xa0 },
|
||||
{ R23_AGC21, 0x09 },
|
||||
{ R20_AGC11, 0xe0 },
|
||||
{ R23_AGC21, 0x0c },
|
||||
{ R20_AGC11, 0x40 },
|
||||
{ R23_AGC21, 0x01 },
|
||||
{ R20_AGC11, 0x80 },
|
||||
{ R23_AGC21, 0x08 },
|
||||
{ R20_AGC11, 0xc0 },
|
||||
{ R23_AGC21, 0x0b },
|
||||
{ R24_AGC22, 0x1c },
|
||||
{ R24_AGC22, 0x0c },
|
||||
};
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
|
||||
|
||||
/* low-pass filter cut-off frequency */
|
||||
switch (params->u.ofdm.bandwidth) {
|
||||
case BANDWIDTH_6_MHZ:
|
||||
LP_Fc = 0;
|
||||
LO_Frac = params->frequency + 4000000;
|
||||
break;
|
||||
case BANDWIDTH_7_MHZ:
|
||||
LP_Fc = 1;
|
||||
LO_Frac = params->frequency + 3500000;
|
||||
break;
|
||||
case BANDWIDTH_8_MHZ:
|
||||
default:
|
||||
LP_Fc = 2;
|
||||
LO_Frac = params->frequency + 4000000;
|
||||
break;
|
||||
}
|
||||
|
||||
/* band-pass filter */
|
||||
if (LO_Frac < 188000000)
|
||||
BP_Filter = 3;
|
||||
else if (LO_Frac < 253000000)
|
||||
BP_Filter = 4;
|
||||
else if (LO_Frac < 343000000)
|
||||
BP_Filter = 5;
|
||||
else
|
||||
BP_Filter = 6;
|
||||
|
||||
buf[0] = (priv->regs[R1A_IF1] & ~7) | BP_Filter; /* BP_Filter */
|
||||
buf[1] = (priv->regs[R1B_IF2] & ~3) | LP_Fc; /* LP_Fc */
|
||||
buf[2] = priv->regs[R1C_AGC2B];
|
||||
ret = tda18218_wr_regs(priv, R1A_IF1, buf, 3);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
buf[0] = (LO_Frac / 1000) >> 12; /* LO_Frac_0 */
|
||||
buf[1] = (LO_Frac / 1000) >> 4; /* LO_Frac_1 */
|
||||
buf[2] = (LO_Frac / 1000) << 4 |
|
||||
(priv->regs[R0C_MD5] & 0x0f); /* LO_Frac_2 */
|
||||
ret = tda18218_wr_regs(priv, R0A_MD3, buf, 3);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
buf[0] = priv->regs[R0F_MD8] | (1 << 6); /* Freq_prog_Start */
|
||||
ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
buf[0] = priv->regs[R0F_MD8] & ~(1 << 6); /* Freq_prog_Start */
|
||||
ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* trigger AGC */
|
||||
for (i = 0; i < ARRAY_SIZE(agc); i++) {
|
||||
ret = tda18218_wr_reg(priv, agc[i][0], agc[i][1]);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
|
||||
|
||||
if (ret)
|
||||
dbg("%s: failed ret:%d", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tda18218_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct tda18218_priv *priv = fe->tuner_priv;
|
||||
int ret;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
|
||||
|
||||
/* standby */
|
||||
ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
|
||||
|
||||
if (ret)
|
||||
dbg("%s: failed ret:%d", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tda18218_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct tda18218_priv *priv = fe->tuner_priv;
|
||||
int ret;
|
||||
|
||||
/* TODO: calibrations */
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
|
||||
|
||||
ret = tda18218_wr_regs(priv, R00_ID, priv->regs, TDA18218_NUM_REGS);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
|
||||
|
||||
if (ret)
|
||||
dbg("%s: failed ret:%d", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tda18218_release(struct dvb_frontend *fe)
|
||||
{
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dvb_tuner_ops tda18218_tuner_ops = {
|
||||
.info = {
|
||||
.name = "NXP TDA18218",
|
||||
|
||||
.frequency_min = 174000000,
|
||||
.frequency_max = 864000000,
|
||||
.frequency_step = 1000,
|
||||
},
|
||||
|
||||
.release = tda18218_release,
|
||||
.init = tda18218_init,
|
||||
.sleep = tda18218_sleep,
|
||||
|
||||
.set_params = tda18218_set_params,
|
||||
};
|
||||
|
||||
struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c, struct tda18218_config *cfg)
|
||||
{
|
||||
struct tda18218_priv *priv = NULL;
|
||||
u8 val;
|
||||
int ret;
|
||||
/* chip default registers values */
|
||||
static u8 def_regs[] = {
|
||||
0xc0, 0x88, 0x00, 0x8e, 0x03, 0x00, 0x00, 0xd0, 0x00, 0x40,
|
||||
0x00, 0x00, 0x07, 0xff, 0x84, 0x09, 0x00, 0x13, 0x00, 0x00,
|
||||
0x01, 0x84, 0x09, 0xf0, 0x19, 0x0a, 0x8e, 0x69, 0x98, 0x01,
|
||||
0x00, 0x58, 0x10, 0x40, 0x8c, 0x00, 0x0c, 0x48, 0x85, 0xc9,
|
||||
0xa7, 0x00, 0x00, 0x00, 0x30, 0x81, 0x80, 0x00, 0x39, 0x00,
|
||||
0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf6
|
||||
};
|
||||
|
||||
priv = kzalloc(sizeof(struct tda18218_priv), GFP_KERNEL);
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
|
||||
priv->cfg = cfg;
|
||||
priv->i2c = i2c;
|
||||
fe->tuner_priv = priv;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
|
||||
|
||||
/* check if the tuner is there */
|
||||
ret = tda18218_rd_reg(priv, R00_ID, &val);
|
||||
dbg("%s: ret:%d chip ID:%02x", __func__, ret, val);
|
||||
if (ret || val != def_regs[R00_ID]) {
|
||||
kfree(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info("NXP TDA18218HN successfully identified.");
|
||||
|
||||
memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops,
|
||||
sizeof(struct dvb_tuner_ops));
|
||||
memcpy(priv->regs, def_regs, sizeof(def_regs));
|
||||
|
||||
/* loop-through enabled chip default register values */
|
||||
if (priv->cfg->loop_through) {
|
||||
priv->regs[R17_PD1] = 0xb0;
|
||||
priv->regs[R18_PD2] = 0x59;
|
||||
}
|
||||
|
||||
/* standby */
|
||||
ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
|
||||
if (ret)
|
||||
dbg("%s: failed ret:%d", __func__, ret);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
|
||||
|
||||
return fe;
|
||||
}
|
||||
EXPORT_SYMBOL(tda18218_attach);
|
||||
|
||||
MODULE_DESCRIPTION("NXP TDA18218HN silicon tuner driver");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* NXP TDA18218HN silicon tuner driver
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef TDA18218_H
|
||||
#define TDA18218_H
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
struct tda18218_config {
|
||||
u8 i2c_address;
|
||||
u8 i2c_wr_max;
|
||||
u8 loop_through:1;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_MEDIA_TUNER_TDA18218) || \
|
||||
(defined(CONFIG_MEDIA_TUNER_TDA18218_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c, struct tda18218_config *cfg);
|
||||
#else
|
||||
static inline struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c, struct tda18218_config *cfg)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* NXP TDA18218HN silicon tuner driver
|
||||
*
|
||||
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef TDA18218_PRIV_H
|
||||
#define TDA18218_PRIV_H
|
||||
|
||||
#define LOG_PREFIX "tda18218"
|
||||
|
||||
#undef dbg
|
||||
#define dbg(f, arg...) \
|
||||
if (debug) \
|
||||
printk(KERN_DEBUG LOG_PREFIX": " f "\n" , ## arg)
|
||||
#undef err
|
||||
#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg)
|
||||
#undef info
|
||||
#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
|
||||
#undef warn
|
||||
#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
|
||||
|
||||
#define R00_ID 0x00 /* ID byte */
|
||||
#define R01_R1 0x01 /* Read byte 1 */
|
||||
#define R02_R2 0x02 /* Read byte 2 */
|
||||
#define R03_R3 0x03 /* Read byte 3 */
|
||||
#define R04_R4 0x04 /* Read byte 4 */
|
||||
#define R05_R5 0x05 /* Read byte 5 */
|
||||
#define R06_R6 0x06 /* Read byte 6 */
|
||||
#define R07_MD1 0x07 /* Main divider byte 1 */
|
||||
#define R08_PSM1 0x08 /* PSM byte 1 */
|
||||
#define R09_MD2 0x09 /* Main divider byte 2 */
|
||||
#define R0A_MD3 0x0a /* Main divider byte 1 */
|
||||
#define R0B_MD4 0x0b /* Main divider byte 4 */
|
||||
#define R0C_MD5 0x0c /* Main divider byte 5 */
|
||||
#define R0D_MD6 0x0d /* Main divider byte 6 */
|
||||
#define R0E_MD7 0x0e /* Main divider byte 7 */
|
||||
#define R0F_MD8 0x0f /* Main divider byte 8 */
|
||||
#define R10_CD1 0x10 /* Call divider byte 1 */
|
||||
#define R11_CD2 0x11 /* Call divider byte 2 */
|
||||
#define R12_CD3 0x12 /* Call divider byte 3 */
|
||||
#define R13_CD4 0x13 /* Call divider byte 4 */
|
||||
#define R14_CD5 0x14 /* Call divider byte 5 */
|
||||
#define R15_CD6 0x15 /* Call divider byte 6 */
|
||||
#define R16_CD7 0x16 /* Call divider byte 7 */
|
||||
#define R17_PD1 0x17 /* Power-down byte 1 */
|
||||
#define R18_PD2 0x18 /* Power-down byte 2 */
|
||||
#define R19_XTOUT 0x19 /* XTOUT byte */
|
||||
#define R1A_IF1 0x1a /* IF byte 1 */
|
||||
#define R1B_IF2 0x1b /* IF byte 2 */
|
||||
#define R1C_AGC2B 0x1c /* AGC2b byte */
|
||||
#define R1D_PSM2 0x1d /* PSM byte 2 */
|
||||
#define R1E_PSM3 0x1e /* PSM byte 3 */
|
||||
#define R1F_PSM4 0x1f /* PSM byte 4 */
|
||||
#define R20_AGC11 0x20 /* AGC1 byte 1 */
|
||||
#define R21_AGC12 0x21 /* AGC1 byte 2 */
|
||||
#define R22_AGC13 0x22 /* AGC1 byte 3 */
|
||||
#define R23_AGC21 0x23 /* AGC2 byte 1 */
|
||||
#define R24_AGC22 0x24 /* AGC2 byte 2 */
|
||||
#define R25_AAGC 0x25 /* Analog AGC byte */
|
||||
#define R26_RC 0x26 /* RC byte */
|
||||
#define R27_RSSI 0x27 /* RSSI byte */
|
||||
#define R28_IRCAL1 0x28 /* IR CAL byte 1 */
|
||||
#define R29_IRCAL2 0x29 /* IR CAL byte 2 */
|
||||
#define R2A_IRCAL3 0x2a /* IR CAL byte 3 */
|
||||
#define R2B_IRCAL4 0x2b /* IR CAL byte 4 */
|
||||
#define R2C_RFCAL1 0x2c /* RF CAL byte 1 */
|
||||
#define R2D_RFCAL2 0x2d /* RF CAL byte 2 */
|
||||
#define R2E_RFCAL3 0x2e /* RF CAL byte 3 */
|
||||
#define R2F_RFCAL4 0x2f /* RF CAL byte 4 */
|
||||
#define R30_RFCAL5 0x30 /* RF CAL byte 5 */
|
||||
#define R31_RFCAL6 0x31 /* RF CAL byte 6 */
|
||||
#define R32_RFCAL7 0x32 /* RF CAL byte 7 */
|
||||
#define R33_RFCAL8 0x33 /* RF CAL byte 8 */
|
||||
#define R34_RFCAL9 0x34 /* RF CAL byte 9 */
|
||||
#define R35_RFCAL10 0x35 /* RF CAL byte 10 */
|
||||
#define R36_RFCALRAM1 0x36 /* RF CAL RAM byte 1 */
|
||||
#define R37_RFCALRAM2 0x37 /* RF CAL RAM byte 2 */
|
||||
#define R38_MARGIN 0x38 /* Margin byte */
|
||||
#define R39_FMAX1 0x39 /* Fmax byte 1 */
|
||||
#define R3A_FMAX2 0x3a /* Fmax byte 2 */
|
||||
|
||||
#define TDA18218_NUM_REGS 59
|
||||
|
||||
struct tda18218_priv {
|
||||
struct tda18218_config *cfg;
|
||||
struct i2c_adapter *i2c;
|
||||
|
||||
u8 regs[TDA18218_NUM_REGS];
|
||||
};
|
||||
|
||||
#endif
|
|
@ -193,25 +193,51 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
|
|||
unsigned char *regs = priv->tda18271_regs;
|
||||
unsigned char buf[TDA18271_NUM_REGS + 1];
|
||||
struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0,
|
||||
.buf = buf, .len = len + 1 };
|
||||
int i, ret;
|
||||
.buf = buf };
|
||||
int i, ret = 1, max;
|
||||
|
||||
BUG_ON((len == 0) || (idx + len > sizeof(buf)));
|
||||
|
||||
buf[0] = idx;
|
||||
for (i = 1; i <= len; i++)
|
||||
buf[i] = regs[idx - 1 + i];
|
||||
|
||||
switch (priv->small_i2c) {
|
||||
case TDA18271_03_BYTE_CHUNK_INIT:
|
||||
max = 3;
|
||||
break;
|
||||
case TDA18271_08_BYTE_CHUNK_INIT:
|
||||
max = 8;
|
||||
break;
|
||||
case TDA18271_16_BYTE_CHUNK_INIT:
|
||||
max = 16;
|
||||
break;
|
||||
case TDA18271_39_BYTE_CHUNK_INIT:
|
||||
default:
|
||||
max = 39;
|
||||
}
|
||||
|
||||
tda18271_i2c_gate_ctrl(fe, 1);
|
||||
while (len) {
|
||||
if (max > len)
|
||||
max = len;
|
||||
|
||||
/* write registers */
|
||||
ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
|
||||
buf[0] = idx;
|
||||
for (i = 1; i <= max; i++)
|
||||
buf[i] = regs[idx - 1 + i];
|
||||
|
||||
msg.len = max + 1;
|
||||
|
||||
/* write registers */
|
||||
ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
|
||||
if (ret != 1)
|
||||
break;
|
||||
|
||||
idx += max;
|
||||
len -= max;
|
||||
}
|
||||
tda18271_i2c_gate_ctrl(fe, 0);
|
||||
|
||||
if (ret != 1)
|
||||
tda_err("ERROR: idx = 0x%x, len = %d, "
|
||||
"i2c_transfer returned: %d\n", idx, len, ret);
|
||||
"i2c_transfer returned: %d\n", idx, max, ret);
|
||||
|
||||
return (ret == 1 ? 0 : ret);
|
||||
}
|
||||
|
@ -326,24 +352,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
|
|||
regs[R_EB22] = 0x48;
|
||||
regs[R_EB23] = 0xb0;
|
||||
|
||||
switch (priv->small_i2c) {
|
||||
case TDA18271_08_BYTE_CHUNK_INIT:
|
||||
tda18271_write_regs(fe, 0x00, 0x08);
|
||||
tda18271_write_regs(fe, 0x08, 0x08);
|
||||
tda18271_write_regs(fe, 0x10, 0x08);
|
||||
tda18271_write_regs(fe, 0x18, 0x08);
|
||||
tda18271_write_regs(fe, 0x20, 0x07);
|
||||
break;
|
||||
case TDA18271_16_BYTE_CHUNK_INIT:
|
||||
tda18271_write_regs(fe, 0x00, 0x10);
|
||||
tda18271_write_regs(fe, 0x10, 0x10);
|
||||
tda18271_write_regs(fe, 0x20, 0x07);
|
||||
break;
|
||||
case TDA18271_39_BYTE_CHUNK_INIT:
|
||||
default:
|
||||
tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
|
||||
break;
|
||||
}
|
||||
tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
|
||||
|
||||
/* setup agc1 gain */
|
||||
regs[R_EB17] = 0x00;
|
||||
|
|
|
@ -1156,7 +1156,6 @@ static int tda18271_get_id(struct dvb_frontend *fe)
|
|||
struct tda18271_priv *priv = fe->tuner_priv;
|
||||
unsigned char *regs = priv->tda18271_regs;
|
||||
char *name;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
tda18271_read_regs(fe);
|
||||
|
@ -1172,17 +1171,16 @@ static int tda18271_get_id(struct dvb_frontend *fe)
|
|||
priv->id = TDA18271HDC2;
|
||||
break;
|
||||
default:
|
||||
name = "Unknown device";
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
tda_info("Unknown device (%i) detected @ %d-%04x, device not supported.\n",
|
||||
regs[R_ID], i2c_adapter_id(priv->i2c_props.adap),
|
||||
priv->i2c_props.addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tda_info("%s detected @ %d-%04x%s\n", name,
|
||||
i2c_adapter_id(priv->i2c_props.adap),
|
||||
priv->i2c_props.addr,
|
||||
(0 == ret) ? "" : ", device not supported.");
|
||||
tda_info("%s detected @ %d-%04x\n", name,
|
||||
i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda18271_setup_configuration(struct dvb_frontend *fe,
|
||||
|
|
|
@ -80,8 +80,9 @@ enum tda18271_output_options {
|
|||
|
||||
enum tda18271_small_i2c {
|
||||
TDA18271_39_BYTE_CHUNK_INIT = 0,
|
||||
TDA18271_16_BYTE_CHUNK_INIT = 1,
|
||||
TDA18271_08_BYTE_CHUNK_INIT = 2,
|
||||
TDA18271_16_BYTE_CHUNK_INIT = 16,
|
||||
TDA18271_08_BYTE_CHUNK_INIT = 8,
|
||||
TDA18271_03_BYTE_CHUNK_INIT = 3,
|
||||
};
|
||||
|
||||
struct tda18271_config {
|
||||
|
|
|
@ -1042,7 +1042,7 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = {
|
|||
|
||||
struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c,
|
||||
struct xc5000_config *cfg)
|
||||
const struct xc5000_config *cfg)
|
||||
{
|
||||
struct xc5000_priv *priv = NULL;
|
||||
int instance;
|
||||
|
|
|
@ -53,11 +53,11 @@ struct xc5000_config {
|
|||
(defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c,
|
||||
struct xc5000_config *cfg);
|
||||
const struct xc5000_config *cfg);
|
||||
#else
|
||||
static inline struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c,
|
||||
struct xc5000_config *cfg)
|
||||
const struct xc5000_config *cfg)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
|
|
|
@ -245,9 +245,6 @@ int flexcop_i2c_init(struct flexcop_device *fc)
|
|||
i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);
|
||||
i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]);
|
||||
|
||||
fc->fc_i2c_adap[0].i2c_adap.class =
|
||||
fc->fc_i2c_adap[1].i2c_adap.class =
|
||||
fc->fc_i2c_adap[2].i2c_adap.class = I2C_CLASS_TV_DIGITAL;
|
||||
fc->fc_i2c_adap[0].i2c_adap.algo =
|
||||
fc->fc_i2c_adap[1].i2c_adap.algo =
|
||||
fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo;
|
||||
|
|
|
@ -862,7 +862,6 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
|
|||
i2c_set_adapdata(&dev->i2c_adap, dev);
|
||||
strcpy(dev->i2c_adap.name, DRIVER_NAME);
|
||||
dev->i2c_adap.owner = THIS_MODULE;
|
||||
dev->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
|
||||
dev->i2c_adap.dev.parent = &pdev->dev;
|
||||
dev->i2c_adap.algo = &dm1105_algo;
|
||||
dev->i2c_adap.algo_data = dev;
|
||||
|
|
|
@ -702,7 +702,7 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
|
|||
|
||||
kthread_stop(fepriv->thread);
|
||||
|
||||
init_MUTEX (&fepriv->sem);
|
||||
sema_init(&fepriv->sem, 1);
|
||||
fepriv->state = FESTATE_IDLE;
|
||||
|
||||
/* paranoia check in case a signal arrived */
|
||||
|
@ -2062,7 +2062,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
|
|||
}
|
||||
fepriv = fe->frontend_priv;
|
||||
|
||||
init_MUTEX (&fepriv->sem);
|
||||
sema_init(&fepriv->sem, 1);
|
||||
init_waitqueue_head (&fepriv->wait_queue);
|
||||
init_waitqueue_head (&fepriv->events.wait_queue);
|
||||
mutex_init(&fepriv->events.mtx);
|
||||
|
|
|
@ -260,7 +260,7 @@ struct dvb_frontend_ops {
|
|||
int (*init)(struct dvb_frontend* fe);
|
||||
int (*sleep)(struct dvb_frontend* fe);
|
||||
|
||||
int (*write)(struct dvb_frontend* fe, u8* buf, int len);
|
||||
int (*write)(struct dvb_frontend* fe, const u8 buf[], int len);
|
||||
|
||||
/* if this is set, it overrides the default swzigzag */
|
||||
int (*tune)(struct dvb_frontend* fe,
|
||||
|
|
|
@ -314,6 +314,8 @@ config DVB_USB_AF9015
|
|||
select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver
|
||||
|
||||
|
@ -346,3 +348,13 @@ config DVB_USB_AZ6027
|
|||
select DVB_STB6100 if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the AZ6027 device
|
||||
|
||||
config DVB_USB_LME2510
|
||||
tristate "LME DM04/QQBOX DVB-S USB2.0 support"
|
||||
depends on DVB_USB
|
||||
select DVB_TDA10086 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA826X if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV0288 if !DVB_FE_CUSTOMISE
|
||||
select DVB_IX2505V if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 .
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue