mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
Merge branch 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (243 commits) V4L/DVB: sms: Convert IR support to use the Remote Controller core V4L/DVB: sms: properly initialize IR phys and IR name V4L/DVB: standardize names at rc-dib0700 tables V4L/DVB: smsusb: enable IR port for Hauppauge WinTV MiniStick V4L/DVB: dib0700: Fix RC protocol logic to properly handle NEC/NECx and RC-5 V4L/DVB: dib0700: properly implement IR change_protocol V4L/DVB: dib0700: break keytable into NEC and RC-5 variants V4L/DVB: dib0700: avoid bad repeat V4L/DVB: Port dib0700 to rc-core V4L/DVB: Add a keymap file with dib0700 table V4L/DVB: dvb-usb: add support for rc-core mode V4L/DVB: dvb-usb: prepare drivers for using rc-core V4L/DVB: dvb-usb: get rid of struct dvb_usb_rc_key V4L/DVB: rj54n1cb0c: fix a comment in the driver V4L/DVB: V4L2: sh_vou: VOU does support the full PAL resolution too V4L/DVB: V4L2: sh_mobile_camera_ceu: add support for CSI2 V4L/DVB: V4L2: soc-camera: add a MIPI CSI-2 driver for SH-Mobile platforms V4L/DVB: V4L2: soc-camera: export soc-camera bus type for notifications V4L/DVB: V4L2: mediabus: add 12-bit Bayer and YUV420 pixel formats V4L/DVB: mediabus: fix ambiguous pixel code names ...
This commit is contained in:
commit
f63b759c44
320 changed files with 27755 additions and 31629 deletions
|
@ -12,10 +12,12 @@
|
|||
<othername role="mi">O. C.</othername>
|
||||
<affiliation><address><email>rjkm@metzlerbros.de</email></address></affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Mauro</firstname>
|
||||
<surname>Chehab</surname>
|
||||
<othername role="mi">Carvalho</othername>
|
||||
<surname>Chehab</surname>
|
||||
<affiliation><address><email>mchehab@redhat.com</email></address></affiliation>
|
||||
<contrib>Ported document to Docbook XML.</contrib>
|
||||
</author>
|
||||
|
@ -23,12 +25,23 @@
|
|||
<copyright>
|
||||
<year>2002</year>
|
||||
<year>2003</year>
|
||||
<year>2009</year>
|
||||
<holder>Convergence GmbH</holder>
|
||||
</copyright>
|
||||
<copyright>
|
||||
<year>2009-2010</year>
|
||||
<holder>Mauro Carvalho Chehab</holder>
|
||||
</copyright>
|
||||
|
||||
<revhistory>
|
||||
<!-- Put document revisions here, newest first. -->
|
||||
<revision>
|
||||
<revnumber>2.0.3</revnumber>
|
||||
<date>2010-07-03</date>
|
||||
<authorinitials>mcc</authorinitials>
|
||||
<revremark>
|
||||
Add some frontend capabilities flags, present on kernel, but missing at the specs.
|
||||
</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>2.0.2</revnumber>
|
||||
<date>2009-10-25</date>
|
||||
|
@ -63,7 +76,7 @@ Added ISDB-T test originally written by Patrick Boettcher
|
|||
|
||||
|
||||
<title>LINUX DVB API</title>
|
||||
<subtitle>Version 3</subtitle>
|
||||
<subtitle>Version 5.2</subtitle>
|
||||
<!-- ADD THE CHAPTERS HERE -->
|
||||
<chapter id="dvb_introdution">
|
||||
&sub-intro;
|
||||
|
|
|
@ -63,6 +63,7 @@ typedef enum fe_caps {
|
|||
FE_CAN_8VSB = 0x200000,
|
||||
FE_CAN_16VSB = 0x400000,
|
||||
FE_HAS_EXTENDED_CAPS = 0x800000, /* We need more bitspace for newer APIs, indicate this. */
|
||||
FE_CAN_TURBO_FEC = 0x8000000, /* frontend supports "turbo fec modulation" */
|
||||
FE_CAN_2G_MODULATION = 0x10000000, /* frontend supports "2nd generation modulation" (DVB-S2) */
|
||||
FE_NEEDS_BENDING = 0x20000000, /* not supported anymore, don't use (frontend requires frequency bending) */
|
||||
FE_CAN_RECOVER = 0x40000000, /* frontend can recover from a cable unplug automatically */
|
||||
|
|
|
@ -64,8 +64,14 @@ a specific frontend type.</para>
|
|||
FE_CAN_BANDWIDTH_AUTO = 0x40000,
|
||||
FE_CAN_GUARD_INTERVAL_AUTO = 0x80000,
|
||||
FE_CAN_HIERARCHY_AUTO = 0x100000,
|
||||
FE_CAN_MUTE_TS = 0x80000000,
|
||||
FE_CAN_CLEAN_SETUP = 0x40000000
|
||||
FE_CAN_8VSB = 0x200000,
|
||||
FE_CAN_16VSB = 0x400000,
|
||||
FE_HAS_EXTENDED_CAPS = 0x800000,
|
||||
FE_CAN_TURBO_FEC = 0x8000000,
|
||||
FE_CAN_2G_MODULATION = 0x10000000,
|
||||
FE_NEEDS_BENDING = 0x20000000,
|
||||
FE_CAN_RECOVER = 0x40000000,
|
||||
FE_CAN_MUTE_TS = 0x80000000
|
||||
} fe_caps_t;
|
||||
</programlisting>
|
||||
</section>
|
||||
|
|
|
@ -218,6 +218,7 @@
|
|||
<!ENTITY sub-dev-teletext SYSTEM "v4l/dev-teletext.xml">
|
||||
<!ENTITY sub-driver SYSTEM "v4l/driver.xml">
|
||||
<!ENTITY sub-libv4l SYSTEM "v4l/libv4l.xml">
|
||||
<!ENTITY sub-lirc_device_interface SYSTEM "v4l/lirc_device_interface.xml">
|
||||
<!ENTITY sub-remote_controllers SYSTEM "v4l/remote_controllers.xml">
|
||||
<!ENTITY sub-fdl-appendix SYSTEM "v4l/fdl-appendix.xml">
|
||||
<!ENTITY sub-close SYSTEM "v4l/func-close.xml">
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<title>LINUX MEDIA INFRASTRUCTURE API</title>
|
||||
|
||||
<copyright>
|
||||
<year>2009</year>
|
||||
<year>2009-2010</year>
|
||||
<holder>LinuxTV Developers</holder>
|
||||
</copyright>
|
||||
|
||||
|
@ -61,7 +61,7 @@ Foundation. A copy of the license is included in the chapter entitled
|
|||
in fact it covers several different video standards including
|
||||
DVB-T, DVB-S, DVB-C and ATSC. The API is currently being updated
|
||||
to documment support also for DVB-S2, ISDB-T and ISDB-S.</para>
|
||||
<para>The third part covers other API's used by all media infrastructure devices</para>
|
||||
<para>The third part covers Remote Controller API</para>
|
||||
<para>For additional information and for the latest development code,
|
||||
see: <ulink url="http://linuxtv.org">http://linuxtv.org</ulink>.</para>
|
||||
<para>For discussing improvements, reporting troubles, sending new drivers, etc, please mail to: <ulink url="http://vger.kernel.org/vger-lists.html#linux-media">Linux Media Mailing List (LMML).</ulink>.</para>
|
||||
|
@ -86,7 +86,7 @@ Foundation. A copy of the license is included in the chapter entitled
|
|||
</author>
|
||||
</authorgroup>
|
||||
<copyright>
|
||||
<year>2009</year>
|
||||
<year>2009-2010</year>
|
||||
<holder>Mauro Carvalho Chehab</holder>
|
||||
</copyright>
|
||||
|
||||
|
@ -101,7 +101,7 @@ Foundation. A copy of the license is included in the chapter entitled
|
|||
</revhistory>
|
||||
</partinfo>
|
||||
|
||||
<title>Other API's used by media infrastructure drivers</title>
|
||||
<title>Remote Controller API</title>
|
||||
<chapter id="remote_controllers">
|
||||
&sub-remote_controllers;
|
||||
</chapter>
|
||||
|
|
235
Documentation/DocBook/v4l/lirc_device_interface.xml
Normal file
235
Documentation/DocBook/v4l/lirc_device_interface.xml
Normal file
|
@ -0,0 +1,235 @@
|
|||
<section id="lirc_dev">
|
||||
<title>LIRC Device Interface</title>
|
||||
|
||||
|
||||
<section id="lirc_dev_intro">
|
||||
<title>Introduction</title>
|
||||
|
||||
<para>The LIRC device interface is a bi-directional interface for
|
||||
transporting raw IR data between userspace and kernelspace. Fundamentally,
|
||||
it is just a chardev (/dev/lircX, for X = 0, 1, 2, ...), with a number
|
||||
of standard struct file_operations defined on it. With respect to
|
||||
transporting raw IR data to and fro, the essential fops are read, write
|
||||
and ioctl.</para>
|
||||
|
||||
<para>Example dmesg output upon a driver registering w/LIRC:</para>
|
||||
<blockquote>
|
||||
<para>$ dmesg |grep lirc_dev</para>
|
||||
<para>lirc_dev: IR Remote Control driver registered, major 248</para>
|
||||
<para>rc rc0: lirc_dev: driver ir-lirc-codec (mceusb) registered at minor = 0</para>
|
||||
</blockquote>
|
||||
|
||||
<para>What you should see for a chardev:</para>
|
||||
<blockquote>
|
||||
<para>$ ls -l /dev/lirc*</para>
|
||||
<para>crw-rw---- 1 root root 248, 0 Jul 2 22:20 /dev/lirc0</para>
|
||||
</blockquote>
|
||||
</section>
|
||||
|
||||
<section id="lirc_read">
|
||||
<title>LIRC read fop</title>
|
||||
|
||||
<para>The lircd userspace daemon reads raw IR data from the LIRC chardev. The
|
||||
exact format of the data depends on what modes a driver supports, and what
|
||||
mode has been selected. lircd obtains supported modes and sets the active mode
|
||||
via the ioctl interface, detailed at <xref linkend="lirc_ioctl"/>. The generally
|
||||
preferred mode is LIRC_MODE_MODE2, in which packets containing an int value
|
||||
describing an IR signal are read from the chardev.</para>
|
||||
|
||||
<para>See also <ulink url="http://www.lirc.org/html/technical.html">http://www.lirc.org/html/technical.html</ulink> for more info.</para>
|
||||
</section>
|
||||
|
||||
<section id="lirc_write">
|
||||
<title>LIRC write fop</title>
|
||||
|
||||
<para>The data written to the chardev is a pulse/space sequence of integer
|
||||
values. Pulses and spaces are only marked implicitly by their position. The
|
||||
data must start and end with a pulse, therefore, the data must always include
|
||||
an unevent number of samples. The write function must block until the data has
|
||||
been transmitted by the hardware.</para>
|
||||
</section>
|
||||
|
||||
<section id="lirc_ioctl">
|
||||
<title>LIRC ioctl fop</title>
|
||||
|
||||
<para>The LIRC device's ioctl definition is bound by the ioctl function
|
||||
definition of struct file_operations, leaving us with an unsigned int
|
||||
for the ioctl command and an unsigned long for the arg. For the purposes
|
||||
of ioctl portability across 32-bit and 64-bit, these values are capped
|
||||
to their 32-bit sizes.</para>
|
||||
|
||||
<para>The following ioctls can be used to change specific hardware settings.
|
||||
In general each driver should have a default set of settings. The driver
|
||||
implementation is expected to re-apply the default settings when the device
|
||||
is closed by user-space, so that every application opening the device can rely
|
||||
on working with the default settings initially.</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>LIRC_GET_FEATURES</term>
|
||||
<listitem>
|
||||
<para>Obviously, get the underlying hardware device's features. If a driver
|
||||
does not announce support of certain features, calling of the corresponding
|
||||
ioctls is undefined.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_GET_SEND_MODE</term>
|
||||
<listitem>
|
||||
<para>Get supported transmit mode. Only LIRC_MODE_PULSE is supported by lircd.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_GET_REC_MODE</term>
|
||||
<listitem>
|
||||
<para>Get supported receive modes. Only LIRC_MODE_MODE2 and LIRC_MODE_LIRCCODE
|
||||
are supported by lircd.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_GET_SEND_CARRIER</term>
|
||||
<listitem>
|
||||
<para>Get carrier frequency (in Hz) currently used for transmit.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_GET_REC_CARRIER</term>
|
||||
<listitem>
|
||||
<para>Get carrier frequency (in Hz) currently used for IR reception.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_{G,S}ET_{SEND,REC}_DUTY_CYCLE</term>
|
||||
<listitem>
|
||||
<para>Get/set the duty cycle (from 0 to 100) of the carrier signal. Currently,
|
||||
no special meaning is defined for 0 or 100, but this could be used to switch
|
||||
off carrier generation in the future, so these values should be reserved.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_GET_REC_RESOLUTION</term>
|
||||
<listitem>
|
||||
<para>Some receiver have maximum resolution which is defined by internal
|
||||
sample rate or data format limitations. E.g. it's common that signals can
|
||||
only be reported in 50 microsecond steps. This integer value is used by
|
||||
lircd to automatically adjust the aeps tolerance value in the lircd
|
||||
config file.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_GET_M{IN,AX}_TIMEOUT</term>
|
||||
<listitem>
|
||||
<para>Some devices have internal timers that can be used to detect when
|
||||
there's no IR activity for a long time. This can help lircd in detecting
|
||||
that a IR signal is finished and can speed up the decoding process.
|
||||
Returns an integer value with the minimum/maximum timeout that can be
|
||||
set. Some devices have a fixed timeout, in that case both ioctls will
|
||||
return the same value even though the timeout cannot be changed.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_GET_M{IN,AX}_FILTER_{PULSE,SPACE}</term>
|
||||
<listitem>
|
||||
<para>Some devices are able to filter out spikes in the incoming signal
|
||||
using given filter rules. These ioctls return the hardware capabilities
|
||||
that describe the bounds of the possible filters. Filter settings depend
|
||||
on the IR protocols that are expected. lircd derives the settings from
|
||||
all protocols definitions found in its config file.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_GET_LENGTH</term>
|
||||
<listitem>
|
||||
<para>Retrieves the code length in bits (only for LIRC_MODE_LIRCCODE).
|
||||
Reads on the device must be done in blocks matching the bit count.
|
||||
The bit could should be rounded up so that it matches full bytes.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_SET_{SEND,REC}_MODE</term>
|
||||
<listitem>
|
||||
<para>Set send/receive mode. Largely obsolete for send, as only
|
||||
LIRC_MODE_PULSE is supported.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_SET_{SEND,REC}_CARRIER</term>
|
||||
<listitem>
|
||||
<para>Set send/receive carrier (in Hz).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_SET_TRANSMITTER_MASK</term>
|
||||
<listitem>
|
||||
<para>This enables the given set of transmitters. The first transmitter
|
||||
is encoded by the least significant bit, etc. When an invalid bit mask
|
||||
is given, i.e. a bit is set, even though the device does not have so many
|
||||
transitters, then this ioctl returns the number of available transitters
|
||||
and does nothing otherwise.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_SET_REC_TIMEOUT</term>
|
||||
<listitem>
|
||||
<para>Sets the integer value for IR inactivity timeout (cf.
|
||||
LIRC_GET_MIN_TIMEOUT and LIRC_GET_MAX_TIMEOUT). A value of 0 (if
|
||||
supported by the hardware) disables all hardware timeouts and data should
|
||||
be reported as soon as possible. If the exact value cannot be set, then
|
||||
the next possible value _greater_ than the given value should be set.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_SET_REC_TIMEOUT_REPORTS</term>
|
||||
<listitem>
|
||||
<para>Enable (1) or disable (0) timeout reports in LIRC_MODE_MODE2. By
|
||||
default, timeout reports should be turned off.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_SET_REC_FILTER_{,PULSE,SPACE}</term>
|
||||
<listitem>
|
||||
<para>Pulses/spaces shorter than this are filtered out by hardware. If
|
||||
filters cannot be set independently for pulse/space, the corresponding
|
||||
ioctls must return an error and LIRC_SET_REC_FILTER shall be used instead.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_SET_MEASURE_CARRIER_MODE</term>
|
||||
<listitem>
|
||||
<para>Enable (1)/disable (0) measure mode. If enabled, from the next key
|
||||
press on, the driver will send LIRC_MODE2_FREQUENCY packets. By default
|
||||
this should be turned off.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_SET_REC_{DUTY_CYCLE,CARRIER}_RANGE</term>
|
||||
<listitem>
|
||||
<para>To set a range use LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE
|
||||
with the lower bound first and later LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER
|
||||
with the upper bound.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_NOTIFY_DECODE</term>
|
||||
<listitem>
|
||||
<para>This ioctl is called by lircd whenever a successful decoding of an
|
||||
incoming IR signal could be done. This can be used by supporting hardware
|
||||
to give visual feedback to the user e.g. by flashing a LED.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_SETUP_{START,END}</term>
|
||||
<listitem>
|
||||
<para>Setting of several driver parameters can be optimized by encapsulating
|
||||
the according ioctl calls with LIRC_SETUP_START/LIRC_SETUP_END. When a
|
||||
driver receives a LIRC_SETUP_START ioctl it can choose to not commit
|
||||
further setting changes to the hardware until a LIRC_SETUP_END is received.
|
||||
But this is open to the driver implementation and every driver must also
|
||||
handle parameter changes which are not encapsulated by LIRC_SETUP_START
|
||||
and LIRC_SETUP_END. Drivers can also choose to ignore these ioctls.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
</section>
|
|
@ -173,3 +173,5 @@ keymapping.</para>
|
|||
<para>This program demonstrates how to replace the keymap tables.</para>
|
||||
&sub-keytable-c;
|
||||
</section>
|
||||
|
||||
&sub-lirc_device_interface;
|
||||
|
|
|
@ -26,7 +26,7 @@ use IO::Handle;
|
|||
"dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004",
|
||||
"or51211", "or51132_qam", "or51132_vsb", "bluebird",
|
||||
"opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718",
|
||||
"af9015", "ngene");
|
||||
"af9015", "ngene", "az6027");
|
||||
|
||||
# Check args
|
||||
syntax() if (scalar(@ARGV) != 1);
|
||||
|
@ -518,11 +518,11 @@ sub bluebird {
|
|||
sub af9015 {
|
||||
my $sourcefile = "download.ashx?file=57";
|
||||
my $url = "http://www.ite.com.tw/EN/Services/$sourcefile";
|
||||
my $hash = "ff5b096ed47c080870eacdab2de33ad6";
|
||||
my $hash = "e3f08935158038d385ad382442f4bb2d";
|
||||
my $outfile = "dvb-usb-af9015.fw";
|
||||
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
|
||||
my $fwoffset = 0x22708;
|
||||
my $fwlength = 18225;
|
||||
my $fwoffset = 0x25690;
|
||||
my $fwlength = 18725;
|
||||
my ($chunklength, $buf, $rcount);
|
||||
|
||||
checkstandard();
|
||||
|
@ -567,6 +567,23 @@ sub ngene {
|
|||
"$file1, $file2";
|
||||
}
|
||||
|
||||
sub az6027{
|
||||
my $file = "AZ6027_Linux_Driver.tar.gz";
|
||||
my $url = "http://linux.terratec.de/files/$file";
|
||||
my $firmware = "dvb-usb-az6027-03.fw";
|
||||
|
||||
wgetfile($file, $url);
|
||||
|
||||
#untar
|
||||
if( system("tar xzvf $file $firmware")){
|
||||
die "failed to untar firmware";
|
||||
}
|
||||
if( system("rm $file")){
|
||||
die ("unable to remove unnecessary files");
|
||||
}
|
||||
|
||||
$firmware;
|
||||
}
|
||||
# ---------------------------------------------------------------
|
||||
# Utilities
|
||||
|
||||
|
|
|
@ -459,57 +459,6 @@ Who: Corentin Chary <corentin.chary@gmail.com>
|
|||
|
||||
----------------------------
|
||||
|
||||
What: usbvideo quickcam_messenger driver
|
||||
When: 2.6.35
|
||||
Files: drivers/media/video/usbvideo/quickcam_messenger.[ch]
|
||||
Why: obsolete v4l1 driver replaced by gspca_stv06xx
|
||||
Who: Hans de Goede <hdegoede@redhat.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: ov511 v4l1 driver
|
||||
When: 2.6.35
|
||||
Files: drivers/media/video/ov511.[ch]
|
||||
Why: obsolete v4l1 driver replaced by gspca_ov519
|
||||
Who: Hans de Goede <hdegoede@redhat.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: w9968cf v4l1 driver
|
||||
When: 2.6.35
|
||||
Files: drivers/media/video/w9968cf*.[ch]
|
||||
Why: obsolete v4l1 driver replaced by gspca_ov519
|
||||
Who: Hans de Goede <hdegoede@redhat.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: ovcamchip sensor framework
|
||||
When: 2.6.35
|
||||
Files: drivers/media/video/ovcamchip/*
|
||||
Why: Only used by obsoleted v4l1 drivers
|
||||
Who: Hans de Goede <hdegoede@redhat.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: stv680 v4l1 driver
|
||||
When: 2.6.35
|
||||
Files: drivers/media/video/stv680.[ch]
|
||||
Why: obsolete v4l1 driver replaced by gspca_stv0680
|
||||
Who: Hans de Goede <hdegoede@redhat.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: zc0301 v4l driver
|
||||
When: 2.6.35
|
||||
Files: drivers/media/video/zc0301/*
|
||||
Why: Duplicate functionality with the gspca_zc3xx driver, zc0301 only
|
||||
supports 2 USB-ID's (because it only supports a limited set of
|
||||
sensors) wich are also supported by the gspca_zc3xx driver
|
||||
(which supports 53 USB-ID's in total)
|
||||
Who: Hans de Goede <hdegoede@redhat.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: sysfs-class-rfkill state file
|
||||
When: Feb 2014
|
||||
Files: net/rfkill/core.c
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
16 -> DVBWorld DVB-S2 2005 [0001:2005]
|
||||
17 -> NetUP Dual DVB-S2 CI [1b55:2a2c]
|
||||
18 -> Hauppauge WinTV-HVR1270 [0070:2211]
|
||||
19 -> Hauppauge WinTV-HVR1275 [0070:2215]
|
||||
20 -> Hauppauge WinTV-HVR1255 [0070:2251]
|
||||
21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295]
|
||||
19 -> Hauppauge WinTV-HVR1275 [0070:2215,0070:221d,0070:22f2]
|
||||
20 -> Hauppauge WinTV-HVR1255 [0070:2251,0070:2259,0070:22f1]
|
||||
21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295,0070:2299,0070:229d,0070:22f0,0070:22f3,0070:22f4,0070:22f5]
|
||||
22 -> Mygica X8506 DMB-TH [14f1:8651]
|
||||
23 -> Magic-Pro ProHDTV Extreme 2 [14f1:8657]
|
||||
24 -> Hauppauge WinTV-HVR1850 [0070:8541]
|
||||
|
|
|
@ -72,3 +72,4 @@
|
|||
73 -> Reddo DVB-C USB TV Box (em2870)
|
||||
74 -> Actionmaster/LinXcel/Digitus VC211A (em2800)
|
||||
75 -> Dikom DK300 (em2882)
|
||||
76 -> KWorld PlusTV 340U or UB435-Q (ATSC) (em2870) [1b80:a340]
|
||||
|
|
|
@ -178,4 +178,5 @@
|
|||
177 -> Hawell HW-404M7
|
||||
178 -> Beholder BeholdTV H7 [5ace:7190]
|
||||
179 -> Beholder BeholdTV A7 [5ace:7090]
|
||||
180 -> Avermedia M733A [1461:4155,1461:4255]
|
||||
180 -> Avermedia PCI M733A [1461:4155,1461:4255]
|
||||
181 -> TechoTrend TT-budget T-3000 [13c2:2804]
|
||||
|
|
|
@ -29,8 +29,12 @@ zc3xx 041e:4029 Creative WebCam Vista Pro
|
|||
zc3xx 041e:4034 Creative Instant P0620
|
||||
zc3xx 041e:4035 Creative Instant P0620D
|
||||
zc3xx 041e:4036 Creative Live !
|
||||
sq930x 041e:4038 Creative Joy-IT
|
||||
zc3xx 041e:403a Creative Nx Pro 2
|
||||
spca561 041e:403b Creative Webcam Vista (VF0010)
|
||||
sq930x 041e:403c Creative Live! Ultra
|
||||
sq930x 041e:403d Creative Live! Ultra for Notebooks
|
||||
sq930x 041e:4041 Creative Live! Motion
|
||||
zc3xx 041e:4051 Creative Live!Cam Notebook Pro (VF0250)
|
||||
ov519 041e:4052 Creative Live! VISTA IM
|
||||
zc3xx 041e:4053 Creative Live!Cam Video IM
|
||||
|
@ -138,6 +142,7 @@ finepix 04cb:013d Fujifilm FinePix unknown model
|
|||
finepix 04cb:013f Fujifilm FinePix F420
|
||||
sunplus 04f1:1001 JVC GC A50
|
||||
spca561 04fc:0561 Flexcam 100
|
||||
spca1528 04fc:1528 Sunplus MD80 clone
|
||||
sunplus 04fc:500c Sunplus CA500C
|
||||
sunplus 04fc:504a Aiptek Mini PenCam 1.3
|
||||
sunplus 04fc:504b Maxell MaxPocket LE 1.3
|
||||
|
@ -253,6 +258,7 @@ pac7302 093a:2620 Apollo AC-905
|
|||
pac7302 093a:2621 PAC731x
|
||||
pac7302 093a:2622 Genius Eye 312
|
||||
pac7302 093a:2624 PAC7302
|
||||
pac7302 093a:2625 Genius iSlim 310
|
||||
pac7302 093a:2626 Labtec 2200
|
||||
pac7302 093a:2628 Genius iLook 300
|
||||
pac7302 093a:2629 Genious iSlim 300
|
||||
|
@ -362,6 +368,8 @@ sq905c 2770:9052 Disney pix micro 2 (VGA)
|
|||
sq905c 2770:905c All 11 known cameras with this ID
|
||||
sq905 2770:9120 All 24 known cameras with this ID
|
||||
sq905c 2770:913d All 4 known cameras with this ID
|
||||
sq930x 2770:930b Sweex Motion Tracking / I-Tec iCam Tracer
|
||||
sq930x 2770:930c Trust WB-3500T / NSG Robbie 2.0
|
||||
spca500 2899:012c Toptro Industrial
|
||||
ov519 8020:ef04 ov519
|
||||
spca508 8086:0110 Intel Easy PC Camera
|
||||
|
|
|
@ -316,7 +316,7 @@ static struct soc_camera_platform_info camera_info = {
|
|||
.format_name = "UYVY",
|
||||
.format_depth = 16,
|
||||
.format = {
|
||||
.code = V4L2_MBUS_FMT_YUYV8_2X8_BE,
|
||||
.code = V4L2_MBUS_FMT_UYVY8_2X8,
|
||||
.colorspace = V4L2_COLORSPACE_SMPTE170M,
|
||||
.field = V4L2_FIELD_NONE,
|
||||
.width = 640,
|
||||
|
|
|
@ -8,6 +8,17 @@ config VIDEO_IR
|
|||
depends on IR_CORE
|
||||
default IR_CORE
|
||||
|
||||
config LIRC
|
||||
tristate
|
||||
default y
|
||||
|
||||
---help---
|
||||
Enable this option to build the Linux Infrared Remote
|
||||
Control (LIRC) core device interface driver. The LIRC
|
||||
interface passes raw IR to and from userspace, where the
|
||||
LIRC daemon handles protocol decoding for IR reception ann
|
||||
encoding for IR transmitting (aka "blasting").
|
||||
|
||||
source "drivers/media/IR/keymaps/Kconfig"
|
||||
|
||||
config IR_NEC_DECODER
|
||||
|
@ -33,6 +44,7 @@ config IR_RC5_DECODER
|
|||
config IR_RC6_DECODER
|
||||
tristate "Enable IR raw decoder for the RC6 protocol"
|
||||
depends on IR_CORE
|
||||
select BITREVERSE
|
||||
default y
|
||||
|
||||
---help---
|
||||
|
@ -42,6 +54,7 @@ config IR_RC6_DECODER
|
|||
config IR_JVC_DECODER
|
||||
tristate "Enable IR raw decoder for the JVC protocol"
|
||||
depends on IR_CORE
|
||||
select BITREVERSE
|
||||
default y
|
||||
|
||||
---help---
|
||||
|
@ -57,6 +70,16 @@ 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_LIRC_CODEC
|
||||
tristate "Enable IR to LIRC bridge"
|
||||
depends on IR_CORE
|
||||
depends on LIRC
|
||||
default y
|
||||
|
||||
---help---
|
||||
Enable this option to pass raw IR to and from userspace via
|
||||
the LIRC interface.
|
||||
|
||||
config IR_IMON
|
||||
tristate "SoundGraph iMON Receiver and Display"
|
||||
depends on USB_ARCH_HAS_HCD
|
||||
|
@ -68,3 +91,15 @@ config IR_IMON
|
|||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imon.
|
||||
|
||||
config IR_MCEUSB
|
||||
tristate "Windows Media Center Ed. eHome Infrared Transceiver"
|
||||
depends on USB_ARCH_HAS_HCD
|
||||
depends on IR_CORE
|
||||
select USB
|
||||
---help---
|
||||
Say Y here if you want to use a Windows Media Center Edition
|
||||
eHome Infrared Transceiver.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called mceusb.
|
||||
|
|
|
@ -5,11 +5,14 @@ obj-y += keymaps/
|
|||
|
||||
obj-$(CONFIG_IR_CORE) += ir-core.o
|
||||
obj-$(CONFIG_VIDEO_IR) += ir-common.o
|
||||
obj-$(CONFIG_LIRC) += lirc_dev.o
|
||||
obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
|
||||
obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
|
||||
obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
|
||||
obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
|
||||
obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-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
|
||||
|
|
|
@ -407,7 +407,7 @@ static int display_close(struct inode *inode, struct file *file)
|
|||
struct imon_context *ictx = NULL;
|
||||
int retval = 0;
|
||||
|
||||
ictx = (struct imon_context *)file->private_data;
|
||||
ictx = file->private_data;
|
||||
|
||||
if (!ictx) {
|
||||
err("%s: no context for device", __func__);
|
||||
|
@ -812,7 +812,7 @@ static ssize_t vfd_write(struct file *file, const char *buf,
|
|||
const unsigned char vfd_packet6[] = {
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
|
||||
|
||||
ictx = (struct imon_context *)file->private_data;
|
||||
ictx = file->private_data;
|
||||
if (!ictx) {
|
||||
err("%s: no context for device", __func__);
|
||||
return -ENODEV;
|
||||
|
@ -896,7 +896,7 @@ static ssize_t lcd_write(struct file *file, const char *buf,
|
|||
int retval = 0;
|
||||
struct imon_context *ictx;
|
||||
|
||||
ictx = (struct imon_context *)file->private_data;
|
||||
ictx = file->private_data;
|
||||
if (!ictx) {
|
||||
err("%s: no context for device", __func__);
|
||||
return -ENODEV;
|
||||
|
@ -1943,7 +1943,7 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
|
|||
return ictx;
|
||||
|
||||
urb_submit_failed:
|
||||
input_unregister_device(ictx->idev);
|
||||
ir_input_unregister(ictx->idev);
|
||||
input_free_device(ictx->idev);
|
||||
idev_setup_failed:
|
||||
find_endpoint_failed:
|
||||
|
@ -2067,6 +2067,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
|
|||
detected_display_type = IMON_DISPLAY_TYPE_VFD;
|
||||
break;
|
||||
/* iMON LCD, MCE IR */
|
||||
case 0x9e:
|
||||
case 0x9f:
|
||||
dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
|
||||
detected_display_type = IMON_DISPLAY_TYPE_LCD;
|
||||
|
@ -2306,7 +2307,7 @@ static void __devexit imon_disconnect(struct usb_interface *interface)
|
|||
if (ifnum == 0) {
|
||||
ictx->dev_present_intf0 = false;
|
||||
usb_kill_urb(ictx->rx_urb_intf0);
|
||||
input_unregister_device(ictx->idev);
|
||||
ir_input_unregister(ictx->idev);
|
||||
if (ictx->display_supported) {
|
||||
if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
|
||||
usb_deregister_dev(interface, &imon_lcd_class);
|
||||
|
|
|
@ -22,17 +22,62 @@
|
|||
struct ir_raw_handler {
|
||||
struct list_head list;
|
||||
|
||||
u64 protocols; /* which are handled by this handler */
|
||||
int (*decode)(struct input_dev *input_dev, struct ir_raw_event event);
|
||||
|
||||
/* These two should only be used by the lirc decoder */
|
||||
int (*raw_register)(struct input_dev *input_dev);
|
||||
int (*raw_unregister)(struct input_dev *input_dev);
|
||||
};
|
||||
|
||||
struct ir_raw_event_ctrl {
|
||||
struct list_head list; /* to keep track of raw clients */
|
||||
struct work_struct rx_work; /* for the rx decoding workqueue */
|
||||
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 */
|
||||
struct input_dev *input_dev; /* pointer to the parent input_dev */
|
||||
u64 enabled_protocols; /* enabled raw protocol decoders */
|
||||
|
||||
/* raw decoder state follows */
|
||||
struct ir_raw_event prev_ev;
|
||||
struct nec_dec {
|
||||
int state;
|
||||
unsigned count;
|
||||
u32 bits;
|
||||
} nec;
|
||||
struct rc5_dec {
|
||||
int state;
|
||||
u32 bits;
|
||||
unsigned count;
|
||||
unsigned wanted_bits;
|
||||
} rc5;
|
||||
struct rc6_dec {
|
||||
int state;
|
||||
u8 header;
|
||||
u32 body;
|
||||
bool toggle;
|
||||
unsigned count;
|
||||
unsigned wanted_bits;
|
||||
} rc6;
|
||||
struct sony_dec {
|
||||
int state;
|
||||
u32 bits;
|
||||
unsigned count;
|
||||
} sony;
|
||||
struct jvc_dec {
|
||||
int state;
|
||||
u16 bits;
|
||||
u16 old_bits;
|
||||
unsigned count;
|
||||
bool first;
|
||||
bool toggle;
|
||||
} jvc;
|
||||
struct lirc_codec {
|
||||
struct ir_input_dev *ir_dev;
|
||||
struct lirc_driver *drv;
|
||||
int lircdata;
|
||||
} lirc;
|
||||
};
|
||||
|
||||
/* macros for IR decoders */
|
||||
|
@ -74,6 +119,7 @@ void ir_unregister_class(struct input_dev *input_dev);
|
|||
/*
|
||||
* Routines from ir-raw-event.c to be used internally and by decoders
|
||||
*/
|
||||
u64 ir_raw_get_allowed_protocols(void);
|
||||
int ir_raw_event_register(struct input_dev *input_dev);
|
||||
void ir_raw_event_unregister(struct input_dev *input_dev);
|
||||
int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
|
||||
|
@ -123,4 +169,12 @@ void ir_raw_init(void);
|
|||
#define load_sony_decode() 0
|
||||
#endif
|
||||
|
||||
/* from ir-lirc-codec.c */
|
||||
#ifdef CONFIG_IR_LIRC_CODEC_MODULE
|
||||
#define load_lirc_codec() request_module("ir-lirc-codec")
|
||||
#else
|
||||
#define load_lirc_codec() 0
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _IR_RAW_EVENT */
|
||||
|
|
|
@ -25,10 +25,6 @@
|
|||
#define JVC_TRAILER_PULSE (1 * JVC_UNIT)
|
||||
#define JVC_TRAILER_SPACE (35 * JVC_UNIT)
|
||||
|
||||
/* Used to register jvc_decoder clients */
|
||||
static LIST_HEAD(decoder_list);
|
||||
DEFINE_SPINLOCK(decoder_lock);
|
||||
|
||||
enum jvc_state {
|
||||
STATE_INACTIVE,
|
||||
STATE_HEADER_SPACE,
|
||||
|
@ -38,87 +34,6 @@ enum jvc_state {
|
|||
STATE_TRAILER_SPACE,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int enabled:1;
|
||||
|
||||
/* State machine control */
|
||||
enum jvc_state state;
|
||||
u16 jvc_bits;
|
||||
u16 jvc_old_bits;
|
||||
unsigned count;
|
||||
bool first;
|
||||
bool toggle;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* get_decoder_data() - gets decoder data
|
||||
* @input_dev: input device
|
||||
*
|
||||
* Returns the struct decoder_data that corresponds to a device
|
||||
*/
|
||||
static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
||||
{
|
||||
struct decoder_data *data = NULL;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_for_each_entry(data, &decoder_list, list) {
|
||||
if (data->ir_dev == ir_dev)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&decoder_lock);
|
||||
return data;
|
||||
}
|
||||
|
||||
static ssize_t store_enabled(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
unsigned long value;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (strict_strtoul(buf, 10, &value) || value > 1)
|
||||
return -EINVAL;
|
||||
|
||||
data->enabled = value;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_enabled(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (data->enabled)
|
||||
return sprintf(buf, "1\n");
|
||||
else
|
||||
return sprintf(buf, "0\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
|
||||
|
||||
static struct attribute *decoder_attributes[] = {
|
||||
&dev_attr_enabled.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group decoder_attribute_group = {
|
||||
.name = "jvc_decoder",
|
||||
.attrs = decoder_attributes,
|
||||
};
|
||||
|
||||
/**
|
||||
* ir_jvc_decode() - Decode one JVC pulse or space
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
|
@ -128,14 +43,10 @@ static struct attribute_group decoder_attribute_group = {
|
|||
*/
|
||||
static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
{
|
||||
struct decoder_data *data;
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct jvc_dec *data = &ir_dev->raw->jvc;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!data->enabled)
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
|
@ -188,9 +99,9 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (ev.pulse)
|
||||
break;
|
||||
|
||||
data->jvc_bits <<= 1;
|
||||
data->bits <<= 1;
|
||||
if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) {
|
||||
data->jvc_bits |= 1;
|
||||
data->bits |= 1;
|
||||
decrease_duration(&ev, JVC_BIT_1_SPACE);
|
||||
} else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2))
|
||||
decrease_duration(&ev, JVC_BIT_0_SPACE);
|
||||
|
@ -223,13 +134,13 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
|
||||
if (data->first) {
|
||||
u32 scancode;
|
||||
scancode = (bitrev8((data->jvc_bits >> 8) & 0xff) << 8) |
|
||||
(bitrev8((data->jvc_bits >> 0) & 0xff) << 0);
|
||||
scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) |
|
||||
(bitrev8((data->bits >> 0) & 0xff) << 0);
|
||||
IR_dprintk(1, "JVC scancode 0x%04x\n", scancode);
|
||||
ir_keydown(input_dev, scancode, data->toggle);
|
||||
data->first = false;
|
||||
data->jvc_old_bits = data->jvc_bits;
|
||||
} else if (data->jvc_bits == data->jvc_old_bits) {
|
||||
data->old_bits = data->bits;
|
||||
} else if (data->bits == data->old_bits) {
|
||||
IR_dprintk(1, "JVC repeat\n");
|
||||
ir_repeat(input_dev);
|
||||
} else {
|
||||
|
@ -249,54 +160,9 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ir_jvc_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct decoder_data *data;
|
||||
int rc;
|
||||
|
||||
rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
data->enabled = 1;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_add_tail(&data->list, &decoder_list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir_jvc_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
static struct decoder_data *data;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler jvc_handler = {
|
||||
.protocols = IR_TYPE_JVC,
|
||||
.decode = ir_jvc_decode,
|
||||
.raw_register = ir_jvc_register,
|
||||
.raw_unregister = ir_jvc_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_jvc_decode_init(void)
|
||||
|
|
|
@ -497,8 +497,9 @@ int __ir_input_register(struct input_dev *input_dev,
|
|||
goto out_event;
|
||||
}
|
||||
|
||||
IR_dprintk(1, "Registered input device on %s for %s remote.\n",
|
||||
driver_name, rc_tab->name);
|
||||
IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
|
||||
driver_name, rc_tab->name,
|
||||
ir_dev->props->driver_type == RC_DRIVER_IR_RAW ? " in raw mode" : "");
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
278
drivers/media/IR/ir-lirc-codec.c
Normal file
278
drivers/media/IR/ir-lirc-codec.c
Normal file
|
@ -0,0 +1,278 @@
|
|||
/* ir-lirc-codec.c - ir-core to classic lirc interface bridge
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <media/lirc.h>
|
||||
#include <media/lirc_dev.h>
|
||||
#include <media/ir-core.h>
|
||||
#include "ir-core-priv.h"
|
||||
|
||||
#define LIRCBUF_SIZE 256
|
||||
|
||||
/**
|
||||
* ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the
|
||||
* lircd userspace daemon for decoding.
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
* @duration: the struct ir_raw_event descriptor of the pulse/space
|
||||
*
|
||||
* This function returns -EINVAL if the lirc interfaces aren't wired up.
|
||||
*/
|
||||
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);
|
||||
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
|
||||
return 0;
|
||||
|
||||
if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
|
||||
return -EINVAL;
|
||||
|
||||
IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
|
||||
TO_US(ev.duration), TO_STR(ev.pulse));
|
||||
|
||||
ir_dev->raw->lirc.lircdata += ev.duration / 1000;
|
||||
if (ev.pulse)
|
||||
ir_dev->raw->lirc.lircdata |= PULSE_BIT;
|
||||
|
||||
lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
|
||||
(unsigned char *) &ir_dev->raw->lirc.lircdata);
|
||||
wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
|
||||
|
||||
ir_dev->raw->lirc.lircdata = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,
|
||||
size_t n, loff_t *ppos)
|
||||
{
|
||||
struct lirc_codec *lirc;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int *txbuf; /* buffer with values to transmit */
|
||||
int ret = 0, count;
|
||||
|
||||
lirc = lirc_get_pdata(file);
|
||||
if (!lirc)
|
||||
return -EFAULT;
|
||||
|
||||
if (n % sizeof(int))
|
||||
return -EINVAL;
|
||||
|
||||
count = n / sizeof(int);
|
||||
if (count > LIRCBUF_SIZE || count % 2 == 0)
|
||||
return -EINVAL;
|
||||
|
||||
txbuf = memdup_user(buf, n);
|
||||
if (IS_ERR(txbuf))
|
||||
return PTR_ERR(txbuf);
|
||||
|
||||
ir_dev = lirc->ir_dev;
|
||||
if (!ir_dev) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ir_dev->props && ir_dev->props->tx_ir)
|
||||
ret = ir_dev->props->tx_ir(ir_dev->props->priv, txbuf, (u32)n);
|
||||
|
||||
out:
|
||||
kfree(txbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct lirc_codec *lirc;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int ret = 0;
|
||||
void *drv_data;
|
||||
unsigned long val;
|
||||
|
||||
lirc = lirc_get_pdata(filep);
|
||||
if (!lirc)
|
||||
return -EFAULT;
|
||||
|
||||
ir_dev = lirc->ir_dev;
|
||||
if (!ir_dev || !ir_dev->props || !ir_dev->props->priv)
|
||||
return -EFAULT;
|
||||
|
||||
drv_data = ir_dev->props->priv;
|
||||
|
||||
switch (cmd) {
|
||||
case LIRC_SET_TRANSMITTER_MASK:
|
||||
ret = get_user(val, (unsigned long *)arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ir_dev->props && ir_dev->props->s_tx_mask)
|
||||
ret = ir_dev->props->s_tx_mask(drv_data, (u32)val);
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case LIRC_SET_SEND_CARRIER:
|
||||
ret = get_user(val, (unsigned long *)arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ir_dev->props && ir_dev->props->s_tx_carrier)
|
||||
ir_dev->props->s_tx_carrier(drv_data, (u32)val);
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case LIRC_GET_SEND_MODE:
|
||||
val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
|
||||
ret = put_user(val, (unsigned long *)arg);
|
||||
break;
|
||||
|
||||
case LIRC_SET_SEND_MODE:
|
||||
ret = get_user(val, (unsigned long *)arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
return lirc_dev_fop_ioctl(filep, cmd, arg);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ir_lirc_open(void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ir_lirc_close(void *data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static struct file_operations lirc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.write = ir_lirc_transmit_ir,
|
||||
.unlocked_ioctl = ir_lirc_ioctl,
|
||||
.read = lirc_dev_fop_read,
|
||||
.poll = lirc_dev_fop_poll,
|
||||
.open = lirc_dev_fop_open,
|
||||
.release = lirc_dev_fop_close,
|
||||
};
|
||||
|
||||
static int ir_lirc_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct lirc_driver *drv;
|
||||
struct lirc_buffer *rbuf;
|
||||
int rc = -ENOMEM;
|
||||
unsigned long features;
|
||||
|
||||
drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
|
||||
if (!drv)
|
||||
return rc;
|
||||
|
||||
rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
|
||||
if (!rbuf)
|
||||
goto rbuf_alloc_failed;
|
||||
|
||||
rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE);
|
||||
if (rc)
|
||||
goto rbuf_init_failed;
|
||||
|
||||
features = LIRC_CAN_REC_MODE2;
|
||||
if (ir_dev->props->tx_ir) {
|
||||
features |= LIRC_CAN_SEND_PULSE;
|
||||
if (ir_dev->props->s_tx_mask)
|
||||
features |= LIRC_CAN_SET_TRANSMITTER_MASK;
|
||||
if (ir_dev->props->s_tx_carrier)
|
||||
features |= LIRC_CAN_SET_SEND_CARRIER;
|
||||
}
|
||||
|
||||
snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
|
||||
ir_dev->driver_name);
|
||||
drv->minor = -1;
|
||||
drv->features = features;
|
||||
drv->data = &ir_dev->raw->lirc;
|
||||
drv->rbuf = rbuf;
|
||||
drv->set_use_inc = &ir_lirc_open;
|
||||
drv->set_use_dec = &ir_lirc_close;
|
||||
drv->code_length = sizeof(struct ir_raw_event) * 8;
|
||||
drv->fops = &lirc_fops;
|
||||
drv->dev = &ir_dev->dev;
|
||||
drv->owner = THIS_MODULE;
|
||||
|
||||
drv->minor = lirc_register_driver(drv);
|
||||
if (drv->minor < 0) {
|
||||
rc = -ENODEV;
|
||||
goto lirc_register_failed;
|
||||
}
|
||||
|
||||
ir_dev->raw->lirc.drv = drv;
|
||||
ir_dev->raw->lirc.ir_dev = ir_dev;
|
||||
ir_dev->raw->lirc.lircdata = PULSE_MASK;
|
||||
|
||||
return 0;
|
||||
|
||||
lirc_register_failed:
|
||||
rbuf_init_failed:
|
||||
kfree(rbuf);
|
||||
rbuf_alloc_failed:
|
||||
kfree(drv);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ir_lirc_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct lirc_codec *lirc = &ir_dev->raw->lirc;
|
||||
|
||||
lirc_unregister_driver(lirc->drv->minor);
|
||||
lirc_buffer_free(lirc->drv->rbuf);
|
||||
kfree(lirc->drv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler lirc_handler = {
|
||||
.protocols = IR_TYPE_LIRC,
|
||||
.decode = ir_lirc_decode,
|
||||
.raw_register = ir_lirc_register,
|
||||
.raw_unregister = ir_lirc_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_lirc_codec_init(void)
|
||||
{
|
||||
ir_raw_handler_register(&lirc_handler);
|
||||
|
||||
printk(KERN_INFO "IR LIRC bridge handler initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ir_lirc_codec_exit(void)
|
||||
{
|
||||
ir_raw_handler_unregister(&lirc_handler);
|
||||
}
|
||||
|
||||
module_init(ir_lirc_codec_init);
|
||||
module_exit(ir_lirc_codec_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
|
||||
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
|
||||
MODULE_DESCRIPTION("LIRC IR handler bridge");
|
|
@ -27,10 +27,6 @@
|
|||
#define NEC_TRAILER_PULSE (1 * NEC_UNIT)
|
||||
#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */
|
||||
|
||||
/* Used to register nec_decoder clients */
|
||||
static LIST_HEAD(decoder_list);
|
||||
static DEFINE_SPINLOCK(decoder_lock);
|
||||
|
||||
enum nec_state {
|
||||
STATE_INACTIVE,
|
||||
STATE_HEADER_SPACE,
|
||||
|
@ -40,84 +36,6 @@ enum nec_state {
|
|||
STATE_TRAILER_SPACE,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int enabled:1;
|
||||
|
||||
/* State machine control */
|
||||
enum nec_state state;
|
||||
u32 nec_bits;
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* get_decoder_data() - gets decoder data
|
||||
* @input_dev: input device
|
||||
*
|
||||
* Returns the struct decoder_data that corresponds to a device
|
||||
*/
|
||||
static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
||||
{
|
||||
struct decoder_data *data = NULL;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_for_each_entry(data, &decoder_list, list) {
|
||||
if (data->ir_dev == ir_dev)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&decoder_lock);
|
||||
return data;
|
||||
}
|
||||
|
||||
static ssize_t store_enabled(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
unsigned long value;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (strict_strtoul(buf, 10, &value) || value > 1)
|
||||
return -EINVAL;
|
||||
|
||||
data->enabled = value;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_enabled(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (data->enabled)
|
||||
return sprintf(buf, "1\n");
|
||||
else
|
||||
return sprintf(buf, "0\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
|
||||
|
||||
static struct attribute *decoder_attributes[] = {
|
||||
&dev_attr_enabled.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group decoder_attribute_group = {
|
||||
.name = "nec_decoder",
|
||||
.attrs = decoder_attributes,
|
||||
};
|
||||
|
||||
/**
|
||||
* ir_nec_decode() - Decode one NEC pulse or space
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
|
@ -127,16 +45,12 @@ static struct attribute_group decoder_attribute_group = {
|
|||
*/
|
||||
static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
{
|
||||
struct decoder_data *data;
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct nec_dec *data = &ir_dev->raw->nec;
|
||||
u32 scancode;
|
||||
u8 address, not_address, command, not_command;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!data->enabled)
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
|
@ -191,9 +105,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (ev.pulse)
|
||||
break;
|
||||
|
||||
data->nec_bits <<= 1;
|
||||
data->bits <<= 1;
|
||||
if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
|
||||
data->nec_bits |= 1;
|
||||
data->bits |= 1;
|
||||
else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))
|
||||
break;
|
||||
data->count++;
|
||||
|
@ -222,14 +136,14 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))
|
||||
break;
|
||||
|
||||
address = bitrev8((data->nec_bits >> 24) & 0xff);
|
||||
not_address = bitrev8((data->nec_bits >> 16) & 0xff);
|
||||
command = bitrev8((data->nec_bits >> 8) & 0xff);
|
||||
not_command = bitrev8((data->nec_bits >> 0) & 0xff);
|
||||
address = bitrev8((data->bits >> 24) & 0xff);
|
||||
not_address = bitrev8((data->bits >> 16) & 0xff);
|
||||
command = bitrev8((data->bits >> 8) & 0xff);
|
||||
not_command = bitrev8((data->bits >> 0) & 0xff);
|
||||
|
||||
if ((command ^ not_command) != 0xff) {
|
||||
IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
|
||||
data->nec_bits);
|
||||
data->bits);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -256,54 +170,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ir_nec_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct decoder_data *data;
|
||||
int rc;
|
||||
|
||||
rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
data->enabled = 1;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_add_tail(&data->list, &decoder_list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir_nec_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
static struct decoder_data *data;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler nec_handler = {
|
||||
.protocols = IR_TYPE_NEC,
|
||||
.decode = ir_nec_decode,
|
||||
.raw_register = ir_nec_register,
|
||||
.raw_unregister = ir_nec_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_nec_decode_init(void)
|
||||
|
|
|
@ -20,35 +20,13 @@
|
|||
/* Define the max number of pulse/space transitions to buffer */
|
||||
#define MAX_IR_EVENT_SIZE 512
|
||||
|
||||
/* Used to handle IR raw handler extensions */
|
||||
static LIST_HEAD(ir_raw_handler_list);
|
||||
static DEFINE_SPINLOCK(ir_raw_handler_lock);
|
||||
/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
|
||||
static LIST_HEAD(ir_raw_client_list);
|
||||
|
||||
/**
|
||||
* RUN_DECODER() - runs an operation on all IR decoders
|
||||
* @ops: IR raw handler operation to be called
|
||||
* @arg: arguments to be passed to the callback
|
||||
*
|
||||
* Calls ir_raw_handler::ops for all registered IR handlers. It prevents
|
||||
* new decode addition/removal while running, by locking ir_raw_handler_lock
|
||||
* mutex. If an error occurs, it stops the ops. Otherwise, it returns a sum
|
||||
* of the return codes.
|
||||
*/
|
||||
#define RUN_DECODER(ops, ...) ({ \
|
||||
struct ir_raw_handler *_ir_raw_handler; \
|
||||
int _sumrc = 0, _rc; \
|
||||
spin_lock(&ir_raw_handler_lock); \
|
||||
list_for_each_entry(_ir_raw_handler, &ir_raw_handler_list, list) { \
|
||||
if (_ir_raw_handler->ops) { \
|
||||
_rc = _ir_raw_handler->ops(__VA_ARGS__); \
|
||||
if (_rc < 0) \
|
||||
break; \
|
||||
_sumrc += _rc; \
|
||||
} \
|
||||
} \
|
||||
spin_unlock(&ir_raw_handler_lock); \
|
||||
_sumrc; \
|
||||
})
|
||||
/* Used to handle IR raw handler extensions */
|
||||
static DEFINE_SPINLOCK(ir_raw_handler_lock);
|
||||
static LIST_HEAD(ir_raw_handler_list);
|
||||
static u64 available_protocols;
|
||||
|
||||
#ifdef MODULE
|
||||
/* Used to load the decoders */
|
||||
|
@ -58,57 +36,17 @@ static struct work_struct wq_load;
|
|||
static void ir_raw_event_work(struct work_struct *work)
|
||||
{
|
||||
struct ir_raw_event ev;
|
||||
struct ir_raw_handler *handler;
|
||||
struct ir_raw_event_ctrl *raw =
|
||||
container_of(work, struct ir_raw_event_ctrl, rx_work);
|
||||
|
||||
while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev))
|
||||
RUN_DECODER(decode, raw->input_dev, ev);
|
||||
}
|
||||
|
||||
int ir_raw_event_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir = input_get_drvdata(input_dev);
|
||||
int rc;
|
||||
|
||||
ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
|
||||
if (!ir->raw)
|
||||
return -ENOMEM;
|
||||
|
||||
ir->raw->input_dev = input_dev;
|
||||
INIT_WORK(&ir->raw->rx_work, ir_raw_event_work);
|
||||
|
||||
rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
|
||||
GFP_KERNEL);
|
||||
if (rc < 0) {
|
||||
kfree(ir->raw);
|
||||
ir->raw = NULL;
|
||||
return rc;
|
||||
while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
handler->decode(raw->input_dev, ev);
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
raw->prev_ev = ev;
|
||||
}
|
||||
|
||||
rc = RUN_DECODER(raw_register, input_dev);
|
||||
if (rc < 0) {
|
||||
kfifo_free(&ir->raw->kfifo);
|
||||
kfree(ir->raw);
|
||||
ir->raw = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void ir_raw_event_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir = input_get_drvdata(input_dev);
|
||||
|
||||
if (!ir->raw)
|
||||
return;
|
||||
|
||||
cancel_work_sync(&ir->raw->rx_work);
|
||||
RUN_DECODER(raw_unregister, input_dev);
|
||||
|
||||
kfifo_free(&ir->raw->kfifo);
|
||||
kfree(ir->raw);
|
||||
ir->raw = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -204,23 +142,103 @@ void ir_raw_event_handle(struct input_dev *input_dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(ir_raw_event_handle);
|
||||
|
||||
/* used internally by the sysfs interface */
|
||||
u64
|
||||
ir_raw_get_allowed_protocols()
|
||||
{
|
||||
u64 protocols;
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
protocols = available_protocols;
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
return protocols;
|
||||
}
|
||||
|
||||
/*
|
||||
* Used to (un)register raw event clients
|
||||
*/
|
||||
int ir_raw_event_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir = input_get_drvdata(input_dev);
|
||||
int rc;
|
||||
struct ir_raw_handler *handler;
|
||||
|
||||
ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
|
||||
if (!ir->raw)
|
||||
return -ENOMEM;
|
||||
|
||||
ir->raw->input_dev = input_dev;
|
||||
INIT_WORK(&ir->raw->rx_work, ir_raw_event_work);
|
||||
ir->raw->enabled_protocols = ~0;
|
||||
rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
|
||||
GFP_KERNEL);
|
||||
if (rc < 0) {
|
||||
kfree(ir->raw);
|
||||
ir->raw = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_add_tail(&ir->raw->list, &ir_raw_client_list);
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
if (handler->raw_register)
|
||||
handler->raw_register(ir->raw->input_dev);
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ir_raw_event_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir = input_get_drvdata(input_dev);
|
||||
struct ir_raw_handler *handler;
|
||||
|
||||
if (!ir->raw)
|
||||
return;
|
||||
|
||||
cancel_work_sync(&ir->raw->rx_work);
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_del(&ir->raw->list);
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
if (handler->raw_unregister)
|
||||
handler->raw_unregister(ir->raw->input_dev);
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
|
||||
kfifo_free(&ir->raw->kfifo);
|
||||
kfree(ir->raw);
|
||||
ir->raw = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extension interface - used to register the IR decoders
|
||||
*/
|
||||
|
||||
int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
|
||||
{
|
||||
struct ir_raw_event_ctrl *raw;
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
|
||||
if (ir_raw_handler->raw_register)
|
||||
list_for_each_entry(raw, &ir_raw_client_list, list)
|
||||
ir_raw_handler->raw_register(raw->input_dev);
|
||||
available_protocols |= ir_raw_handler->protocols;
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ir_raw_handler_register);
|
||||
|
||||
void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
|
||||
{
|
||||
struct ir_raw_event_ctrl *raw;
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_del(&ir_raw_handler->list);
|
||||
if (ir_raw_handler->raw_unregister)
|
||||
list_for_each_entry(raw, &ir_raw_client_list, list)
|
||||
ir_raw_handler->raw_unregister(raw->input_dev);
|
||||
available_protocols &= ~ir_raw_handler->protocols;
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(ir_raw_handler_unregister);
|
||||
|
@ -235,6 +253,7 @@ static void init_decoders(struct work_struct *work)
|
|||
load_rc6_decode();
|
||||
load_jvc_decode();
|
||||
load_sony_decode();
|
||||
load_lirc_codec();
|
||||
|
||||
/* If needed, we may later add some init code. In this case,
|
||||
it is needed to change the CONFIG_MODULE test at ir-core.h
|
||||
|
|
|
@ -30,10 +30,6 @@
|
|||
#define RC5_BIT_END (1 * RC5_UNIT)
|
||||
#define RC5X_SPACE (4 * RC5_UNIT)
|
||||
|
||||
/* Used to register rc5_decoder clients */
|
||||
static LIST_HEAD(decoder_list);
|
||||
static DEFINE_SPINLOCK(decoder_lock);
|
||||
|
||||
enum rc5_state {
|
||||
STATE_INACTIVE,
|
||||
STATE_BIT_START,
|
||||
|
@ -42,87 +38,6 @@ enum rc5_state {
|
|||
STATE_FINISHED,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int enabled:1;
|
||||
|
||||
/* State machine control */
|
||||
enum rc5_state state;
|
||||
u32 rc5_bits;
|
||||
struct ir_raw_event prev_ev;
|
||||
unsigned count;
|
||||
unsigned wanted_bits;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* get_decoder_data() - gets decoder data
|
||||
* @input_dev: input device
|
||||
*
|
||||
* Returns the struct decoder_data that corresponds to a device
|
||||
*/
|
||||
|
||||
static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
||||
{
|
||||
struct decoder_data *data = NULL;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_for_each_entry(data, &decoder_list, list) {
|
||||
if (data->ir_dev == ir_dev)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&decoder_lock);
|
||||
return data;
|
||||
}
|
||||
|
||||
static ssize_t store_enabled(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
unsigned long value;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (strict_strtoul(buf, 10, &value) || value > 1)
|
||||
return -EINVAL;
|
||||
|
||||
data->enabled = value;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_enabled(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (data->enabled)
|
||||
return sprintf(buf, "1\n");
|
||||
else
|
||||
return sprintf(buf, "0\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
|
||||
|
||||
static struct attribute *decoder_attributes[] = {
|
||||
&dev_attr_enabled.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group decoder_attribute_group = {
|
||||
.name = "rc5_decoder",
|
||||
.attrs = decoder_attributes,
|
||||
};
|
||||
|
||||
/**
|
||||
* ir_rc5_decode() - Decode one RC-5 pulse or space
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
|
@ -132,17 +47,13 @@ static struct attribute_group decoder_attribute_group = {
|
|||
*/
|
||||
static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
{
|
||||
struct decoder_data *data;
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct rc5_dec *data = &ir_dev->raw->rc5;
|
||||
u8 toggle;
|
||||
u32 scancode;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!data->enabled)
|
||||
return 0;
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
data->state = STATE_INACTIVE;
|
||||
|
@ -176,16 +87,15 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
|
||||
break;
|
||||
|
||||
data->rc5_bits <<= 1;
|
||||
data->bits <<= 1;
|
||||
if (!ev.pulse)
|
||||
data->rc5_bits |= 1;
|
||||
data->bits |= 1;
|
||||
data->count++;
|
||||
data->prev_ev = ev;
|
||||
data->state = STATE_BIT_END;
|
||||
return 0;
|
||||
|
||||
case STATE_BIT_END:
|
||||
if (!is_transition(&ev, &data->prev_ev))
|
||||
if (!is_transition(&ev, &ir_dev->raw->prev_ev))
|
||||
break;
|
||||
|
||||
if (data->count == data->wanted_bits)
|
||||
|
@ -217,11 +127,11 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (data->wanted_bits == RC5X_NBITS) {
|
||||
/* RC5X */
|
||||
u8 xdata, command, system;
|
||||
xdata = (data->rc5_bits & 0x0003F) >> 0;
|
||||
command = (data->rc5_bits & 0x00FC0) >> 6;
|
||||
system = (data->rc5_bits & 0x1F000) >> 12;
|
||||
toggle = (data->rc5_bits & 0x20000) ? 1 : 0;
|
||||
command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
|
||||
xdata = (data->bits & 0x0003F) >> 0;
|
||||
command = (data->bits & 0x00FC0) >> 6;
|
||||
system = (data->bits & 0x1F000) >> 12;
|
||||
toggle = (data->bits & 0x20000) ? 1 : 0;
|
||||
command += (data->bits & 0x01000) ? 0 : 0x40;
|
||||
scancode = system << 16 | command << 8 | xdata;
|
||||
|
||||
IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
|
||||
|
@ -230,10 +140,10 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
} else {
|
||||
/* RC5 */
|
||||
u8 command, system;
|
||||
command = (data->rc5_bits & 0x0003F) >> 0;
|
||||
system = (data->rc5_bits & 0x007C0) >> 6;
|
||||
toggle = (data->rc5_bits & 0x00800) ? 1 : 0;
|
||||
command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
|
||||
command = (data->bits & 0x0003F) >> 0;
|
||||
system = (data->bits & 0x007C0) >> 6;
|
||||
toggle = (data->bits & 0x00800) ? 1 : 0;
|
||||
command += (data->bits & 0x01000) ? 0 : 0x40;
|
||||
scancode = system << 8 | command;
|
||||
|
||||
IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
|
||||
|
@ -252,54 +162,9 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ir_rc5_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct decoder_data *data;
|
||||
int rc;
|
||||
|
||||
rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
data->enabled = 1;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_add_tail(&data->list, &decoder_list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir_rc5_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
static struct decoder_data *data;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler rc5_handler = {
|
||||
.protocols = IR_TYPE_RC5,
|
||||
.decode = ir_rc5_decode,
|
||||
.raw_register = ir_rc5_register,
|
||||
.raw_unregister = ir_rc5_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_rc5_decode_init(void)
|
||||
|
|
|
@ -36,10 +36,6 @@
|
|||
#define RC6_STARTBIT_MASK 0x08 /* for the header bits */
|
||||
#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */
|
||||
|
||||
/* Used to register rc6_decoder clients */
|
||||
static LIST_HEAD(decoder_list);
|
||||
static DEFINE_SPINLOCK(decoder_lock);
|
||||
|
||||
enum rc6_mode {
|
||||
RC6_MODE_0,
|
||||
RC6_MODE_6A,
|
||||
|
@ -58,89 +54,8 @@ enum rc6_state {
|
|||
STATE_FINISHED,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int enabled:1;
|
||||
|
||||
/* State machine control */
|
||||
enum rc6_state state;
|
||||
u8 header;
|
||||
u32 body;
|
||||
struct ir_raw_event prev_ev;
|
||||
bool toggle;
|
||||
unsigned count;
|
||||
unsigned wanted_bits;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* get_decoder_data() - gets decoder data
|
||||
* @input_dev: input device
|
||||
*
|
||||
* Returns the struct decoder_data that corresponds to a device
|
||||
*/
|
||||
static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
||||
static enum rc6_mode rc6_mode(struct rc6_dec *data)
|
||||
{
|
||||
struct decoder_data *data = NULL;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_for_each_entry(data, &decoder_list, list) {
|
||||
if (data->ir_dev == ir_dev)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&decoder_lock);
|
||||
return data;
|
||||
}
|
||||
|
||||
static ssize_t store_enabled(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
unsigned long value;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (strict_strtoul(buf, 10, &value) || value > 1)
|
||||
return -EINVAL;
|
||||
|
||||
data->enabled = value;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_enabled(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (data->enabled)
|
||||
return sprintf(buf, "1\n");
|
||||
else
|
||||
return sprintf(buf, "0\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
|
||||
|
||||
static struct attribute *decoder_attributes[] = {
|
||||
&dev_attr_enabled.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group decoder_attribute_group = {
|
||||
.name = "rc6_decoder",
|
||||
.attrs = decoder_attributes,
|
||||
};
|
||||
|
||||
static enum rc6_mode rc6_mode(struct decoder_data *data) {
|
||||
switch (data->header & RC6_MODE_MASK) {
|
||||
case 0:
|
||||
return RC6_MODE_0;
|
||||
|
@ -162,16 +77,12 @@ static enum rc6_mode rc6_mode(struct decoder_data *data) {
|
|||
*/
|
||||
static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
{
|
||||
struct decoder_data *data;
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct rc6_dec *data = &ir_dev->raw->rc6;
|
||||
u32 scancode;
|
||||
u8 toggle;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!data->enabled)
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
|
@ -223,12 +134,11 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (ev.pulse)
|
||||
data->header |= 1;
|
||||
data->count++;
|
||||
data->prev_ev = ev;
|
||||
data->state = STATE_HEADER_BIT_END;
|
||||
return 0;
|
||||
|
||||
case STATE_HEADER_BIT_END:
|
||||
if (!is_transition(&ev, &data->prev_ev))
|
||||
if (!is_transition(&ev, &ir_dev->raw->prev_ev))
|
||||
break;
|
||||
|
||||
if (data->count == RC6_HEADER_NBITS)
|
||||
|
@ -244,12 +154,11 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
break;
|
||||
|
||||
data->toggle = ev.pulse;
|
||||
data->prev_ev = ev;
|
||||
data->state = STATE_TOGGLE_END;
|
||||
return 0;
|
||||
|
||||
case STATE_TOGGLE_END:
|
||||
if (!is_transition(&ev, &data->prev_ev) ||
|
||||
if (!is_transition(&ev, &ir_dev->raw->prev_ev) ||
|
||||
!geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
|
||||
break;
|
||||
|
||||
|
@ -259,7 +168,6 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
}
|
||||
|
||||
data->state = STATE_BODY_BIT_START;
|
||||
data->prev_ev = ev;
|
||||
decrease_duration(&ev, RC6_TOGGLE_END);
|
||||
data->count = 0;
|
||||
|
||||
|
@ -291,13 +199,11 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (ev.pulse)
|
||||
data->body |= 1;
|
||||
data->count++;
|
||||
data->prev_ev = ev;
|
||||
|
||||
data->state = STATE_BODY_BIT_END;
|
||||
return 0;
|
||||
|
||||
case STATE_BODY_BIT_END:
|
||||
if (!is_transition(&ev, &data->prev_ev))
|
||||
if (!is_transition(&ev, &ir_dev->raw->prev_ev))
|
||||
break;
|
||||
|
||||
if (data->count == data->wanted_bits)
|
||||
|
@ -348,54 +254,9 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ir_rc6_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct decoder_data *data;
|
||||
int rc;
|
||||
|
||||
rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
data->enabled = 1;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_add_tail(&data->list, &decoder_list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir_rc6_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
static struct decoder_data *data;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler rc6_handler = {
|
||||
.protocols = IR_TYPE_RC6,
|
||||
.decode = ir_rc6_decode,
|
||||
.raw_register = ir_rc6_register,
|
||||
.raw_unregister = ir_rc6_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_rc6_decode_init(void)
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
#define SONY_BIT_SPACE (1 * SONY_UNIT)
|
||||
#define SONY_TRAILER_SPACE (10 * SONY_UNIT) /* minimum */
|
||||
|
||||
/* Used to register sony_decoder clients */
|
||||
static LIST_HEAD(decoder_list);
|
||||
static DEFINE_SPINLOCK(decoder_lock);
|
||||
|
||||
enum sony_state {
|
||||
STATE_INACTIVE,
|
||||
STATE_HEADER_SPACE,
|
||||
|
@ -35,84 +31,6 @@ enum sony_state {
|
|||
STATE_FINISHED,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int enabled:1;
|
||||
|
||||
/* State machine control */
|
||||
enum sony_state state;
|
||||
u32 sony_bits;
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* get_decoder_data() - gets decoder data
|
||||
* @input_dev: input device
|
||||
*
|
||||
* Returns the struct decoder_data that corresponds to a device
|
||||
*/
|
||||
static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
||||
{
|
||||
struct decoder_data *data = NULL;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_for_each_entry(data, &decoder_list, list) {
|
||||
if (data->ir_dev == ir_dev)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&decoder_lock);
|
||||
return data;
|
||||
}
|
||||
|
||||
static ssize_t store_enabled(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
unsigned long value;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (strict_strtoul(buf, 10, &value) || value > 1)
|
||||
return -EINVAL;
|
||||
|
||||
data->enabled = value;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_enabled(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (data->enabled)
|
||||
return sprintf(buf, "1\n");
|
||||
else
|
||||
return sprintf(buf, "0\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
|
||||
|
||||
static struct attribute *decoder_attributes[] = {
|
||||
&dev_attr_enabled.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group decoder_attribute_group = {
|
||||
.name = "sony_decoder",
|
||||
.attrs = decoder_attributes,
|
||||
};
|
||||
|
||||
/**
|
||||
* ir_sony_decode() - Decode one Sony pulse or space
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
|
@ -122,16 +40,12 @@ static struct attribute_group decoder_attribute_group = {
|
|||
*/
|
||||
static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
{
|
||||
struct decoder_data *data;
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct sony_dec *data = &ir_dev->raw->sony;
|
||||
u32 scancode;
|
||||
u8 device, subdevice, function;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!data->enabled)
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
|
@ -172,9 +86,9 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (!ev.pulse)
|
||||
break;
|
||||
|
||||
data->sony_bits <<= 1;
|
||||
data->bits <<= 1;
|
||||
if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2))
|
||||
data->sony_bits |= 1;
|
||||
data->bits |= 1;
|
||||
else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2))
|
||||
break;
|
||||
|
||||
|
@ -208,19 +122,19 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
|
||||
switch (data->count) {
|
||||
case 12:
|
||||
device = bitrev8((data->sony_bits << 3) & 0xF8);
|
||||
device = bitrev8((data->bits << 3) & 0xF8);
|
||||
subdevice = 0;
|
||||
function = bitrev8((data->sony_bits >> 4) & 0xFE);
|
||||
function = bitrev8((data->bits >> 4) & 0xFE);
|
||||
break;
|
||||
case 15:
|
||||
device = bitrev8((data->sony_bits >> 0) & 0xFF);
|
||||
device = bitrev8((data->bits >> 0) & 0xFF);
|
||||
subdevice = 0;
|
||||
function = bitrev8((data->sony_bits >> 7) & 0xFD);
|
||||
function = bitrev8((data->bits >> 7) & 0xFD);
|
||||
break;
|
||||
case 20:
|
||||
device = bitrev8((data->sony_bits >> 5) & 0xF8);
|
||||
subdevice = bitrev8((data->sony_bits >> 0) & 0xFF);
|
||||
function = bitrev8((data->sony_bits >> 12) & 0xFE);
|
||||
device = bitrev8((data->bits >> 5) & 0xF8);
|
||||
subdevice = bitrev8((data->bits >> 0) & 0xFF);
|
||||
function = bitrev8((data->bits >> 12) & 0xFE);
|
||||
break;
|
||||
default:
|
||||
IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
|
||||
|
@ -241,54 +155,9 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ir_sony_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct decoder_data *data;
|
||||
int rc;
|
||||
|
||||
rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
data->enabled = 1;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_add_tail(&data->list, &decoder_list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir_sony_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
static struct decoder_data *data;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler sony_handler = {
|
||||
.protocols = IR_TYPE_SONY,
|
||||
.decode = ir_sony_decode,
|
||||
.raw_register = ir_sony_register,
|
||||
.raw_unregister = ir_sony_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_sony_decode_init(void)
|
||||
|
|
|
@ -33,125 +33,172 @@ static struct class ir_input_class = {
|
|||
.devnode = ir_devnode,
|
||||
};
|
||||
|
||||
static struct {
|
||||
u64 type;
|
||||
char *name;
|
||||
} proto_names[] = {
|
||||
{ IR_TYPE_UNKNOWN, "unknown" },
|
||||
{ IR_TYPE_RC5, "rc-5" },
|
||||
{ IR_TYPE_NEC, "nec" },
|
||||
{ IR_TYPE_RC6, "rc-6" },
|
||||
{ IR_TYPE_JVC, "jvc" },
|
||||
{ IR_TYPE_SONY, "sony" },
|
||||
{ IR_TYPE_LIRC, "lirc" },
|
||||
};
|
||||
|
||||
#define PROTO_NONE "none"
|
||||
|
||||
/**
|
||||
* show_protocol() - shows the current IR protocol
|
||||
* show_protocols() - shows the current IR protocol(s)
|
||||
* @d: the device descriptor
|
||||
* @mattr: the device attribute struct (unused)
|
||||
* @buf: a pointer to the output buffer
|
||||
*
|
||||
* This routine is a callback routine for input read the IR protocol type.
|
||||
* it is trigged by reading /sys/class/rc/rc?/current_protocol.
|
||||
* It returns the protocol name, as understood by the driver.
|
||||
* This routine is a callback routine for input read the IR protocol type(s).
|
||||
* it is trigged by reading /sys/class/rc/rc?/protocols.
|
||||
* It returns the protocol names of supported protocols.
|
||||
* Enabled protocols are printed in brackets.
|
||||
*/
|
||||
static ssize_t show_protocol(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
static ssize_t show_protocols(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
char *s;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
u64 ir_type = ir_dev->rc_tab.ir_type;
|
||||
u64 allowed, enabled;
|
||||
char *tmp = buf;
|
||||
int i;
|
||||
|
||||
IR_dprintk(1, "Current protocol is %lld\n", (long long)ir_type);
|
||||
if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
|
||||
enabled = ir_dev->rc_tab.ir_type;
|
||||
allowed = ir_dev->props->allowed_protos;
|
||||
} else {
|
||||
enabled = ir_dev->raw->enabled_protocols;
|
||||
allowed = ir_raw_get_allowed_protocols();
|
||||
}
|
||||
|
||||
/* FIXME: doesn't support multiple protocols at the same time */
|
||||
if (ir_type == IR_TYPE_UNKNOWN)
|
||||
s = "Unknown";
|
||||
else if (ir_type == IR_TYPE_RC5)
|
||||
s = "rc-5";
|
||||
else if (ir_type == IR_TYPE_NEC)
|
||||
s = "nec";
|
||||
else if (ir_type == IR_TYPE_RC6)
|
||||
s = "rc6";
|
||||
else if (ir_type == IR_TYPE_JVC)
|
||||
s = "jvc";
|
||||
else if (ir_type == IR_TYPE_SONY)
|
||||
s = "sony";
|
||||
else
|
||||
s = "other";
|
||||
IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
|
||||
(long long)allowed,
|
||||
(long long)enabled);
|
||||
|
||||
return sprintf(buf, "%s\n", s);
|
||||
for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
|
||||
if (allowed & enabled & proto_names[i].type)
|
||||
tmp += sprintf(tmp, "[%s] ", proto_names[i].name);
|
||||
else if (allowed & proto_names[i].type)
|
||||
tmp += sprintf(tmp, "%s ", proto_names[i].name);
|
||||
}
|
||||
|
||||
if (tmp != buf)
|
||||
tmp--;
|
||||
*tmp = '\n';
|
||||
return tmp + 1 - buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* store_protocol() - shows the current IR protocol
|
||||
* store_protocols() - changes the current IR protocol(s)
|
||||
* @d: the device descriptor
|
||||
* @mattr: the device attribute struct (unused)
|
||||
* @buf: a pointer to the input buffer
|
||||
* @len: length of the input buffer
|
||||
*
|
||||
* This routine is a callback routine for changing the IR protocol type.
|
||||
* it is trigged by reading /sys/class/rc/rc?/current_protocol.
|
||||
* It changes the IR the protocol name, if the IR type is recognized
|
||||
* by the driver.
|
||||
* If an unknown protocol name is used, returns -EINVAL.
|
||||
* It is trigged by writing to /sys/class/rc/rc?/protocols.
|
||||
* Writing "+proto" will add a protocol to the list of enabled protocols.
|
||||
* Writing "-proto" will remove a protocol from the list of enabled protocols.
|
||||
* Writing "proto" will enable only "proto".
|
||||
* Writing "none" will disable all protocols.
|
||||
* Returns -EINVAL if an invalid protocol combination or unknown protocol name
|
||||
* is used, otherwise @len.
|
||||
*/
|
||||
static ssize_t store_protocol(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *data,
|
||||
size_t len)
|
||||
static ssize_t store_protocols(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *data,
|
||||
size_t len)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
u64 ir_type = 0;
|
||||
int rc = -EINVAL;
|
||||
bool enable, disable;
|
||||
const char *tmp;
|
||||
u64 type;
|
||||
u64 mask;
|
||||
int rc, i, count = 0;
|
||||
unsigned long flags;
|
||||
char *buf;
|
||||
|
||||
while ((buf = strsep((char **) &data, " \n")) != NULL) {
|
||||
if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5"))
|
||||
ir_type |= IR_TYPE_RC5;
|
||||
if (!strcasecmp(buf, "nec"))
|
||||
ir_type |= IR_TYPE_NEC;
|
||||
if (!strcasecmp(buf, "jvc"))
|
||||
ir_type |= IR_TYPE_JVC;
|
||||
if (!strcasecmp(buf, "sony"))
|
||||
ir_type |= IR_TYPE_SONY;
|
||||
if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
|
||||
type = ir_dev->rc_tab.ir_type;
|
||||
else
|
||||
type = ir_dev->raw->enabled_protocols;
|
||||
|
||||
while ((tmp = strsep((char **) &data, " \n")) != NULL) {
|
||||
if (!*tmp)
|
||||
break;
|
||||
|
||||
if (*tmp == '+') {
|
||||
enable = true;
|
||||
disable = false;
|
||||
tmp++;
|
||||
} else if (*tmp == '-') {
|
||||
enable = false;
|
||||
disable = true;
|
||||
tmp++;
|
||||
} else {
|
||||
enable = false;
|
||||
disable = false;
|
||||
}
|
||||
|
||||
if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) {
|
||||
tmp += sizeof(PROTO_NONE);
|
||||
mask = 0;
|
||||
count++;
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
|
||||
if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) {
|
||||
tmp += strlen(proto_names[i].name);
|
||||
mask = proto_names[i].type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == ARRAY_SIZE(proto_names)) {
|
||||
IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
|
||||
return -EINVAL;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
if (enable)
|
||||
type |= mask;
|
||||
else if (disable)
|
||||
type &= ~mask;
|
||||
else
|
||||
type = mask;
|
||||
}
|
||||
|
||||
if (!ir_type) {
|
||||
IR_dprintk(1, "Unknown protocol\n");
|
||||
if (!count) {
|
||||
IR_dprintk(1, "Protocol not specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ir_dev->props && ir_dev->props->change_protocol)
|
||||
if (ir_dev->props && ir_dev->props->change_protocol) {
|
||||
rc = ir_dev->props->change_protocol(ir_dev->props->priv,
|
||||
ir_type);
|
||||
|
||||
if (rc < 0) {
|
||||
IR_dprintk(1, "Error setting protocol to %lld\n",
|
||||
(long long)ir_type);
|
||||
return -EINVAL;
|
||||
type);
|
||||
if (rc < 0) {
|
||||
IR_dprintk(1, "Error setting protocols to 0x%llx\n",
|
||||
(long long)type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
|
||||
ir_dev->rc_tab.ir_type = ir_type;
|
||||
spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
|
||||
if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
|
||||
spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
|
||||
ir_dev->rc_tab.ir_type = type;
|
||||
spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
|
||||
} else {
|
||||
ir_dev->raw->enabled_protocols = type;
|
||||
}
|
||||
|
||||
IR_dprintk(1, "Current protocol(s) is(are) %lld\n",
|
||||
(long long)ir_type);
|
||||
IR_dprintk(1, "Current protocol(s): 0x%llx\n",
|
||||
(long long)type);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_supported_protocols(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
char *orgbuf = buf;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
|
||||
/* FIXME: doesn't support multiple protocols at the same time */
|
||||
if (ir_dev->props->allowed_protos == IR_TYPE_UNKNOWN)
|
||||
buf += sprintf(buf, "unknown ");
|
||||
if (ir_dev->props->allowed_protos & IR_TYPE_RC5)
|
||||
buf += sprintf(buf, "rc-5 ");
|
||||
if (ir_dev->props->allowed_protos & IR_TYPE_NEC)
|
||||
buf += sprintf(buf, "nec ");
|
||||
if (buf == orgbuf)
|
||||
buf += sprintf(buf, "other ");
|
||||
|
||||
buf += sprintf(buf - 1, "\n");
|
||||
|
||||
return buf - orgbuf;
|
||||
}
|
||||
|
||||
#define ADD_HOTPLUG_VAR(fmt, val...) \
|
||||
do { \
|
||||
int err = add_uevent_var(env, fmt, val); \
|
||||
|
@ -159,7 +206,7 @@ static ssize_t show_supported_protocols(struct device *d,
|
|||
return err; \
|
||||
} while (0)
|
||||
|
||||
static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env)
|
||||
static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(device);
|
||||
|
||||
|
@ -174,34 +221,26 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env)
|
|||
/*
|
||||
* Static device attribute struct with the sysfs attributes for IR's
|
||||
*/
|
||||
static DEVICE_ATTR(protocol, S_IRUGO | S_IWUSR,
|
||||
show_protocol, store_protocol);
|
||||
static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR,
|
||||
show_protocols, store_protocols);
|
||||
|
||||
static DEVICE_ATTR(supported_protocols, S_IRUGO | S_IWUSR,
|
||||
show_supported_protocols, NULL);
|
||||
|
||||
static struct attribute *ir_hw_dev_attrs[] = {
|
||||
&dev_attr_protocol.attr,
|
||||
&dev_attr_supported_protocols.attr,
|
||||
static struct attribute *rc_dev_attrs[] = {
|
||||
&dev_attr_protocols.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group ir_hw_dev_attr_grp = {
|
||||
.attrs = ir_hw_dev_attrs,
|
||||
static struct attribute_group rc_dev_attr_grp = {
|
||||
.attrs = rc_dev_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *ir_hw_dev_attr_groups[] = {
|
||||
&ir_hw_dev_attr_grp,
|
||||
static const struct attribute_group *rc_dev_attr_groups[] = {
|
||||
&rc_dev_attr_grp,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct device_type rc_dev_type = {
|
||||
.groups = ir_hw_dev_attr_groups,
|
||||
.uevent = ir_dev_uevent,
|
||||
};
|
||||
|
||||
static struct device_type ir_raw_dev_type = {
|
||||
.uevent = ir_dev_uevent,
|
||||
.groups = rc_dev_attr_groups,
|
||||
.uevent = rc_dev_uevent,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -221,11 +260,7 @@ int ir_register_class(struct input_dev *input_dev)
|
|||
if (unlikely(devno < 0))
|
||||
return devno;
|
||||
|
||||
if (ir_dev->props) {
|
||||
if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
|
||||
ir_dev->dev.type = &rc_dev_type;
|
||||
} else
|
||||
ir_dev->dev.type = &ir_raw_dev_type;
|
||||
ir_dev->dev.type = &rc_dev_type;
|
||||
|
||||
ir_dev->dev.class = &ir_input_class;
|
||||
ir_dev->dev.parent = input_dev->dev.parent;
|
||||
|
|
|
@ -14,6 +14,8 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
|
|||
rc-budget-ci-old.o \
|
||||
rc-cinergy-1400.o \
|
||||
rc-cinergy.o \
|
||||
rc-dib0700-nec.o \
|
||||
rc-dib0700-rc5.o \
|
||||
rc-dm1105-nec.o \
|
||||
rc-dntv-live-dvb-t.o \
|
||||
rc-dntv-live-dvbt-pro.o \
|
||||
|
@ -37,6 +39,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
|
|||
rc-kaiomy.o \
|
||||
rc-kworld-315u.o \
|
||||
rc-kworld-plus-tv-analog.o \
|
||||
rc-lirc.o \
|
||||
rc-manli.o \
|
||||
rc-msi-tvanywhere.o \
|
||||
rc-msi-tvanywhere-plus.o \
|
||||
|
@ -57,6 +60,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
|
|||
rc-pv951.o \
|
||||
rc-rc5-hauppauge-new.o \
|
||||
rc-rc5-tv.o \
|
||||
rc-rc6-mce.o \
|
||||
rc-real-audio-220-32-keys.o \
|
||||
rc-tbs-nec.o \
|
||||
rc-terratec-cinergy-xs.o \
|
||||
|
|
124
drivers/media/IR/keymaps/rc-dib0700-nec.c
Normal file
124
drivers/media/IR/keymaps/rc-dib0700-nec.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
/* rc-dvb0700-big.c - Keytable for devices in dvb0700
|
||||
*
|
||||
* Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
*
|
||||
* TODO: This table is a real mess, as it merges RC codes from several
|
||||
* devices into a big table. It also has both RC-5 and NEC codes inside.
|
||||
* It should be broken into small tables, and the protocols should properly
|
||||
* be indentificated.
|
||||
*
|
||||
* The table were imported from dib0700_devices.c.
|
||||
*
|
||||
* 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 dib0700_nec_table[] = {
|
||||
/* Key codes for the Pixelview SBTVD remote */
|
||||
{ 0x8613, KEY_MUTE },
|
||||
{ 0x8612, KEY_POWER },
|
||||
{ 0x8601, KEY_1 },
|
||||
{ 0x8602, KEY_2 },
|
||||
{ 0x8603, KEY_3 },
|
||||
{ 0x8604, KEY_4 },
|
||||
{ 0x8605, KEY_5 },
|
||||
{ 0x8606, KEY_6 },
|
||||
{ 0x8607, KEY_7 },
|
||||
{ 0x8608, KEY_8 },
|
||||
{ 0x8609, KEY_9 },
|
||||
{ 0x8600, KEY_0 },
|
||||
{ 0x860d, KEY_CHANNELUP },
|
||||
{ 0x8619, KEY_CHANNELDOWN },
|
||||
{ 0x8610, KEY_VOLUMEUP },
|
||||
{ 0x860c, KEY_VOLUMEDOWN },
|
||||
|
||||
{ 0x860a, KEY_CAMERA },
|
||||
{ 0x860b, KEY_ZOOM },
|
||||
{ 0x861b, KEY_BACKSPACE },
|
||||
{ 0x8615, KEY_ENTER },
|
||||
|
||||
{ 0x861d, KEY_UP },
|
||||
{ 0x861e, KEY_DOWN },
|
||||
{ 0x860e, KEY_LEFT },
|
||||
{ 0x860f, KEY_RIGHT },
|
||||
|
||||
{ 0x8618, KEY_RECORD },
|
||||
{ 0x861a, KEY_STOP },
|
||||
|
||||
/* Key codes for the EvolutePC TVWay+ remote */
|
||||
{ 0x7a00, KEY_MENU },
|
||||
{ 0x7a01, KEY_RECORD },
|
||||
{ 0x7a02, KEY_PLAY },
|
||||
{ 0x7a03, KEY_STOP },
|
||||
{ 0x7a10, KEY_CHANNELUP },
|
||||
{ 0x7a11, KEY_CHANNELDOWN },
|
||||
{ 0x7a12, KEY_VOLUMEUP },
|
||||
{ 0x7a13, KEY_VOLUMEDOWN },
|
||||
{ 0x7a40, KEY_POWER },
|
||||
{ 0x7a41, KEY_MUTE },
|
||||
|
||||
/* Key codes for the Elgato EyeTV Diversity silver remote */
|
||||
{ 0x4501, KEY_POWER },
|
||||
{ 0x4502, KEY_MUTE },
|
||||
{ 0x4503, KEY_1 },
|
||||
{ 0x4504, KEY_2 },
|
||||
{ 0x4505, KEY_3 },
|
||||
{ 0x4506, KEY_4 },
|
||||
{ 0x4507, KEY_5 },
|
||||
{ 0x4508, KEY_6 },
|
||||
{ 0x4509, KEY_7 },
|
||||
{ 0x450a, KEY_8 },
|
||||
{ 0x450b, KEY_9 },
|
||||
{ 0x450c, KEY_LAST },
|
||||
{ 0x450d, KEY_0 },
|
||||
{ 0x450e, KEY_ENTER },
|
||||
{ 0x450f, KEY_RED },
|
||||
{ 0x4510, KEY_CHANNELUP },
|
||||
{ 0x4511, KEY_GREEN },
|
||||
{ 0x4512, KEY_VOLUMEDOWN },
|
||||
{ 0x4513, KEY_OK },
|
||||
{ 0x4514, KEY_VOLUMEUP },
|
||||
{ 0x4515, KEY_YELLOW },
|
||||
{ 0x4516, KEY_CHANNELDOWN },
|
||||
{ 0x4517, KEY_BLUE },
|
||||
{ 0x4518, KEY_LEFT }, /* Skip backwards */
|
||||
{ 0x4519, KEY_PLAYPAUSE },
|
||||
{ 0x451a, KEY_RIGHT }, /* Skip forward */
|
||||
{ 0x451b, KEY_REWIND },
|
||||
{ 0x451c, KEY_L }, /* Live */
|
||||
{ 0x451d, KEY_FASTFORWARD },
|
||||
{ 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */
|
||||
{ 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */
|
||||
{ 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */
|
||||
{ 0x4541, KEY_SCREEN }, /* Full screen toggle, 'Hold' for Teletext */
|
||||
{ 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */
|
||||
};
|
||||
|
||||
static struct rc_keymap dib0700_nec_map = {
|
||||
.map = {
|
||||
.scan = dib0700_nec_table,
|
||||
.size = ARRAY_SIZE(dib0700_nec_table),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
.name = RC_MAP_DIB0700_NEC_TABLE,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map(void)
|
||||
{
|
||||
return ir_register_map(&dib0700_nec_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map(void)
|
||||
{
|
||||
ir_unregister_map(&dib0700_nec_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map)
|
||||
module_exit(exit_rc_map)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
|
235
drivers/media/IR/keymaps/rc-dib0700-rc5.c
Normal file
235
drivers/media/IR/keymaps/rc-dib0700-rc5.c
Normal file
|
@ -0,0 +1,235 @@
|
|||
/* rc-dvb0700-big.c - Keytable for devices in dvb0700
|
||||
*
|
||||
* Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
*
|
||||
* TODO: This table is a real mess, as it merges RC codes from several
|
||||
* devices into a big table. It also has both RC-5 and NEC codes inside.
|
||||
* It should be broken into small tables, and the protocols should properly
|
||||
* be indentificated.
|
||||
*
|
||||
* The table were imported from dib0700_devices.c.
|
||||
*
|
||||
* 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 dib0700_rc5_table[] = {
|
||||
/* Key codes for the tiny Pinnacle remote*/
|
||||
{ 0x0700, KEY_MUTE },
|
||||
{ 0x0701, KEY_MENU }, /* Pinnacle logo */
|
||||
{ 0x0739, KEY_POWER },
|
||||
{ 0x0703, KEY_VOLUMEUP },
|
||||
{ 0x0709, KEY_VOLUMEDOWN },
|
||||
{ 0x0706, KEY_CHANNELUP },
|
||||
{ 0x070c, KEY_CHANNELDOWN },
|
||||
{ 0x070f, KEY_1 },
|
||||
{ 0x0715, KEY_2 },
|
||||
{ 0x0710, KEY_3 },
|
||||
{ 0x0718, KEY_4 },
|
||||
{ 0x071b, KEY_5 },
|
||||
{ 0x071e, KEY_6 },
|
||||
{ 0x0711, KEY_7 },
|
||||
{ 0x0721, KEY_8 },
|
||||
{ 0x0712, KEY_9 },
|
||||
{ 0x0727, KEY_0 },
|
||||
{ 0x0724, KEY_SCREEN }, /* 'Square' key */
|
||||
{ 0x072a, KEY_TEXT }, /* 'T' key */
|
||||
{ 0x072d, KEY_REWIND },
|
||||
{ 0x0730, KEY_PLAY },
|
||||
{ 0x0733, KEY_FASTFORWARD },
|
||||
{ 0x0736, KEY_RECORD },
|
||||
{ 0x073c, KEY_STOP },
|
||||
{ 0x073f, KEY_CANCEL }, /* '?' key */
|
||||
|
||||
/* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
|
||||
{ 0xeb01, KEY_POWER },
|
||||
{ 0xeb02, KEY_1 },
|
||||
{ 0xeb03, KEY_2 },
|
||||
{ 0xeb04, KEY_3 },
|
||||
{ 0xeb05, KEY_4 },
|
||||
{ 0xeb06, KEY_5 },
|
||||
{ 0xeb07, KEY_6 },
|
||||
{ 0xeb08, KEY_7 },
|
||||
{ 0xeb09, KEY_8 },
|
||||
{ 0xeb0a, KEY_9 },
|
||||
{ 0xeb0b, KEY_VIDEO },
|
||||
{ 0xeb0c, KEY_0 },
|
||||
{ 0xeb0d, KEY_REFRESH },
|
||||
{ 0xeb0f, KEY_EPG },
|
||||
{ 0xeb10, KEY_UP },
|
||||
{ 0xeb11, KEY_LEFT },
|
||||
{ 0xeb12, KEY_OK },
|
||||
{ 0xeb13, KEY_RIGHT },
|
||||
{ 0xeb14, KEY_DOWN },
|
||||
{ 0xeb16, KEY_INFO },
|
||||
{ 0xeb17, KEY_RED },
|
||||
{ 0xeb18, KEY_GREEN },
|
||||
{ 0xeb19, KEY_YELLOW },
|
||||
{ 0xeb1a, KEY_BLUE },
|
||||
{ 0xeb1b, KEY_CHANNELUP },
|
||||
{ 0xeb1c, KEY_VOLUMEUP },
|
||||
{ 0xeb1d, KEY_MUTE },
|
||||
{ 0xeb1e, KEY_VOLUMEDOWN },
|
||||
{ 0xeb1f, KEY_CHANNELDOWN },
|
||||
{ 0xeb40, KEY_PAUSE },
|
||||
{ 0xeb41, KEY_HOME },
|
||||
{ 0xeb42, KEY_MENU }, /* DVD Menu */
|
||||
{ 0xeb43, KEY_SUBTITLE },
|
||||
{ 0xeb44, KEY_TEXT }, /* Teletext */
|
||||
{ 0xeb45, KEY_DELETE },
|
||||
{ 0xeb46, KEY_TV },
|
||||
{ 0xeb47, KEY_DVD },
|
||||
{ 0xeb48, KEY_STOP },
|
||||
{ 0xeb49, KEY_VIDEO },
|
||||
{ 0xeb4a, KEY_AUDIO }, /* Music */
|
||||
{ 0xeb4b, KEY_SCREEN }, /* Pic */
|
||||
{ 0xeb4c, KEY_PLAY },
|
||||
{ 0xeb4d, KEY_BACK },
|
||||
{ 0xeb4e, KEY_REWIND },
|
||||
{ 0xeb4f, KEY_FASTFORWARD },
|
||||
{ 0xeb54, KEY_PREVIOUS },
|
||||
{ 0xeb58, KEY_RECORD },
|
||||
{ 0xeb5c, KEY_NEXT },
|
||||
|
||||
/* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */
|
||||
{ 0x1e00, KEY_0 },
|
||||
{ 0x1e01, KEY_1 },
|
||||
{ 0x1e02, KEY_2 },
|
||||
{ 0x1e03, KEY_3 },
|
||||
{ 0x1e04, KEY_4 },
|
||||
{ 0x1e05, KEY_5 },
|
||||
{ 0x1e06, KEY_6 },
|
||||
{ 0x1e07, KEY_7 },
|
||||
{ 0x1e08, KEY_8 },
|
||||
{ 0x1e09, KEY_9 },
|
||||
{ 0x1e0a, KEY_KPASTERISK },
|
||||
{ 0x1e0b, KEY_RED },
|
||||
{ 0x1e0c, KEY_RADIO },
|
||||
{ 0x1e0d, KEY_MENU },
|
||||
{ 0x1e0e, KEY_GRAVE }, /* # */
|
||||
{ 0x1e0f, KEY_MUTE },
|
||||
{ 0x1e10, KEY_VOLUMEUP },
|
||||
{ 0x1e11, KEY_VOLUMEDOWN },
|
||||
{ 0x1e12, KEY_CHANNEL },
|
||||
{ 0x1e14, KEY_UP },
|
||||
{ 0x1e15, KEY_DOWN },
|
||||
{ 0x1e16, KEY_LEFT },
|
||||
{ 0x1e17, KEY_RIGHT },
|
||||
{ 0x1e18, KEY_VIDEO },
|
||||
{ 0x1e19, KEY_AUDIO },
|
||||
{ 0x1e1a, KEY_MEDIA },
|
||||
{ 0x1e1b, KEY_EPG },
|
||||
{ 0x1e1c, KEY_TV },
|
||||
{ 0x1e1e, KEY_NEXT },
|
||||
{ 0x1e1f, KEY_BACK },
|
||||
{ 0x1e20, KEY_CHANNELUP },
|
||||
{ 0x1e21, KEY_CHANNELDOWN },
|
||||
{ 0x1e24, KEY_LAST }, /* Skip backwards */
|
||||
{ 0x1e25, KEY_OK },
|
||||
{ 0x1e29, KEY_BLUE},
|
||||
{ 0x1e2e, KEY_GREEN },
|
||||
{ 0x1e30, KEY_PAUSE },
|
||||
{ 0x1e32, KEY_REWIND },
|
||||
{ 0x1e34, KEY_FASTFORWARD },
|
||||
{ 0x1e35, KEY_PLAY },
|
||||
{ 0x1e36, KEY_STOP },
|
||||
{ 0x1e37, KEY_RECORD },
|
||||
{ 0x1e38, KEY_YELLOW },
|
||||
{ 0x1e3b, KEY_GOTO },
|
||||
{ 0x1e3d, KEY_POWER },
|
||||
|
||||
/* Key codes for the Leadtek Winfast DTV Dongle */
|
||||
{ 0x0042, KEY_POWER },
|
||||
{ 0x077c, KEY_TUNER },
|
||||
{ 0x0f4e, KEY_PRINT }, /* PREVIEW */
|
||||
{ 0x0840, KEY_SCREEN }, /* full screen toggle*/
|
||||
{ 0x0f71, KEY_DOT }, /* frequency */
|
||||
{ 0x0743, KEY_0 },
|
||||
{ 0x0c41, KEY_1 },
|
||||
{ 0x0443, KEY_2 },
|
||||
{ 0x0b7f, KEY_3 },
|
||||
{ 0x0e41, KEY_4 },
|
||||
{ 0x0643, KEY_5 },
|
||||
{ 0x097f, KEY_6 },
|
||||
{ 0x0d7e, KEY_7 },
|
||||
{ 0x057c, KEY_8 },
|
||||
{ 0x0a40, KEY_9 },
|
||||
{ 0x0e4e, KEY_CLEAR },
|
||||
{ 0x047c, KEY_CHANNEL }, /* show channel number */
|
||||
{ 0x0f41, KEY_LAST }, /* recall */
|
||||
{ 0x0342, KEY_MUTE },
|
||||
{ 0x064c, KEY_RESERVED }, /* PIP button*/
|
||||
{ 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */
|
||||
{ 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */
|
||||
{ 0x0b70, KEY_RECORD },
|
||||
{ 0x037d, KEY_VOLUMEUP },
|
||||
{ 0x017d, KEY_VOLUMEDOWN },
|
||||
{ 0x0242, KEY_CHANNELUP },
|
||||
{ 0x007d, KEY_CHANNELDOWN },
|
||||
|
||||
/* Key codes for Nova-TD "credit card" remote control. */
|
||||
{ 0x1d00, KEY_0 },
|
||||
{ 0x1d01, KEY_1 },
|
||||
{ 0x1d02, KEY_2 },
|
||||
{ 0x1d03, KEY_3 },
|
||||
{ 0x1d04, KEY_4 },
|
||||
{ 0x1d05, KEY_5 },
|
||||
{ 0x1d06, KEY_6 },
|
||||
{ 0x1d07, KEY_7 },
|
||||
{ 0x1d08, KEY_8 },
|
||||
{ 0x1d09, KEY_9 },
|
||||
{ 0x1d0a, KEY_TEXT },
|
||||
{ 0x1d0d, KEY_MENU },
|
||||
{ 0x1d0f, KEY_MUTE },
|
||||
{ 0x1d10, KEY_VOLUMEUP },
|
||||
{ 0x1d11, KEY_VOLUMEDOWN },
|
||||
{ 0x1d12, KEY_CHANNEL },
|
||||
{ 0x1d14, KEY_UP },
|
||||
{ 0x1d15, KEY_DOWN },
|
||||
{ 0x1d16, KEY_LEFT },
|
||||
{ 0x1d17, KEY_RIGHT },
|
||||
{ 0x1d1c, KEY_TV },
|
||||
{ 0x1d1e, KEY_NEXT },
|
||||
{ 0x1d1f, KEY_BACK },
|
||||
{ 0x1d20, KEY_CHANNELUP },
|
||||
{ 0x1d21, KEY_CHANNELDOWN },
|
||||
{ 0x1d24, KEY_LAST },
|
||||
{ 0x1d25, KEY_OK },
|
||||
{ 0x1d30, KEY_PAUSE },
|
||||
{ 0x1d32, KEY_REWIND },
|
||||
{ 0x1d34, KEY_FASTFORWARD },
|
||||
{ 0x1d35, KEY_PLAY },
|
||||
{ 0x1d36, KEY_STOP },
|
||||
{ 0x1d37, KEY_RECORD },
|
||||
{ 0x1d3b, KEY_GOTO },
|
||||
{ 0x1d3d, KEY_POWER },
|
||||
};
|
||||
|
||||
static struct rc_keymap dib0700_rc5_map = {
|
||||
.map = {
|
||||
.scan = dib0700_rc5_table,
|
||||
.size = ARRAY_SIZE(dib0700_rc5_table),
|
||||
.ir_type = IR_TYPE_RC5,
|
||||
.name = RC_MAP_DIB0700_RC5_TABLE,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map(void)
|
||||
{
|
||||
return ir_register_map(&dib0700_rc5_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map(void)
|
||||
{
|
||||
ir_unregister_map(&dib0700_rc5_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map)
|
||||
module_exit(exit_rc_map)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
|
41
drivers/media/IR/keymaps/rc-lirc.c
Normal file
41
drivers/media/IR/keymaps/rc-lirc.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* rc-lirc.c - Empty dummy keytable, for use when its preferred to pass
|
||||
* all raw IR data to the lirc userspace decoder.
|
||||
*
|
||||
* 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/ir-core.h>
|
||||
|
||||
static struct ir_scancode lirc[] = {
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct rc_keymap lirc_map = {
|
||||
.map = {
|
||||
.scan = lirc,
|
||||
.size = ARRAY_SIZE(lirc),
|
||||
.ir_type = IR_TYPE_LIRC,
|
||||
.name = RC_MAP_LIRC,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_lirc(void)
|
||||
{
|
||||
return ir_register_map(&lirc_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_lirc(void)
|
||||
{
|
||||
ir_unregister_map(&lirc_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_lirc)
|
||||
module_exit(exit_rc_map_lirc)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
|
105
drivers/media/IR/keymaps/rc-rc6-mce.c
Normal file
105
drivers/media/IR/keymaps/rc-rc6-mce.c
Normal file
|
@ -0,0 +1,105 @@
|
|||
/* rc-rc6-mce.c - Keytable for Windows Media Center RC-6 remotes for use
|
||||
* with the Media Center Edition eHome Infrared Transceiver.
|
||||
*
|
||||
* 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 rc6_mce[] = {
|
||||
{ 0x800f0415, KEY_REWIND },
|
||||
{ 0x800f0414, KEY_FASTFORWARD },
|
||||
{ 0x800f041b, KEY_PREVIOUS },
|
||||
{ 0x800f041a, KEY_NEXT },
|
||||
|
||||
{ 0x800f0416, KEY_PLAY },
|
||||
{ 0x800f0418, KEY_PAUSE },
|
||||
{ 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 },
|
||||
|
||||
{ 0x800f0401, KEY_NUMERIC_1 },
|
||||
{ 0x800f0402, KEY_NUMERIC_2 },
|
||||
{ 0x800f0403, KEY_NUMERIC_3 },
|
||||
{ 0x800f0404, KEY_NUMERIC_4 },
|
||||
{ 0x800f0405, KEY_NUMERIC_5 },
|
||||
{ 0x800f0406, KEY_NUMERIC_6 },
|
||||
{ 0x800f0407, KEY_NUMERIC_7 },
|
||||
{ 0x800f0408, KEY_NUMERIC_8 },
|
||||
{ 0x800f0409, KEY_NUMERIC_9 },
|
||||
{ 0x800f0400, KEY_NUMERIC_0 },
|
||||
|
||||
{ 0x800f041d, KEY_NUMERIC_STAR },
|
||||
{ 0x800f041c, KEY_NUMERIC_POUND },
|
||||
|
||||
{ 0x800f0446, KEY_TV },
|
||||
{ 0x800f0447, KEY_AUDIO }, /* My Music */
|
||||
{ 0x800f0448, KEY_PVR }, /* RecordedTV */
|
||||
{ 0x800f0449, KEY_CAMERA },
|
||||
{ 0x800f044a, KEY_VIDEO },
|
||||
{ 0x800f0424, KEY_DVD },
|
||||
{ 0x800f0425, KEY_TUNER }, /* LiveTV */
|
||||
{ 0x800f0450, KEY_RADIO },
|
||||
|
||||
{ 0x800f044c, KEY_LANGUAGE },
|
||||
{ 0x800f0427, KEY_ZOOM }, /* Aspect */
|
||||
|
||||
{ 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 },
|
||||
|
||||
{ 0x800f040c, KEY_POWER },
|
||||
{ 0x800f040d, KEY_PROG1 }, /* Windows MCE button */
|
||||
|
||||
};
|
||||
|
||||
static struct rc_keymap rc6_mce_map = {
|
||||
.map = {
|
||||
.scan = rc6_mce,
|
||||
.size = ARRAY_SIZE(rc6_mce),
|
||||
.ir_type = IR_TYPE_RC6,
|
||||
.name = RC_MAP_RC6_MCE,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_rc6_mce(void)
|
||||
{
|
||||
return ir_register_map(&rc6_mce_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_rc6_mce(void)
|
||||
{
|
||||
ir_unregister_map(&rc6_mce_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_rc6_mce)
|
||||
module_exit(exit_rc_map_rc6_mce)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
|
764
drivers/media/IR/lirc_dev.c
Normal file
764
drivers/media/IR/lirc_dev.c
Normal file
|
@ -0,0 +1,764 @@
|
|||
/*
|
||||
* LIRC base driver
|
||||
*
|
||||
* by Artur Lipowski <alipowski@interia.pl>
|
||||
*
|
||||
* 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/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/cdev.h>
|
||||
|
||||
#include <media/lirc.h>
|
||||
#include <media/lirc_dev.h>
|
||||
|
||||
static int debug;
|
||||
|
||||
#define IRCTL_DEV_NAME "BaseRemoteCtl"
|
||||
#define NOPLUG -1
|
||||
#define LOGHEAD "lirc_dev (%s[%d]): "
|
||||
|
||||
static dev_t lirc_base_dev;
|
||||
|
||||
struct irctl {
|
||||
struct lirc_driver d;
|
||||
int attached;
|
||||
int open;
|
||||
|
||||
struct mutex irctl_lock;
|
||||
struct lirc_buffer *buf;
|
||||
unsigned int chunk_size;
|
||||
|
||||
struct task_struct *task;
|
||||
long jiffies_to_wait;
|
||||
|
||||
struct cdev cdev;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(lirc_dev_lock);
|
||||
|
||||
static struct irctl *irctls[MAX_IRCTL_DEVICES];
|
||||
|
||||
/* Only used for sysfs but defined to void otherwise */
|
||||
static struct class *lirc_class;
|
||||
|
||||
/* helper function
|
||||
* initializes the irctl structure
|
||||
*/
|
||||
static void init_irctl(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)
|
||||
{
|
||||
dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
|
||||
|
||||
device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
|
||||
|
||||
if (ir->buf != ir->d.rbuf) {
|
||||
lirc_buffer_free(ir->buf);
|
||||
kfree(ir->buf);
|
||||
}
|
||||
ir->buf = NULL;
|
||||
}
|
||||
|
||||
/* helper function
|
||||
* reads key codes from driver and puts them into buffer
|
||||
* returns 0 on success
|
||||
*/
|
||||
static int add_to_buf(struct irctl *ir)
|
||||
{
|
||||
if (ir->d.add_to_buf) {
|
||||
int res = -ENODATA;
|
||||
int got_data = 0;
|
||||
|
||||
/*
|
||||
* service the device as long as it is returning
|
||||
* data and we have space
|
||||
*/
|
||||
get_data:
|
||||
res = ir->d.add_to_buf(ir->d.data, ir->buf);
|
||||
if (res == 0) {
|
||||
got_data++;
|
||||
goto get_data;
|
||||
}
|
||||
|
||||
if (res == -ENODEV)
|
||||
kthread_stop(ir->task);
|
||||
|
||||
return got_data ? 0 : res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* main function of the polling thread
|
||||
*/
|
||||
static int lirc_thread(void *irctl)
|
||||
{
|
||||
struct irctl *ir = irctl;
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "poll thread started\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
|
||||
do {
|
||||
if (ir->open) {
|
||||
if (ir->jiffies_to_wait) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(ir->jiffies_to_wait);
|
||||
}
|
||||
if (kthread_should_stop())
|
||||
break;
|
||||
if (!add_to_buf(ir))
|
||||
wake_up_interruptible(&ir->buf->wait_poll);
|
||||
} else {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
}
|
||||
} while (!kthread_should_stop());
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "poll thread ended\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct file_operations 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,
|
||||
.open = lirc_dev_fop_open,
|
||||
.release = lirc_dev_fop_close,
|
||||
};
|
||||
|
||||
static int lirc_cdev_add(struct irctl *ir)
|
||||
{
|
||||
int retval;
|
||||
struct lirc_driver *d = &ir->d;
|
||||
|
||||
if (d->fops) {
|
||||
cdev_init(&ir->cdev, d->fops);
|
||||
ir->cdev.owner = d->owner;
|
||||
} else {
|
||||
cdev_init(&ir->cdev, &fops);
|
||||
ir->cdev.owner = THIS_MODULE;
|
||||
}
|
||||
kobject_set_name(&ir->cdev.kobj, "lirc%d", d->minor);
|
||||
|
||||
retval = cdev_add(&ir->cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
|
||||
if (retval)
|
||||
kobject_put(&ir->cdev.kobj);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int lirc_register_driver(struct lirc_driver *d)
|
||||
{
|
||||
struct irctl *ir;
|
||||
int minor;
|
||||
int bytes_in_key;
|
||||
unsigned int chunk_size;
|
||||
unsigned int buffer_size;
|
||||
int err;
|
||||
|
||||
if (!d) {
|
||||
printk(KERN_ERR "lirc_dev: lirc_register_driver: "
|
||||
"driver pointer must be not NULL!\n");
|
||||
err = -EBADRQC;
|
||||
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",
|
||||
MAX_IRCTL_DEVICES-1, d->minor);
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (1 > d->code_length || (BUFLEN * 8) < d->code_length) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"code length in bits for minor (%d) "
|
||||
"must be less than %d!\n",
|
||||
d->minor, BUFLEN * 8);
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_dbg(d->dev, "lirc_dev: lirc_register_driver: sample_rate: %d\n",
|
||||
d->sample_rate);
|
||||
if (d->sample_rate) {
|
||||
if (2 > d->sample_rate || HZ < d->sample_rate) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"sample_rate must be between 2 and %d!\n", HZ);
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
}
|
||||
if (!d->add_to_buf) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"add_to_buf cannot be NULL when "
|
||||
"sample_rate is set\n");
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
}
|
||||
} else if (!(d->fops && d->fops->read) && !d->rbuf) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"fops->read and rbuf cannot all be NULL!\n");
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
} else if (!d->rbuf) {
|
||||
if (!(d->fops && d->fops->read && d->fops->poll &&
|
||||
d->fops->unlocked_ioctl)) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"neither read, poll nor unlocked_ioctl can be NULL!\n");
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&lirc_dev_lock);
|
||||
|
||||
minor = d->minor;
|
||||
|
||||
if (minor < 0) {
|
||||
/* find first free slot for driver */
|
||||
for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++)
|
||||
if (!irctls[minor])
|
||||
break;
|
||||
if (MAX_IRCTL_DEVICES == minor) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"no free slots for drivers!\n");
|
||||
err = -ENOMEM;
|
||||
goto out_lock;
|
||||
}
|
||||
} else if (irctls[minor]) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"minor (%d) just registered!\n", minor);
|
||||
err = -EBUSY;
|
||||
goto out_lock;
|
||||
}
|
||||
|
||||
ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
|
||||
if (!ir) {
|
||||
err = -ENOMEM;
|
||||
goto out_lock;
|
||||
}
|
||||
init_irctl(ir);
|
||||
irctls[minor] = ir;
|
||||
d->minor = minor;
|
||||
|
||||
if (d->sample_rate) {
|
||||
ir->jiffies_to_wait = HZ / d->sample_rate;
|
||||
} else {
|
||||
/* it means - wait for external event in task queue */
|
||||
ir->jiffies_to_wait = 0;
|
||||
}
|
||||
|
||||
/* some safety check 8-) */
|
||||
d->name[sizeof(d->name)-1] = '\0';
|
||||
|
||||
bytes_in_key = BITS_TO_LONGS(d->code_length) +
|
||||
(d->code_length % 8 ? 1 : 0);
|
||||
buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key;
|
||||
chunk_size = d->chunk_size ? d->chunk_size : bytes_in_key;
|
||||
|
||||
if (d->rbuf) {
|
||||
ir->buf = d->rbuf;
|
||||
} else {
|
||||
ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
|
||||
if (!ir->buf) {
|
||||
err = -ENOMEM;
|
||||
goto out_lock;
|
||||
}
|
||||
err = lirc_buffer_init(ir->buf, chunk_size, buffer_size);
|
||||
if (err) {
|
||||
kfree(ir->buf);
|
||||
goto out_lock;
|
||||
}
|
||||
}
|
||||
ir->chunk_size = ir->buf->chunk_size;
|
||||
|
||||
if (d->features == 0)
|
||||
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,
|
||||
"lirc%u", ir->d.minor);
|
||||
|
||||
if (d->sample_rate) {
|
||||
/* try to fire up polling thread */
|
||||
ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev");
|
||||
if (IS_ERR(ir->task)) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"cannot run poll thread for minor = %d\n",
|
||||
d->minor);
|
||||
err = -ECHILD;
|
||||
goto out_sysfs;
|
||||
}
|
||||
}
|
||||
|
||||
err = lirc_cdev_add(ir);
|
||||
if (err)
|
||||
goto out_sysfs;
|
||||
|
||||
ir->attached = 1;
|
||||
mutex_unlock(&lirc_dev_lock);
|
||||
|
||||
dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
return minor;
|
||||
|
||||
out_sysfs:
|
||||
device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
|
||||
out_lock:
|
||||
mutex_unlock(&lirc_dev_lock);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_register_driver);
|
||||
|
||||
int lirc_unregister_driver(int minor)
|
||||
{
|
||||
struct irctl *ir;
|
||||
|
||||
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);
|
||||
return -EBADRQC;
|
||||
}
|
||||
|
||||
ir = irctls[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);
|
||||
mutex_unlock(&lirc_dev_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* end up polling thread */
|
||||
if (ir->task)
|
||||
kthread_stop(ir->task);
|
||||
|
||||
dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
|
||||
ir->attached = 0;
|
||||
if (ir->open) {
|
||||
dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
wake_up_interruptible(&ir->buf->wait_poll);
|
||||
mutex_lock(&ir->irctl_lock);
|
||||
ir->d.set_use_dec(ir->d.data);
|
||||
module_put(ir->d.owner);
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
cdev_del(&ir->cdev);
|
||||
} else {
|
||||
cleanup(ir);
|
||||
cdev_del(&ir->cdev);
|
||||
kfree(ir);
|
||||
irctls[minor] = NULL;
|
||||
}
|
||||
|
||||
mutex_unlock(&lirc_dev_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_unregister_driver);
|
||||
|
||||
int lirc_dev_fop_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct irctl *ir;
|
||||
int retval = 0;
|
||||
|
||||
if (iminor(inode) >= MAX_IRCTL_DEVICES) {
|
||||
printk(KERN_WARNING "lirc_dev [%d]: open result = -ENODEV\n",
|
||||
iminor(inode));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (mutex_lock_interruptible(&lirc_dev_lock))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
ir = irctls[iminor(inode)];
|
||||
if (!ir) {
|
||||
retval = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
file->private_data = ir;
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
if (ir->d.minor == NOPLUG) {
|
||||
retval = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ir->open) {
|
||||
retval = -EBUSY;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (try_module_get(ir->d.owner)) {
|
||||
++ir->open;
|
||||
retval = ir->d.set_use_inc(ir->d.data);
|
||||
|
||||
if (retval) {
|
||||
module_put(ir->d.owner);
|
||||
--ir->open;
|
||||
} else {
|
||||
lirc_buffer_clear(ir->buf);
|
||||
}
|
||||
if (ir->task)
|
||||
wake_up_process(ir->task);
|
||||
}
|
||||
|
||||
error:
|
||||
if (ir)
|
||||
dev_dbg(ir->d.dev, LOGHEAD "open result = %d\n",
|
||||
ir->d.name, ir->d.minor, retval);
|
||||
|
||||
mutex_unlock(&lirc_dev_lock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_dev_fop_open);
|
||||
|
||||
int lirc_dev_fop_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct irctl *ir = irctls[iminor(inode)];
|
||||
|
||||
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;
|
||||
if (ir->attached) {
|
||||
ir->d.set_use_dec(ir->d.data);
|
||||
module_put(ir->d.owner);
|
||||
} else {
|
||||
cleanup(ir);
|
||||
irctls[ir->d.minor] = NULL;
|
||||
kfree(ir);
|
||||
}
|
||||
|
||||
mutex_unlock(&lirc_dev_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_dev_fop_close);
|
||||
|
||||
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;
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
if (!ir->attached) {
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
return POLLERR;
|
||||
}
|
||||
|
||||
poll_wait(file, &ir->buf->wait_poll, wait);
|
||||
|
||||
if (ir->buf)
|
||||
if (lirc_buffer_empty(ir->buf))
|
||||
ret = 0;
|
||||
else
|
||||
ret = POLLIN | POLLRDNORM;
|
||||
else
|
||||
ret = POLLERR;
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
|
||||
ir->d.name, ir->d.minor, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_dev_fop_poll);
|
||||
|
||||
long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned long mode;
|
||||
int result = 0;
|
||||
struct irctl *ir = file->private_data;
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
|
||||
ir->d.name, ir->d.minor, cmd);
|
||||
|
||||
if (ir->d.minor == NOPLUG || !ir->attached) {
|
||||
dev_dbg(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mutex_lock(&ir->irctl_lock);
|
||||
|
||||
switch (cmd) {
|
||||
case LIRC_GET_FEATURES:
|
||||
result = put_user(ir->d.features, (unsigned long *)arg);
|
||||
break;
|
||||
case LIRC_GET_REC_MODE:
|
||||
if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
|
||||
result = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
result = put_user(LIRC_REC2MODE
|
||||
(ir->d.features & LIRC_CAN_REC_MASK),
|
||||
(unsigned long *)arg);
|
||||
break;
|
||||
case LIRC_SET_REC_MODE:
|
||||
if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
|
||||
result = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
result = get_user(mode, (unsigned long *)arg);
|
||||
if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
|
||||
result = -EINVAL;
|
||||
/*
|
||||
* FIXME: We should actually set the mode somehow but
|
||||
* for now, lirc_serial doesn't support mode changing either
|
||||
*/
|
||||
break;
|
||||
case LIRC_GET_LENGTH:
|
||||
result = put_user(ir->d.code_length, (unsigned long *)arg);
|
||||
break;
|
||||
case LIRC_GET_MIN_TIMEOUT:
|
||||
if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
|
||||
ir->d.min_timeout == 0) {
|
||||
result = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
result = put_user(ir->d.min_timeout, (unsigned long *)arg);
|
||||
break;
|
||||
case LIRC_GET_MAX_TIMEOUT:
|
||||
if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
|
||||
ir->d.max_timeout == 0) {
|
||||
result = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
result = put_user(ir->d.max_timeout, (unsigned long *)arg);
|
||||
break;
|
||||
default:
|
||||
result = -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "ioctl result = %d\n",
|
||||
ir->d.name, ir->d.minor, result);
|
||||
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_dev_fop_ioctl);
|
||||
|
||||
ssize_t lirc_dev_fop_read(struct file *file,
|
||||
char *buffer,
|
||||
size_t length,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
|
||||
unsigned char buf[ir->chunk_size];
|
||||
int ret = 0, written = 0;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
if (mutex_lock_interruptible(&ir->irctl_lock))
|
||||
return -ERESTARTSYS;
|
||||
if (!ir->attached) {
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (length % ir->chunk_size) {
|
||||
dev_dbg(ir->d.dev, LOGHEAD "read result = -EINVAL\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* we add ourselves to the task queue before buffer check
|
||||
* to avoid losing scan code (in case when queue is awaken somewhere
|
||||
* between while condition checking and scheduling)
|
||||
*/
|
||||
add_wait_queue(&ir->buf->wait_poll, &wait);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
/*
|
||||
* while we didn't provide 'length' bytes, device is opened in blocking
|
||||
* mode and 'copy_to_user' is happy, wait for data.
|
||||
*/
|
||||
while (written < length && ret == 0) {
|
||||
if (lirc_buffer_empty(ir->buf)) {
|
||||
/* According to the read(2) man page, 'written' can be
|
||||
* returned as less than 'length', instead of blocking
|
||||
* again, returning -EWOULDBLOCK, or returning
|
||||
* -ERESTARTSYS */
|
||||
if (written)
|
||||
break;
|
||||
if (file->f_flags & O_NONBLOCK) {
|
||||
ret = -EWOULDBLOCK;
|
||||
break;
|
||||
}
|
||||
if (signal_pending(current)) {
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
schedule();
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
if (mutex_lock_interruptible(&ir->irctl_lock)) {
|
||||
ret = -ERESTARTSYS;
|
||||
remove_wait_queue(&ir->buf->wait_poll, &wait);
|
||||
set_current_state(TASK_RUNNING);
|
||||
goto out_unlocked;
|
||||
}
|
||||
|
||||
if (!ir->attached) {
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
lirc_buffer_read(ir->buf, buf);
|
||||
ret = copy_to_user((void *)buffer+written, buf,
|
||||
ir->buf->chunk_size);
|
||||
written += ir->buf->chunk_size;
|
||||
}
|
||||
}
|
||||
|
||||
remove_wait_queue(&ir->buf->wait_poll, &wait);
|
||||
set_current_state(TASK_RUNNING);
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
|
||||
out_unlocked:
|
||||
dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
|
||||
ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret);
|
||||
|
||||
return ret ? ret : written;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_dev_fop_read);
|
||||
|
||||
void *lirc_get_pdata(struct file *file)
|
||||
{
|
||||
void *data = NULL;
|
||||
|
||||
if (file && file->f_dentry && file->f_dentry->d_inode &&
|
||||
file->f_dentry->d_inode->i_rdev) {
|
||||
struct irctl *ir;
|
||||
ir = irctls[iminor(file->f_dentry->d_inode)];
|
||||
data = ir->d.data;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_get_pdata);
|
||||
|
||||
|
||||
ssize_t lirc_dev_fop_write(struct file *file, const char *buffer,
|
||||
size_t length, loff_t *ppos)
|
||||
{
|
||||
struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
if (!ir->attached)
|
||||
return -ENODEV;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_dev_fop_write);
|
||||
|
||||
|
||||
static int __init lirc_dev_init(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
lirc_class = class_create(THIS_MODULE, "lirc");
|
||||
if (IS_ERR(lirc_class)) {
|
||||
retval = PTR_ERR(lirc_class);
|
||||
printk(KERN_ERR "lirc_dev: class_create failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES,
|
||||
IRCTL_DEV_NAME);
|
||||
if (retval) {
|
||||
class_destroy(lirc_class);
|
||||
printk(KERN_ERR "lirc_dev: alloc_chrdev_region failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, "
|
||||
"major %d \n", MAJOR(lirc_base_dev));
|
||||
|
||||
error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void __exit lirc_dev_exit(void)
|
||||
{
|
||||
class_destroy(lirc_class);
|
||||
unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES);
|
||||
printk(KERN_INFO "lirc_dev: module unloaded\n");
|
||||
}
|
||||
|
||||
module_init(lirc_dev_init);
|
||||
module_exit(lirc_dev_exit);
|
||||
|
||||
MODULE_DESCRIPTION("LIRC base driver module");
|
||||
MODULE_AUTHOR("Artur Lipowski");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_param(debug, bool, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(debug, "Enable debugging messages");
|
1143
drivers/media/IR/mceusb.c
Normal file
1143
drivers/media/IR/mceusb.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -57,7 +57,7 @@ void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
|
|||
BUG_ON(in_interrupt());
|
||||
|
||||
videobuf_waiton(&buf->vb,0,0);
|
||||
videobuf_dma_unmap(q, dma);
|
||||
videobuf_dma_unmap(q->dev, dma);
|
||||
videobuf_dma_free(dma);
|
||||
buf->vb.state = VIDEOBUF_NEEDS_INIT;
|
||||
}
|
||||
|
|
|
@ -375,7 +375,7 @@ static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
|
|||
|
||||
static int vbi_open(struct saa7146_dev *dev, struct file *file)
|
||||
{
|
||||
struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
|
||||
struct saa7146_fh *fh = file->private_data;
|
||||
|
||||
u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
|
||||
int ret = 0;
|
||||
|
@ -437,7 +437,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
|
|||
|
||||
static void vbi_close(struct saa7146_dev *dev, struct file *file)
|
||||
{
|
||||
struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
|
||||
struct saa7146_fh *fh = file->private_data;
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
|
||||
|
||||
|
|
|
@ -1370,7 +1370,7 @@ static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
|
|||
|
||||
static int video_open(struct saa7146_dev *dev, struct file *file)
|
||||
{
|
||||
struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
|
||||
struct saa7146_fh *fh = file->private_data;
|
||||
struct saa7146_format *sfmt;
|
||||
|
||||
fh->video_fmt.width = 384;
|
||||
|
@ -1394,7 +1394,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
|
|||
|
||||
static void video_close(struct saa7146_dev *dev, struct file *file)
|
||||
{
|
||||
struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
|
||||
struct saa7146_fh *fh = file->private_data;
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
struct videobuf_queue *q = &fh->video_q;
|
||||
int err;
|
||||
|
|
|
@ -1249,7 +1249,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
|
|||
struct tda18271_config *cfg)
|
||||
{
|
||||
struct tda18271_priv *priv = NULL;
|
||||
int instance;
|
||||
int instance, ret;
|
||||
|
||||
mutex_lock(&tda18271_list_mutex);
|
||||
|
||||
|
@ -1268,10 +1268,12 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
|
|||
priv->cal_initialized = false;
|
||||
mutex_init(&priv->lock);
|
||||
|
||||
if (tda_fail(tda18271_get_id(fe)))
|
||||
ret = tda18271_get_id(fe);
|
||||
if (tda_fail(ret))
|
||||
goto fail;
|
||||
|
||||
if (tda_fail(tda18271_assign_map_layout(fe)))
|
||||
ret = tda18271_assign_map_layout(fe);
|
||||
if (tda_fail(ret))
|
||||
goto fail;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
|
|
@ -546,14 +546,11 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
|
|||
struct tuner_simple_priv *priv = fe->tuner_priv;
|
||||
u8 config, cb;
|
||||
u16 div;
|
||||
struct tunertype *tun;
|
||||
u8 buffer[4];
|
||||
int rc, IFPCoff, i;
|
||||
enum param_type desired_type;
|
||||
struct tuner_params *t_params;
|
||||
|
||||
tun = priv->tun;
|
||||
|
||||
/* IFPCoff = Video Intermediate Frequency - Vif:
|
||||
940 =16*58.75 NTSC/J (Japan)
|
||||
732 =16*45.75 M/N STD
|
||||
|
|
|
@ -217,6 +217,7 @@ static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
|
|||
return XC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* This routine is never used because the only time we read data from the
|
||||
i2c bus is when we read registers, and we want that to be an atomic i2c
|
||||
transaction in case we are on a multi-master bus */
|
||||
|
@ -231,6 +232,27 @@ static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
|
||||
{
|
||||
u8 buf[2] = { reg >> 8, reg & 0xff };
|
||||
u8 bval[2] = { 0, 0 };
|
||||
struct i2c_msg msg[2] = {
|
||||
{ .addr = priv->i2c_props.addr,
|
||||
.flags = 0, .buf = &buf[0], .len = 2 },
|
||||
{ .addr = priv->i2c_props.addr,
|
||||
.flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
|
||||
};
|
||||
|
||||
if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
|
||||
printk(KERN_WARNING "xc5000: I2C read failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
*val = (bval[0] << 8) | bval[1];
|
||||
return XC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static void xc_wait(int wait_ms)
|
||||
{
|
||||
|
@ -275,20 +297,14 @@ static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
|
|||
if (result == XC_RESULT_SUCCESS) {
|
||||
/* wait for busy flag to clear */
|
||||
while ((WatchDogTimer > 0) && (result == XC_RESULT_SUCCESS)) {
|
||||
buf[0] = 0;
|
||||
buf[1] = XREG_BUSY;
|
||||
|
||||
result = xc_send_i2c_data(priv, buf, 2);
|
||||
result = xc5000_readreg(priv, XREG_BUSY, (u16 *)buf);
|
||||
if (result == XC_RESULT_SUCCESS) {
|
||||
result = xc_read_i2c_data(priv, buf, 2);
|
||||
if (result == XC_RESULT_SUCCESS) {
|
||||
if ((buf[0] == 0) && (buf[1] == 0)) {
|
||||
/* busy flag cleared */
|
||||
if ((buf[0] == 0) && (buf[1] == 0)) {
|
||||
/* busy flag cleared */
|
||||
break;
|
||||
} else {
|
||||
xc_wait(5); /* wait 5 ms */
|
||||
WatchDogTimer--;
|
||||
}
|
||||
} else {
|
||||
xc_wait(5); /* wait 5 ms */
|
||||
WatchDogTimer--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -526,25 +542,6 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode)
|
|||
return found;
|
||||
}
|
||||
|
||||
static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
|
||||
{
|
||||
u8 buf[2] = { reg >> 8, reg & 0xff };
|
||||
u8 bval[2] = { 0, 0 };
|
||||
struct i2c_msg msg[2] = {
|
||||
{ .addr = priv->i2c_props.addr,
|
||||
.flags = 0, .buf = &buf[0], .len = 2 },
|
||||
{ .addr = priv->i2c_props.addr,
|
||||
.flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
|
||||
};
|
||||
|
||||
if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
|
||||
printk(KERN_WARNING "xc5000: I2C read failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
*val = (bval[0] << 8) | bval[1];
|
||||
return XC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int xc5000_fwupload(struct dvb_frontend *fe)
|
||||
{
|
||||
|
|
|
@ -565,7 +565,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct
|
|||
int result = 0;
|
||||
|
||||
lock_kernel();
|
||||
dvbdev = (struct dvb_device *)file->private_data;
|
||||
dvbdev = file->private_data;
|
||||
state = (struct dst_state *)dvbdev->priv;
|
||||
p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
|
||||
p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL);
|
||||
|
|
|
@ -207,7 +207,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
|
|||
}
|
||||
/* TODO */
|
||||
dvbdev->users--;
|
||||
if(dvbdev->users==-1 && dmxdev->exit==1) {
|
||||
if (dvbdev->users == 1 && dmxdev->exit == 1) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = NULL;
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
|
|
|
@ -1318,8 +1318,11 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
|
|||
|
||||
fragbuf[0] = connection_id;
|
||||
fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00;
|
||||
if ((status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen)) != 0)
|
||||
status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen);
|
||||
if (status) {
|
||||
status = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
timeout = jiffies + HZ / 2;
|
||||
written = 0;
|
||||
|
@ -1494,8 +1497,11 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
|
|||
|
||||
hdr[0] = slot;
|
||||
hdr[1] = connection_id;
|
||||
if ((status = copy_to_user(buf, hdr, 2)) != 0)
|
||||
status = copy_to_user(buf, hdr, 2);
|
||||
if (status) {
|
||||
status = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
status = pktlen;
|
||||
|
||||
exit:
|
||||
|
|
|
@ -1130,13 +1130,9 @@ static int dvbdmx_write(struct dmx_demux *demux, const char __user *buf, size_t
|
|||
if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
|
||||
return -EINVAL;
|
||||
|
||||
p = kmalloc(count, GFP_USER);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(p, buf, count)) {
|
||||
kfree(p);
|
||||
return -EFAULT;
|
||||
}
|
||||
p = memdup_user(buf, count);
|
||||
if (IS_ERR(p))
|
||||
return PTR_ERR(p);
|
||||
if (mutex_lock_interruptible(&dvbdemux->mutex)) {
|
||||
kfree(p);
|
||||
return -ERESTARTSYS;
|
||||
|
|
|
@ -465,7 +465,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
|
|||
if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
|
||||
fepriv->delay = fepriv->min_delay;
|
||||
|
||||
/* peform a tune */
|
||||
/* perform a tune */
|
||||
retval = dvb_frontend_swzigzag_autotune(fe,
|
||||
fepriv->check_wrapped);
|
||||
if (retval < 0) {
|
||||
|
@ -791,7 +791,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void dvb_frontend_get_frequeny_limits(struct dvb_frontend *fe,
|
||||
static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
|
||||
u32 *freq_min, u32 *freq_max)
|
||||
{
|
||||
*freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min);
|
||||
|
@ -815,7 +815,7 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
|
|||
u32 freq_max;
|
||||
|
||||
/* range check: frequency */
|
||||
dvb_frontend_get_frequeny_limits(fe, &freq_min, &freq_max);
|
||||
dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max);
|
||||
if ((freq_min && parms->frequency < freq_min) ||
|
||||
(freq_max && parms->frequency > freq_max)) {
|
||||
printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n",
|
||||
|
@ -1627,7 +1627,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
|||
case FE_GET_INFO: {
|
||||
struct dvb_frontend_info* info = parg;
|
||||
memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
|
||||
dvb_frontend_get_frequeny_limits(fe, &info->frequency_min, &info->frequency_max);
|
||||
dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max);
|
||||
|
||||
/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
|
||||
* do it, it is done for it. */
|
||||
|
@ -1726,7 +1726,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
|||
* (stv0299 for instance) take longer than 8msec to
|
||||
* respond to a set_voltage command. Those switches
|
||||
* need custom routines to switch properly. For all
|
||||
* other frontends, the following shoule work ok.
|
||||
* other frontends, the following should work ok.
|
||||
* Dish network legacy switches (as used by Dish500)
|
||||
* are controlled by sending 9-bit command words
|
||||
* spaced 8msec apart.
|
||||
|
|
|
@ -37,7 +37,7 @@ static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_pr
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_a800_table[] = {
|
||||
static struct ir_scancode ir_codes_a800_table[] = {
|
||||
{ 0x0201, KEY_PROG1 }, /* SOURCE */
|
||||
{ 0x0200, KEY_POWER }, /* POWER */
|
||||
{ 0x0205, KEY_1 }, /* 1 */
|
||||
|
@ -146,10 +146,12 @@ static struct dvb_usb_device_properties a800_properties = {
|
|||
.power_ctrl = a800_power_ctrl,
|
||||
.identify_state = a800_identify_state,
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_a800_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_a800_table),
|
||||
.rc_query = a800_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_a800_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_a800_table),
|
||||
.rc_query = a800_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ MODULE_PARM_DESC(debug,
|
|||
|
||||
#define deb_decode(args...) dprintk(dvb_usb_af9005_remote_debug,0x01,args)
|
||||
|
||||
struct dvb_usb_rc_key ir_codes_af9005_table[] = {
|
||||
struct ir_scancode ir_codes_af9005_table[] = {
|
||||
|
||||
{0x01b7, KEY_POWER},
|
||||
{0x01a7, KEY_VOLUMEUP},
|
||||
|
@ -133,7 +133,7 @@ int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event,
|
|||
for (i = 0; i < ir_codes_af9005_table_size; i++) {
|
||||
if (rc5_custom(&ir_codes_af9005_table[i]) == cust
|
||||
&& rc5_data(&ir_codes_af9005_table[i]) == dat) {
|
||||
*event = ir_codes_af9005_table[i].event;
|
||||
*event = ir_codes_af9005_table[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
deb_decode
|
||||
("key pressed, event %x\n", *event);
|
||||
|
|
|
@ -54,50 +54,6 @@ struct af9005_device_state {
|
|||
int led_state;
|
||||
};
|
||||
|
||||
static int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen,
|
||||
u8 *rbuf, u16 rlen, int delay_ms)
|
||||
{
|
||||
int actlen, ret = -ENOMEM;
|
||||
|
||||
if (wbuf == NULL || wlen == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
|
||||
return ret;
|
||||
|
||||
deb_xfer(">>> ");
|
||||
debug_dump(wbuf, wlen, deb_xfer);
|
||||
|
||||
ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev,
|
||||
2), wbuf, wlen,
|
||||
&actlen, 2000);
|
||||
|
||||
if (ret)
|
||||
err("bulk message failed: %d (%d/%d)", ret, wlen, actlen);
|
||||
else
|
||||
ret = actlen != wlen ? -1 : 0;
|
||||
|
||||
/* an answer is expected, and no error before */
|
||||
if (!ret && rbuf && rlen) {
|
||||
if (delay_ms)
|
||||
msleep(delay_ms);
|
||||
|
||||
ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
|
||||
0x01), rbuf,
|
||||
rlen, &actlen, 2000);
|
||||
|
||||
if (ret)
|
||||
err("recv bulk message failed: %d", ret);
|
||||
else {
|
||||
deb_xfer("<<< ");
|
||||
debug_dump(rbuf, actlen, deb_xfer);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
|
||||
int readwrite, int type, u8 * values, int len)
|
||||
{
|
||||
|
@ -146,7 +102,7 @@ static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
|
|||
obuf[8] = values[0];
|
||||
obuf[7] = command;
|
||||
|
||||
ret = af9005_usb_generic_rw(d, obuf, 16, ibuf, 17, 0);
|
||||
ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 17, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -534,7 +490,7 @@ int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf,
|
|||
buf[6] = wlen;
|
||||
for (i = 0; i < wlen; i++)
|
||||
buf[7 + i] = wbuf[i];
|
||||
ret = af9005_usb_generic_rw(d, buf, wlen + 7, ibuf, rlen + 7, 0);
|
||||
ret = dvb_usb_generic_rw(d, buf, wlen + 7, ibuf, rlen + 7, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ibuf[2] != 0x27) {
|
||||
|
@ -581,7 +537,7 @@ int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values,
|
|||
|
||||
obuf[6] = len;
|
||||
obuf[7] = address;
|
||||
ret = af9005_usb_generic_rw(d, obuf, 16, ibuf, 14, 0);
|
||||
ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 14, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ibuf[2] != 0x2b) {
|
||||
|
@ -882,7 +838,7 @@ static int af9005_rc_query(struct dvb_usb_device *d, u32 * event, int *state)
|
|||
obuf[2] = 0x40; /* read remote */
|
||||
obuf[3] = 1; /* rest of packet length */
|
||||
obuf[4] = st->sequence++; /* sequence number */
|
||||
ret = af9005_usb_generic_rw(d, obuf, 5, ibuf, 256, 0);
|
||||
ret = dvb_usb_generic_rw(d, obuf, 5, ibuf, 256, 0);
|
||||
if (ret) {
|
||||
err("rc query failed");
|
||||
return ret;
|
||||
|
@ -1069,10 +1025,15 @@ static struct dvb_usb_device_properties af9005_properties = {
|
|||
|
||||
.i2c_algo = &af9005_i2c_algo,
|
||||
|
||||
.rc_interval = 200,
|
||||
.rc_key_map = NULL,
|
||||
.rc_key_map_size = 0,
|
||||
.rc_query = af9005_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 200,
|
||||
.rc_key_map = NULL,
|
||||
.rc_key_map_size = 0,
|
||||
.rc_query = af9005_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 2,
|
||||
.generic_bulk_ctrl_endpoint_response = 1,
|
||||
|
||||
.num_device_descs = 3,
|
||||
.devices = {
|
||||
|
@ -1113,10 +1074,10 @@ static int __init af9005_usb_module_init(void)
|
|||
rc_keys_size = symbol_request(ir_codes_af9005_table_size);
|
||||
if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) {
|
||||
err("af9005_rc_decode function not found, disabling remote");
|
||||
af9005_properties.rc_query = NULL;
|
||||
af9005_properties.rc.legacy.rc_query = NULL;
|
||||
} else {
|
||||
af9005_properties.rc_key_map = rc_keys;
|
||||
af9005_properties.rc_key_map_size = *rc_keys_size;
|
||||
af9005_properties.rc.legacy.rc_key_map = rc_keys;
|
||||
af9005_properties.rc.legacy.rc_key_map_size = *rc_keys_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -3490,7 +3490,7 @@ extern u8 regmask[8];
|
|||
/* remote control decoder */
|
||||
extern int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len,
|
||||
u32 * event, int *state);
|
||||
extern struct dvb_usb_rc_key ir_codes_af9005_table[];
|
||||
extern struct ir_scancode ir_codes_af9005_table[];
|
||||
extern int ir_codes_af9005_table_size;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -735,7 +735,7 @@ static int af9015_download_firmware(struct usb_device *udev,
|
|||
|
||||
struct af9015_setup {
|
||||
unsigned int id;
|
||||
struct dvb_usb_rc_key *rc_key_map;
|
||||
struct ir_scancode *rc_key_map;
|
||||
unsigned int rc_key_map_size;
|
||||
u8 *ir_table;
|
||||
unsigned int ir_table_size;
|
||||
|
@ -847,8 +847,8 @@ static void af9015_set_remote_config(struct usb_device *udev,
|
|||
}
|
||||
|
||||
if (table) {
|
||||
props->rc_key_map = table->rc_key_map;
|
||||
props->rc_key_map_size = table->rc_key_map_size;
|
||||
props->rc.legacy.rc_key_map = table->rc_key_map;
|
||||
props->rc.legacy.rc_key_map_size = table->rc_key_map_size;
|
||||
af9015_config.ir_table = table->ir_table;
|
||||
af9015_config.ir_table_size = table->ir_table_size;
|
||||
}
|
||||
|
@ -878,8 +878,8 @@ static int af9015_read_config(struct usb_device *udev)
|
|||
deb_info("%s: IR mode:%d\n", __func__, val);
|
||||
for (i = 0; i < af9015_properties_count; i++) {
|
||||
if (val == AF9015_IR_MODE_DISABLED) {
|
||||
af9015_properties[i].rc_key_map = NULL;
|
||||
af9015_properties[i].rc_key_map_size = 0;
|
||||
af9015_properties[i].rc.legacy.rc_key_map = NULL;
|
||||
af9015_properties[i].rc.legacy.rc_key_map_size = 0;
|
||||
} else
|
||||
af9015_set_remote_config(udev, &af9015_properties[i]);
|
||||
}
|
||||
|
@ -1063,7 +1063,7 @@ static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
{
|
||||
u8 buf[8];
|
||||
struct req_t req = {GET_IR_CODE, 0, 0, 0, 0, sizeof(buf), buf};
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
int i, ret;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
@ -1075,10 +1075,10 @@ static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
if (!buf[1] && rc5_custom(&keymap[i]) == buf[0] &&
|
||||
rc5_data(&keymap[i]) == buf[2]) {
|
||||
*event = keymap[i].event;
|
||||
*event = keymap[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
break;
|
||||
}
|
||||
|
@ -1299,6 +1299,7 @@ static struct usb_device_id af9015_usb_table[] = {
|
|||
{USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)},
|
||||
/* 30 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T)},
|
||||
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4)},
|
||||
{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M)},
|
||||
{0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, af9015_usb_table);
|
||||
|
@ -1353,8 +1354,10 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
|
||||
.identify_state = af9015_identify_state,
|
||||
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = 150,
|
||||
.rc.legacy = {
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = 150,
|
||||
},
|
||||
|
||||
.i2c_algo = &af9015_i2c_algo,
|
||||
|
||||
|
@ -1460,8 +1463,10 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
|
||||
.identify_state = af9015_identify_state,
|
||||
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = 150,
|
||||
.rc.legacy = {
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = 150,
|
||||
},
|
||||
|
||||
.i2c_algo = &af9015_i2c_algo,
|
||||
|
||||
|
@ -1567,12 +1572,14 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
|
||||
.identify_state = af9015_identify_state,
|
||||
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = 150,
|
||||
.rc.legacy = {
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = 150,
|
||||
},
|
||||
|
||||
.i2c_algo = &af9015_i2c_algo,
|
||||
|
||||
.num_device_descs = 8, /* max 9 */
|
||||
.num_device_descs = 9, /* max 9 */
|
||||
.devices = {
|
||||
{
|
||||
.name = "AverMedia AVerTV Volar GPS 805 (A805)",
|
||||
|
@ -1617,6 +1624,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
.cold_ids = {&af9015_usb_table[30], NULL},
|
||||
.warm_ids = {NULL},
|
||||
},
|
||||
{
|
||||
.name = "AverMedia AVerTV Volar M (A815Mac)",
|
||||
.cold_ids = {&af9015_usb_table[32], NULL},
|
||||
.warm_ids = {NULL},
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -123,7 +123,7 @@ enum af9015_remote {
|
|||
|
||||
/* LeadTek - Y04G0051 */
|
||||
/* Leadtek WinFast DTV Dongle Gold */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_leadtek[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_leadtek[] = {
|
||||
{ 0x001e, KEY_1 },
|
||||
{ 0x001f, KEY_2 },
|
||||
{ 0x0020, KEY_3 },
|
||||
|
@ -227,7 +227,7 @@ static u8 af9015_ir_table_leadtek[] = {
|
|||
};
|
||||
|
||||
/* TwinHan AzureWave AD-TU700(704J) */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_twinhan[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_twinhan[] = {
|
||||
{ 0x053f, KEY_POWER },
|
||||
{ 0x0019, KEY_FAVORITES }, /* Favorite List */
|
||||
{ 0x0004, KEY_TEXT }, /* Teletext */
|
||||
|
@ -338,7 +338,7 @@ static u8 af9015_ir_table_twinhan[] = {
|
|||
};
|
||||
|
||||
/* A-Link DTU(m) */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_a_link[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_a_link[] = {
|
||||
{ 0x001e, KEY_1 },
|
||||
{ 0x001f, KEY_2 },
|
||||
{ 0x0020, KEY_3 },
|
||||
|
@ -381,7 +381,7 @@ static u8 af9015_ir_table_a_link[] = {
|
|||
};
|
||||
|
||||
/* MSI DIGIVOX mini II V3.0 */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_msi[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_msi[] = {
|
||||
{ 0x001e, KEY_1 },
|
||||
{ 0x001f, KEY_2 },
|
||||
{ 0x0020, KEY_3 },
|
||||
|
@ -424,7 +424,7 @@ static u8 af9015_ir_table_msi[] = {
|
|||
};
|
||||
|
||||
/* MYGICTV U718 */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_mygictv[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_mygictv[] = {
|
||||
{ 0x003d, KEY_SWITCHVIDEOMODE },
|
||||
/* TV / AV */
|
||||
{ 0x0545, KEY_POWER },
|
||||
|
@ -550,7 +550,7 @@ static u8 af9015_ir_table_kworld[] = {
|
|||
};
|
||||
|
||||
/* AverMedia Volar X */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_avermedia[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_avermedia[] = {
|
||||
{ 0x053d, KEY_PROG1 }, /* SOURCE */
|
||||
{ 0x0512, KEY_POWER }, /* POWER */
|
||||
{ 0x051e, KEY_1 }, /* 1 */
|
||||
|
@ -656,7 +656,7 @@ static u8 af9015_ir_table_avermedia_ks[] = {
|
|||
};
|
||||
|
||||
/* Digittrade DVB-T USB Stick */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_digittrade[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_digittrade[] = {
|
||||
{ 0x010f, KEY_LAST }, /* RETURN */
|
||||
{ 0x0517, KEY_TEXT }, /* TELETEXT */
|
||||
{ 0x0108, KEY_EPG }, /* EPG */
|
||||
|
@ -719,7 +719,7 @@ static u8 af9015_ir_table_digittrade[] = {
|
|||
};
|
||||
|
||||
/* TREKSTOR DVB-T USB Stick */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_trekstor[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_trekstor[] = {
|
||||
{ 0x0704, KEY_AGAIN }, /* Home */
|
||||
{ 0x0705, KEY_MUTE }, /* Mute */
|
||||
{ 0x0706, KEY_UP }, /* Up */
|
||||
|
@ -782,7 +782,7 @@ static u8 af9015_ir_table_trekstor[] = {
|
|||
};
|
||||
|
||||
/* MSI DIGIVOX mini III */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_msi_digivox_iii[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_msi_digivox_iii[] = {
|
||||
{ 0x0713, KEY_POWER }, /* [red power button] */
|
||||
{ 0x073b, KEY_VIDEO }, /* Source */
|
||||
{ 0x073e, KEY_ZOOM }, /* Zoom */
|
||||
|
|
|
@ -377,7 +377,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
u8 buf[] = {CMD_GET_IR_CODE};
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
u8 ircode[2];
|
||||
int i, ret;
|
||||
|
||||
|
@ -388,10 +388,10 @@ static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == ircode[0] &&
|
||||
rc5_data(&keymap[i]) == ircode[1]) {
|
||||
*event = keymap[i].event;
|
||||
*event = keymap[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
return 0;
|
||||
}
|
||||
|
@ -399,7 +399,7 @@ static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_anysee_table[] = {
|
||||
static struct ir_scancode ir_codes_anysee_table[] = {
|
||||
{ 0x0100, KEY_0 },
|
||||
{ 0x0101, KEY_1 },
|
||||
{ 0x0102, KEY_2 },
|
||||
|
@ -463,6 +463,11 @@ static int anysee_probe(struct usb_interface *intf,
|
|||
if (intf->num_altsetting < 1)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Anysee is always warm (its USB-bridge, Cypress FX2, uploads
|
||||
* firmware from eeprom). If dvb_usb_device_init() succeeds that
|
||||
* means d is a valid pointer.
|
||||
*/
|
||||
ret = dvb_usb_device_init(intf, &anysee_properties, THIS_MODULE, &d,
|
||||
adapter_nr);
|
||||
if (ret)
|
||||
|
@ -479,10 +484,7 @@ static int anysee_probe(struct usb_interface *intf,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (d)
|
||||
ret = anysee_init(d);
|
||||
|
||||
return ret;
|
||||
return anysee_init(d);
|
||||
}
|
||||
|
||||
static struct usb_device_id anysee_table[] = {
|
||||
|
@ -518,10 +520,12 @@ static struct dvb_usb_device_properties anysee_properties = {
|
|||
}
|
||||
},
|
||||
|
||||
.rc_key_map = ir_codes_anysee_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_anysee_table),
|
||||
.rc_query = anysee_rc_query,
|
||||
.rc_interval = 200, /* windows driver uses 500ms */
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_anysee_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_anysee_table),
|
||||
.rc_query = anysee_rc_query,
|
||||
.rc_interval = 200, /* windows driver uses 500ms */
|
||||
},
|
||||
|
||||
.i2c_algo = &anysee_i2c_algo,
|
||||
|
||||
|
|
|
@ -386,7 +386,7 @@ static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
}
|
||||
|
||||
/* keys for the enclosed remote control */
|
||||
static struct dvb_usb_rc_key ir_codes_az6027_table[] = {
|
||||
static struct ir_scancode ir_codes_az6027_table[] = {
|
||||
{ 0x01, KEY_1 },
|
||||
{ 0x02, KEY_2 },
|
||||
};
|
||||
|
@ -1125,10 +1125,13 @@ static struct dvb_usb_device_properties az6027_properties = {
|
|||
.power_ctrl = az6027_power_ctrl,
|
||||
.read_mac_address = az6027_read_mac_addr,
|
||||
*/
|
||||
.rc_key_map = ir_codes_az6027_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_az6027_table),
|
||||
.rc_interval = 400,
|
||||
.rc_query = az6027_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_az6027_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_az6027_table),
|
||||
.rc_interval = 400,
|
||||
.rc_query = az6027_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &az6027_i2c_algo,
|
||||
|
||||
.num_device_descs = 5,
|
||||
|
|
|
@ -84,7 +84,7 @@ static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_cinergyt2_table[] = {
|
||||
static struct ir_scancode ir_codes_cinergyt2_table[] = {
|
||||
{ 0x0401, KEY_POWER },
|
||||
{ 0x0402, KEY_1 },
|
||||
{ 0x0403, KEY_2 },
|
||||
|
@ -217,10 +217,12 @@ static struct dvb_usb_device_properties cinergyt2_properties = {
|
|||
|
||||
.power_ctrl = cinergyt2_power_ctrl,
|
||||
|
||||
.rc_interval = 50,
|
||||
.rc_key_map = ir_codes_cinergyt2_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_cinergyt2_table),
|
||||
.rc_query = cinergyt2_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 50,
|
||||
.rc_key_map = ir_codes_cinergyt2_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_cinergyt2_table),
|
||||
.rc_query = cinergyt2_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 1,
|
||||
|
||||
|
|
|
@ -385,7 +385,7 @@ static int cxusb_d680_dmb_streaming_ctrl(
|
|||
|
||||
static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
u8 ircode[4];
|
||||
int i;
|
||||
|
||||
|
@ -394,10 +394,10 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == ircode[2] &&
|
||||
rc5_data(&keymap[i]) == ircode[3]) {
|
||||
*event = keymap[i].event;
|
||||
*event = keymap[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
|
||||
return 0;
|
||||
|
@ -410,7 +410,7 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
|
||||
int *state)
|
||||
{
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
u8 ircode[4];
|
||||
int i;
|
||||
struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
|
||||
|
@ -422,10 +422,10 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
|
|||
if (cxusb_i2c_xfer(&d->i2c_adap, &msg, 1) != 1)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == ircode[1] &&
|
||||
rc5_data(&keymap[i]) == ircode[2]) {
|
||||
*event = keymap[i].event;
|
||||
*event = keymap[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
|
||||
return 0;
|
||||
|
@ -438,7 +438,7 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
|
|||
static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
|
||||
int *state)
|
||||
{
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
u8 ircode[2];
|
||||
int i;
|
||||
|
||||
|
@ -448,10 +448,10 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
|
|||
if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == ircode[0] &&
|
||||
rc5_data(&keymap[i]) == ircode[1]) {
|
||||
*event = keymap[i].event;
|
||||
*event = keymap[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
|
||||
return 0;
|
||||
|
@ -461,7 +461,7 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_dvico_mce_table[] = {
|
||||
static struct ir_scancode ir_codes_dvico_mce_table[] = {
|
||||
{ 0xfe02, KEY_TV },
|
||||
{ 0xfe0e, KEY_MP3 },
|
||||
{ 0xfe1a, KEY_DVD },
|
||||
|
@ -509,7 +509,7 @@ static struct dvb_usb_rc_key ir_codes_dvico_mce_table[] = {
|
|||
{ 0xfe4e, KEY_POWER },
|
||||
};
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_dvico_portable_table[] = {
|
||||
static struct ir_scancode ir_codes_dvico_portable_table[] = {
|
||||
{ 0xfc02, KEY_SETUP }, /* Profile */
|
||||
{ 0xfc43, KEY_POWER2 },
|
||||
{ 0xfc06, KEY_EPG },
|
||||
|
@ -548,7 +548,7 @@ static struct dvb_usb_rc_key ir_codes_dvico_portable_table[] = {
|
|||
{ 0xfc00, KEY_UNKNOWN }, /* HD */
|
||||
};
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_d680_dmb_table[] = {
|
||||
static struct ir_scancode ir_codes_d680_dmb_table[] = {
|
||||
{ 0x0038, KEY_UNKNOWN }, /* TV/AV */
|
||||
{ 0x080c, KEY_ZOOM },
|
||||
{ 0x0800, KEY_0 },
|
||||
|
@ -923,7 +923,7 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
return -EIO;
|
||||
|
||||
/* try to determine if there is no IR decoder on the I2C bus */
|
||||
for (i = 0; adap->dev->props.rc_key_map != NULL && i < 5; i++) {
|
||||
for (i = 0; adap->dev->props.rc.legacy.rc_key_map != NULL && i < 5; i++) {
|
||||
msleep(20);
|
||||
if (cxusb_i2c_xfer(&adap->dev->i2c_adap, &msg, 1) != 1)
|
||||
goto no_IR;
|
||||
|
@ -931,7 +931,7 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
continue;
|
||||
if (ircode[2] + ircode[3] != 0xff) {
|
||||
no_IR:
|
||||
adap->dev->props.rc_key_map = NULL;
|
||||
adap->dev->props.rc.legacy.rc_key_map = NULL;
|
||||
info("No IR receiver detected on this device.");
|
||||
break;
|
||||
}
|
||||
|
@ -1451,10 +1451,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
|
|||
|
||||
.i2c_algo = &cxusb_i2c_algo,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
|
@ -1502,10 +1504,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
|
|||
|
||||
.i2c_algo = &cxusb_i2c_algo,
|
||||
|
||||
.rc_interval = 150,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 150,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
|
@ -1561,10 +1565,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
|
|||
|
||||
.i2c_algo = &cxusb_i2c_algo,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
.num_device_descs = 1,
|
||||
|
@ -1611,10 +1617,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
|
|||
|
||||
.i2c_algo = &cxusb_i2c_algo,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
|
@ -1660,10 +1668,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
|
|||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_query = cxusb_bluebird2_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_query = cxusb_bluebird2_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
|
@ -1708,10 +1718,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
|
|||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_bluebird2_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_bluebird2_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
|
@ -1758,10 +1770,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
|
|||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
|
@ -1849,10 +1863,12 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
|
|||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
|
@ -1897,10 +1913,12 @@ static struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
|
|||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_d680_dmb_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_d680_dmb_table),
|
||||
.rc_query = cxusb_d680_dmb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_d680_dmb_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_d680_dmb_table),
|
||||
.rc_query = cxusb_d680_dmb_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
|
@ -1946,10 +1964,12 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
|
|||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_d680_dmb_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_d680_dmb_table),
|
||||
.rc_query = cxusb_d680_dmb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_d680_dmb_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_d680_dmb_table),
|
||||
.rc_query = cxusb_d680_dmb_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
|
|
|
@ -60,6 +60,7 @@ extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
|
|||
extern struct i2c_algorithm dib0700_i2c_algo;
|
||||
extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
|
||||
struct dvb_usb_device_description **desc, int *cold);
|
||||
extern int dib0700_change_protocol(void *priv, u64 ir_type);
|
||||
|
||||
extern int dib0700_device_count;
|
||||
extern int dvb_usb_dib0700_ir_proto;
|
||||
|
|
|
@ -13,10 +13,6 @@ int dvb_usb_dib0700_debug;
|
|||
module_param_named(debug,dvb_usb_dib0700_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS);
|
||||
|
||||
int dvb_usb_dib0700_ir_proto = 1;
|
||||
module_param(dvb_usb_dib0700_ir_proto, int, 0644);
|
||||
MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6).");
|
||||
|
||||
static int nb_packet_buffer_size = 21;
|
||||
module_param(nb_packet_buffer_size, int, 0644);
|
||||
MODULE_PARM_DESC(nb_packet_buffer_size,
|
||||
|
@ -53,7 +49,7 @@ static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
|
|||
int status;
|
||||
|
||||
deb_data(">>> ");
|
||||
debug_dump(tx,txlen,deb_data);
|
||||
debug_dump(tx, txlen, deb_data);
|
||||
|
||||
status = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev,0),
|
||||
tx[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, tx, txlen,
|
||||
|
@ -98,7 +94,7 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen
|
|||
deb_info("ep 0 read error (status = %d)\n",status);
|
||||
|
||||
deb_data("<<< ");
|
||||
debug_dump(rx,rxlen,deb_data);
|
||||
debug_dump(rx, rxlen, deb_data);
|
||||
|
||||
return status; /* length in case of success */
|
||||
}
|
||||
|
@ -106,28 +102,29 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen
|
|||
int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
|
||||
{
|
||||
u8 buf[3] = { REQUEST_SET_GPIO, gpio, ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6) };
|
||||
return dib0700_ctrl_wr(d,buf,3);
|
||||
return dib0700_ctrl_wr(d, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
|
||||
{
|
||||
struct dib0700_state *st = d->priv;
|
||||
u8 b[3];
|
||||
int ret;
|
||||
struct dib0700_state *st = d->priv;
|
||||
u8 b[3];
|
||||
int ret;
|
||||
|
||||
if (st->fw_version >= 0x10201) {
|
||||
b[0] = REQUEST_SET_USB_XFER_LEN;
|
||||
b[1] = (nb_ts_packets >> 8)&0xff;
|
||||
b[2] = nb_ts_packets & 0xff;
|
||||
if (st->fw_version >= 0x10201) {
|
||||
b[0] = REQUEST_SET_USB_XFER_LEN;
|
||||
b[1] = (nb_ts_packets >> 8) & 0xff;
|
||||
b[2] = nb_ts_packets & 0xff;
|
||||
|
||||
deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
|
||||
deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
|
||||
|
||||
ret = dib0700_ctrl_wr(d, b, 3);
|
||||
} else {
|
||||
deb_info("this firmware does not allow to change the USB xfer len\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
return ret;
|
||||
ret = dib0700_ctrl_wr(d, b, sizeof(b));
|
||||
} else {
|
||||
deb_info("this firmware does not allow to change the USB xfer len\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -178,7 +175,8 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
|
|||
value = ((en_start << 7) | (en_stop << 6) |
|
||||
(msg[i].len & 0x3F)) << 8 | i2c_dest;
|
||||
/* I2C ctrl + FE bus; */
|
||||
index = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30);
|
||||
index = ((gen_mode << 6) & 0xC0) |
|
||||
((bus_mode << 4) & 0x30);
|
||||
|
||||
result = usb_control_msg(d->udev,
|
||||
usb_rcvctrlpipe(d->udev, 0),
|
||||
|
@ -198,11 +196,12 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
|
|||
} else {
|
||||
/* Write request */
|
||||
buf[0] = REQUEST_NEW_I2C_WRITE;
|
||||
buf[1] = (msg[i].addr << 1);
|
||||
buf[1] = msg[i].addr << 1;
|
||||
buf[2] = (en_start << 7) | (en_stop << 6) |
|
||||
(msg[i].len & 0x3F);
|
||||
/* I2C ctrl + FE bus; */
|
||||
buf[3] = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30);
|
||||
buf[3] = ((gen_mode << 6) & 0xC0) |
|
||||
((bus_mode << 4) & 0x30);
|
||||
/* The Actual i2c payload */
|
||||
memcpy(&buf[4], msg[i].buf, msg[i].len);
|
||||
|
||||
|
@ -240,7 +239,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
|
|||
|
||||
for (i = 0; i < num; i++) {
|
||||
/* fill in the address */
|
||||
buf[1] = (msg[i].addr << 1);
|
||||
buf[1] = msg[i].addr << 1;
|
||||
/* fill the buffer */
|
||||
memcpy(&buf[2], msg[i].buf, msg[i].len);
|
||||
|
||||
|
@ -368,7 +367,8 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
|
|||
u8 buf[260];
|
||||
|
||||
while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) {
|
||||
deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n",hx.addr, hx.len, hx.chk);
|
||||
deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n",
|
||||
hx.addr, hx.len, hx.chk);
|
||||
|
||||
buf[0] = hx.len;
|
||||
buf[1] = (hx.addr >> 8) & 0xff;
|
||||
|
@ -408,16 +408,16 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
|
|||
REQUEST_GET_VERSION,
|
||||
USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
|
||||
b, sizeof(b), USB_CTRL_GET_TIMEOUT);
|
||||
fw_version = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
|
||||
fw_version = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
|
||||
|
||||
/* set the buffer size - DVB-USB is allocating URB buffers
|
||||
* only after the firwmare download was successful */
|
||||
for (i = 0; i < dib0700_device_count; i++) {
|
||||
for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters;
|
||||
adap_num++) {
|
||||
if (fw_version >= 0x10201)
|
||||
if (fw_version >= 0x10201) {
|
||||
dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
|
||||
else {
|
||||
} else {
|
||||
/* for fw version older than 1.20.1,
|
||||
* the buffersize has to be n times 512 */
|
||||
dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
|
||||
|
@ -453,7 +453,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
if (st->disable_streaming_master_mode == 1)
|
||||
b[2] = 0x00;
|
||||
else
|
||||
b[2] = (0x01 << 4); /* Master mode */
|
||||
b[2] = 0x01 << 4; /* Master mode */
|
||||
|
||||
b[3] = 0x00;
|
||||
|
||||
|
@ -466,11 +466,44 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
|
||||
b[2] |= st->channel_state;
|
||||
|
||||
deb_info("data for streaming: %x %x\n",b[1],b[2]);
|
||||
deb_info("data for streaming: %x %x\n", b[1], b[2]);
|
||||
|
||||
return dib0700_ctrl_wr(adap->dev, b, 4);
|
||||
}
|
||||
|
||||
int dib0700_change_protocol(void *priv, u64 ir_type)
|
||||
{
|
||||
struct dvb_usb_device *d = priv;
|
||||
struct dib0700_state *st = d->priv;
|
||||
u8 rc_setup[3] = { REQUEST_SET_RC, 0, 0 };
|
||||
int new_proto, ret;
|
||||
|
||||
/* Set the IR mode */
|
||||
if (ir_type == IR_TYPE_RC5)
|
||||
new_proto = 1;
|
||||
else if (ir_type == IR_TYPE_NEC)
|
||||
new_proto = 0;
|
||||
else if (ir_type == IR_TYPE_RC6) {
|
||||
if (st->fw_version < 0x10200)
|
||||
return -EINVAL;
|
||||
|
||||
new_proto = 2;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
rc_setup[1] = new_proto;
|
||||
|
||||
ret = dib0700_ctrl_wr(d, rc_setup, sizeof(rc_setup));
|
||||
if (ret < 0) {
|
||||
err("ir protocol setup failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
d->props.rc.core.protocol = ir_type;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Number of keypresses to ignore before start repeating */
|
||||
#define RC_REPEAT_DELAY_V1_20 10
|
||||
|
||||
|
@ -478,7 +511,13 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
struct dib0700_rc_response {
|
||||
u8 report_id;
|
||||
u8 data_state;
|
||||
u16 system;
|
||||
union {
|
||||
u16 system16;
|
||||
struct {
|
||||
u8 system;
|
||||
u8 not_system;
|
||||
};
|
||||
};
|
||||
u8 data;
|
||||
u8 not_data;
|
||||
};
|
||||
|
@ -487,14 +526,10 @@ struct dib0700_rc_response {
|
|||
static void dib0700_rc_urb_completion(struct urb *purb)
|
||||
{
|
||||
struct dvb_usb_device *d = purb->context;
|
||||
struct dvb_usb_rc_key *keymap;
|
||||
struct dib0700_state *st;
|
||||
struct dib0700_rc_response poll_reply;
|
||||
u8 *buf;
|
||||
int found = 0;
|
||||
u32 event;
|
||||
int state;
|
||||
int i;
|
||||
struct dib0700_rc_response *poll_reply;
|
||||
u32 uninitialized_var(keycode);
|
||||
u8 toggle;
|
||||
|
||||
deb_info("%s()\n", __func__);
|
||||
if (d == NULL)
|
||||
|
@ -506,9 +541,8 @@ static void dib0700_rc_urb_completion(struct urb *purb)
|
|||
return;
|
||||
}
|
||||
|
||||
keymap = d->props.rc_key_map;
|
||||
st = d->priv;
|
||||
buf = (u8 *)purb->transfer_buffer;
|
||||
poll_reply = purb->transfer_buffer;
|
||||
|
||||
if (purb->status < 0) {
|
||||
deb_info("discontinuing polling\n");
|
||||
|
@ -521,104 +555,52 @@ static void dib0700_rc_urb_completion(struct urb *purb)
|
|||
goto resubmit;
|
||||
}
|
||||
|
||||
/* Set initial results in case we exit the function early */
|
||||
event = 0;
|
||||
state = REMOTE_NO_KEY_PRESSED;
|
||||
deb_data("IR ID = %02X state = %02X System = %02X %02X Cmd = %02X %02X (len %d)\n",
|
||||
poll_reply->report_id, poll_reply->data_state,
|
||||
poll_reply->system, poll_reply->not_system,
|
||||
poll_reply->data, poll_reply->not_data,
|
||||
purb->actual_length);
|
||||
|
||||
deb_data("IR raw %02X %02X %02X %02X %02X %02X (len %d)\n", buf[0],
|
||||
buf[1], buf[2], buf[3], buf[4], buf[5], purb->actual_length);
|
||||
|
||||
switch (dvb_usb_dib0700_ir_proto) {
|
||||
case 0:
|
||||
/* NEC Protocol */
|
||||
poll_reply.report_id = 0;
|
||||
poll_reply.data_state = 1;
|
||||
poll_reply.system = buf[2];
|
||||
poll_reply.data = buf[4];
|
||||
poll_reply.not_data = buf[5];
|
||||
switch (d->props.rc.core.protocol) {
|
||||
case IR_TYPE_NEC:
|
||||
toggle = 0;
|
||||
|
||||
/* NEC protocol sends repeat code as 0 0 0 FF */
|
||||
if ((poll_reply.system == 0x00) && (poll_reply.data == 0x00)
|
||||
&& (poll_reply.not_data == 0xff)) {
|
||||
poll_reply.data_state = 2;
|
||||
if ((poll_reply->system == 0x00) && (poll_reply->data == 0x00)
|
||||
&& (poll_reply->not_data == 0xff)) {
|
||||
poll_reply->data_state = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((poll_reply->system ^ poll_reply->not_system) != 0xff) {
|
||||
deb_data("NEC extended protocol\n");
|
||||
/* NEC extended code - 24 bits */
|
||||
keycode = poll_reply->system16 << 8 | poll_reply->data;
|
||||
} else {
|
||||
deb_data("NEC normal protocol\n");
|
||||
/* normal NEC code - 16 bits */
|
||||
keycode = poll_reply->system << 8 | poll_reply->data;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
deb_data("RC5 protocol\n");
|
||||
/* RC5 Protocol */
|
||||
poll_reply.report_id = buf[0];
|
||||
poll_reply.data_state = buf[1];
|
||||
poll_reply.system = (buf[2] << 8) | buf[3];
|
||||
poll_reply.data = buf[4];
|
||||
poll_reply.not_data = buf[5];
|
||||
toggle = poll_reply->report_id;
|
||||
keycode = poll_reply->system16 << 8 | poll_reply->data;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ((poll_reply.data + poll_reply.not_data) != 0xff) {
|
||||
if ((poll_reply->data + poll_reply->not_data) != 0xff) {
|
||||
/* Key failed integrity check */
|
||||
err("key failed integrity check: %04x %02x %02x",
|
||||
poll_reply.system,
|
||||
poll_reply.data, poll_reply.not_data);
|
||||
poll_reply->system,
|
||||
poll_reply->data, poll_reply->not_data);
|
||||
goto resubmit;
|
||||
}
|
||||
|
||||
deb_data("rid=%02x ds=%02x sm=%04x d=%02x nd=%02x\n",
|
||||
poll_reply.report_id, poll_reply.data_state,
|
||||
poll_reply.system, poll_reply.data, poll_reply.not_data);
|
||||
|
||||
/* Find the key in the map */
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) &&
|
||||
rc5_data(&keymap[i]) == poll_reply.data) {
|
||||
event = keymap[i].event;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
err("Unknown remote controller key: %04x %02x %02x",
|
||||
poll_reply.system, poll_reply.data, poll_reply.not_data);
|
||||
d->last_event = 0;
|
||||
goto resubmit;
|
||||
}
|
||||
|
||||
if (poll_reply.data_state == 1) {
|
||||
/* New key hit */
|
||||
st->rc_counter = 0;
|
||||
event = keymap[i].event;
|
||||
state = REMOTE_KEY_PRESSED;
|
||||
d->last_event = keymap[i].event;
|
||||
} else if (poll_reply.data_state == 2) {
|
||||
/* Key repeated */
|
||||
st->rc_counter++;
|
||||
|
||||
/* prevents unwanted double hits */
|
||||
if (st->rc_counter > RC_REPEAT_DELAY_V1_20) {
|
||||
event = d->last_event;
|
||||
state = REMOTE_KEY_PRESSED;
|
||||
st->rc_counter = RC_REPEAT_DELAY_V1_20;
|
||||
}
|
||||
} else {
|
||||
err("Unknown data state [%d]", poll_reply.data_state);
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case REMOTE_NO_KEY_PRESSED:
|
||||
break;
|
||||
case REMOTE_KEY_PRESSED:
|
||||
deb_info("key pressed\n");
|
||||
d->last_event = event;
|
||||
case REMOTE_KEY_REPEAT:
|
||||
deb_info("key repeated\n");
|
||||
input_event(d->rc_input_dev, EV_KEY, event, 1);
|
||||
input_sync(d->rc_input_dev);
|
||||
input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
|
||||
input_sync(d->rc_input_dev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ir_keydown(d->rc_input_dev, keycode, toggle);
|
||||
|
||||
resubmit:
|
||||
/* Clean the buffer before we requeue */
|
||||
|
@ -631,21 +613,10 @@ static void dib0700_rc_urb_completion(struct urb *purb)
|
|||
int dib0700_rc_setup(struct dvb_usb_device *d)
|
||||
{
|
||||
struct dib0700_state *st = d->priv;
|
||||
u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0};
|
||||
struct urb *purb;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (d->props.rc_key_map == NULL)
|
||||
return 0;
|
||||
|
||||
/* Set the IR mode */
|
||||
i = dib0700_ctrl_wr(d, rc_setup, 3);
|
||||
if (i<0) {
|
||||
err("ir protocol setup failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Poll-based. Don't initialize bulk mode */
|
||||
if (st->fw_version < 0x10200)
|
||||
return 0;
|
||||
|
||||
|
@ -653,14 +624,14 @@ int dib0700_rc_setup(struct dvb_usb_device *d)
|
|||
purb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (purb == NULL) {
|
||||
err("rc usb alloc urb failed\n");
|
||||
return -1;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
purb->transfer_buffer = kzalloc(RC_MSG_SIZE_V1_20, GFP_KERNEL);
|
||||
if (purb->transfer_buffer == NULL) {
|
||||
err("rc kzalloc failed\n");
|
||||
usb_free_urb(purb);
|
||||
return -1;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
purb->status = -EINPROGRESS;
|
||||
|
@ -669,12 +640,10 @@ int dib0700_rc_setup(struct dvb_usb_device *d)
|
|||
dib0700_rc_urb_completion, d);
|
||||
|
||||
ret = usb_submit_urb(purb, GFP_ATOMIC);
|
||||
if (ret != 0) {
|
||||
if (ret)
|
||||
err("rc submit urb failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dib0700_probe(struct usb_interface *intf,
|
||||
|
@ -698,6 +667,15 @@ static int dib0700_probe(struct usb_interface *intf,
|
|||
st->fw_version = fw_version;
|
||||
st->nb_packet_buffer_size = (u32)nb_packet_buffer_size;
|
||||
|
||||
/* Disable polling mode on newer firmwares */
|
||||
if (st->fw_version >= 0x10200)
|
||||
dev->props.rc.core.bulk_mode = true;
|
||||
else
|
||||
dev->props.rc.core.bulk_mode = false;
|
||||
|
||||
/* Need a higher delay, to avoid wrong repeat */
|
||||
dev->rc_input_dev->rep[REP_DELAY] = 500;
|
||||
|
||||
dib0700_rc_setup(dev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -473,16 +473,19 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
|
|||
/* Number of keypresses to ignore before start repeating */
|
||||
#define RC_REPEAT_DELAY 6
|
||||
|
||||
static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
/*
|
||||
* This function is used only when firmware is < 1.20 version. Newer
|
||||
* firmwares use bulk mode, with functions implemented at dib0700_core,
|
||||
* at dib0700_rc_urb_completion()
|
||||
*/
|
||||
static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
|
||||
{
|
||||
u8 key[4];
|
||||
u32 keycode;
|
||||
u8 toggle;
|
||||
int i;
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct dib0700_state *st = d->priv;
|
||||
|
||||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
if (st->fw_version >= 0x10200) {
|
||||
/* For 1.20 firmware , We need to keep the RC polling
|
||||
callback so we can reuse the input device setup in
|
||||
|
@ -491,348 +494,45 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
i=dib0700_ctrl_rd(d,rc_request,2,key,4);
|
||||
if (i<=0) {
|
||||
i = dib0700_ctrl_rd(d, rc_request, 2, key, 4);
|
||||
if (i <= 0) {
|
||||
err("RC Query Failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* losing half of KEY_0 events from Philipps rc5 remotes.. */
|
||||
if (key[0]==0 && key[1]==0 && key[2]==0 && key[3]==0) return 0;
|
||||
if (key[0] == 0 && key[1] == 0 && key[2] == 0 && key[3] == 0)
|
||||
return 0;
|
||||
|
||||
/* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]); */
|
||||
|
||||
dib0700_rc_setup(d); /* reset ir sensor data to prevent false events */
|
||||
|
||||
switch (dvb_usb_dib0700_ir_proto) {
|
||||
case 0: {
|
||||
d->last_event = 0;
|
||||
switch (d->props.rc.core.protocol) {
|
||||
case IR_TYPE_NEC:
|
||||
/* NEC protocol sends repeat code as 0 0 0 FF */
|
||||
if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
|
||||
(key[3] == 0xFF)) {
|
||||
st->rc_counter++;
|
||||
if (st->rc_counter > RC_REPEAT_DELAY) {
|
||||
*event = d->last_event;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
st->rc_counter = RC_REPEAT_DELAY;
|
||||
}
|
||||
return 0;
|
||||
(key[3] == 0xff))
|
||||
keycode = d->last_event;
|
||||
else {
|
||||
keycode = key[3-2] << 8 | key[3-3];
|
||||
d->last_event = keycode;
|
||||
}
|
||||
for (i=0;i<d->props.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == key[3-2] &&
|
||||
rc5_data(&keymap[i]) == key[3-3]) {
|
||||
st->rc_counter = 0;
|
||||
*event = keymap[i].event;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
d->last_event = keymap[i].event;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
/* RC-5 protocol changes toggle bit on new keypress */
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == key[3-2] &&
|
||||
rc5_data(&keymap[i]) == key[3-3]) {
|
||||
if (d->last_event == keymap[i].event &&
|
||||
key[3-1] == st->rc_toggle) {
|
||||
st->rc_counter++;
|
||||
/* prevents unwanted double hits */
|
||||
if (st->rc_counter > RC_REPEAT_DELAY) {
|
||||
*event = d->last_event;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
st->rc_counter = RC_REPEAT_DELAY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
st->rc_counter = 0;
|
||||
*event = keymap[i].event;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
st->rc_toggle = key[3-1];
|
||||
d->last_event = keymap[i].event;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ir_keydown(d->rc_input_dev, keycode, 0);
|
||||
break;
|
||||
default:
|
||||
/* RC-5 protocol changes toggle bit on new keypress */
|
||||
keycode = key[3-2] << 8 | key[3-3];
|
||||
toggle = key[3-1];
|
||||
ir_keydown(d->rc_input_dev, keycode, toggle);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
err("Unknown remote controller key: %2X %2X %2X %2X", (int) key[3-2], (int) key[3-3], (int) key[3-1], (int) key[3]);
|
||||
d->last_event = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_dib0700_table[] = {
|
||||
/* Key codes for the tiny Pinnacle remote*/
|
||||
{ 0x0700, KEY_MUTE },
|
||||
{ 0x0701, KEY_MENU }, /* Pinnacle logo */
|
||||
{ 0x0739, KEY_POWER },
|
||||
{ 0x0703, KEY_VOLUMEUP },
|
||||
{ 0x0709, KEY_VOLUMEDOWN },
|
||||
{ 0x0706, KEY_CHANNELUP },
|
||||
{ 0x070c, KEY_CHANNELDOWN },
|
||||
{ 0x070f, KEY_1 },
|
||||
{ 0x0715, KEY_2 },
|
||||
{ 0x0710, KEY_3 },
|
||||
{ 0x0718, KEY_4 },
|
||||
{ 0x071b, KEY_5 },
|
||||
{ 0x071e, KEY_6 },
|
||||
{ 0x0711, KEY_7 },
|
||||
{ 0x0721, KEY_8 },
|
||||
{ 0x0712, KEY_9 },
|
||||
{ 0x0727, KEY_0 },
|
||||
{ 0x0724, KEY_SCREEN }, /* 'Square' key */
|
||||
{ 0x072a, KEY_TEXT }, /* 'T' key */
|
||||
{ 0x072d, KEY_REWIND },
|
||||
{ 0x0730, KEY_PLAY },
|
||||
{ 0x0733, KEY_FASTFORWARD },
|
||||
{ 0x0736, KEY_RECORD },
|
||||
{ 0x073c, KEY_STOP },
|
||||
{ 0x073f, KEY_CANCEL }, /* '?' key */
|
||||
/* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
|
||||
{ 0xeb01, KEY_POWER },
|
||||
{ 0xeb02, KEY_1 },
|
||||
{ 0xeb03, KEY_2 },
|
||||
{ 0xeb04, KEY_3 },
|
||||
{ 0xeb05, KEY_4 },
|
||||
{ 0xeb06, KEY_5 },
|
||||
{ 0xeb07, KEY_6 },
|
||||
{ 0xeb08, KEY_7 },
|
||||
{ 0xeb09, KEY_8 },
|
||||
{ 0xeb0a, KEY_9 },
|
||||
{ 0xeb0b, KEY_VIDEO },
|
||||
{ 0xeb0c, KEY_0 },
|
||||
{ 0xeb0d, KEY_REFRESH },
|
||||
{ 0xeb0f, KEY_EPG },
|
||||
{ 0xeb10, KEY_UP },
|
||||
{ 0xeb11, KEY_LEFT },
|
||||
{ 0xeb12, KEY_OK },
|
||||
{ 0xeb13, KEY_RIGHT },
|
||||
{ 0xeb14, KEY_DOWN },
|
||||
{ 0xeb16, KEY_INFO },
|
||||
{ 0xeb17, KEY_RED },
|
||||
{ 0xeb18, KEY_GREEN },
|
||||
{ 0xeb19, KEY_YELLOW },
|
||||
{ 0xeb1a, KEY_BLUE },
|
||||
{ 0xeb1b, KEY_CHANNELUP },
|
||||
{ 0xeb1c, KEY_VOLUMEUP },
|
||||
{ 0xeb1d, KEY_MUTE },
|
||||
{ 0xeb1e, KEY_VOLUMEDOWN },
|
||||
{ 0xeb1f, KEY_CHANNELDOWN },
|
||||
{ 0xeb40, KEY_PAUSE },
|
||||
{ 0xeb41, KEY_HOME },
|
||||
{ 0xeb42, KEY_MENU }, /* DVD Menu */
|
||||
{ 0xeb43, KEY_SUBTITLE },
|
||||
{ 0xeb44, KEY_TEXT }, /* Teletext */
|
||||
{ 0xeb45, KEY_DELETE },
|
||||
{ 0xeb46, KEY_TV },
|
||||
{ 0xeb47, KEY_DVD },
|
||||
{ 0xeb48, KEY_STOP },
|
||||
{ 0xeb49, KEY_VIDEO },
|
||||
{ 0xeb4a, KEY_AUDIO }, /* Music */
|
||||
{ 0xeb4b, KEY_SCREEN }, /* Pic */
|
||||
{ 0xeb4c, KEY_PLAY },
|
||||
{ 0xeb4d, KEY_BACK },
|
||||
{ 0xeb4e, KEY_REWIND },
|
||||
{ 0xeb4f, KEY_FASTFORWARD },
|
||||
{ 0xeb54, KEY_PREVIOUS },
|
||||
{ 0xeb58, KEY_RECORD },
|
||||
{ 0xeb5c, KEY_NEXT },
|
||||
|
||||
/* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */
|
||||
{ 0x1e00, KEY_0 },
|
||||
{ 0x1e01, KEY_1 },
|
||||
{ 0x1e02, KEY_2 },
|
||||
{ 0x1e03, KEY_3 },
|
||||
{ 0x1e04, KEY_4 },
|
||||
{ 0x1e05, KEY_5 },
|
||||
{ 0x1e06, KEY_6 },
|
||||
{ 0x1e07, KEY_7 },
|
||||
{ 0x1e08, KEY_8 },
|
||||
{ 0x1e09, KEY_9 },
|
||||
{ 0x1e0a, KEY_KPASTERISK },
|
||||
{ 0x1e0b, KEY_RED },
|
||||
{ 0x1e0c, KEY_RADIO },
|
||||
{ 0x1e0d, KEY_MENU },
|
||||
{ 0x1e0e, KEY_GRAVE }, /* # */
|
||||
{ 0x1e0f, KEY_MUTE },
|
||||
{ 0x1e10, KEY_VOLUMEUP },
|
||||
{ 0x1e11, KEY_VOLUMEDOWN },
|
||||
{ 0x1e12, KEY_CHANNEL },
|
||||
{ 0x1e14, KEY_UP },
|
||||
{ 0x1e15, KEY_DOWN },
|
||||
{ 0x1e16, KEY_LEFT },
|
||||
{ 0x1e17, KEY_RIGHT },
|
||||
{ 0x1e18, KEY_VIDEO },
|
||||
{ 0x1e19, KEY_AUDIO },
|
||||
{ 0x1e1a, KEY_MEDIA },
|
||||
{ 0x1e1b, KEY_EPG },
|
||||
{ 0x1e1c, KEY_TV },
|
||||
{ 0x1e1e, KEY_NEXT },
|
||||
{ 0x1e1f, KEY_BACK },
|
||||
{ 0x1e20, KEY_CHANNELUP },
|
||||
{ 0x1e21, KEY_CHANNELDOWN },
|
||||
{ 0x1e24, KEY_LAST }, /* Skip backwards */
|
||||
{ 0x1e25, KEY_OK },
|
||||
{ 0x1e29, KEY_BLUE},
|
||||
{ 0x1e2e, KEY_GREEN },
|
||||
{ 0x1e30, KEY_PAUSE },
|
||||
{ 0x1e32, KEY_REWIND },
|
||||
{ 0x1e34, KEY_FASTFORWARD },
|
||||
{ 0x1e35, KEY_PLAY },
|
||||
{ 0x1e36, KEY_STOP },
|
||||
{ 0x1e37, KEY_RECORD },
|
||||
{ 0x1e38, KEY_YELLOW },
|
||||
{ 0x1e3b, KEY_GOTO },
|
||||
{ 0x1e3d, KEY_POWER },
|
||||
|
||||
/* Key codes for the Leadtek Winfast DTV Dongle */
|
||||
{ 0x0042, KEY_POWER },
|
||||
{ 0x077c, KEY_TUNER },
|
||||
{ 0x0f4e, KEY_PRINT }, /* PREVIEW */
|
||||
{ 0x0840, KEY_SCREEN }, /* full screen toggle*/
|
||||
{ 0x0f71, KEY_DOT }, /* frequency */
|
||||
{ 0x0743, KEY_0 },
|
||||
{ 0x0c41, KEY_1 },
|
||||
{ 0x0443, KEY_2 },
|
||||
{ 0x0b7f, KEY_3 },
|
||||
{ 0x0e41, KEY_4 },
|
||||
{ 0x0643, KEY_5 },
|
||||
{ 0x097f, KEY_6 },
|
||||
{ 0x0d7e, KEY_7 },
|
||||
{ 0x057c, KEY_8 },
|
||||
{ 0x0a40, KEY_9 },
|
||||
{ 0x0e4e, KEY_CLEAR },
|
||||
{ 0x047c, KEY_CHANNEL }, /* show channel number */
|
||||
{ 0x0f41, KEY_LAST }, /* recall */
|
||||
{ 0x0342, KEY_MUTE },
|
||||
{ 0x064c, KEY_RESERVED }, /* PIP button*/
|
||||
{ 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */
|
||||
{ 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */
|
||||
{ 0x0b70, KEY_RECORD },
|
||||
{ 0x037d, KEY_VOLUMEUP },
|
||||
{ 0x017d, KEY_VOLUMEDOWN },
|
||||
{ 0x0242, KEY_CHANNELUP },
|
||||
{ 0x007d, KEY_CHANNELDOWN },
|
||||
|
||||
/* Key codes for Nova-TD "credit card" remote control. */
|
||||
{ 0x1d00, KEY_0 },
|
||||
{ 0x1d01, KEY_1 },
|
||||
{ 0x1d02, KEY_2 },
|
||||
{ 0x1d03, KEY_3 },
|
||||
{ 0x1d04, KEY_4 },
|
||||
{ 0x1d05, KEY_5 },
|
||||
{ 0x1d06, KEY_6 },
|
||||
{ 0x1d07, KEY_7 },
|
||||
{ 0x1d08, KEY_8 },
|
||||
{ 0x1d09, KEY_9 },
|
||||
{ 0x1d0a, KEY_TEXT },
|
||||
{ 0x1d0d, KEY_MENU },
|
||||
{ 0x1d0f, KEY_MUTE },
|
||||
{ 0x1d10, KEY_VOLUMEUP },
|
||||
{ 0x1d11, KEY_VOLUMEDOWN },
|
||||
{ 0x1d12, KEY_CHANNEL },
|
||||
{ 0x1d14, KEY_UP },
|
||||
{ 0x1d15, KEY_DOWN },
|
||||
{ 0x1d16, KEY_LEFT },
|
||||
{ 0x1d17, KEY_RIGHT },
|
||||
{ 0x1d1c, KEY_TV },
|
||||
{ 0x1d1e, KEY_NEXT },
|
||||
{ 0x1d1f, KEY_BACK },
|
||||
{ 0x1d20, KEY_CHANNELUP },
|
||||
{ 0x1d21, KEY_CHANNELDOWN },
|
||||
{ 0x1d24, KEY_LAST },
|
||||
{ 0x1d25, KEY_OK },
|
||||
{ 0x1d30, KEY_PAUSE },
|
||||
{ 0x1d32, KEY_REWIND },
|
||||
{ 0x1d34, KEY_FASTFORWARD },
|
||||
{ 0x1d35, KEY_PLAY },
|
||||
{ 0x1d36, KEY_STOP },
|
||||
{ 0x1d37, KEY_RECORD },
|
||||
{ 0x1d3b, KEY_GOTO },
|
||||
{ 0x1d3d, KEY_POWER },
|
||||
|
||||
/* Key codes for the Pixelview SBTVD remote (proto NEC) */
|
||||
{ 0x8613, KEY_MUTE },
|
||||
{ 0x8612, KEY_POWER },
|
||||
{ 0x8601, KEY_1 },
|
||||
{ 0x8602, KEY_2 },
|
||||
{ 0x8603, KEY_3 },
|
||||
{ 0x8604, KEY_4 },
|
||||
{ 0x8605, KEY_5 },
|
||||
{ 0x8606, KEY_6 },
|
||||
{ 0x8607, KEY_7 },
|
||||
{ 0x8608, KEY_8 },
|
||||
{ 0x8609, KEY_9 },
|
||||
{ 0x8600, KEY_0 },
|
||||
{ 0x860d, KEY_CHANNELUP },
|
||||
{ 0x8619, KEY_CHANNELDOWN },
|
||||
{ 0x8610, KEY_VOLUMEUP },
|
||||
{ 0x860c, KEY_VOLUMEDOWN },
|
||||
|
||||
{ 0x860a, KEY_CAMERA },
|
||||
{ 0x860b, KEY_ZOOM },
|
||||
{ 0x861b, KEY_BACKSPACE },
|
||||
{ 0x8615, KEY_ENTER },
|
||||
|
||||
{ 0x861d, KEY_UP },
|
||||
{ 0x861e, KEY_DOWN },
|
||||
{ 0x860e, KEY_LEFT },
|
||||
{ 0x860f, KEY_RIGHT },
|
||||
|
||||
{ 0x8618, KEY_RECORD },
|
||||
{ 0x861a, KEY_STOP },
|
||||
|
||||
/* Key codes for the EvolutePC TVWay+ remote (proto NEC) */
|
||||
{ 0x7a00, KEY_MENU },
|
||||
{ 0x7a01, KEY_RECORD },
|
||||
{ 0x7a02, KEY_PLAY },
|
||||
{ 0x7a03, KEY_STOP },
|
||||
{ 0x7a10, KEY_CHANNELUP },
|
||||
{ 0x7a11, KEY_CHANNELDOWN },
|
||||
{ 0x7a12, KEY_VOLUMEUP },
|
||||
{ 0x7a13, KEY_VOLUMEDOWN },
|
||||
{ 0x7a40, KEY_POWER },
|
||||
{ 0x7a41, KEY_MUTE },
|
||||
|
||||
/* Key codes for the Elgato EyeTV Diversity silver remote,
|
||||
set dvb_usb_dib0700_ir_proto=0 */
|
||||
{ 0x4501, KEY_POWER },
|
||||
{ 0x4502, KEY_MUTE },
|
||||
{ 0x4503, KEY_1 },
|
||||
{ 0x4504, KEY_2 },
|
||||
{ 0x4505, KEY_3 },
|
||||
{ 0x4506, KEY_4 },
|
||||
{ 0x4507, KEY_5 },
|
||||
{ 0x4508, KEY_6 },
|
||||
{ 0x4509, KEY_7 },
|
||||
{ 0x450a, KEY_8 },
|
||||
{ 0x450b, KEY_9 },
|
||||
{ 0x450c, KEY_LAST },
|
||||
{ 0x450d, KEY_0 },
|
||||
{ 0x450e, KEY_ENTER },
|
||||
{ 0x450f, KEY_RED },
|
||||
{ 0x4510, KEY_CHANNELUP },
|
||||
{ 0x4511, KEY_GREEN },
|
||||
{ 0x4512, KEY_VOLUMEDOWN },
|
||||
{ 0x4513, KEY_OK },
|
||||
{ 0x4514, KEY_VOLUMEUP },
|
||||
{ 0x4515, KEY_YELLOW },
|
||||
{ 0x4516, KEY_CHANNELDOWN },
|
||||
{ 0x4517, KEY_BLUE },
|
||||
{ 0x4518, KEY_LEFT }, /* Skip backwards */
|
||||
{ 0x4519, KEY_PLAYPAUSE },
|
||||
{ 0x451a, KEY_RIGHT }, /* Skip forward */
|
||||
{ 0x451b, KEY_REWIND },
|
||||
{ 0x451c, KEY_L }, /* Live */
|
||||
{ 0x451d, KEY_FASTFORWARD },
|
||||
{ 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */
|
||||
{ 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */
|
||||
{ 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */
|
||||
{ 0x4541, KEY_SCREEN }, /* Full screen toggle, 'Hold' for Teletext */
|
||||
{ 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */
|
||||
};
|
||||
|
||||
/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
|
||||
static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
|
||||
BAND_UHF | BAND_VHF,
|
||||
|
@ -2168,10 +1868,17 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
}
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 2,
|
||||
|
@ -2197,10 +1904,17 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 2,
|
||||
|
@ -2251,11 +1965,17 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 1,
|
||||
|
@ -2288,10 +2008,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
}
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 1,
|
||||
|
@ -2358,11 +2086,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 1,
|
||||
|
@ -2397,11 +2132,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 2,
|
||||
|
@ -2431,7 +2173,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
}
|
||||
},
|
||||
|
||||
.num_device_descs = 7,
|
||||
.num_device_descs = 6,
|
||||
.devices = {
|
||||
{ "DiBcom STK7070PD reference design",
|
||||
{ &dib0700_usb_id_table[17], NULL },
|
||||
|
@ -2458,15 +2200,69 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ &dib0700_usb_id_table[44], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
},
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 2,
|
||||
.adapter = {
|
||||
{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 32,
|
||||
.pid_filter = stk70x0p_pid_filter,
|
||||
.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
|
||||
.frontend_attach = stk7070pd_frontend_attach0,
|
||||
.tuner_attach = dib7070p_tuner_attach,
|
||||
|
||||
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
|
||||
|
||||
.size_of_priv = sizeof(struct dib0700_adapter_state),
|
||||
}, {
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 32,
|
||||
.pid_filter = stk70x0p_pid_filter,
|
||||
.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
|
||||
.frontend_attach = stk7070pd_frontend_attach1,
|
||||
.tuner_attach = dib7070p_tuner_attach,
|
||||
|
||||
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
|
||||
|
||||
.size_of_priv = sizeof(struct dib0700_adapter_state),
|
||||
}
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ "Elgato EyeTV Diversity",
|
||||
{ &dib0700_usb_id_table[68], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
},
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_NEC_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 1,
|
||||
|
@ -2525,10 +2321,19 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ NULL },
|
||||
},
|
||||
},
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
|
@ -2554,10 +2359,19 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ NULL },
|
||||
},
|
||||
},
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
|
@ -2615,10 +2429,19 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ NULL },
|
||||
},
|
||||
},
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
|
@ -2653,11 +2476,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_NEC_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 2,
|
||||
.adapter = {
|
||||
|
@ -2697,10 +2527,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
|
@ -2728,10 +2566,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -327,7 +327,7 @@ EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
|
|||
/*
|
||||
* common remote control stuff
|
||||
*/
|
||||
struct dvb_usb_rc_key ir_codes_dibusb_table[] = {
|
||||
struct ir_scancode ir_codes_dibusb_table[] = {
|
||||
/* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
|
||||
{ 0x0016, KEY_POWER },
|
||||
{ 0x0010, KEY_MUTE },
|
||||
|
|
|
@ -211,10 +211,12 @@ static struct dvb_usb_device_properties dibusb1_1_properties = {
|
|||
|
||||
.power_ctrl = dibusb_power_ctrl,
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
||||
|
@ -295,10 +297,12 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
|
|||
},
|
||||
.power_ctrl = dibusb_power_ctrl,
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
||||
|
@ -359,10 +363,12 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = {
|
|||
},
|
||||
.power_ctrl = dibusb2_0_power_ctrl,
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
||||
|
@ -416,10 +422,12 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = {
|
|||
},
|
||||
.power_ctrl = dibusb2_0_power_ctrl,
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
||||
|
|
|
@ -81,10 +81,12 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
|
|||
},
|
||||
.power_ctrl = dibusb2_0_power_ctrl,
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* FIXME */
|
||||
.rc_query = dibusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* FIXME */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int);
|
|||
#define DEFAULT_RC_INTERVAL 150
|
||||
//#define DEFAULT_RC_INTERVAL 100000
|
||||
|
||||
extern struct dvb_usb_rc_key ir_codes_dibusb_table[];
|
||||
extern struct ir_scancode ir_codes_dibusb_table[];
|
||||
extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *);
|
||||
extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *);
|
||||
|
||||
|
|
|
@ -161,7 +161,7 @@ static int digitv_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_digitv_table[] = {
|
||||
static struct ir_scancode ir_codes_digitv_table[] = {
|
||||
{ 0x5f55, KEY_0 },
|
||||
{ 0x6f55, KEY_1 },
|
||||
{ 0x9f55, KEY_2 },
|
||||
|
@ -237,10 +237,10 @@ static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
/* if something is inside the buffer, simulate key press */
|
||||
if (key[1] != 0)
|
||||
{
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&d->props.rc_key_map[i]) == key[1] &&
|
||||
rc5_data(&d->props.rc_key_map[i]) == key[2]) {
|
||||
*event = d->props.rc_key_map[i].event;
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&d->props.rc.legacy.rc_key_map[i]) == key[1] &&
|
||||
rc5_data(&d->props.rc.legacy.rc_key_map[i]) == key[2]) {
|
||||
*event = d->props.rc.legacy.rc_key_map[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
return 0;
|
||||
}
|
||||
|
@ -310,10 +310,12 @@ static struct dvb_usb_device_properties digitv_properties = {
|
|||
},
|
||||
.identify_state = digitv_identify_state,
|
||||
|
||||
.rc_interval = 1000,
|
||||
.rc_key_map = ir_codes_digitv_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_digitv_table),
|
||||
.rc_query = digitv_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 1000,
|
||||
.rc_key_map = ir_codes_digitv_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_digitv_table),
|
||||
.rc_query = digitv_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &digitv_i2c_algo,
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
|
|||
|
||||
/* remote control */
|
||||
/* key list for the tiny remote control (Yakumo, don't know about the others) */
|
||||
static struct dvb_usb_rc_key ir_codes_dtt200u_table[] = {
|
||||
static struct ir_scancode ir_codes_dtt200u_table[] = {
|
||||
{ 0x8001, KEY_MUTE },
|
||||
{ 0x8002, KEY_CHANNELDOWN },
|
||||
{ 0x8003, KEY_VOLUMEDOWN },
|
||||
|
@ -161,10 +161,12 @@ static struct dvb_usb_device_properties dtt200u_properties = {
|
|||
},
|
||||
.power_ctrl = dtt200u_power_ctrl,
|
||||
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
|
@ -206,10 +208,12 @@ static struct dvb_usb_device_properties wt220u_properties = {
|
|||
},
|
||||
.power_ctrl = dtt200u_power_ctrl,
|
||||
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
|
@ -251,10 +255,12 @@ static struct dvb_usb_device_properties wt220u_fc_properties = {
|
|||
},
|
||||
.power_ctrl = dtt200u_power_ctrl,
|
||||
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
|
@ -296,10 +302,12 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
|
|||
},
|
||||
.power_ctrl = dtt200u_power_ctrl,
|
||||
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
|
|
|
@ -197,6 +197,7 @@
|
|||
#define USB_PID_AVERMEDIA_A310 0xa310
|
||||
#define USB_PID_AVERMEDIA_A850 0x850a
|
||||
#define USB_PID_AVERMEDIA_A805 0xa805
|
||||
#define USB_PID_AVERMEDIA_A815M 0x815a
|
||||
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
|
||||
#define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d
|
||||
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
/* debug */
|
||||
int dvb_usb_debug;
|
||||
module_param_named(debug,dvb_usb_debug, int, 0644);
|
||||
module_param_named(debug, dvb_usb_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64,mem=128,uxfer=256 (or-able))." DVB_USB_DEBUG_STATUS);
|
||||
|
||||
int dvb_usb_disable_rc_polling;
|
||||
|
@ -29,7 +29,7 @@ MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID
|
|||
static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
||||
{
|
||||
struct dvb_usb_adapter *adap;
|
||||
int ret,n;
|
||||
int ret, n;
|
||||
|
||||
for (n = 0; n < d->props.num_adapters; n++) {
|
||||
adap = &d->adapter[n];
|
||||
|
@ -38,7 +38,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
|||
|
||||
memcpy(&adap->props, &d->props.adapter[n], sizeof(struct dvb_usb_adapter_properties));
|
||||
|
||||
/* speed - when running at FULL speed we need a HW PID filter */
|
||||
/* speed - when running at FULL speed we need a HW PID filter */
|
||||
if (d->udev->speed == USB_SPEED_FULL && !(adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
|
||||
err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)");
|
||||
return -ENODEV;
|
||||
|
@ -46,7 +46,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
|||
|
||||
if ((d->udev->speed == USB_SPEED_FULL && adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
|
||||
(adap->props.caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
|
||||
info("will use the device's hardware PID filter (table count: %d).",adap->props.pid_filter_count);
|
||||
info("will use the device's hardware PID filter (table count: %d).", adap->props.pid_filter_count);
|
||||
adap->pid_filtering = 1;
|
||||
adap->max_feed_count = adap->props.pid_filter_count;
|
||||
} else {
|
||||
|
@ -64,9 +64,9 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
|||
}
|
||||
|
||||
if (adap->props.size_of_priv > 0) {
|
||||
adap->priv = kzalloc(adap->props.size_of_priv,GFP_KERNEL);
|
||||
adap->priv = kzalloc(adap->props.size_of_priv, GFP_KERNEL);
|
||||
if (adap->priv == NULL) {
|
||||
err("no memory for priv for adapter %d.",n);
|
||||
err("no memory for priv for adapter %d.", n);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
@ -86,8 +86,8 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
|||
* sometimes a timeout occures, this helps
|
||||
*/
|
||||
if (d->props.generic_bulk_ctrl_endpoint != 0) {
|
||||
usb_clear_halt(d->udev,usb_sndbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
|
||||
usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
|
||||
usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
|
||||
usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -96,6 +96,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
|||
static int dvb_usb_adapter_exit(struct dvb_usb_device *d)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < d->num_adapters_initialized; n++) {
|
||||
dvb_usb_adapter_frontend_exit(&d->adapter[n]);
|
||||
dvb_usb_adapter_dvb_exit(&d->adapter[n]);
|
||||
|
@ -111,11 +112,11 @@ static int dvb_usb_adapter_exit(struct dvb_usb_device *d)
|
|||
/* general initialization functions */
|
||||
static int dvb_usb_exit(struct dvb_usb_device *d)
|
||||
{
|
||||
deb_info("state before exiting everything: %x\n",d->state);
|
||||
deb_info("state before exiting everything: %x\n", d->state);
|
||||
dvb_usb_remote_exit(d);
|
||||
dvb_usb_adapter_exit(d);
|
||||
dvb_usb_i2c_exit(d);
|
||||
deb_info("state should be zero now: %x\n",d->state);
|
||||
deb_info("state should be zero now: %x\n", d->state);
|
||||
d->state = DVB_USB_STATE_INIT;
|
||||
kfree(d->priv);
|
||||
kfree(d);
|
||||
|
@ -132,14 +133,14 @@ static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
|
|||
d->state = DVB_USB_STATE_INIT;
|
||||
|
||||
if (d->props.size_of_priv > 0) {
|
||||
d->priv = kzalloc(d->props.size_of_priv,GFP_KERNEL);
|
||||
d->priv = kzalloc(d->props.size_of_priv, GFP_KERNEL);
|
||||
if (d->priv == NULL) {
|
||||
err("no memory for priv in 'struct dvb_usb_device'");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
/* check the capabilities and set appropriate variables */
|
||||
/* check the capabilities and set appropriate variables */
|
||||
dvb_usb_device_power_ctrl(d, 1);
|
||||
|
||||
if ((ret = dvb_usb_i2c_init(d)) ||
|
||||
|
@ -157,16 +158,17 @@ static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
|
|||
}
|
||||
|
||||
/* determine the name and the state of the just found USB device */
|
||||
static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device *udev,struct dvb_usb_device_properties *props, int *cold)
|
||||
static struct dvb_usb_device_description *dvb_usb_find_device(struct usb_device *udev, struct dvb_usb_device_properties *props, int *cold)
|
||||
{
|
||||
int i,j;
|
||||
int i, j;
|
||||
struct dvb_usb_device_description *desc = NULL;
|
||||
|
||||
*cold = -1;
|
||||
|
||||
for (i = 0; i < props->num_device_descs; i++) {
|
||||
|
||||
for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].cold_ids[j] != NULL; j++) {
|
||||
deb_info("check for cold %x %x\n",props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct);
|
||||
deb_info("check for cold %x %x\n", props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct);
|
||||
if (props->devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
|
||||
props->devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
|
||||
*cold = 1;
|
||||
|
@ -179,7 +181,7 @@ static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device
|
|||
break;
|
||||
|
||||
for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].warm_ids[j] != NULL; j++) {
|
||||
deb_info("check for warm %x %x\n",props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct);
|
||||
deb_info("check for warm %x %x\n", props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct);
|
||||
if (props->devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
|
||||
props->devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
|
||||
*cold = 0;
|
||||
|
@ -190,7 +192,7 @@ static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device
|
|||
}
|
||||
|
||||
if (desc != NULL && props->identify_state != NULL)
|
||||
props->identify_state(udev,props,&desc,cold);
|
||||
props->identify_state(udev, props, &desc, cold);
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
@ -202,7 +204,7 @@ int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff)
|
|||
else
|
||||
d->powered--;
|
||||
|
||||
if (d->powered == 0 || (onoff && d->powered == 1)) { // when switching from 1 to 0 or from 0 to 1
|
||||
if (d->powered == 0 || (onoff && d->powered == 1)) { /* when switching from 1 to 0 or from 0 to 1 */
|
||||
deb_info("power control: %d\n", onoff);
|
||||
if (d->props.power_ctrl)
|
||||
return d->props.power_ctrl(d, onoff);
|
||||
|
@ -222,32 +224,32 @@ int dvb_usb_device_init(struct usb_interface *intf,
|
|||
struct dvb_usb_device *d = NULL;
|
||||
struct dvb_usb_device_description *desc = NULL;
|
||||
|
||||
int ret = -ENOMEM,cold=0;
|
||||
int ret = -ENOMEM, cold = 0;
|
||||
|
||||
if (du != NULL)
|
||||
*du = NULL;
|
||||
|
||||
if ((desc = dvb_usb_find_device(udev,props,&cold)) == NULL) {
|
||||
if ((desc = dvb_usb_find_device(udev, props, &cold)) == NULL) {
|
||||
deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (cold) {
|
||||
info("found a '%s' in cold state, will try to load a firmware",desc->name);
|
||||
ret = dvb_usb_download_firmware(udev,props);
|
||||
info("found a '%s' in cold state, will try to load a firmware", desc->name);
|
||||
ret = dvb_usb_download_firmware(udev, props);
|
||||
if (!props->no_reconnect || ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
info("found a '%s' in warm state.",desc->name);
|
||||
d = kzalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
|
||||
info("found a '%s' in warm state.", desc->name);
|
||||
d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL);
|
||||
if (d == NULL) {
|
||||
err("no memory for 'struct dvb_usb_device'");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
d->udev = udev;
|
||||
memcpy(&d->props,props,sizeof(struct dvb_usb_device_properties));
|
||||
memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties));
|
||||
d->desc = desc;
|
||||
d->owner = owner;
|
||||
|
||||
|
@ -259,9 +261,9 @@ int dvb_usb_device_init(struct usb_interface *intf,
|
|||
ret = dvb_usb_init(d, adapter_nums);
|
||||
|
||||
if (ret == 0)
|
||||
info("%s successfully initialized and connected.",desc->name);
|
||||
info("%s successfully initialized and connected.", desc->name);
|
||||
else
|
||||
info("%s error while loading driver (%d)",desc->name,ret);
|
||||
info("%s error while loading driver (%d)", desc->name, ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_usb_device_init);
|
||||
|
@ -271,12 +273,12 @@ void dvb_usb_device_exit(struct usb_interface *intf)
|
|||
struct dvb_usb_device *d = usb_get_intfdata(intf);
|
||||
const char *name = "generic DVB-USB module";
|
||||
|
||||
usb_set_intfdata(intf,NULL);
|
||||
usb_set_intfdata(intf, NULL);
|
||||
if (d != NULL && d->desc != NULL) {
|
||||
name = d->desc->name;
|
||||
dvb_usb_exit(d);
|
||||
}
|
||||
info("%s successfully deinitialized and disconnected.",name);
|
||||
info("%s successfully deinitialized and disconnected.", name);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_usb_device_exit);
|
||||
|
|
|
@ -8,29 +8,29 @@
|
|||
#include "dvb-usb-common.h"
|
||||
#include <linux/usb/input.h>
|
||||
|
||||
static int dvb_usb_getkeycode(struct input_dev *dev,
|
||||
static int legacy_dvb_usb_getkeycode(struct input_dev *dev,
|
||||
unsigned int scancode, unsigned int *keycode)
|
||||
{
|
||||
struct dvb_usb_device *d = input_get_drvdata(dev);
|
||||
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
int i;
|
||||
|
||||
/* See if we can match the raw key code. */
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++)
|
||||
if (keymap[i].scan == scancode) {
|
||||
*keycode = keymap[i].event;
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
if (keymap[i].scancode == scancode) {
|
||||
*keycode = keymap[i].keycode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If is there extra space, returns KEY_RESERVED,
|
||||
* otherwise, input core won't let dvb_usb_setkeycode
|
||||
* otherwise, input core won't let legacy_dvb_usb_setkeycode
|
||||
* to work
|
||||
*/
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++)
|
||||
if (keymap[i].event == KEY_RESERVED ||
|
||||
keymap[i].event == KEY_UNKNOWN) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
if (keymap[i].keycode == KEY_RESERVED ||
|
||||
keymap[i].keycode == KEY_UNKNOWN) {
|
||||
*keycode = KEY_RESERVED;
|
||||
return 0;
|
||||
}
|
||||
|
@ -38,27 +38,27 @@ static int dvb_usb_getkeycode(struct input_dev *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int dvb_usb_setkeycode(struct input_dev *dev,
|
||||
static int legacy_dvb_usb_setkeycode(struct input_dev *dev,
|
||||
unsigned int scancode, unsigned int keycode)
|
||||
{
|
||||
struct dvb_usb_device *d = input_get_drvdata(dev);
|
||||
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
int i;
|
||||
|
||||
/* Search if it is replacing an existing keycode */
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++)
|
||||
if (keymap[i].scan == scancode) {
|
||||
keymap[i].event = keycode;
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
if (keymap[i].scancode == scancode) {
|
||||
keymap[i].keycode = keycode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Search if is there a clean entry. If so, use it */
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++)
|
||||
if (keymap[i].event == KEY_RESERVED ||
|
||||
keymap[i].event == KEY_UNKNOWN) {
|
||||
keymap[i].scan = scancode;
|
||||
keymap[i].event = keycode;
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
if (keymap[i].keycode == KEY_RESERVED ||
|
||||
keymap[i].keycode == KEY_UNKNOWN) {
|
||||
keymap[i].scancode = scancode;
|
||||
keymap[i].keycode = keycode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ static int dvb_usb_setkeycode(struct input_dev *dev,
|
|||
*
|
||||
* TODO: Fix the repeat rate of the input device.
|
||||
*/
|
||||
static void dvb_usb_read_remote_control(struct work_struct *work)
|
||||
static void legacy_dvb_usb_read_remote_control(struct work_struct *work)
|
||||
{
|
||||
struct dvb_usb_device *d =
|
||||
container_of(work, struct dvb_usb_device, rc_query_work.work);
|
||||
|
@ -92,7 +92,7 @@ static void dvb_usb_read_remote_control(struct work_struct *work)
|
|||
if (dvb_usb_disable_rc_polling)
|
||||
return;
|
||||
|
||||
if (d->props.rc_query(d,&event,&state)) {
|
||||
if (d->props.rc.legacy.rc_query(d,&event,&state)) {
|
||||
err("error while querying for an remote control event.");
|
||||
goto schedule;
|
||||
}
|
||||
|
@ -151,18 +151,117 @@ static void dvb_usb_read_remote_control(struct work_struct *work)
|
|||
*/
|
||||
|
||||
schedule:
|
||||
schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
|
||||
schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval));
|
||||
}
|
||||
|
||||
static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d,
|
||||
struct input_dev *input_dev)
|
||||
{
|
||||
int i, err, rc_interval;
|
||||
|
||||
input_dev->getkeycode = legacy_dvb_usb_getkeycode;
|
||||
input_dev->setkeycode = legacy_dvb_usb_setkeycode;
|
||||
|
||||
/* set the bits for the keys */
|
||||
deb_rc("key map size: %d\n", d->props.rc.legacy.rc_key_map_size);
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
deb_rc("setting bit for event %d item %d\n",
|
||||
d->props.rc.legacy.rc_key_map[i].keycode, i);
|
||||
set_bit(d->props.rc.legacy.rc_key_map[i].keycode, input_dev->keybit);
|
||||
}
|
||||
|
||||
/* setting these two values to non-zero, we have to manage key repeats */
|
||||
input_dev->rep[REP_PERIOD] = d->props.rc.legacy.rc_interval;
|
||||
input_dev->rep[REP_DELAY] = d->props.rc.legacy.rc_interval + 150;
|
||||
|
||||
input_set_drvdata(input_dev, d);
|
||||
|
||||
err = input_register_device(input_dev);
|
||||
if (err)
|
||||
input_free_device(input_dev);
|
||||
|
||||
rc_interval = d->props.rc.legacy.rc_interval;
|
||||
|
||||
INIT_DELAYED_WORK(&d->rc_query_work, legacy_dvb_usb_read_remote_control);
|
||||
|
||||
info("schedule remote query interval to %d msecs.", rc_interval);
|
||||
schedule_delayed_work(&d->rc_query_work,
|
||||
msecs_to_jiffies(rc_interval));
|
||||
|
||||
d->state |= DVB_USB_STATE_REMOTE;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Remote-control poll function - called every dib->rc_query_interval ms to see
|
||||
* whether the remote control has received anything.
|
||||
*
|
||||
* TODO: Fix the repeat rate of the input device.
|
||||
*/
|
||||
static void dvb_usb_read_remote_control(struct work_struct *work)
|
||||
{
|
||||
struct dvb_usb_device *d =
|
||||
container_of(work, struct dvb_usb_device, rc_query_work.work);
|
||||
int err;
|
||||
|
||||
/* TODO: need a lock here. We can simply skip checking for the remote control
|
||||
if we're busy. */
|
||||
|
||||
/* when the parameter has been set to 1 via sysfs while the
|
||||
* driver was running, or when bulk mode is enabled after IR init
|
||||
*/
|
||||
if (dvb_usb_disable_rc_polling || d->props.rc.core.bulk_mode)
|
||||
return;
|
||||
|
||||
err = d->props.rc.core.rc_query(d);
|
||||
if (err)
|
||||
err("error %d while querying for an remote control event.", err);
|
||||
|
||||
schedule_delayed_work(&d->rc_query_work,
|
||||
msecs_to_jiffies(d->props.rc.core.rc_interval));
|
||||
}
|
||||
|
||||
static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d,
|
||||
struct input_dev *input_dev)
|
||||
{
|
||||
int err, rc_interval;
|
||||
|
||||
d->props.rc.core.rc_props.priv = d;
|
||||
err = ir_input_register(input_dev,
|
||||
d->props.rc.core.rc_codes,
|
||||
&d->props.rc.core.rc_props,
|
||||
d->props.rc.core.module_name);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode)
|
||||
return 0;
|
||||
|
||||
/* Polling mode - initialize a work queue for handling it */
|
||||
INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
|
||||
|
||||
rc_interval = d->props.rc.core.rc_interval;
|
||||
|
||||
info("schedule remote query interval to %d msecs.", rc_interval);
|
||||
schedule_delayed_work(&d->rc_query_work,
|
||||
msecs_to_jiffies(rc_interval));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dvb_usb_remote_init(struct dvb_usb_device *d)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
int i;
|
||||
int err;
|
||||
|
||||
if (d->props.rc_key_map == NULL ||
|
||||
d->props.rc_query == NULL ||
|
||||
dvb_usb_disable_rc_polling)
|
||||
if (dvb_usb_disable_rc_polling)
|
||||
return 0;
|
||||
|
||||
if (d->props.rc.legacy.rc_key_map && d->props.rc.legacy.rc_query)
|
||||
d->props.rc.mode = DVB_RC_LEGACY;
|
||||
else if (d->props.rc.core.rc_codes)
|
||||
d->props.rc.mode = DVB_RC_CORE;
|
||||
else
|
||||
return 0;
|
||||
|
||||
usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
|
||||
|
@ -177,39 +276,19 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
|
|||
input_dev->phys = d->rc_phys;
|
||||
usb_to_input_id(d->udev, &input_dev->id);
|
||||
input_dev->dev.parent = &d->udev->dev;
|
||||
input_dev->getkeycode = dvb_usb_getkeycode;
|
||||
input_dev->setkeycode = dvb_usb_setkeycode;
|
||||
|
||||
/* set the bits for the keys */
|
||||
deb_rc("key map size: %d\n", d->props.rc_key_map_size);
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
deb_rc("setting bit for event %d item %d\n",
|
||||
d->props.rc_key_map[i].event, i);
|
||||
set_bit(d->props.rc_key_map[i].event, input_dev->keybit);
|
||||
}
|
||||
|
||||
/* Start the remote-control polling. */
|
||||
if (d->props.rc_interval < 40)
|
||||
d->props.rc_interval = 100; /* default */
|
||||
|
||||
/* setting these two values to non-zero, we have to manage key repeats */
|
||||
input_dev->rep[REP_PERIOD] = d->props.rc_interval;
|
||||
input_dev->rep[REP_DELAY] = d->props.rc_interval + 150;
|
||||
|
||||
input_set_drvdata(input_dev, d);
|
||||
|
||||
err = input_register_device(input_dev);
|
||||
if (err) {
|
||||
input_free_device(input_dev);
|
||||
return err;
|
||||
}
|
||||
if (d->props.rc.legacy.rc_interval < 40)
|
||||
d->props.rc.legacy.rc_interval = 100; /* default */
|
||||
|
||||
d->rc_input_dev = input_dev;
|
||||
|
||||
INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
|
||||
|
||||
info("schedule remote query interval to %d msecs.", d->props.rc_interval);
|
||||
schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
|
||||
if (d->props.rc.mode == DVB_RC_LEGACY)
|
||||
err = legacy_dvb_usb_remote_init(d, input_dev);
|
||||
else
|
||||
err = rc_core_dvb_usb_remote_init(d, input_dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
d->state |= DVB_USB_STATE_REMOTE;
|
||||
|
||||
|
@ -221,7 +300,10 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d)
|
|||
if (d->state & DVB_USB_STATE_REMOTE) {
|
||||
cancel_rearming_delayed_work(&d->rc_query_work);
|
||||
flush_scheduled_work();
|
||||
input_unregister_device(d->rc_input_dev);
|
||||
if (d->props.rc.mode == DVB_RC_LEGACY)
|
||||
input_unregister_device(d->rc_input_dev);
|
||||
else
|
||||
ir_input_unregister(d->rc_input_dev);
|
||||
}
|
||||
d->state &= ~DVB_USB_STATE_REMOTE;
|
||||
return 0;
|
||||
|
@ -234,7 +316,7 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
|
|||
u8 keybuf[5], u32 *event, int *state)
|
||||
{
|
||||
int i;
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
switch (keybuf[0]) {
|
||||
|
@ -247,10 +329,10 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
|
|||
break;
|
||||
}
|
||||
/* See if we can match the raw key code. */
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++)
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
if (rc5_custom(&keymap[i]) == keybuf[1] &&
|
||||
rc5_data(&keymap[i]) == keybuf[3]) {
|
||||
*event = keymap[i].event;
|
||||
*event = keymap[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/usb.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <media/ir-core.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
#include "dvb_demux.h"
|
||||
|
@ -74,30 +75,19 @@ struct dvb_usb_device_description {
|
|||
struct usb_device_id *warm_ids[DVB_USB_ID_MAX_NUM];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dvb_usb_rc_key - a remote control key and its input-event
|
||||
* @custom: the vendor/custom part of the key
|
||||
* @data: the actual key part
|
||||
* @event: the input event assigned to key identified by custom and data
|
||||
*/
|
||||
struct dvb_usb_rc_key {
|
||||
u16 scan;
|
||||
u32 event;
|
||||
};
|
||||
|
||||
static inline u8 rc5_custom(struct dvb_usb_rc_key *key)
|
||||
static inline u8 rc5_custom(struct ir_scancode *key)
|
||||
{
|
||||
return (key->scan >> 8) & 0xff;
|
||||
return (key->scancode >> 8) & 0xff;
|
||||
}
|
||||
|
||||
static inline u8 rc5_data(struct dvb_usb_rc_key *key)
|
||||
static inline u8 rc5_data(struct ir_scancode *key)
|
||||
{
|
||||
return key->scan & 0xff;
|
||||
return key->scancode & 0xff;
|
||||
}
|
||||
|
||||
static inline u8 rc5_scan(struct dvb_usb_rc_key *key)
|
||||
static inline u8 rc5_scan(struct ir_scancode *key)
|
||||
{
|
||||
return key->scan & 0xffff;
|
||||
return key->scancode & 0xffff;
|
||||
}
|
||||
|
||||
struct dvb_usb_device;
|
||||
|
@ -167,6 +157,55 @@ struct dvb_usb_adapter_properties {
|
|||
unsigned int, void *, unsigned int);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dvb_rc_legacy - old properties of remote controller
|
||||
* @rc_key_map: a hard-wired array of struct ir_scancode (NULL to disable
|
||||
* remote control handling).
|
||||
* @rc_key_map_size: number of items in @rc_key_map.
|
||||
* @rc_query: called to query an event event.
|
||||
* @rc_interval: time in ms between two queries.
|
||||
*/
|
||||
struct dvb_rc_legacy {
|
||||
/* remote control properties */
|
||||
#define REMOTE_NO_KEY_PRESSED 0x00
|
||||
#define REMOTE_KEY_PRESSED 0x01
|
||||
#define REMOTE_KEY_REPEAT 0x02
|
||||
struct ir_scancode *rc_key_map;
|
||||
int rc_key_map_size;
|
||||
int (*rc_query) (struct dvb_usb_device *, u32 *, int *);
|
||||
int rc_interval;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dvb_rc properties of remote controller, using rc-core
|
||||
* @rc_codes: name of rc codes table
|
||||
* @protocol: type of protocol(s) currently used by the driver
|
||||
* @rc_query: called to query an event event.
|
||||
* @rc_interval: time in ms between two queries.
|
||||
* @rc_props: remote controller properties
|
||||
* @bulk_mode: device supports bulk mode for RC (disable polling mode)
|
||||
*/
|
||||
struct dvb_rc {
|
||||
char *rc_codes;
|
||||
u64 protocol;
|
||||
char *module_name;
|
||||
int (*rc_query) (struct dvb_usb_device *d);
|
||||
int rc_interval;
|
||||
struct ir_dev_props rc_props;
|
||||
bool bulk_mode; /* uses bulk mode */
|
||||
};
|
||||
|
||||
/**
|
||||
* enum dvb_usb_mode - Specifies if it is using a legacy driver or a new one
|
||||
* based on rc-core
|
||||
* This is initialized/used only inside dvb-usb-remote.c.
|
||||
* It shouldn't be set by the drivers.
|
||||
*/
|
||||
enum dvb_usb_mode {
|
||||
DVB_RC_LEGACY,
|
||||
DVB_RC_CORE,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dvb_usb_device_properties - properties of a dvb-usb-device
|
||||
* @usb_ctrl: which USB device-side controller is in use. Needed for firmware
|
||||
|
@ -185,11 +224,7 @@ struct dvb_usb_adapter_properties {
|
|||
* @identify_state: called to determine the state (cold or warm), when it
|
||||
* is not distinguishable by the USB IDs.
|
||||
*
|
||||
* @rc_key_map: a hard-wired array of struct dvb_usb_rc_key (NULL to disable
|
||||
* remote control handling).
|
||||
* @rc_key_map_size: number of items in @rc_key_map.
|
||||
* @rc_query: called to query an event event.
|
||||
* @rc_interval: time in ms between two queries.
|
||||
* @rc: remote controller properties
|
||||
*
|
||||
* @i2c_algo: i2c_algorithm if the device has I2CoverUSB.
|
||||
*
|
||||
|
@ -233,14 +268,11 @@ struct dvb_usb_device_properties {
|
|||
int (*identify_state) (struct usb_device *, struct dvb_usb_device_properties *,
|
||||
struct dvb_usb_device_description **, int *);
|
||||
|
||||
/* remote control properties */
|
||||
#define REMOTE_NO_KEY_PRESSED 0x00
|
||||
#define REMOTE_KEY_PRESSED 0x01
|
||||
#define REMOTE_KEY_REPEAT 0x02
|
||||
struct dvb_usb_rc_key *rc_key_map;
|
||||
int rc_key_map_size;
|
||||
int (*rc_query) (struct dvb_usb_device *, u32 *, int *);
|
||||
int rc_interval;
|
||||
struct {
|
||||
enum dvb_usb_mode mode; /* Drivers shouldn't touch on it */
|
||||
struct dvb_rc_legacy legacy;
|
||||
struct dvb_rc core;
|
||||
} rc;
|
||||
|
||||
struct i2c_algorithm *i2c_algo;
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
"on firmware-problems."
|
||||
|
||||
struct ir_codes_dvb_usb_table_table {
|
||||
struct dvb_usb_rc_key *rc_keys;
|
||||
struct ir_scancode *rc_keys;
|
||||
int rc_keys_size;
|
||||
};
|
||||
|
||||
|
@ -948,7 +948,7 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_dw210x_table[] = {
|
||||
static struct ir_scancode ir_codes_dw210x_table[] = {
|
||||
{ 0xf80a, KEY_Q }, /*power*/
|
||||
{ 0xf80c, KEY_M }, /*mute*/
|
||||
{ 0xf811, KEY_1 },
|
||||
|
@ -982,7 +982,7 @@ static struct dvb_usb_rc_key ir_codes_dw210x_table[] = {
|
|||
{ 0xf81b, KEY_B }, /*recall*/
|
||||
};
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_tevii_table[] = {
|
||||
static struct ir_scancode ir_codes_tevii_table[] = {
|
||||
{ 0xf80a, KEY_POWER },
|
||||
{ 0xf80c, KEY_MUTE },
|
||||
{ 0xf811, KEY_1 },
|
||||
|
@ -1032,7 +1032,7 @@ static struct dvb_usb_rc_key ir_codes_tevii_table[] = {
|
|||
{ 0xf858, KEY_SWITCHVIDEOMODE },
|
||||
};
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_tbs_table[] = {
|
||||
static struct ir_scancode ir_codes_tbs_table[] = {
|
||||
{ 0xf884, KEY_POWER },
|
||||
{ 0xf894, KEY_MUTE },
|
||||
{ 0xf887, KEY_1 },
|
||||
|
@ -1075,8 +1075,8 @@ static struct ir_codes_dvb_usb_table_table keys_tables[] = {
|
|||
|
||||
static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
int keymap_size = d->props.rc_key_map_size;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
int keymap_size = d->props.rc.legacy.rc_key_map_size;
|
||||
u8 key[2];
|
||||
struct i2c_msg msg = {
|
||||
.addr = DW2102_RC_QUERY,
|
||||
|
@ -1096,7 +1096,7 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
for (i = 0; i < keymap_size ; i++) {
|
||||
if (rc5_data(&keymap[i]) == msg.buf[0]) {
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
*event = keymap[i].event;
|
||||
*event = keymap[i].keycode;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1185,13 +1185,13 @@ static int dw2102_load_firmware(struct usb_device *dev,
|
|||
/* init registers */
|
||||
switch (dev->descriptor.idProduct) {
|
||||
case USB_PID_PROF_1100:
|
||||
s6x0_properties.rc_key_map = ir_codes_tbs_table;
|
||||
s6x0_properties.rc_key_map_size =
|
||||
s6x0_properties.rc.legacy.rc_key_map = ir_codes_tbs_table;
|
||||
s6x0_properties.rc.legacy.rc_key_map_size =
|
||||
ARRAY_SIZE(ir_codes_tbs_table);
|
||||
break;
|
||||
case USB_PID_TEVII_S650:
|
||||
dw2104_properties.rc_key_map = ir_codes_tevii_table;
|
||||
dw2104_properties.rc_key_map_size =
|
||||
dw2104_properties.rc.legacy.rc_key_map = ir_codes_tevii_table;
|
||||
dw2104_properties.rc.legacy.rc_key_map_size =
|
||||
ARRAY_SIZE(ir_codes_tevii_table);
|
||||
case USB_PID_DW2104:
|
||||
reset = 1;
|
||||
|
@ -1255,10 +1255,13 @@ static struct dvb_usb_device_properties dw2102_properties = {
|
|||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &dw2102_serit_i2c_algo,
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
|
@ -1306,10 +1309,12 @@ static struct dvb_usb_device_properties dw2104_properties = {
|
|||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &dw2104_i2c_algo,
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
|
@ -1353,10 +1358,12 @@ static struct dvb_usb_device_properties dw3101_properties = {
|
|||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &dw3101_i2c_algo,
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
|
@ -1396,10 +1403,12 @@ static struct dvb_usb_device_properties s6x0_properties = {
|
|||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &s6x0_i2c_algo,
|
||||
.rc_key_map = ir_codes_tevii_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_tevii_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_tevii_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_tevii_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
.num_adapters = 1,
|
||||
|
@ -1459,8 +1468,8 @@ static int dw2102_probe(struct usb_interface *intf,
|
|||
/* fill only different fields */
|
||||
p7500->firmware = "dvb-usb-p7500.fw";
|
||||
p7500->devices[0] = d7500;
|
||||
p7500->rc_key_map = ir_codes_tbs_table;
|
||||
p7500->rc_key_map_size = ARRAY_SIZE(ir_codes_tbs_table);
|
||||
p7500->rc.legacy.rc_key_map = ir_codes_tbs_table;
|
||||
p7500->rc.legacy.rc_key_map_size = ARRAY_SIZE(ir_codes_tbs_table);
|
||||
p7500->adapter->frontend_attach = prof_7500_frontend_attach;
|
||||
|
||||
if (0 == dvb_usb_device_init(intf, &dw2102_properties,
|
||||
|
|
|
@ -349,7 +349,7 @@ static struct dvb_frontend_ops gp8psk_fe_ops = {
|
|||
* FE_CAN_QAM_16 is for compatibility
|
||||
* (Myth incorrectly detects Turbo-QPSK as plain QAM-16)
|
||||
*/
|
||||
FE_CAN_QPSK | FE_CAN_QAM_16
|
||||
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_TURBO_FEC
|
||||
},
|
||||
|
||||
.release = gp8psk_fe_release,
|
||||
|
|
|
@ -69,7 +69,7 @@ static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
|
|||
int adap_enabled[M9206_MAX_ADAPTERS] = { 0 };
|
||||
|
||||
/* Remote controller init. */
|
||||
if (d->props.rc_query) {
|
||||
if (d->props.rc.legacy.rc_query) {
|
||||
deb("Initialising remote control\n");
|
||||
while (rc_seq->address) {
|
||||
if ((ret = m920x_write(d->udev, M9206_CORE,
|
||||
|
@ -142,9 +142,9 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
|
||||
goto unlock;
|
||||
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++)
|
||||
if (rc5_data(&d->props.rc_key_map[i]) == rc_state[1]) {
|
||||
*event = d->props.rc_key_map[i].event;
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
if (rc5_data(&d->props.rc.legacy.rc_key_map[i]) == rc_state[1]) {
|
||||
*event = d->props.rc.legacy.rc_key_map[i].keycode;
|
||||
|
||||
switch(rc_state[0]) {
|
||||
case 0x80:
|
||||
|
@ -589,7 +589,7 @@ static struct m920x_inits pinnacle310e_init[] = {
|
|||
};
|
||||
|
||||
/* ir keymaps */
|
||||
static struct dvb_usb_rc_key ir_codes_megasky_table [] = {
|
||||
static struct ir_scancode ir_codes_megasky_table[] = {
|
||||
{ 0x0012, KEY_POWER },
|
||||
{ 0x001e, KEY_CYCLEWINDOWS }, /* min/max */
|
||||
{ 0x0002, KEY_CHANNELUP },
|
||||
|
@ -608,7 +608,7 @@ static struct dvb_usb_rc_key ir_codes_megasky_table [] = {
|
|||
{ 0x000e, KEY_COFFEE }, /* "MTS" */
|
||||
};
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_tvwalkertwin_table [] = {
|
||||
static struct ir_scancode ir_codes_tvwalkertwin_table[] = {
|
||||
{ 0x0001, KEY_ZOOM }, /* Full Screen */
|
||||
{ 0x0002, KEY_CAMERA }, /* snapshot */
|
||||
{ 0x0003, KEY_MUTE },
|
||||
|
@ -628,7 +628,7 @@ static struct dvb_usb_rc_key ir_codes_tvwalkertwin_table [] = {
|
|||
{ 0x001e, KEY_VOLUMEUP },
|
||||
};
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_pinnacle310e_table[] = {
|
||||
static struct ir_scancode ir_codes_pinnacle310e_table[] = {
|
||||
{ 0x16, KEY_POWER },
|
||||
{ 0x17, KEY_FAVORITES },
|
||||
{ 0x0f, KEY_TEXT },
|
||||
|
@ -784,10 +784,12 @@ static struct dvb_usb_device_properties megasky_properties = {
|
|||
.firmware = "dvb-usb-megasky-02.fw",
|
||||
.download_firmware = m920x_firmware_download,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_megasky_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_megasky_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_megasky_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_megasky_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
},
|
||||
|
||||
.size_of_priv = sizeof(struct m920x_state),
|
||||
|
||||
|
@ -885,10 +887,12 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
|
|||
.firmware = "dvb-usb-tvwalkert.fw",
|
||||
.download_firmware = m920x_firmware_download,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_tvwalkertwin_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_tvwalkertwin_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_tvwalkertwin_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_tvwalkertwin_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
},
|
||||
|
||||
.size_of_priv = sizeof(struct m920x_state),
|
||||
|
||||
|
@ -992,10 +996,12 @@ static struct dvb_usb_device_properties pinnacle_pctv310e_properties = {
|
|||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.download_firmware = NULL,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_pinnacle310e_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_pinnacle310e_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_pinnacle310e_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_pinnacle310e_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
},
|
||||
|
||||
.size_of_priv = sizeof(struct m920x_state),
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
|||
#define deb_ee(args...) dprintk(debug,0x02,args)
|
||||
|
||||
/* Hauppauge NOVA-T USB2 keys */
|
||||
static struct dvb_usb_rc_key ir_codes_haupp_table [] = {
|
||||
static struct ir_scancode ir_codes_haupp_table[] = {
|
||||
{ 0x1e00, KEY_0 },
|
||||
{ 0x1e01, KEY_1 },
|
||||
{ 0x1e02, KEY_2 },
|
||||
|
@ -98,7 +98,7 @@ static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
deb_rc("c: %x, d: %x\n", rc5_data(&ir_codes_haupp_table[i]),
|
||||
rc5_custom(&ir_codes_haupp_table[i]));
|
||||
|
||||
*event = ir_codes_haupp_table[i].event;
|
||||
*event = ir_codes_haupp_table[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
if (st->old_toggle == toggle) {
|
||||
if (st->last_repeat_count++ < 2)
|
||||
|
@ -195,10 +195,12 @@ static struct dvb_usb_device_properties nova_t_properties = {
|
|||
.power_ctrl = dibusb2_0_power_ctrl,
|
||||
.read_mac_address = nova_t_read_mac_address,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_haupp_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_haupp_table),
|
||||
.rc_query = nova_t_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_haupp_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_haupp_table),
|
||||
.rc_query = nova_t_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
||||
|
|
|
@ -331,7 +331,7 @@ static int opera1_pid_filter_control(struct dvb_usb_adapter *adap, int onoff)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_opera1_table[] = {
|
||||
static struct ir_scancode ir_codes_opera1_table[] = {
|
||||
{0x5fa0, KEY_1},
|
||||
{0x51af, KEY_2},
|
||||
{0x5da2, KEY_3},
|
||||
|
@ -407,9 +407,9 @@ static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state)
|
|||
for (i = 0; i < ARRAY_SIZE(ir_codes_opera1_table); i++) {
|
||||
if (rc5_scan(&ir_codes_opera1_table[i]) == (send_key & 0xffff)) {
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
*event = ir_codes_opera1_table[i].event;
|
||||
*event = ir_codes_opera1_table[i].keycode;
|
||||
opst->last_key_pressed =
|
||||
ir_codes_opera1_table[i].event;
|
||||
ir_codes_opera1_table[i].keycode;
|
||||
break;
|
||||
}
|
||||
opst->last_key_pressed = 0;
|
||||
|
@ -498,10 +498,12 @@ static struct dvb_usb_device_properties opera1_properties = {
|
|||
.power_ctrl = opera1_power_ctrl,
|
||||
.i2c_algo = &opera1_i2c_algo,
|
||||
|
||||
.rc_key_map = ir_codes_opera1_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_opera1_table),
|
||||
.rc_interval = 200,
|
||||
.rc_query = opera1_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_opera1_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_opera1_table),
|
||||
.rc_interval = 200,
|
||||
.rc_query = opera1_rc_query,
|
||||
},
|
||||
.read_mac_address = opera1_read_mac_address,
|
||||
.generic_bulk_ctrl_endpoint = 0x00,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
|
|
|
@ -174,7 +174,7 @@ static int vp702x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
}
|
||||
|
||||
/* keys for the enclosed remote control */
|
||||
static struct dvb_usb_rc_key ir_codes_vp702x_table[] = {
|
||||
static struct ir_scancode ir_codes_vp702x_table[] = {
|
||||
{ 0x0001, KEY_1 },
|
||||
{ 0x0002, KEY_2 },
|
||||
};
|
||||
|
@ -200,7 +200,7 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
for (i = 0; i < ARRAY_SIZE(ir_codes_vp702x_table); i++)
|
||||
if (rc5_custom(&ir_codes_vp702x_table[i]) == key[1]) {
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
*event = ir_codes_vp702x_table[i].event;
|
||||
*event = ir_codes_vp702x_table[i].keycode;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
@ -283,10 +283,12 @@ static struct dvb_usb_device_properties vp702x_properties = {
|
|||
},
|
||||
.read_mac_address = vp702x_read_mac_addr,
|
||||
|
||||
.rc_key_map = ir_codes_vp702x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_vp702x_table),
|
||||
.rc_interval = 400,
|
||||
.rc_query = vp702x_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_vp702x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_vp702x_table),
|
||||
.rc_interval = 400,
|
||||
.rc_query = vp702x_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
|
|
|
@ -99,7 +99,7 @@ static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff)
|
|||
|
||||
/* The keymapping struct. Somehow this should be loaded to the driver, but
|
||||
* currently it is hardcoded. */
|
||||
static struct dvb_usb_rc_key ir_codes_vp7045_table[] = {
|
||||
static struct ir_scancode ir_codes_vp7045_table[] = {
|
||||
{ 0x0016, KEY_POWER },
|
||||
{ 0x0010, KEY_MUTE },
|
||||
{ 0x0003, KEY_1 },
|
||||
|
@ -168,7 +168,7 @@ static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
for (i = 0; i < ARRAY_SIZE(ir_codes_vp7045_table); i++)
|
||||
if (rc5_data(&ir_codes_vp7045_table[i]) == key) {
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
*event = ir_codes_vp7045_table[i].event;
|
||||
*event = ir_codes_vp7045_table[i].keycode;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
@ -259,10 +259,12 @@ static struct dvb_usb_device_properties vp7045_properties = {
|
|||
.power_ctrl = vp7045_power_ctrl,
|
||||
.read_mac_address = vp7045_read_mac_addr,
|
||||
|
||||
.rc_interval = 400,
|
||||
.rc_key_map = ir_codes_vp7045_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_vp7045_table),
|
||||
.rc_query = vp7045_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 400,
|
||||
.rc_key_map = ir_codes_vp7045_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_vp7045_table),
|
||||
.rc_query = vp7045_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 2,
|
||||
.devices = {
|
||||
|
|
|
@ -584,6 +584,7 @@ config DVB_LGS8GL5
|
|||
config DVB_LGS8GXX
|
||||
tristate "Legend Silicon LGS8913/LGS8GL5/LGS8GXX DMB-TH demodulator"
|
||||
depends on DVB_CORE && I2C
|
||||
select FW_LOADER
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DMB-TH tuner module. Say Y when you want to support this frontend.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
|
||||
* Afatech AF9013 demodulator driver
|
||||
*
|
||||
* Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
|
@ -761,6 +761,10 @@ static int af9013_set_frontend(struct dvb_frontend *fe,
|
|||
|
||||
state->frequency = params->frequency;
|
||||
|
||||
/* program tuner */
|
||||
if (fe->ops.tuner_ops.set_params)
|
||||
fe->ops.tuner_ops.set_params(fe, params);
|
||||
|
||||
/* program CFOE coefficients */
|
||||
ret = af9013_set_coeff(state, params->u.ofdm.bandwidth);
|
||||
if (ret)
|
||||
|
@ -791,10 +795,6 @@ static int af9013_set_frontend(struct dvb_frontend *fe,
|
|||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* program tuner */
|
||||
if (fe->ops.tuner_ops.set_params)
|
||||
fe->ops.tuner_ops.set_params(fe, params);
|
||||
|
||||
/* program TPS and bandwidth, check if auto mode needed */
|
||||
ret = af9013_set_ofdm_params(state, ¶ms->u.ofdm, &auto_mode);
|
||||
if (ret)
|
||||
|
@ -1184,21 +1184,43 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
|||
u8 tmp;
|
||||
*status = 0;
|
||||
|
||||
/* TPS lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (tmp)
|
||||
*status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
|
||||
|
||||
/* MPEG2 lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd507, 6, 1, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (tmp)
|
||||
*status |= FE_HAS_SYNC | FE_HAS_LOCK;
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
|
||||
FE_HAS_SYNC | FE_HAS_LOCK;
|
||||
|
||||
if (!(*status & FE_HAS_SIGNAL)) {
|
||||
if (!*status) {
|
||||
/* TPS lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (tmp)
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
|
||||
FE_HAS_VITERBI;
|
||||
}
|
||||
|
||||
if (!*status) {
|
||||
/* CFO lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (tmp)
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
|
||||
}
|
||||
|
||||
if (!*status) {
|
||||
/* SFOE lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (tmp)
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
|
||||
}
|
||||
|
||||
if (!*status) {
|
||||
/* AGC lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp);
|
||||
if (ret)
|
||||
|
@ -1207,24 +1229,6 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
|||
*status |= FE_HAS_SIGNAL;
|
||||
}
|
||||
|
||||
if (!(*status & FE_HAS_CARRIER)) {
|
||||
/* CFO lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (tmp)
|
||||
*status |= FE_HAS_CARRIER;
|
||||
}
|
||||
|
||||
if (!(*status & FE_HAS_CARRIER)) {
|
||||
/* SFOE lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (tmp)
|
||||
*status |= FE_HAS_CARRIER;
|
||||
}
|
||||
|
||||
ret = af9013_update_statistics(fe);
|
||||
|
||||
error:
|
||||
|
@ -1574,7 +1578,7 @@ struct dvb_frontend *af9013_attach(const struct af9013_config *config,
|
|||
{
|
||||
int ret;
|
||||
struct af9013_state *state = NULL;
|
||||
u8 buf[3], i;
|
||||
u8 buf[4], i;
|
||||
|
||||
/* allocate memory for the internal state */
|
||||
state = kzalloc(sizeof(struct af9013_state), GFP_KERNEL);
|
||||
|
@ -1607,12 +1611,12 @@ struct dvb_frontend *af9013_attach(const struct af9013_config *config,
|
|||
}
|
||||
|
||||
/* firmware version */
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
ret = af9013_read_reg(state, 0x5103 + i, &buf[i]);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
info("firmware version:%d.%d.%d", buf[0], buf[1], buf[2]);
|
||||
info("firmware version:%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]);
|
||||
|
||||
/* settings for mp2if */
|
||||
if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
|
||||
* Afatech AF9013 demodulator driver
|
||||
*
|
||||
* Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
|
||||
* Afatech AF9013 demodulator driver
|
||||
*
|
||||
* Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
|
@ -132,6 +132,8 @@ static struct regdesc ofsm_init[] = {
|
|||
{ 0xd740, 2, 1, 0x00 },
|
||||
{ 0xd740, 3, 1, 0x01 },
|
||||
{ 0xd3c1, 4, 1, 0x01 },
|
||||
{ 0x9124, 0, 8, 0x58 },
|
||||
{ 0x9125, 0, 2, 0x02 },
|
||||
{ 0xd3a2, 0, 8, 0x00 },
|
||||
{ 0xd3a3, 0, 8, 0x04 },
|
||||
{ 0xd305, 0, 8, 0x32 },
|
||||
|
@ -143,7 +145,7 @@ static struct regdesc ofsm_init[] = {
|
|||
{ 0x911b, 0, 1, 0x01 },
|
||||
{ 0x9bce, 0, 4, 0x02 },
|
||||
{ 0x9116, 0, 1, 0x01 },
|
||||
{ 0x9bd1, 0, 1, 0x01 },
|
||||
{ 0x9122, 0, 8, 0xd0 },
|
||||
{ 0xd2e0, 0, 8, 0xd0 },
|
||||
{ 0xd2e9, 0, 4, 0x0d },
|
||||
{ 0xd38c, 0, 8, 0xfc },
|
||||
|
@ -165,7 +167,6 @@ static struct regdesc ofsm_init[] = {
|
|||
{ 0xd081, 4, 4, 0x09 },
|
||||
{ 0xd098, 4, 4, 0x0f },
|
||||
{ 0xd098, 0, 4, 0x03 },
|
||||
{ 0xdbc0, 3, 1, 0x01 },
|
||||
{ 0xdbc0, 4, 1, 0x01 },
|
||||
{ 0xdbc7, 0, 8, 0x08 },
|
||||
{ 0xdbc8, 4, 4, 0x00 },
|
||||
|
@ -179,6 +180,7 @@ static struct regdesc ofsm_init[] = {
|
|||
{ 0xd0f0, 0, 7, 0x1a },
|
||||
{ 0xd0f1, 4, 1, 0x01 },
|
||||
{ 0xd0f2, 0, 8, 0x0c },
|
||||
{ 0xd101, 5, 3, 0x06 },
|
||||
{ 0xd103, 0, 4, 0x08 },
|
||||
{ 0xd0f8, 0, 7, 0x20 },
|
||||
{ 0xd111, 5, 1, 0x00 },
|
||||
|
|
|
@ -38,11 +38,10 @@
|
|||
#define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator"
|
||||
#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
|
||||
|
||||
#ifdef CONFIG_DVB_DIBCOM_DEBUG
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able)).");
|
||||
#endif
|
||||
|
||||
#define deb_info(args...) dprintk(0x01,args)
|
||||
#define deb_i2c(args...) dprintk(0x02,args)
|
||||
#define deb_srch(args...) dprintk(0x04,args)
|
||||
|
@ -51,12 +50,6 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-a
|
|||
#define deb_setf(args...) dprintk(0x04,args)
|
||||
#define deb_getf(args...) dprintk(0x08,args)
|
||||
|
||||
#ifdef CONFIG_DVB_DIBCOM_DEBUG
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able)).");
|
||||
#endif
|
||||
|
||||
static int dib3000_read_reg(struct dib3000_state *state, u16 reg)
|
||||
{
|
||||
u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
|
||||
|
|
|
@ -37,12 +37,8 @@
|
|||
|
||||
/* debug */
|
||||
|
||||
#ifdef CONFIG_DVB_DIBCOM_DEBUG
|
||||
#define dprintk(level,args...) \
|
||||
do { if ((debug & level)) { printk(args); } } while (0)
|
||||
#else
|
||||
#define dprintk(args...) do { } while (0)
|
||||
#endif
|
||||
|
||||
/* mask for enabling a specific pid for the pid_filter */
|
||||
#define DIB3000_ACTIVATE_PID_FILTERING (0x2000)
|
||||
|
|
|
@ -822,7 +822,7 @@ int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defa
|
|||
|
||||
dmcst = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
|
||||
if (dmcst == NULL)
|
||||
return -ENODEV;
|
||||
return -ENOMEM;
|
||||
|
||||
dmcst->i2c_adap = i2c;
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
/*
|
||||
* Support for LGDT3305 - VSB/QAM
|
||||
* Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM
|
||||
*
|
||||
* Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org>
|
||||
* Copyright (C) 2008, 2009, 2010 Michael Krufky <mkrufky@linuxtv.org>
|
||||
*
|
||||
* LGDT3304 support 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
|
||||
|
@ -65,6 +67,8 @@ struct lgdt3305_state {
|
|||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* FIXME: verify & document the LGDT3304 registers */
|
||||
|
||||
#define LGDT3305_GEN_CTRL_1 0x0000
|
||||
#define LGDT3305_GEN_CTRL_2 0x0001
|
||||
#define LGDT3305_GEN_CTRL_3 0x0002
|
||||
|
@ -358,7 +362,12 @@ static int lgdt3305_rfagc_loop(struct lgdt3305_state *state,
|
|||
case QAM_256:
|
||||
agcdelay = 0x046b;
|
||||
rfbw = 0x8889;
|
||||
ifbw = 0x8888;
|
||||
/* FIXME: investigate optimal ifbw & rfbw values for the
|
||||
* DT3304 and re-write this switch..case block */
|
||||
if (state->cfg->demod_chip == LGDT3304)
|
||||
ifbw = 0x6666;
|
||||
else /* (state->cfg->demod_chip == LGDT3305) */
|
||||
ifbw = 0x8888;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -410,8 +419,18 @@ static int lgdt3305_agc_setup(struct lgdt3305_state *state,
|
|||
lg_dbg("lockdten = %d, acqen = %d\n", lockdten, acqen);
|
||||
|
||||
/* control agc function */
|
||||
lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
|
||||
lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
|
||||
switch (state->cfg->demod_chip) {
|
||||
case LGDT3304:
|
||||
lgdt3305_write_reg(state, 0x0314, 0xe1 | lockdten << 1);
|
||||
lgdt3305_set_reg_bit(state, 0x030e, 2, acqen);
|
||||
break;
|
||||
case LGDT3305:
|
||||
lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
|
||||
lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return lgdt3305_rfagc_loop(state, param);
|
||||
}
|
||||
|
@ -577,61 +596,79 @@ static int lgdt3305_init(struct dvb_frontend *fe)
|
|||
struct lgdt3305_state *state = fe->demodulator_priv;
|
||||
int ret;
|
||||
|
||||
static struct lgdt3305_reg lgdt3304_init_data[] = {
|
||||
{ .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, },
|
||||
{ .reg = 0x000d, .val = 0x02, },
|
||||
{ .reg = 0x000e, .val = 0x02, },
|
||||
{ .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, },
|
||||
{ .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTRL_7, .val = 0xf9, },
|
||||
{ .reg = 0x0112, .val = 0x17, },
|
||||
{ .reg = 0x0113, .val = 0x15, },
|
||||
{ .reg = 0x0114, .val = 0x18, },
|
||||
{ .reg = 0x0115, .val = 0xff, },
|
||||
{ .reg = 0x0116, .val = 0x3c, },
|
||||
{ .reg = 0x0214, .val = 0x67, },
|
||||
{ .reg = 0x0424, .val = 0x8d, },
|
||||
{ .reg = 0x0427, .val = 0x12, },
|
||||
{ .reg = 0x0428, .val = 0x4f, },
|
||||
{ .reg = LGDT3305_IFBW_1, .val = 0x80, },
|
||||
{ .reg = LGDT3305_IFBW_2, .val = 0x00, },
|
||||
{ .reg = 0x030a, .val = 0x08, },
|
||||
{ .reg = 0x030b, .val = 0x9b, },
|
||||
{ .reg = 0x030d, .val = 0x00, },
|
||||
{ .reg = 0x030e, .val = 0x1c, },
|
||||
{ .reg = 0x0314, .val = 0xe1, },
|
||||
{ .reg = 0x000d, .val = 0x82, },
|
||||
{ .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, },
|
||||
{ .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, },
|
||||
};
|
||||
|
||||
static struct lgdt3305_reg lgdt3305_init_data[] = {
|
||||
{ .reg = LGDT3305_GEN_CTRL_1,
|
||||
.val = 0x03, },
|
||||
{ .reg = LGDT3305_GEN_CTRL_2,
|
||||
.val = 0xb0, },
|
||||
{ .reg = LGDT3305_GEN_CTRL_3,
|
||||
.val = 0x01, },
|
||||
{ .reg = LGDT3305_GEN_CONTROL,
|
||||
.val = 0x6f, },
|
||||
{ .reg = LGDT3305_GEN_CTRL_4,
|
||||
.val = 0x03, },
|
||||
{ .reg = LGDT3305_DGTL_AGC_REF_1,
|
||||
.val = 0x32, },
|
||||
{ .reg = LGDT3305_DGTL_AGC_REF_2,
|
||||
.val = 0xc4, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_1,
|
||||
.val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_2,
|
||||
.val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_3,
|
||||
.val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_4,
|
||||
.val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTRL_7,
|
||||
.val = 0x79, },
|
||||
{ .reg = LGDT3305_AGC_POWER_REF_1,
|
||||
.val = 0x32, },
|
||||
{ .reg = LGDT3305_AGC_POWER_REF_2,
|
||||
.val = 0xc4, },
|
||||
{ .reg = LGDT3305_AGC_DELAY_PT_1,
|
||||
.val = 0x0d, },
|
||||
{ .reg = LGDT3305_AGC_DELAY_PT_2,
|
||||
.val = 0x30, },
|
||||
{ .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_1,
|
||||
.val = 0x80, },
|
||||
{ .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_2,
|
||||
.val = 0x00, },
|
||||
{ .reg = LGDT3305_IFBW_1,
|
||||
.val = 0x80, },
|
||||
{ .reg = LGDT3305_IFBW_2,
|
||||
.val = 0x00, },
|
||||
{ .reg = LGDT3305_AGC_CTRL_1,
|
||||
.val = 0x30, },
|
||||
{ .reg = LGDT3305_AGC_CTRL_4,
|
||||
.val = 0x61, },
|
||||
{ .reg = LGDT3305_FEC_BLOCK_CTRL,
|
||||
.val = 0xff, },
|
||||
{ .reg = LGDT3305_TP_CTRL_1,
|
||||
.val = 0x1b, },
|
||||
{ .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, },
|
||||
{ .reg = LGDT3305_GEN_CTRL_2, .val = 0xb0, },
|
||||
{ .reg = LGDT3305_GEN_CTRL_3, .val = 0x01, },
|
||||
{ .reg = LGDT3305_GEN_CONTROL, .val = 0x6f, },
|
||||
{ .reg = LGDT3305_GEN_CTRL_4, .val = 0x03, },
|
||||
{ .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, },
|
||||
{ .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTRL_7, .val = 0x79, },
|
||||
{ .reg = LGDT3305_AGC_POWER_REF_1, .val = 0x32, },
|
||||
{ .reg = LGDT3305_AGC_POWER_REF_2, .val = 0xc4, },
|
||||
{ .reg = LGDT3305_AGC_DELAY_PT_1, .val = 0x0d, },
|
||||
{ .reg = LGDT3305_AGC_DELAY_PT_2, .val = 0x30, },
|
||||
{ .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_1, .val = 0x80, },
|
||||
{ .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_2, .val = 0x00, },
|
||||
{ .reg = LGDT3305_IFBW_1, .val = 0x80, },
|
||||
{ .reg = LGDT3305_IFBW_2, .val = 0x00, },
|
||||
{ .reg = LGDT3305_AGC_CTRL_1, .val = 0x30, },
|
||||
{ .reg = LGDT3305_AGC_CTRL_4, .val = 0x61, },
|
||||
{ .reg = LGDT3305_FEC_BLOCK_CTRL, .val = 0xff, },
|
||||
{ .reg = LGDT3305_TP_CTRL_1, .val = 0x1b, },
|
||||
};
|
||||
|
||||
lg_dbg("\n");
|
||||
|
||||
ret = lgdt3305_write_regs(state, lgdt3305_init_data,
|
||||
ARRAY_SIZE(lgdt3305_init_data));
|
||||
switch (state->cfg->demod_chip) {
|
||||
case LGDT3304:
|
||||
ret = lgdt3305_write_regs(state, lgdt3304_init_data,
|
||||
ARRAY_SIZE(lgdt3304_init_data));
|
||||
break;
|
||||
case LGDT3305:
|
||||
ret = lgdt3305_write_regs(state, lgdt3305_init_data,
|
||||
ARRAY_SIZE(lgdt3305_init_data));
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
|
||||
|
@ -640,6 +677,76 @@ static int lgdt3305_init(struct dvb_frontend *fe)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int lgdt3304_set_parameters(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *param)
|
||||
{
|
||||
struct lgdt3305_state *state = fe->demodulator_priv;
|
||||
int ret;
|
||||
|
||||
lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation);
|
||||
|
||||
if (fe->ops.tuner_ops.set_params) {
|
||||
ret = fe->ops.tuner_ops.set_params(fe, param);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
state->current_frequency = param->frequency;
|
||||
}
|
||||
|
||||
ret = lgdt3305_set_modulation(state, param);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = lgdt3305_passband_digital_agc(state, param);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = lgdt3305_agc_setup(state, param);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
|
||||
/* reg 0x030d is 3304-only... seen in vsb and qam usbsnoops... */
|
||||
switch (param->u.vsb.modulation) {
|
||||
case VSB_8:
|
||||
lgdt3305_write_reg(state, 0x030d, 0x00);
|
||||
lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, 0x4f);
|
||||
lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, 0x0c);
|
||||
lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, 0xac);
|
||||
lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, 0xba);
|
||||
break;
|
||||
case QAM_64:
|
||||
case QAM_256:
|
||||
lgdt3305_write_reg(state, 0x030d, 0x14);
|
||||
ret = lgdt3305_set_if(state, param);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
ret = lgdt3305_spectral_inversion(state, param,
|
||||
state->cfg->spectral_inversion
|
||||
? 1 : 0);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
|
||||
state->current_modulation = param->u.vsb.modulation;
|
||||
|
||||
ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
|
||||
/* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
|
||||
ret = lgdt3305_mpeg_mode_polarity(state,
|
||||
state->cfg->tpclk_edge,
|
||||
state->cfg->tpvalid_polarity);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lgdt3305_set_parameters(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *param)
|
||||
{
|
||||
|
@ -848,6 +955,10 @@ static int lgdt3305_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
|||
switch (state->current_modulation) {
|
||||
case QAM_256:
|
||||
case QAM_64:
|
||||
/* signal bit is unreliable on the DT3304 in QAM mode */
|
||||
if (((LGDT3304 == state->cfg->demod_chip)) && (cr_lock))
|
||||
*status |= FE_HAS_SIGNAL;
|
||||
|
||||
ret = lgdt3305_read_fec_lock_status(state, &fec_lock);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
|
@ -993,6 +1104,7 @@ static void lgdt3305_release(struct dvb_frontend *fe)
|
|||
kfree(state);
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops lgdt3304_ops;
|
||||
static struct dvb_frontend_ops lgdt3305_ops;
|
||||
|
||||
struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
|
||||
|
@ -1013,11 +1125,21 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
|
|||
state->cfg = config;
|
||||
state->i2c_adap = i2c_adap;
|
||||
|
||||
memcpy(&state->frontend.ops, &lgdt3305_ops,
|
||||
sizeof(struct dvb_frontend_ops));
|
||||
switch (config->demod_chip) {
|
||||
case LGDT3304:
|
||||
memcpy(&state->frontend.ops, &lgdt3304_ops,
|
||||
sizeof(struct dvb_frontend_ops));
|
||||
break;
|
||||
case LGDT3305:
|
||||
memcpy(&state->frontend.ops, &lgdt3305_ops,
|
||||
sizeof(struct dvb_frontend_ops));
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
state->frontend.demodulator_priv = state;
|
||||
|
||||
/* verify that we're talking to a lg dt3305 */
|
||||
/* verify that we're talking to a lg dt3304/5 */
|
||||
ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_2, &val);
|
||||
if ((lg_fail(ret)) | (val == 0))
|
||||
goto fail;
|
||||
|
@ -1036,12 +1158,35 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
|
|||
|
||||
return &state->frontend;
|
||||
fail:
|
||||
lg_warn("unable to detect LGDT3305 hardware\n");
|
||||
lg_warn("unable to detect %s hardware\n",
|
||||
config->demod_chip ? "LGDT3304" : "LGDT3305");
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(lgdt3305_attach);
|
||||
|
||||
static struct dvb_frontend_ops lgdt3304_ops = {
|
||||
.info = {
|
||||
.name = "LG Electronics LGDT3304 VSB/QAM Frontend",
|
||||
.type = FE_ATSC,
|
||||
.frequency_min = 54000000,
|
||||
.frequency_max = 858000000,
|
||||
.frequency_stepsize = 62500,
|
||||
.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
|
||||
},
|
||||
.i2c_gate_ctrl = lgdt3305_i2c_gate_ctrl,
|
||||
.init = lgdt3305_init,
|
||||
.set_frontend = lgdt3304_set_parameters,
|
||||
.get_frontend = lgdt3305_get_frontend,
|
||||
.get_tune_settings = lgdt3305_get_tune_settings,
|
||||
.read_status = lgdt3305_read_status,
|
||||
.read_ber = lgdt3305_read_ber,
|
||||
.read_signal_strength = lgdt3305_read_signal_strength,
|
||||
.read_snr = lgdt3305_read_snr,
|
||||
.read_ucblocks = lgdt3305_read_ucblocks,
|
||||
.release = lgdt3305_release,
|
||||
};
|
||||
|
||||
static struct dvb_frontend_ops lgdt3305_ops = {
|
||||
.info = {
|
||||
.name = "LG Electronics LGDT3305 VSB/QAM Frontend",
|
||||
|
@ -1065,10 +1210,10 @@ static struct dvb_frontend_ops lgdt3305_ops = {
|
|||
.release = lgdt3305_release,
|
||||
};
|
||||
|
||||
MODULE_DESCRIPTION("LG Electronics LGDT3305 ATSC/QAM-B Demodulator Driver");
|
||||
MODULE_DESCRIPTION("LG Electronics LGDT3304/5 ATSC/QAM-B Demodulator Driver");
|
||||
MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION("0.1");
|
||||
MODULE_VERSION("0.2");
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Support for LGDT3305 - VSB/QAM
|
||||
* Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM
|
||||
*
|
||||
* Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org>
|
||||
* Copyright (C) 2008, 2009, 2010 Michael Krufky <mkrufky@linuxtv.org>
|
||||
*
|
||||
* 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
|
||||
|
@ -41,6 +41,11 @@ enum lgdt3305_tp_valid_polarity {
|
|||
LGDT3305_TP_VALID_HIGH = 1,
|
||||
};
|
||||
|
||||
enum lgdt_demod_chip_type {
|
||||
LGDT3305 = 0,
|
||||
LGDT3304 = 1,
|
||||
};
|
||||
|
||||
struct lgdt3305_config {
|
||||
u8 i2c_addr;
|
||||
|
||||
|
@ -65,6 +70,7 @@ struct lgdt3305_config {
|
|||
enum lgdt3305_mpeg_mode mpeg_mode;
|
||||
enum lgdt3305_tp_clock_edge tpclk_edge;
|
||||
enum lgdt3305_tp_valid_polarity tpvalid_polarity;
|
||||
enum lgdt_demod_chip_type demod_chip;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_LGDT3305) || (defined(CONFIG_DVB_LGDT3305_MODULE) && \
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
|
||||
#include <asm/div64.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
|
@ -46,42 +47,6 @@ module_param(fake_signal_str, int, 0644);
|
|||
MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913."
|
||||
"Signal strength calculation is slow.(default:on).");
|
||||
|
||||
static const u8 lgs8g75_initdat[] = {
|
||||
0x01, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xE4, 0xF5, 0xA8, 0xF5, 0xB8, 0xF5, 0x88, 0xF5,
|
||||
0x89, 0xF5, 0x87, 0x75, 0xD0, 0x00, 0x11, 0x50,
|
||||
0x11, 0x50, 0xF4, 0xF5, 0x80, 0xF5, 0x90, 0xF5,
|
||||
0xA0, 0xF5, 0xB0, 0x75, 0x81, 0x30, 0x80, 0x01,
|
||||
0x32, 0x90, 0x80, 0x12, 0x74, 0xFF, 0xF0, 0x90,
|
||||
0x80, 0x13, 0x74, 0x1F, 0xF0, 0x90, 0x80, 0x23,
|
||||
0x74, 0x01, 0xF0, 0x90, 0x80, 0x22, 0xF0, 0x90,
|
||||
0x00, 0x48, 0x74, 0x00, 0xF0, 0x90, 0x80, 0x4D,
|
||||
0x74, 0x05, 0xF0, 0x90, 0x80, 0x09, 0xE0, 0x60,
|
||||
0x21, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x1B, 0x12,
|
||||
0x00, 0xDD, 0x14, 0x60, 0x15, 0x12, 0x00, 0xDD,
|
||||
0x14, 0x60, 0x0F, 0x12, 0x00, 0xDD, 0x14, 0x60,
|
||||
0x09, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x03, 0x12,
|
||||
0x00, 0xDD, 0x90, 0x80, 0x42, 0xE0, 0x60, 0x0B,
|
||||
0x14, 0x60, 0x0C, 0x14, 0x60, 0x0D, 0x14, 0x60,
|
||||
0x0E, 0x01, 0xB3, 0x74, 0x04, 0x01, 0xB9, 0x74,
|
||||
0x05, 0x01, 0xB9, 0x74, 0x07, 0x01, 0xB9, 0x74,
|
||||
0x0A, 0xC0, 0xE0, 0x74, 0xC8, 0x12, 0x00, 0xE2,
|
||||
0xD0, 0xE0, 0x14, 0x70, 0xF4, 0x90, 0x80, 0x09,
|
||||
0xE0, 0x70, 0xAE, 0x12, 0x00, 0xF6, 0x12, 0x00,
|
||||
0xFE, 0x90, 0x00, 0x48, 0xE0, 0x04, 0xF0, 0x90,
|
||||
0x80, 0x4E, 0xF0, 0x01, 0x73, 0x90, 0x80, 0x08,
|
||||
0xF0, 0x22, 0xF8, 0x7A, 0x0C, 0x79, 0xFD, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9,
|
||||
0xF6, 0xDA, 0xF2, 0xD8, 0xEE, 0x22, 0x90, 0x80,
|
||||
0x65, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x90, 0x80,
|
||||
0x65, 0xE0, 0x44, 0xC2, 0xF0, 0x22
|
||||
};
|
||||
|
||||
/* LGS8GXX internal helper functions */
|
||||
|
||||
static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data)
|
||||
|
@ -627,9 +592,14 @@ static int lgs8913_init(struct lgs8gxx_state *priv)
|
|||
|
||||
static int lgs8g75_init_data(struct lgs8gxx_state *priv)
|
||||
{
|
||||
const u8 *p = lgs8g75_initdat;
|
||||
const struct firmware *fw;
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
rc = request_firmware(&fw, "lgs8g75.fw", &priv->i2c->dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
lgs8gxx_write_reg(priv, 0xC6, 0x40);
|
||||
|
||||
lgs8gxx_write_reg(priv, 0x3D, 0x04);
|
||||
|
@ -640,16 +610,16 @@ static int lgs8g75_init_data(struct lgs8gxx_state *priv)
|
|||
lgs8gxx_write_reg(priv, 0x3B, 0x00);
|
||||
lgs8gxx_write_reg(priv, 0x38, 0x00);
|
||||
|
||||
for (i = 0; i < sizeof(lgs8g75_initdat); i++) {
|
||||
for (i = 0; i < fw->size; i++) {
|
||||
lgs8gxx_write_reg(priv, 0x38, 0x00);
|
||||
lgs8gxx_write_reg(priv, 0x3A, (u8)(i&0xff));
|
||||
lgs8gxx_write_reg(priv, 0x3B, (u8)(i>>8));
|
||||
lgs8gxx_write_reg(priv, 0x3C, *p);
|
||||
p++;
|
||||
lgs8gxx_write_reg(priv, 0x3C, fw->data[i]);
|
||||
}
|
||||
|
||||
lgs8gxx_write_reg(priv, 0x38, 0x00);
|
||||
|
||||
release_firmware(fw);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1833,7 +1833,6 @@ static struct dvb_frontend_ops mb86a16_ops = {
|
|||
|
||||
.get_frontend_algo = mb86a16_frontend_algo,
|
||||
.search = mb86a16_search,
|
||||
.read_status = mb86a16_read_status,
|
||||
.init = mb86a16_init,
|
||||
.sleep = mb86a16_sleep,
|
||||
.read_status = mb86a16_read_status,
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/math64.h>
|
||||
#include <asm/div64.h>
|
||||
#include "dvb_frontend.h"
|
||||
#include "dvb_math.h"
|
||||
|
@ -49,8 +50,8 @@
|
|||
#define TDA10048_CONF_C4_1 0x1E
|
||||
#define TDA10048_CONF_C4_2 0x1F
|
||||
#define TDA10048_CODE_IN_RAM 0x20
|
||||
#define TDA10048_CHANNEL_INFO_1_R 0x22
|
||||
#define TDA10048_CHANNEL_INFO_2_R 0x23
|
||||
#define TDA10048_CHANNEL_INFO1_R 0x22
|
||||
#define TDA10048_CHANNEL_INFO2_R 0x23
|
||||
#define TDA10048_CHANNEL_INFO1 0x24
|
||||
#define TDA10048_CHANNEL_INFO2 0x25
|
||||
#define TDA10048_TIME_ERROR_R 0x26
|
||||
|
@ -63,8 +64,8 @@
|
|||
#define TDA10048_IT_STAT 0x32
|
||||
#define TDA10048_DSP_AD_LSB 0x3C
|
||||
#define TDA10048_DSP_AD_MSB 0x3D
|
||||
#define TDA10048_DSP_REF_LSB 0x3E
|
||||
#define TDA10048_DSP_REF_MSB 0x3F
|
||||
#define TDA10048_DSP_REG_LSB 0x3E
|
||||
#define TDA10048_DSP_REG_MSB 0x3F
|
||||
#define TDA10048_CONF_TRISTATE1 0x44
|
||||
#define TDA10048_CONF_TRISTATE2 0x45
|
||||
#define TDA10048_CONF_POLARITY 0x46
|
||||
|
@ -112,7 +113,7 @@
|
|||
#define TDA10048_FREE_REG_1 0xB2
|
||||
#define TDA10048_FREE_REG_2 0xB3
|
||||
#define TDA10048_CONF_C3_1 0xC0
|
||||
#define TDA10048_CYBER_CTRL 0xC2
|
||||
#define TDA10048_CVBER_CTRL 0xC2
|
||||
#define TDA10048_CBER_NMAX_LSB 0xC4
|
||||
#define TDA10048_CBER_NMAX_MSB 0xC5
|
||||
#define TDA10048_CBER_LSB 0xC6
|
||||
|
@ -120,7 +121,7 @@
|
|||
#define TDA10048_VBER_LSB 0xC8
|
||||
#define TDA10048_VBER_MID 0xC9
|
||||
#define TDA10048_VBER_MSB 0xCA
|
||||
#define TDA10048_CYBER_LUT 0xCC
|
||||
#define TDA10048_CVBER_LUT 0xCC
|
||||
#define TDA10048_UNCOR_CTRL 0xCD
|
||||
#define TDA10048_UNCOR_CPT_LSB 0xCE
|
||||
#define TDA10048_UNCOR_CPT_MSB 0xCF
|
||||
|
@ -183,7 +184,7 @@ static struct init_tab {
|
|||
{ TDA10048_AGC_IF_MAX, 0xff },
|
||||
{ TDA10048_AGC_THRESHOLD_MSB, 0x00 },
|
||||
{ TDA10048_AGC_THRESHOLD_LSB, 0x70 },
|
||||
{ TDA10048_CYBER_CTRL, 0x38 },
|
||||
{ TDA10048_CVBER_CTRL, 0x38 },
|
||||
{ TDA10048_AGC_GAINS, 0x12 },
|
||||
{ TDA10048_CONF_XO, 0x00 },
|
||||
{ TDA10048_CONF_TS1, 0x07 },
|
||||
|
@ -688,7 +689,7 @@ static int tda10048_get_tps(struct tda10048_state *state,
|
|||
p->guard_interval = GUARD_INTERVAL_1_4;
|
||||
break;
|
||||
}
|
||||
switch (val & 0x02) {
|
||||
switch (val & 0x03) {
|
||||
case 0:
|
||||
p->transmission_mode = TRANSMISSION_MODE_2K;
|
||||
break;
|
||||
|
@ -765,6 +766,8 @@ static int tda10048_set_frontend(struct dvb_frontend *fe,
|
|||
|
||||
/* Enable demod TPS auto detection and begin acquisition */
|
||||
tda10048_writereg(state, TDA10048_AUTO, 0x57);
|
||||
/* trigger cber and vber acquisition */
|
||||
tda10048_writereg(state, TDA10048_CVBER_CTRL, 0x3B);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -830,12 +833,27 @@ static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
|||
static int tda10048_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||
{
|
||||
struct tda10048_state *state = fe->demodulator_priv;
|
||||
static u32 cber_current;
|
||||
u32 cber_nmax;
|
||||
u64 cber_tmp;
|
||||
|
||||
dprintk(1, "%s()\n", __func__);
|
||||
|
||||
/* TODO: A reset may be required here */
|
||||
*ber = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 |
|
||||
tda10048_readreg(state, TDA10048_CBER_LSB);
|
||||
/* update cber on interrupt */
|
||||
if (tda10048_readreg(state, TDA10048_SOFT_IT_C3) & 0x01) {
|
||||
cber_tmp = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 |
|
||||
tda10048_readreg(state, TDA10048_CBER_LSB);
|
||||
cber_nmax = tda10048_readreg(state, TDA10048_CBER_NMAX_MSB) << 8 |
|
||||
tda10048_readreg(state, TDA10048_CBER_NMAX_LSB);
|
||||
cber_tmp *= 100000000;
|
||||
cber_tmp *= 2;
|
||||
cber_tmp = div_u64(cber_tmp, (cber_nmax * 32) + 1);
|
||||
cber_current = (u32)cber_tmp;
|
||||
/* retrigger cber acquisition */
|
||||
tda10048_writereg(state, TDA10048_CVBER_CTRL, 0x39);
|
||||
}
|
||||
/* actual cber is (*ber)/1e8 */
|
||||
*ber = cber_current;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1015,6 +1033,9 @@ static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
|
|||
|
||||
*ucblocks = tda10048_readreg(state, TDA10048_UNCOR_CPT_MSB) << 8 |
|
||||
tda10048_readreg(state, TDA10048_UNCOR_CPT_LSB);
|
||||
/* clear the uncorrected TS packets counter when saturated */
|
||||
if (*ucblocks == 0xFFFF)
|
||||
tda10048_writereg(state, TDA10048_UNCOR_CTRL, 0x80);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -10,9 +10,15 @@ config MANTIS_CORE
|
|||
config DVB_MANTIS
|
||||
tristate "MANTIS based cards"
|
||||
depends on MANTIS_CORE && DVB_CORE && PCI && I2C
|
||||
select DVB_MB86A16
|
||||
select DVB_ZL10353
|
||||
select DVB_STV0299
|
||||
select DVB_MB86A16 if !DVB_FE_CUSTOMISE
|
||||
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV0299 if !DVB_FE_CUSTOMISE
|
||||
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STB0899 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STB6100 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA665x if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA10021 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA10023 if !DVB_FE_CUSTOMISE
|
||||
select DVB_PLL
|
||||
help
|
||||
Support for PCI cards based on the Mantis PCI bridge.
|
||||
|
@ -23,7 +29,7 @@ config DVB_MANTIS
|
|||
config DVB_HOPPER
|
||||
tristate "HOPPER based cards"
|
||||
depends on MANTIS_CORE && DVB_CORE && PCI && I2C
|
||||
select DVB_ZL10353
|
||||
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
|
||||
select DVB_PLL
|
||||
help
|
||||
Support for PCI cards based on the Hopper PCI bridge.
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <media/ir-common.h>
|
||||
#include <media/ir-core.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "dmxdev.h"
|
||||
|
@ -104,7 +104,6 @@ EXPORT_SYMBOL_GPL(ir_mantis);
|
|||
int mantis_input_init(struct mantis_pci *mantis)
|
||||
{
|
||||
struct input_dev *rc;
|
||||
struct ir_input_state rc_state;
|
||||
char name[80], dev[80];
|
||||
int err;
|
||||
|
||||
|
@ -120,8 +119,6 @@ int mantis_input_init(struct mantis_pci *mantis)
|
|||
rc->name = name;
|
||||
rc->phys = dev;
|
||||
|
||||
ir_input_init(rc, &rc_state, IR_TYPE_OTHER);
|
||||
|
||||
rc->id.bustype = BUS_PCI;
|
||||
rc->id.vendor = mantis->vendor_id;
|
||||
rc->id.product = mantis->device_id;
|
||||
|
|
|
@ -64,9 +64,11 @@ static struct sms_board sms_boards[] = {
|
|||
.type = SMS_NOVA_B0,
|
||||
.fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw",
|
||||
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
|
||||
.rc_codes = RC_MAP_RC5_HAUPPAUGE_NEW,
|
||||
.board_cfg.leds_power = 26,
|
||||
.board_cfg.led0 = 27,
|
||||
.board_cfg.led1 = 28,
|
||||
.board_cfg.ir = 9,
|
||||
.led_power = 26,
|
||||
.led_lo = 27,
|
||||
.led_hi = 28,
|
||||
|
|
|
@ -75,7 +75,7 @@ struct sms_board {
|
|||
enum sms_device_type_st type;
|
||||
char *name, *fw[DEVICE_MODE_MAX];
|
||||
struct sms_board_gpio_cfg board_cfg;
|
||||
enum ir_kb_type ir_kb_type;
|
||||
char *rc_codes; /* Name of IR codes table */
|
||||
|
||||
/* gpios */
|
||||
int led_power, led_hi, led_lo, lna_ctrl, rf_switch;
|
||||
|
|
|
@ -116,9 +116,7 @@ static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
|
|||
return entry;
|
||||
}
|
||||
}
|
||||
entry = (struct smscore_registry_entry_t *)
|
||||
kmalloc(sizeof(struct smscore_registry_entry_t),
|
||||
GFP_KERNEL);
|
||||
entry = kmalloc(sizeof(struct smscore_registry_entry_t), GFP_KERNEL);
|
||||
if (entry) {
|
||||
entry->mode = default_mode;
|
||||
strcpy(entry->devpath, devpath);
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
MDTV receiver kernel modules.
|
||||
Copyright (C) 2006-2009, Uri Shkolnik
|
||||
|
||||
Copyright (c) 2010 - Mauro Carvalho Chehab
|
||||
- Ported the driver to use rc-core
|
||||
- IR raw event decoding is now done at rc-core
|
||||
- Code almost re-written
|
||||
|
||||
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
|
||||
|
@ -27,226 +32,28 @@
|
|||
#include "smsir.h"
|
||||
#include "sms-cards.h"
|
||||
|
||||
/* In order to add new IR remote control -
|
||||
* 1) Add it to the <enum ir_kb_type> @ smsir,h,
|
||||
* 2) Add its map to keyboard_layout_maps below
|
||||
* 3) Set your board (sms-cards sub-module) to use it
|
||||
*/
|
||||
|
||||
static struct keyboard_layout_map_t keyboard_layout_maps[] = {
|
||||
[SMS_IR_KB_DEFAULT_TV] = {
|
||||
.ir_protocol = IR_RC5,
|
||||
.rc5_kbd_address = KEYBOARD_ADDRESS_TV1,
|
||||
.keyboard_layout_map = {
|
||||
KEY_0, KEY_1, KEY_2,
|
||||
KEY_3, KEY_4, KEY_5,
|
||||
KEY_6, KEY_7, KEY_8,
|
||||
KEY_9, 0, 0, KEY_POWER,
|
||||
KEY_MUTE, 0, 0,
|
||||
KEY_VOLUMEUP, KEY_VOLUMEDOWN,
|
||||
KEY_BRIGHTNESSUP,
|
||||
KEY_BRIGHTNESSDOWN, KEY_CHANNELUP,
|
||||
KEY_CHANNELDOWN,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}
|
||||
},
|
||||
[SMS_IR_KB_HCW_SILVER] = {
|
||||
.ir_protocol = IR_RC5,
|
||||
.rc5_kbd_address = KEYBOARD_ADDRESS_LIGHTING1,
|
||||
.keyboard_layout_map = {
|
||||
KEY_0, KEY_1, KEY_2,
|
||||
KEY_3, KEY_4, KEY_5,
|
||||
KEY_6, KEY_7, KEY_8,
|
||||
KEY_9, KEY_TEXT, KEY_RED,
|
||||
KEY_RADIO, KEY_MENU,
|
||||
KEY_SUBTITLE,
|
||||
KEY_MUTE, KEY_VOLUMEUP,
|
||||
KEY_VOLUMEDOWN, KEY_PREVIOUS, 0,
|
||||
KEY_UP, KEY_DOWN, KEY_LEFT,
|
||||
KEY_RIGHT, KEY_VIDEO, KEY_AUDIO,
|
||||
KEY_MHP, KEY_EPG, KEY_TV,
|
||||
0, KEY_NEXTSONG, KEY_EXIT,
|
||||
KEY_CHANNELUP, KEY_CHANNELDOWN,
|
||||
KEY_CHANNEL, 0,
|
||||
KEY_PREVIOUSSONG, KEY_ENTER,
|
||||
KEY_SLEEP, 0, 0, KEY_BLUE,
|
||||
0, 0, 0, 0, KEY_GREEN, 0,
|
||||
KEY_PAUSE, 0, KEY_REWIND,
|
||||
0, KEY_FASTFORWARD, KEY_PLAY,
|
||||
KEY_STOP, KEY_RECORD,
|
||||
KEY_YELLOW, 0, 0, KEY_SELECT,
|
||||
KEY_ZOOM, KEY_POWER, 0, 0
|
||||
}
|
||||
},
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
static u32 ir_pos;
|
||||
static u32 ir_word;
|
||||
static u32 ir_toggle;
|
||||
|
||||
#define RC5_PUSH_BIT(dst, bit, pos) \
|
||||
{ dst <<= 1; dst |= bit; pos++; }
|
||||
|
||||
|
||||
static void sms_ir_rc5_event(struct smscore_device_t *coredev,
|
||||
u32 toggle, u32 addr, u32 cmd)
|
||||
{
|
||||
bool toggle_changed;
|
||||
u16 keycode;
|
||||
|
||||
sms_log("IR RC5 word: address %d, command %d, toggle %d",
|
||||
addr, cmd, toggle);
|
||||
|
||||
toggle_changed = ir_toggle != toggle;
|
||||
/* keep toggle */
|
||||
ir_toggle = toggle;
|
||||
|
||||
if (addr !=
|
||||
keyboard_layout_maps[coredev->ir.ir_kb_type].rc5_kbd_address)
|
||||
return; /* Check for valid address */
|
||||
|
||||
keycode =
|
||||
keyboard_layout_maps
|
||||
[coredev->ir.ir_kb_type].keyboard_layout_map[cmd];
|
||||
|
||||
if (!toggle_changed &&
|
||||
(keycode != KEY_VOLUMEUP && keycode != KEY_VOLUMEDOWN))
|
||||
return; /* accept only repeated volume, reject other keys */
|
||||
|
||||
sms_log("kernel input keycode (from ir) %d", keycode);
|
||||
input_report_key(coredev->ir.input_dev, keycode, 1);
|
||||
input_sync(coredev->ir.input_dev);
|
||||
|
||||
}
|
||||
|
||||
/* decode raw bit pattern to RC5 code */
|
||||
/* taken from ir-functions.c */
|
||||
static u32 ir_rc5_decode(unsigned int code)
|
||||
{
|
||||
/* unsigned int org_code = code;*/
|
||||
unsigned int pair;
|
||||
unsigned int rc5 = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 14; ++i) {
|
||||
pair = code & 0x3;
|
||||
code >>= 2;
|
||||
|
||||
rc5 <<= 1;
|
||||
switch (pair) {
|
||||
case 0:
|
||||
case 2:
|
||||
break;
|
||||
case 1:
|
||||
rc5 |= 1;
|
||||
break;
|
||||
case 3:
|
||||
/* dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);*/
|
||||
sms_log("bad code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
dprintk(1, "ir-common: code=%x, rc5=%x, start=%x,
|
||||
toggle=%x, address=%x, "
|
||||
"instr=%x\n", rc5, org_code, RC5_START(rc5),
|
||||
RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
|
||||
*/
|
||||
return rc5;
|
||||
}
|
||||
|
||||
static void sms_rc5_parse_word(struct smscore_device_t *coredev)
|
||||
{
|
||||
#define RC5_START(x) (((x)>>12)&3)
|
||||
#define RC5_TOGGLE(x) (((x)>>11)&1)
|
||||
#define RC5_ADDR(x) (((x)>>6)&0x1F)
|
||||
#define RC5_INSTR(x) ((x)&0x3F)
|
||||
|
||||
int i, j;
|
||||
u32 rc5_word = 0;
|
||||
|
||||
/* Reverse the IR word direction */
|
||||
for (i = 0 ; i < 28 ; i++)
|
||||
RC5_PUSH_BIT(rc5_word, (ir_word>>i)&1, j)
|
||||
|
||||
rc5_word = ir_rc5_decode(rc5_word);
|
||||
/* sms_log("temp = 0x%x, rc5_code = 0x%x", ir_word, rc5_word); */
|
||||
|
||||
sms_ir_rc5_event(coredev,
|
||||
RC5_TOGGLE(rc5_word),
|
||||
RC5_ADDR(rc5_word),
|
||||
RC5_INSTR(rc5_word));
|
||||
}
|
||||
|
||||
|
||||
static void sms_rc5_accumulate_bits(struct smscore_device_t *coredev,
|
||||
s32 ir_sample)
|
||||
{
|
||||
#define RC5_TIME_GRANULARITY 200
|
||||
#define RC5_DEF_BIT_TIME 889
|
||||
#define RC5_MAX_SAME_BIT_CONT 4
|
||||
#define RC5_WORD_LEN 27 /* 28 bit */
|
||||
|
||||
u32 i, j;
|
||||
s32 delta_time;
|
||||
u32 time = (ir_sample > 0) ? ir_sample : (0-ir_sample);
|
||||
u32 level = (ir_sample < 0) ? 0 : 1;
|
||||
|
||||
for (i = RC5_MAX_SAME_BIT_CONT; i > 0; i--) {
|
||||
delta_time = time - (i*RC5_DEF_BIT_TIME) + RC5_TIME_GRANULARITY;
|
||||
if (delta_time < 0)
|
||||
continue; /* not so many consecutive bits */
|
||||
if (delta_time > (2 * RC5_TIME_GRANULARITY)) {
|
||||
/* timeout */
|
||||
if (ir_pos == (RC5_WORD_LEN-1))
|
||||
/* complete last bit */
|
||||
RC5_PUSH_BIT(ir_word, level, ir_pos)
|
||||
|
||||
if (ir_pos == RC5_WORD_LEN)
|
||||
sms_rc5_parse_word(coredev);
|
||||
else if (ir_pos) /* timeout within a word */
|
||||
sms_log("IR error parsing a word");
|
||||
|
||||
ir_pos = 0;
|
||||
ir_word = 0;
|
||||
/* sms_log("timeout %d", time); */
|
||||
break;
|
||||
}
|
||||
/* The time is within the range of this number of bits */
|
||||
for (j = 0 ; j < i ; j++)
|
||||
RC5_PUSH_BIT(ir_word, level, ir_pos)
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
#define MODULE_NAME "smsmdtv"
|
||||
|
||||
void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
|
||||
{
|
||||
#define IR_DATA_RECEIVE_MAX_LEN 520 /* 128*4 + 4 + 4 */
|
||||
u32 i;
|
||||
enum ir_protocol ir_protocol =
|
||||
keyboard_layout_maps[coredev->ir.ir_kb_type]
|
||||
.ir_protocol;
|
||||
s32 *samples;
|
||||
int count = len>>2;
|
||||
int i;
|
||||
const s32 *samples = (const void *)buf;
|
||||
|
||||
samples = (s32 *)buf;
|
||||
/* sms_log("IR buffer received, length = %d", count);*/
|
||||
for (i = 0; i < len >> 2; i++) {
|
||||
struct ir_raw_event ev;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
if (ir_protocol == IR_RC5)
|
||||
sms_rc5_accumulate_bits(coredev, samples[i]);
|
||||
/* IR_RCMM not implemented */
|
||||
ev.duration = abs(samples[i]) * 1000; /* Convert to ns */
|
||||
ev.pulse = (samples[i] > 0) ? false : true;
|
||||
|
||||
ir_raw_event_store(coredev->ir.input_dev, &ev);
|
||||
}
|
||||
ir_raw_event_handle(coredev->ir.input_dev);
|
||||
}
|
||||
|
||||
int sms_ir_init(struct smscore_device_t *coredev)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
int board_id = smscore_get_board_id(coredev);
|
||||
|
||||
sms_log("Allocating input device");
|
||||
input_dev = input_allocate_device();
|
||||
|
@ -256,33 +63,38 @@ int sms_ir_init(struct smscore_device_t *coredev)
|
|||
}
|
||||
|
||||
coredev->ir.input_dev = input_dev;
|
||||
coredev->ir.ir_kb_type =
|
||||
sms_get_board(smscore_get_board_id(coredev))->ir_kb_type;
|
||||
coredev->ir.keyboard_layout_map =
|
||||
keyboard_layout_maps[coredev->ir.ir_kb_type].
|
||||
keyboard_layout_map;
|
||||
sms_log("IR remote keyboard type is %d", coredev->ir.ir_kb_type);
|
||||
|
||||
coredev->ir.controller = 0; /* Todo: vega/nova SPI number */
|
||||
coredev->ir.timeout = IR_DEFAULT_TIMEOUT;
|
||||
sms_log("IR port %d, timeout %d ms",
|
||||
coredev->ir.controller, coredev->ir.timeout);
|
||||
|
||||
snprintf(coredev->ir.name,
|
||||
IR_DEV_NAME_MAX_LEN,
|
||||
"SMS IR w/kbd type %d",
|
||||
coredev->ir.ir_kb_type);
|
||||
snprintf(coredev->ir.name, sizeof(coredev->ir.name),
|
||||
"SMS IR (%s)", sms_get_board(board_id)->name);
|
||||
|
||||
strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys));
|
||||
strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys));
|
||||
|
||||
input_dev->name = coredev->ir.name;
|
||||
input_dev->phys = coredev->ir.name;
|
||||
input_dev->phys = coredev->ir.phys;
|
||||
input_dev->dev.parent = coredev->device;
|
||||
|
||||
/* Key press events only */
|
||||
input_dev->evbit[0] = BIT_MASK(EV_KEY);
|
||||
input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
|
||||
#if 0
|
||||
/* TODO: properly initialize the parameters bellow */
|
||||
input_dev->id.bustype = BUS_USB;
|
||||
input_dev->id.version = 1;
|
||||
input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
|
||||
input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
|
||||
#endif
|
||||
|
||||
coredev->ir.props.priv = coredev;
|
||||
coredev->ir.props.driver_type = RC_DRIVER_IR_RAW;
|
||||
coredev->ir.props.allowed_protos = IR_TYPE_ALL;
|
||||
|
||||
sms_log("Input device (IR) %s is set for key events", input_dev->name);
|
||||
|
||||
if (input_register_device(input_dev)) {
|
||||
if (ir_input_register(input_dev, sms_get_board(board_id)->rc_codes,
|
||||
&coredev->ir.props, MODULE_NAME)) {
|
||||
sms_err("Failed to register device");
|
||||
input_free_device(input_dev);
|
||||
return -EACCES;
|
||||
|
@ -294,8 +106,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
|
|||
void sms_ir_exit(struct smscore_device_t *coredev)
|
||||
{
|
||||
if (coredev->ir.input_dev)
|
||||
input_unregister_device(coredev->ir.input_dev);
|
||||
ir_input_unregister(coredev->ir.input_dev);
|
||||
|
||||
sms_log("");
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,11 @@ Siano Mobile Silicon, Inc.
|
|||
MDTV receiver kernel modules.
|
||||
Copyright (C) 2006-2009, Uri Shkolnik
|
||||
|
||||
Copyright (c) 2010 - Mauro Carvalho Chehab
|
||||
- Ported the driver to use rc-core
|
||||
- IR raw event decoding is now done at rc-core
|
||||
- Code almost re-written
|
||||
|
||||
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
|
||||
|
@ -23,63 +28,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define __SMS_IR_H__
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <media/ir-core.h>
|
||||
|
||||
#define IR_DEV_NAME_MAX_LEN 23 /* "SMS IR kbd type nn\0" */
|
||||
#define IR_KEYBOARD_LAYOUT_SIZE 64
|
||||
#define IR_DEFAULT_TIMEOUT 100
|
||||
|
||||
enum ir_kb_type {
|
||||
SMS_IR_KB_DEFAULT_TV,
|
||||
SMS_IR_KB_HCW_SILVER
|
||||
};
|
||||
|
||||
enum rc5_keyboard_address {
|
||||
KEYBOARD_ADDRESS_TV1 = 0,
|
||||
KEYBOARD_ADDRESS_TV2 = 1,
|
||||
KEYBOARD_ADDRESS_TELETEXT = 2,
|
||||
KEYBOARD_ADDRESS_VIDEO = 3,
|
||||
KEYBOARD_ADDRESS_LV1 = 4,
|
||||
KEYBOARD_ADDRESS_VCR1 = 5,
|
||||
KEYBOARD_ADDRESS_VCR2 = 6,
|
||||
KEYBOARD_ADDRESS_EXPERIMENTAL = 7,
|
||||
KEYBOARD_ADDRESS_SAT1 = 8,
|
||||
KEYBOARD_ADDRESS_CAMERA = 9,
|
||||
KEYBOARD_ADDRESS_SAT2 = 10,
|
||||
KEYBOARD_ADDRESS_CDV = 12,
|
||||
KEYBOARD_ADDRESS_CAMCORDER = 13,
|
||||
KEYBOARD_ADDRESS_PRE_AMP = 16,
|
||||
KEYBOARD_ADDRESS_TUNER = 17,
|
||||
KEYBOARD_ADDRESS_RECORDER1 = 18,
|
||||
KEYBOARD_ADDRESS_PRE_AMP1 = 19,
|
||||
KEYBOARD_ADDRESS_CD_PLAYER = 20,
|
||||
KEYBOARD_ADDRESS_PHONO = 21,
|
||||
KEYBOARD_ADDRESS_SATA = 22,
|
||||
KEYBOARD_ADDRESS_RECORDER2 = 23,
|
||||
KEYBOARD_ADDRESS_CDR = 26,
|
||||
KEYBOARD_ADDRESS_LIGHTING = 29,
|
||||
KEYBOARD_ADDRESS_LIGHTING1 = 30, /* KEYBOARD_ADDRESS_HCW_SILVER */
|
||||
KEYBOARD_ADDRESS_PHONE = 31,
|
||||
KEYBOARD_ADDRESS_NOT_RC5 = 0xFFFF
|
||||
};
|
||||
|
||||
enum ir_protocol {
|
||||
IR_RC5,
|
||||
IR_RCMM
|
||||
};
|
||||
|
||||
struct keyboard_layout_map_t {
|
||||
enum ir_protocol ir_protocol;
|
||||
enum rc5_keyboard_address rc5_kbd_address;
|
||||
u16 keyboard_layout_map[IR_KEYBOARD_LAYOUT_SIZE];
|
||||
};
|
||||
|
||||
struct smscore_device_t;
|
||||
|
||||
struct ir_t {
|
||||
struct input_dev *input_dev;
|
||||
enum ir_kb_type ir_kb_type;
|
||||
char name[IR_DEV_NAME_MAX_LEN+1];
|
||||
u16 *keyboard_layout_map;
|
||||
char name[40];
|
||||
char phys[32];
|
||||
|
||||
char *rc_codes;
|
||||
u64 protocol;
|
||||
struct ir_dev_props props;
|
||||
|
||||
u32 timeout;
|
||||
u32 controller;
|
||||
};
|
||||
|
|
|
@ -352,8 +352,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
|
|||
params.num_buffers = MAX_BUFFERS;
|
||||
params.sendrequest_handler = smsusb_sendrequest;
|
||||
params.context = dev;
|
||||
snprintf(params.devpath, sizeof(params.devpath),
|
||||
"usb\\%d-%s", dev->udev->bus->busnum, dev->udev->devpath);
|
||||
usb_make_path(dev->udev, params.devpath, sizeof(params.devpath));
|
||||
|
||||
/* register in smscore */
|
||||
rc = smscore_register_device(¶ms, &dev->coredev);
|
||||
|
|
|
@ -748,7 +748,7 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
|
|||
struct v4l2_tuner *tuner)
|
||||
{
|
||||
struct si470x_device *radio = video_drvdata(file);
|
||||
int retval = -EINVAL;
|
||||
int retval = 0;
|
||||
|
||||
/* safety checks */
|
||||
retval = si470x_disconnect_check(radio);
|
||||
|
|
|
@ -1009,8 +1009,10 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev,
|
|||
goto exit;
|
||||
}
|
||||
rval = copy_from_user(ps_name, control->string, len);
|
||||
if (rval < 0)
|
||||
if (rval) {
|
||||
rval = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
ps_name[len] = '\0';
|
||||
|
||||
if (strlen(ps_name) % vqc.step) {
|
||||
|
@ -1031,8 +1033,10 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev,
|
|||
goto exit;
|
||||
}
|
||||
rval = copy_from_user(radio_text, control->string, len);
|
||||
if (rval < 0)
|
||||
if (rval) {
|
||||
rval = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
radio_text[len] = '\0';
|
||||
|
||||
if (strlen(radio_text) % vqc.step) {
|
||||
|
@ -1367,6 +1371,8 @@ static int si4713_read_econtrol_string(struct si4713_device *sdev,
|
|||
}
|
||||
rval = copy_to_user(control->string, sdev->rds_info.ps_name,
|
||||
strlen(sdev->rds_info.ps_name) + 1);
|
||||
if (rval)
|
||||
rval = -EFAULT;
|
||||
break;
|
||||
|
||||
case V4L2_CID_RDS_TX_RADIO_TEXT:
|
||||
|
@ -1377,6 +1383,8 @@ static int si4713_read_econtrol_string(struct si4713_device *sdev,
|
|||
}
|
||||
rval = copy_to_user(control->string, sdev->rds_info.radio_text,
|
||||
strlen(sdev->rds_info.radio_text) + 1);
|
||||
if (rval)
|
||||
rval = -EFAULT;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -517,19 +517,6 @@ config VIDEO_UPD64083
|
|||
|
||||
endmenu # encoder / decoder chips
|
||||
|
||||
config DISPLAY_DAVINCI_DM646X_EVM
|
||||
tristate "DM646x EVM Video Display"
|
||||
depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM
|
||||
select VIDEOBUF_DMA_CONTIG
|
||||
select VIDEO_DAVINCI_VPIF
|
||||
select VIDEO_ADV7343
|
||||
select VIDEO_THS7303
|
||||
help
|
||||
Support for DM6467 based display device.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpif_display.
|
||||
|
||||
config VIDEO_SH_VOU
|
||||
tristate "SuperH VOU video output driver"
|
||||
depends on VIDEO_DEV && ARCH_SHMOBILE
|
||||
|
@ -537,29 +524,22 @@ config VIDEO_SH_VOU
|
|||
help
|
||||
Support for the Video Output Unit (VOU) on SuperH SoCs.
|
||||
|
||||
config CAPTURE_DAVINCI_DM646X_EVM
|
||||
tristate "DM646x EVM Video Capture"
|
||||
depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM
|
||||
config VIDEO_VIU
|
||||
tristate "Freescale VIU Video Driver"
|
||||
depends on VIDEO_V4L2 && PPC_MPC512x
|
||||
select VIDEOBUF_DMA_CONTIG
|
||||
select VIDEO_DAVINCI_VPIF
|
||||
help
|
||||
Support for DM6467 based capture device.
|
||||
default y
|
||||
---help---
|
||||
Support for Freescale VIU video driver. This device captures
|
||||
video data, or overlays video on DIU frame buffer.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpif_capture.
|
||||
|
||||
config VIDEO_DAVINCI_VPIF
|
||||
tristate "DaVinci VPIF Driver"
|
||||
depends on DISPLAY_DAVINCI_DM646X_EVM
|
||||
help
|
||||
Support for DaVinci VPIF Driver.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpif.
|
||||
Say Y here if you want to enable VIU device on MPC5121e Rev2+.
|
||||
In doubt, say N.
|
||||
|
||||
config VIDEO_VIVI
|
||||
tristate "Virtual Video Driver"
|
||||
depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 && FONTS
|
||||
depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64
|
||||
depends on (FRAMEBUFFER_CONSOLE || STI_CONSOLE) && FONTS
|
||||
select FONT_8x16
|
||||
select VIDEOBUF_VMALLOC
|
||||
default n
|
||||
|
@ -570,66 +550,7 @@ config VIDEO_VIVI
|
|||
Say Y here if you want to test video apps or debug V4L devices.
|
||||
In doubt, say N.
|
||||
|
||||
config VIDEO_VPSS_SYSTEM
|
||||
tristate "VPSS System module driver"
|
||||
depends on ARCH_DAVINCI
|
||||
help
|
||||
Support for vpss system module for video driver
|
||||
|
||||
config VIDEO_VPFE_CAPTURE
|
||||
tristate "VPFE Video Capture Driver"
|
||||
depends on VIDEO_V4L2 && ARCH_DAVINCI
|
||||
select VIDEOBUF_DMA_CONTIG
|
||||
help
|
||||
Support for DMXXXX VPFE based frame grabber. This is the
|
||||
common V4L2 module for following DMXXX SoCs from Texas
|
||||
Instruments:- DM6446 & DM355.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpfe-capture.
|
||||
|
||||
config VIDEO_DM6446_CCDC
|
||||
tristate "DM6446 CCDC HW module"
|
||||
depends on ARCH_DAVINCI_DM644x && VIDEO_VPFE_CAPTURE
|
||||
select VIDEO_VPSS_SYSTEM
|
||||
default y
|
||||
help
|
||||
Enables DaVinci CCD hw module. DaVinci CCDC hw interfaces
|
||||
with decoder modules such as TVP5146 over BT656 or
|
||||
sensor module such as MT9T001 over a raw interface. This
|
||||
module configures the interface and CCDC/ISIF to do
|
||||
video frame capture from slave decoders.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpfe.
|
||||
|
||||
config VIDEO_DM355_CCDC
|
||||
tristate "DM355 CCDC HW module"
|
||||
depends on ARCH_DAVINCI_DM355 && VIDEO_VPFE_CAPTURE
|
||||
select VIDEO_VPSS_SYSTEM
|
||||
default y
|
||||
help
|
||||
Enables DM355 CCD hw module. DM355 CCDC hw interfaces
|
||||
with decoder modules such as TVP5146 over BT656 or
|
||||
sensor module such as MT9T001 over a raw interface. This
|
||||
module configures the interface and CCDC/ISIF to do
|
||||
video frame capture from a slave decoders
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpfe.
|
||||
|
||||
config VIDEO_ISIF
|
||||
tristate "ISIF HW module"
|
||||
depends on ARCH_DAVINCI_DM365 && VIDEO_VPFE_CAPTURE
|
||||
select VIDEO_VPSS_SYSTEM
|
||||
default y
|
||||
help
|
||||
Enables ISIF hw module. This is the hardware module for
|
||||
configuring ISIF in VPFE to capture Raw Bayer RGB data from
|
||||
a image sensor or YUV data from a YUV source.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpfe.
|
||||
source "drivers/media/video/davinci/Kconfig"
|
||||
|
||||
source "drivers/media/video/omap/Kconfig"
|
||||
|
||||
|
@ -955,6 +876,12 @@ config VIDEO_PXA27x
|
|||
---help---
|
||||
This is a v4l2 driver for the PXA27x Quick Capture Interface
|
||||
|
||||
config VIDEO_SH_MOBILE_CSI2
|
||||
tristate "SuperH Mobile MIPI CSI-2 Interface driver"
|
||||
depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK
|
||||
---help---
|
||||
This is a v4l2 driver for the SuperH MIPI CSI-2 Interface
|
||||
|
||||
config VIDEO_SH_MOBILE_CEU
|
||||
tristate "SuperH Mobile CEU Interface driver"
|
||||
depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK
|
||||
|
@ -1013,61 +940,6 @@ source "drivers/media/video/usbvideo/Kconfig"
|
|||
|
||||
source "drivers/media/video/et61x251/Kconfig"
|
||||
|
||||
config VIDEO_OVCAMCHIP
|
||||
tristate "OmniVision Camera Chip support (DEPRECATED)"
|
||||
depends on I2C && VIDEO_V4L1
|
||||
default n
|
||||
---help---
|
||||
This driver is DEPRECATED please use the gspca ov519 module
|
||||
instead. Note that for the ov511 / ov518 support of the gspca module
|
||||
you need atleast version 0.6.0 of libv4l and for the w9968cf
|
||||
atleast version 0.6.3 of libv4l.
|
||||
|
||||
Support for the OmniVision OV6xxx and OV7xxx series of camera chips.
|
||||
This driver is intended to be used with the ov511 and w9968cf USB
|
||||
camera drivers.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ovcamchip.
|
||||
|
||||
config USB_W9968CF
|
||||
tristate "USB W996[87]CF JPEG Dual Mode Camera support (DEPRECATED)"
|
||||
depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP
|
||||
default n
|
||||
---help---
|
||||
This driver is DEPRECATED please use the gspca ov519 module
|
||||
instead. Note that for the w9968cf support of the gspca module
|
||||
you need atleast version 0.6.3 of libv4l.
|
||||
|
||||
Say Y here if you want support for cameras based on OV681 or
|
||||
Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
|
||||
|
||||
This driver has an optional plugin, which is distributed as a
|
||||
separate module only (released under GPL). It allows to use higher
|
||||
resolutions and framerates, but cannot be included in the official
|
||||
Linux kernel for performance purposes.
|
||||
|
||||
See <file:Documentation/video4linux/w9968cf.txt> for more info.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called w9968cf.
|
||||
|
||||
config USB_OV511
|
||||
tristate "USB OV511 Camera support (DEPRECATED)"
|
||||
depends on VIDEO_V4L1
|
||||
default n
|
||||
---help---
|
||||
This driver is DEPRECATED please use the gspca ov519 module
|
||||
instead. Note that for the ov511 / ov518 support of the gspca module
|
||||
you need atleast version 0.6.0 of libv4l.
|
||||
|
||||
Say Y here if you want to connect this type of camera to your
|
||||
computer's USB port. See <file:Documentation/video4linux/ov511.txt>
|
||||
for more information and for a list of supported cameras.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ov511.
|
||||
|
||||
config USB_SE401
|
||||
tristate "USB SE401 Camera support"
|
||||
depends on VIDEO_V4L1
|
||||
|
@ -1081,25 +953,6 @@ config USB_SE401
|
|||
|
||||
source "drivers/media/video/sn9c102/Kconfig"
|
||||
|
||||
config USB_STV680
|
||||
tristate "USB STV680 (Pencam) Camera support (DEPRECATED)"
|
||||
depends on VIDEO_V4L1
|
||||
default n
|
||||
---help---
|
||||
This driver is DEPRECATED please use the gspca stv0680 module
|
||||
instead. Note that for the gspca stv0680 module you need
|
||||
atleast version 0.6.3 of libv4l.
|
||||
|
||||
Say Y here if you want to connect this type of camera to your
|
||||
computer's USB port. This includes the Pencam line of cameras.
|
||||
See <file:Documentation/video4linux/stv680.txt> for more information
|
||||
and for a list of supported cameras.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called stv680.
|
||||
|
||||
source "drivers/media/video/zc0301/Kconfig"
|
||||
|
||||
source "drivers/media/video/pwc/Kconfig"
|
||||
|
||||
config USB_ZR364XX
|
||||
|
|
|
@ -105,7 +105,6 @@ obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/
|
|||
obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
|
||||
obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
|
||||
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
|
||||
obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
|
||||
obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
|
||||
obj-$(CONFIG_VIDEO_MXB) += mxb.o
|
||||
obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
|
||||
|
@ -127,17 +126,13 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
|
|||
obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
|
||||
|
||||
obj-$(CONFIG_USB_DABUSB) += dabusb.o
|
||||
obj-$(CONFIG_USB_OV511) += ov511.o
|
||||
obj-$(CONFIG_USB_SE401) += se401.o
|
||||
obj-$(CONFIG_USB_STV680) += stv680.o
|
||||
obj-$(CONFIG_USB_W9968CF) += w9968cf.o
|
||||
obj-$(CONFIG_USB_ZR364XX) += zr364xx.o
|
||||
obj-$(CONFIG_USB_STKWEBCAM) += stkwebcam.o
|
||||
|
||||
obj-$(CONFIG_USB_SN9C102) += sn9c102/
|
||||
obj-$(CONFIG_USB_ET61X251) += et61x251/
|
||||
obj-$(CONFIG_USB_PWC) += pwc/
|
||||
obj-$(CONFIG_USB_ZC0301) += zc0301/
|
||||
obj-$(CONFIG_USB_GSPCA) += gspca/
|
||||
|
||||
obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/
|
||||
|
@ -151,6 +146,7 @@ obj-$(CONFIG_USB_S2255) += s2255drv.o
|
|||
obj-$(CONFIG_VIDEO_IVTV) += ivtv/
|
||||
obj-$(CONFIG_VIDEO_CX18) += cx18/
|
||||
|
||||
obj-$(CONFIG_VIDEO_VIU) += fsl-viu.o
|
||||
obj-$(CONFIG_VIDEO_VIVI) += vivi.o
|
||||
obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o
|
||||
obj-$(CONFIG_VIDEO_CX23885) += cx23885/
|
||||
|
@ -165,6 +161,7 @@ obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o
|
|||
obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o
|
||||
obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o
|
||||
obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
|
||||
obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o
|
||||
obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
|
||||
|
||||
obj-$(CONFIG_ARCH_DAVINCI) += davinci/
|
||||
|
@ -178,7 +175,7 @@ obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
|
|||
|
||||
obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
|
||||
|
||||
obj-$(CONFIG_ARCH_DAVINCI) += davinci/
|
||||
obj-y += davinci/
|
||||
|
||||
obj-$(CONFIG_ARCH_OMAP) += omap/
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ static int ak881x_try_g_mbus_fmt(struct v4l2_subdev *sd,
|
|||
v4l_bound_align_image(&mf->width, 0, 720, 2,
|
||||
&mf->height, 0, ak881x->lines, 1, 0);
|
||||
mf->field = V4L2_FIELD_INTERLACED;
|
||||
mf->code = V4L2_MBUS_FMT_YUYV8_2X8_LE;
|
||||
mf->code = V4L2_MBUS_FMT_YUYV8_2X8;
|
||||
mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
|
||||
return 0;
|
||||
|
@ -136,7 +136,7 @@ static int ak881x_s_mbus_fmt(struct v4l2_subdev *sd,
|
|||
struct v4l2_mbus_framefmt *mf)
|
||||
{
|
||||
if (mf->field != V4L2_FIELD_INTERLACED ||
|
||||
mf->code != V4L2_MBUS_FMT_YUYV8_2X8_LE)
|
||||
mf->code != V4L2_MBUS_FMT_YUYV8_2X8)
|
||||
return -EINVAL;
|
||||
|
||||
return ak881x_try_g_mbus_fmt(sd, mf);
|
||||
|
@ -148,7 +148,7 @@ static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
|
|||
if (index)
|
||||
return -EINVAL;
|
||||
|
||||
*code = V4L2_MBUS_FMT_YUYV8_2X8_LE;
|
||||
*code = V4L2_MBUS_FMT_YUYV8_2X8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue