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:
Linus Torvalds 2010-08-04 10:38:08 -07:00
commit f63b759c44
320 changed files with 27755 additions and 31629 deletions

View file

@ -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;

View file

@ -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 */

View file

@ -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>

View file

@ -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">

View file

@ -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>

View 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>

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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]

View file

@ -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]

View file

@ -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]

View file

@ -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

View file

@ -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,

View file

@ -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.

View file

@ -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

View file

@ -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);

View file

@ -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 */

View file

@ -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)

View file

@ -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;

View 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");

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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;

View file

@ -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 \

View 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>");

View 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>");

View 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>");

View 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
View 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

File diff suppressed because it is too large Load diff

View file

@ -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;
}

View file

@ -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));

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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)
{

View file

@ -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);

View file

@ -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);

View file

@ -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:

View file

@ -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;

View file

@ -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.

View file

@ -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,

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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},
},
}
},
};

View file

@ -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 */

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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 = {

View file

@ -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;

View file

@ -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;

View file

@ -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,
},
},
},
};

View file

@ -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 },

View file

@ -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,

View file

@ -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,

View file

@ -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 *);

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -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);

View file

@ -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;
}

View file

@ -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;

View file

@ -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,

View file

@ -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,

View file

@ -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),

View file

@ -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,

View file

@ -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 */

View file

@ -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 = {

View file

@ -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 = {

View file

@ -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.

View file

@ -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, &params->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) {

View file

@ -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>
*

View file

@ -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 },

View file

@ -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 };

View file

@ -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)

View file

@ -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;

View file

@ -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:

View file

@ -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) && \

View file

@ -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;
}

View file

@ -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,

View file

@ -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;
}

View file

@ -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.

View file

@ -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;

View file

@ -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,

View file

@ -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;

View file

@ -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);

View file

@ -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("");
}

View file

@ -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;
};

View file

@ -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(&params, &dev->coredev);

View file

@ -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);

View file

@ -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:

View file

@ -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

View file

@ -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/

View file

@ -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