aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/rc
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2010-11-09 21:00:14 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-12-29 05:16:36 -0500
commit32cf86f6d16367db5a10039c1dd938a2427d697c (patch)
tree21e6716b64d80d280da2561efd873430ca833f08 /drivers/media/rc
parent3ffea4988be3f3fa65f2104ba31eff2b5e0e82a0 (diff)
[media] rename drivers/media/IR to drives/media/rc
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/rc')
-rw-r--r--drivers/media/rc/Kconfig167
-rw-r--r--drivers/media/rc/Makefile22
-rw-r--r--drivers/media/rc/ene_ir.c1217
-rw-r--r--drivers/media/rc/ene_ir.h262
-rw-r--r--drivers/media/rc/imon.c2465
-rw-r--r--drivers/media/rc/ir-core-priv.h203
-rw-r--r--drivers/media/rc/ir-functions.c120
-rw-r--r--drivers/media/rc/ir-jvc-decoder.c199
-rw-r--r--drivers/media/rc/ir-keytable.c766
-rw-r--r--drivers/media/rc/ir-lirc-codec.c410
-rw-r--r--drivers/media/rc/ir-nec-decoder.c217
-rw-r--r--drivers/media/rc/ir-raw-event.c382
-rw-r--r--drivers/media/rc/ir-rc5-decoder.c190
-rw-r--r--drivers/media/rc/ir-rc5-sz-decoder.c154
-rw-r--r--drivers/media/rc/ir-rc6-decoder.c281
-rw-r--r--drivers/media/rc/ir-sony-decoder.c182
-rw-r--r--drivers/media/rc/ir-sysfs.c362
-rw-r--r--drivers/media/rc/keymaps/Kconfig15
-rw-r--r--drivers/media/rc/keymaps/Makefile86
-rw-r--r--drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c89
-rw-r--r--drivers/media/rc/keymaps/rc-alink-dtu-m.c68
-rw-r--r--drivers/media/rc/keymaps/rc-anysee.c93
-rw-r--r--drivers/media/rc/keymaps/rc-apac-viewcomp.c80
-rw-r--r--drivers/media/rc/keymaps/rc-asus-pc39.c91
-rw-r--r--drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c69
-rw-r--r--drivers/media/rc/keymaps/rc-avermedia-a16d.c75
-rw-r--r--drivers/media/rc/keymaps/rc-avermedia-cardbus.c97
-rw-r--r--drivers/media/rc/keymaps/rc-avermedia-dvbt.c78
-rw-r--r--drivers/media/rc/keymaps/rc-avermedia-m135a.c147
-rw-r--r--drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c95
-rw-r--r--drivers/media/rc/keymaps/rc-avermedia-rm-ks.c79
-rw-r--r--drivers/media/rc/keymaps/rc-avermedia.c86
-rw-r--r--drivers/media/rc/keymaps/rc-avertv-303.c85
-rw-r--r--drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c102
-rw-r--r--drivers/media/rc/keymaps/rc-behold-columbus.c108
-rw-r--r--drivers/media/rc/keymaps/rc-behold.c141
-rw-r--r--drivers/media/rc/keymaps/rc-budget-ci-old.c92
-rw-r--r--drivers/media/rc/keymaps/rc-cinergy-1400.c84
-rw-r--r--drivers/media/rc/keymaps/rc-cinergy.c78
-rw-r--r--drivers/media/rc/keymaps/rc-dib0700-nec.c124
-rw-r--r--drivers/media/rc/keymaps/rc-dib0700-rc5.c235
-rw-r--r--drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c98
-rw-r--r--drivers/media/rc/keymaps/rc-digittrade.c82
-rw-r--r--drivers/media/rc/keymaps/rc-dm1105-nec.c76
-rw-r--r--drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c78
-rw-r--r--drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c97
-rw-r--r--drivers/media/rc/keymaps/rc-em-terratec.c69
-rw-r--r--drivers/media/rc/keymaps/rc-encore-enltv-fm53.c81
-rw-r--r--drivers/media/rc/keymaps/rc-encore-enltv.c112
-rw-r--r--drivers/media/rc/keymaps/rc-encore-enltv2.c90
-rw-r--r--drivers/media/rc/keymaps/rc-evga-indtube.c61
-rw-r--r--drivers/media/rc/keymaps/rc-eztv.c96
-rw-r--r--drivers/media/rc/keymaps/rc-flydvb.c77
-rw-r--r--drivers/media/rc/keymaps/rc-flyvideo.c70
-rw-r--r--drivers/media/rc/keymaps/rc-fusionhdtv-mce.c98
-rw-r--r--drivers/media/rc/keymaps/rc-gadmei-rm008z.c81
-rw-r--r--drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c84
-rw-r--r--drivers/media/rc/keymaps/rc-gotview7135.c79
-rw-r--r--drivers/media/rc/keymaps/rc-hauppauge-new.c100
-rw-r--r--drivers/media/rc/keymaps/rc-imon-mce.c142
-rw-r--r--drivers/media/rc/keymaps/rc-imon-pad.c156
-rw-r--r--drivers/media/rc/keymaps/rc-iodata-bctv7e.c88
-rw-r--r--drivers/media/rc/keymaps/rc-kaiomy.c87
-rw-r--r--drivers/media/rc/keymaps/rc-kworld-315u.c83
-rw-r--r--drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c99
-rw-r--r--drivers/media/rc/keymaps/rc-leadtek-y04g0051.c99
-rw-r--r--drivers/media/rc/keymaps/rc-lirc.c41
-rw-r--r--drivers/media/rc/keymaps/rc-lme2510.c68
-rw-r--r--drivers/media/rc/keymaps/rc-manli.c134
-rw-r--r--drivers/media/rc/keymaps/rc-msi-digivox-ii.c67
-rw-r--r--drivers/media/rc/keymaps/rc-msi-digivox-iii.c85
-rw-r--r--drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c123
-rw-r--r--drivers/media/rc/keymaps/rc-msi-tvanywhere.c69
-rw-r--r--drivers/media/rc/keymaps/rc-nebula.c96
-rw-r--r--drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c105
-rw-r--r--drivers/media/rc/keymaps/rc-norwood.c85
-rw-r--r--drivers/media/rc/keymaps/rc-npgtech.c80
-rw-r--r--drivers/media/rc/keymaps/rc-pctv-sedna.c80
-rw-r--r--drivers/media/rc/keymaps/rc-pinnacle-color.c94
-rw-r--r--drivers/media/rc/keymaps/rc-pinnacle-grey.c89
-rw-r--r--drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c73
-rw-r--r--drivers/media/rc/keymaps/rc-pixelview-mk12.c83
-rw-r--r--drivers/media/rc/keymaps/rc-pixelview-new.c83
-rw-r--r--drivers/media/rc/keymaps/rc-pixelview.c82
-rw-r--r--drivers/media/rc/keymaps/rc-powercolor-real-angel.c81
-rw-r--r--drivers/media/rc/keymaps/rc-proteus-2309.c69
-rw-r--r--drivers/media/rc/keymaps/rc-purpletv.c81
-rw-r--r--drivers/media/rc/keymaps/rc-pv951.c78
-rw-r--r--drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c103
-rw-r--r--drivers/media/rc/keymaps/rc-rc5-tv.c81
-rw-r--r--drivers/media/rc/keymaps/rc-rc6-mce.c113
-rw-r--r--drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c78
-rw-r--r--drivers/media/rc/keymaps/rc-streamzap.c82
-rw-r--r--drivers/media/rc/keymaps/rc-tbs-nec.c73
-rw-r--r--drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c92
-rw-r--r--drivers/media/rc/keymaps/rc-terratec-slim.c79
-rw-r--r--drivers/media/rc/keymaps/rc-tevii-nec.c88
-rw-r--r--drivers/media/rc/keymaps/rc-total-media-in-hand.c85
-rw-r--r--drivers/media/rc/keymaps/rc-trekstor.c80
-rw-r--r--drivers/media/rc/keymaps/rc-tt-1500.c82
-rw-r--r--drivers/media/rc/keymaps/rc-twinhan1027.c87
-rw-r--r--drivers/media/rc/keymaps/rc-videomate-s350.c85
-rw-r--r--drivers/media/rc/keymaps/rc-videomate-tv-pvr.c87
-rw-r--r--drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c82
-rw-r--r--drivers/media/rc/keymaps/rc-winfast.c102
-rw-r--r--drivers/media/rc/lirc_dev.c814
-rw-r--r--drivers/media/rc/mceusb.c1333
-rw-r--r--drivers/media/rc/nuvoton-cir.c1252
-rw-r--r--drivers/media/rc/nuvoton-cir.h408
-rw-r--r--drivers/media/rc/rc-map.c107
-rw-r--r--drivers/media/rc/streamzap.c572
111 files changed, 19990 insertions, 0 deletions
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
new file mode 100644
index 000000000000..d05003d0995f
--- /dev/null
+++ b/drivers/media/rc/Kconfig
@@ -0,0 +1,167 @@
1menuconfig IR_CORE
2 tristate "Infrared remote controller adapters"
3 depends on INPUT
4 default INPUT
5 ---help---
6 Enable support for Remote Controllers on Linux. This is
7 needed in order to support several video capture adapters.
8
9 Enable this option if you have a video capture board even
10 if you don't need IR, as otherwise, you may not be able to
11 compile the driver for your adapter.
12
13config IR_LEGACY
14 tristate
15 depends on IR_CORE
16 default IR_CORE
17
18if IR_CORE
19
20config LIRC
21 tristate
22 default y
23
24 ---help---
25 Enable this option to build the Linux Infrared Remote
26 Control (LIRC) core device interface driver. The LIRC
27 interface passes raw IR to and from userspace, where the
28 LIRC daemon handles protocol decoding for IR reception and
29 encoding for IR transmitting (aka "blasting").
30
31source "drivers/media/rc/keymaps/Kconfig"
32
33config IR_NEC_DECODER
34 tristate "Enable IR raw decoder for the NEC protocol"
35 depends on IR_CORE
36 select BITREVERSE
37 default y
38
39 ---help---
40 Enable this option if you have IR with NEC protocol, and
41 if the IR is decoded in software
42
43config IR_RC5_DECODER
44 tristate "Enable IR raw decoder for the RC-5 protocol"
45 depends on IR_CORE
46 select BITREVERSE
47 default y
48
49 ---help---
50 Enable this option if you have IR with RC-5 protocol, and
51 if the IR is decoded in software
52
53config IR_RC6_DECODER
54 tristate "Enable IR raw decoder for the RC6 protocol"
55 depends on IR_CORE
56 select BITREVERSE
57 default y
58
59 ---help---
60 Enable this option if you have an infrared remote control which
61 uses the RC6 protocol, and you need software decoding support.
62
63config IR_JVC_DECODER
64 tristate "Enable IR raw decoder for the JVC protocol"
65 depends on IR_CORE
66 select BITREVERSE
67 default y
68
69 ---help---
70 Enable this option if you have an infrared remote control which
71 uses the JVC protocol, and you need software decoding support.
72
73config IR_SONY_DECODER
74 tristate "Enable IR raw decoder for the Sony protocol"
75 depends on IR_CORE
76 default y
77
78 ---help---
79 Enable this option if you have an infrared remote control which
80 uses the Sony protocol, and you need software decoding support.
81
82config IR_RC5_SZ_DECODER
83 tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol"
84 depends on IR_CORE
85 select BITREVERSE
86 default y
87
88 ---help---
89 Enable this option if you have IR with RC-5 (streamzap) protocol,
90 and if the IR is decoded in software. (The Streamzap PC Remote
91 uses an IR protocol that is almost standard RC-5, but not quite,
92 as it uses an additional bit).
93
94config IR_LIRC_CODEC
95 tristate "Enable IR to LIRC bridge"
96 depends on IR_CORE
97 depends on LIRC
98 default y
99
100 ---help---
101 Enable this option to pass raw IR to and from userspace via
102 the LIRC interface.
103
104config IR_ENE
105 tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)"
106 depends on PNP
107 depends on IR_CORE
108 ---help---
109 Say Y here to enable support for integrated infrared receiver
110 /transceiver made by ENE.
111
112 You can see if you have it by looking at lspnp output.
113 Output should include ENE0100 ENE0200 or something similar.
114
115 To compile this driver as a module, choose M here: the
116 module will be called ene_ir.
117
118config IR_IMON
119 tristate "SoundGraph iMON Receiver and Display"
120 depends on USB_ARCH_HAS_HCD
121 depends on IR_CORE
122 select USB
123 ---help---
124 Say Y here if you want to use a SoundGraph iMON (aka Antec Veris)
125 IR Receiver and/or LCD/VFD/VGA display.
126
127 To compile this driver as a module, choose M here: the
128 module will be called imon.
129
130config IR_MCEUSB
131 tristate "Windows Media Center Ed. eHome Infrared Transceiver"
132 depends on USB_ARCH_HAS_HCD
133 depends on IR_CORE
134 select USB
135 ---help---
136 Say Y here if you want to use a Windows Media Center Edition
137 eHome Infrared Transceiver.
138
139 To compile this driver as a module, choose M here: the
140 module will be called mceusb.
141
142config IR_NUVOTON
143 tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
144 depends on PNP
145 depends on IR_CORE
146 ---help---
147 Say Y here to enable support for integrated infrared receiver
148 /transciever made by Nuvoton (formerly Winbond). This chip is
149 found in the ASRock ION 330HT, as well as assorted Intel
150 DP55-series motherboards (and of course, possibly others).
151
152 To compile this driver as a module, choose M here: the
153 module will be called nuvoton-cir.
154
155config IR_STREAMZAP
156 tristate "Streamzap PC Remote IR Receiver"
157 depends on USB_ARCH_HAS_HCD
158 depends on IR_CORE
159 select USB
160 ---help---
161 Say Y here if you want to use a Streamzap PC Remote
162 Infrared Receiver.
163
164 To compile this driver as a module, choose M here: the
165 module will be called streamzap.
166
167endif #IR_CORE
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
new file mode 100644
index 000000000000..38873cff3429
--- /dev/null
+++ b/drivers/media/rc/Makefile
@@ -0,0 +1,22 @@
1ir-common-objs := ir-functions.o
2ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o rc-map.o
3
4obj-y += keymaps/
5
6obj-$(CONFIG_IR_CORE) += ir-core.o
7obj-$(CONFIG_IR_LEGACY) += ir-common.o
8obj-$(CONFIG_LIRC) += lirc_dev.o
9obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
10obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
11obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
12obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
13obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
14obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
15obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
16
17# stand-alone IR receivers/transmitters
18obj-$(CONFIG_IR_IMON) += imon.o
19obj-$(CONFIG_IR_MCEUSB) += mceusb.o
20obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
21obj-$(CONFIG_IR_ENE) += ene_ir.o
22obj-$(CONFIG_IR_STREAMZAP) += streamzap.o
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
new file mode 100644
index 000000000000..7637babcd262
--- /dev/null
+++ b/drivers/media/rc/ene_ir.c
@@ -0,0 +1,1217 @@
1/*
2 * driver for ENE KB3926 B/C/D/E/F CIR (pnp id: ENE0XXX)
3 *
4 * Copyright (C) 2010 Maxim Levitsky <maximlevitsky@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 * USA
20 *
21 * Special thanks to:
22 * Sami R. <maesesami@gmail.com> for lot of help in debugging and therefore
23 * bringing to life support for transmission & learning mode.
24 *
25 * Charlie Andrews <charliethepilot@googlemail.com> for lots of help in
26 * bringing up the support of new firmware buffer that is popular
27 * on latest notebooks
28 *
29 * ENE for partial device documentation
30 *
31 */
32
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/pnp.h>
36#include <linux/io.h>
37#include <linux/interrupt.h>
38#include <linux/sched.h>
39#include <linux/slab.h>
40#include <linux/input.h>
41#include <media/ir-core.h>
42#include <media/ir-common.h>
43#include "ene_ir.h"
44
45static int sample_period;
46static bool learning_mode_force;
47static int debug;
48static bool txsim;
49
50static void ene_set_reg_addr(struct ene_device *dev, u16 reg)
51{
52 outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
53 outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
54}
55
56/* read a hardware register */
57static u8 ene_read_reg(struct ene_device *dev, u16 reg)
58{
59 u8 retval;
60 ene_set_reg_addr(dev, reg);
61 retval = inb(dev->hw_io + ENE_IO);
62 dbg_regs("reg %04x == %02x", reg, retval);
63 return retval;
64}
65
66/* write a hardware register */
67static void ene_write_reg(struct ene_device *dev, u16 reg, u8 value)
68{
69 dbg_regs("reg %04x <- %02x", reg, value);
70 ene_set_reg_addr(dev, reg);
71 outb(value, dev->hw_io + ENE_IO);
72}
73
74/* Set bits in hardware register */
75static void ene_set_reg_mask(struct ene_device *dev, u16 reg, u8 mask)
76{
77 dbg_regs("reg %04x |= %02x", reg, mask);
78 ene_set_reg_addr(dev, reg);
79 outb(inb(dev->hw_io + ENE_IO) | mask, dev->hw_io + ENE_IO);
80}
81
82/* Clear bits in hardware register */
83static void ene_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask)
84{
85 dbg_regs("reg %04x &= ~%02x ", reg, mask);
86 ene_set_reg_addr(dev, reg);
87 outb(inb(dev->hw_io + ENE_IO) & ~mask, dev->hw_io + ENE_IO);
88}
89
90/* A helper to set/clear a bit in register according to boolean variable */
91static void ene_set_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask,
92 bool set)
93{
94 if (set)
95 ene_set_reg_mask(dev, reg, mask);
96 else
97 ene_clear_reg_mask(dev, reg, mask);
98}
99
100/* detect hardware features */
101static int ene_hw_detect(struct ene_device *dev)
102{
103 u8 chip_major, chip_minor;
104 u8 hw_revision, old_ver;
105 u8 fw_reg2, fw_reg1;
106
107 ene_clear_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD);
108 chip_major = ene_read_reg(dev, ENE_ECVER_MAJOR);
109 chip_minor = ene_read_reg(dev, ENE_ECVER_MINOR);
110 ene_set_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD);
111
112 hw_revision = ene_read_reg(dev, ENE_ECHV);
113 old_ver = ene_read_reg(dev, ENE_HW_VER_OLD);
114
115 dev->pll_freq = (ene_read_reg(dev, ENE_PLLFRH) << 4) +
116 (ene_read_reg(dev, ENE_PLLFRL) >> 4);
117
118 if (sample_period != ENE_DEFAULT_SAMPLE_PERIOD)
119 dev->rx_period_adjust =
120 dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 2 : 4;
121
122 if (hw_revision == 0xFF) {
123 ene_warn("device seems to be disabled");
124 ene_warn("send a mail to lirc-list@lists.sourceforge.net");
125 ene_warn("please attach output of acpidump and dmidecode");
126 return -ENODEV;
127 }
128
129 ene_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x",
130 chip_major, chip_minor, old_ver, hw_revision);
131
132 ene_notice("PLL freq = %d", dev->pll_freq);
133
134 if (chip_major == 0x33) {
135 ene_warn("chips 0x33xx aren't supported");
136 return -ENODEV;
137 }
138
139 if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) {
140 dev->hw_revision = ENE_HW_C;
141 ene_notice("KB3926C detected");
142 } else if (old_ver == 0x24 && hw_revision == 0xC0) {
143 dev->hw_revision = ENE_HW_B;
144 ene_notice("KB3926B detected");
145 } else {
146 dev->hw_revision = ENE_HW_D;
147 ene_notice("KB3926D or higher detected");
148 }
149
150 /* detect features hardware supports */
151 if (dev->hw_revision < ENE_HW_C)
152 return 0;
153
154 fw_reg1 = ene_read_reg(dev, ENE_FW1);
155 fw_reg2 = ene_read_reg(dev, ENE_FW2);
156
157 ene_notice("Firmware regs: %02x %02x", fw_reg1, fw_reg2);
158
159 dev->hw_use_gpio_0a = !!(fw_reg2 & ENE_FW2_GP0A);
160 dev->hw_learning_and_tx_capable = !!(fw_reg2 & ENE_FW2_LEARNING);
161 dev->hw_extra_buffer = !!(fw_reg1 & ENE_FW1_HAS_EXTRA_BUF);
162
163 if (dev->hw_learning_and_tx_capable)
164 dev->hw_fan_input = !!(fw_reg2 & ENE_FW2_FAN_INPUT);
165
166 ene_notice("Hardware features:");
167
168 if (dev->hw_learning_and_tx_capable) {
169 ene_notice("* Supports transmitting & learning mode");
170 ene_notice(" This feature is rare and therefore,");
171 ene_notice(" you are welcome to test it,");
172 ene_notice(" and/or contact the author via:");
173 ene_notice(" lirc-list@lists.sourceforge.net");
174 ene_notice(" or maximlevitsky@gmail.com");
175
176 ene_notice("* Uses GPIO %s for IR raw input",
177 dev->hw_use_gpio_0a ? "40" : "0A");
178
179 if (dev->hw_fan_input)
180 ene_notice("* Uses unused fan feedback input as source"
181 " of demodulated IR data");
182 }
183
184 if (!dev->hw_fan_input)
185 ene_notice("* Uses GPIO %s for IR demodulated input",
186 dev->hw_use_gpio_0a ? "0A" : "40");
187
188 if (dev->hw_extra_buffer)
189 ene_notice("* Uses new style input buffer");
190 return 0;
191}
192
193/* Read properities of hw sample buffer */
194static void ene_rx_setup_hw_buffer(struct ene_device *dev)
195{
196 u16 tmp;
197
198 ene_rx_read_hw_pointer(dev);
199 dev->r_pointer = dev->w_pointer;
200
201 if (!dev->hw_extra_buffer) {
202 dev->buffer_len = ENE_FW_PACKET_SIZE * 2;
203 return;
204 }
205
206 tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER);
207 tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER+1) << 8;
208 dev->extra_buf1_address = tmp;
209
210 dev->extra_buf1_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 2);
211
212 tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 3);
213 tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 4) << 8;
214 dev->extra_buf2_address = tmp;
215
216 dev->extra_buf2_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 5);
217
218 dev->buffer_len = dev->extra_buf1_len + dev->extra_buf2_len + 8;
219
220 ene_notice("Hardware uses 2 extended buffers:");
221 ene_notice(" 0x%04x - len : %d", dev->extra_buf1_address,
222 dev->extra_buf1_len);
223 ene_notice(" 0x%04x - len : %d", dev->extra_buf2_address,
224 dev->extra_buf2_len);
225
226 ene_notice("Total buffer len = %d", dev->buffer_len);
227
228 if (dev->buffer_len > 64 || dev->buffer_len < 16)
229 goto error;
230
231 if (dev->extra_buf1_address > 0xFBFC ||
232 dev->extra_buf1_address < 0xEC00)
233 goto error;
234
235 if (dev->extra_buf2_address > 0xFBFC ||
236 dev->extra_buf2_address < 0xEC00)
237 goto error;
238
239 if (dev->r_pointer > dev->buffer_len)
240 goto error;
241
242 ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
243 return;
244error:
245 ene_warn("Error validating extra buffers, device probably won't work");
246 dev->hw_extra_buffer = false;
247 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
248}
249
250
251/* Restore the pointers to extra buffers - to make module reload work*/
252static void ene_rx_restore_hw_buffer(struct ene_device *dev)
253{
254 if (!dev->hw_extra_buffer)
255 return;
256
257 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 0,
258 dev->extra_buf1_address & 0xFF);
259 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 1,
260 dev->extra_buf1_address >> 8);
261 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 2, dev->extra_buf1_len);
262
263 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 3,
264 dev->extra_buf2_address & 0xFF);
265 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 4,
266 dev->extra_buf2_address >> 8);
267 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 5,
268 dev->extra_buf2_len);
269 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
270}
271
272/* Read hardware write pointer */
273static void ene_rx_read_hw_pointer(struct ene_device *dev)
274{
275 if (dev->hw_extra_buffer)
276 dev->w_pointer = ene_read_reg(dev, ENE_FW_RX_POINTER);
277 else
278 dev->w_pointer = ene_read_reg(dev, ENE_FW2)
279 & ENE_FW2_BUF_WPTR ? 0 : ENE_FW_PACKET_SIZE;
280
281 dbg_verbose("RB: HW write pointer: %02x, driver read pointer: %02x",
282 dev->w_pointer, dev->r_pointer);
283}
284
285/* Gets address of next sample from HW ring buffer */
286static int ene_rx_get_sample_reg(struct ene_device *dev)
287{
288 int r_pointer;
289
290 if (dev->r_pointer == dev->w_pointer) {
291 dbg_verbose("RB: hit end, try update w_pointer");
292 ene_rx_read_hw_pointer(dev);
293 }
294
295 if (dev->r_pointer == dev->w_pointer) {
296 dbg_verbose("RB: end of data at %d", dev->r_pointer);
297 return 0;
298 }
299
300 dbg_verbose("RB: reading at offset %d", dev->r_pointer);
301 r_pointer = dev->r_pointer;
302
303 dev->r_pointer++;
304 if (dev->r_pointer == dev->buffer_len)
305 dev->r_pointer = 0;
306
307 dbg_verbose("RB: next read will be from offset %d", dev->r_pointer);
308
309 if (r_pointer < 8) {
310 dbg_verbose("RB: read at main buffer at %d", r_pointer);
311 return ENE_FW_SAMPLE_BUFFER + r_pointer;
312 }
313
314 r_pointer -= 8;
315
316 if (r_pointer < dev->extra_buf1_len) {
317 dbg_verbose("RB: read at 1st extra buffer at %d", r_pointer);
318 return dev->extra_buf1_address + r_pointer;
319 }
320
321 r_pointer -= dev->extra_buf1_len;
322
323 if (r_pointer < dev->extra_buf2_len) {
324 dbg_verbose("RB: read at 2nd extra buffer at %d", r_pointer);
325 return dev->extra_buf2_address + r_pointer;
326 }
327
328 dbg("attempt to read beyong ring bufer end");
329 return 0;
330}
331
332/* Sense current received carrier */
333void ene_rx_sense_carrier(struct ene_device *dev)
334{
335 DEFINE_IR_RAW_EVENT(ev);
336
337 int carrier, duty_cycle;
338 int period = ene_read_reg(dev, ENE_CIRCAR_PRD);
339 int hperiod = ene_read_reg(dev, ENE_CIRCAR_HPRD);
340
341 if (!(period & ENE_CIRCAR_PRD_VALID))
342 return;
343
344 period &= ~ENE_CIRCAR_PRD_VALID;
345
346 if (!period)
347 return;
348
349 dbg("RX: hardware carrier period = %02x", period);
350 dbg("RX: hardware carrier pulse period = %02x", hperiod);
351
352 carrier = 2000000 / period;
353 duty_cycle = (hperiod * 100) / period;
354 dbg("RX: sensed carrier = %d Hz, duty cycle %d%%",
355 carrier, duty_cycle);
356 if (dev->carrier_detect_enabled) {
357 ev.carrier_report = true;
358 ev.carrier = carrier;
359 ev.duty_cycle = duty_cycle;
360 ir_raw_event_store(dev->idev, &ev);
361 }
362}
363
364/* this enables/disables the CIR RX engine */
365static void ene_rx_enable_cir_engine(struct ene_device *dev, bool enable)
366{
367 ene_set_clear_reg_mask(dev, ENE_CIRCFG,
368 ENE_CIRCFG_RX_EN | ENE_CIRCFG_RX_IRQ, enable);
369}
370
371/* this selects input for CIR engine. Ether GPIO 0A or GPIO40*/
372static void ene_rx_select_input(struct ene_device *dev, bool gpio_0a)
373{
374 ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_GPIO0A, gpio_0a);
375}
376
377/*
378 * this enables alternative input via fan tachometer sensor and bypasses
379 * the hw CIR engine
380 */
381static void ene_rx_enable_fan_input(struct ene_device *dev, bool enable)
382{
383 if (!dev->hw_fan_input)
384 return;
385
386 if (!enable)
387 ene_write_reg(dev, ENE_FAN_AS_IN1, 0);
388 else {
389 ene_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN);
390 ene_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN);
391 }
392}
393
394/* setup the receiver for RX*/
395static void ene_rx_setup(struct ene_device *dev)
396{
397 bool learning_mode = dev->learning_mode_enabled ||
398 dev->carrier_detect_enabled;
399 int sample_period_adjust = 0;
400
401 dbg("RX: setup receiver, learning mode = %d", learning_mode);
402
403
404 /* This selects RLC input and clears CFG2 settings */
405 ene_write_reg(dev, ENE_CIRCFG2, 0x00);
406
407 /* set sample period*/
408 if (sample_period == ENE_DEFAULT_SAMPLE_PERIOD)
409 sample_period_adjust =
410 dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 1 : 2;
411
412 ene_write_reg(dev, ENE_CIRRLC_CFG,
413 (sample_period + sample_period_adjust) |
414 ENE_CIRRLC_CFG_OVERFLOW);
415 /* revB doesn't support inputs */
416 if (dev->hw_revision < ENE_HW_C)
417 goto select_timeout;
418
419 if (learning_mode) {
420
421 WARN_ON(!dev->hw_learning_and_tx_capable);
422
423 /* Enable the opposite of the normal input
424 That means that if GPIO40 is normally used, use GPIO0A
425 and vice versa.
426 This input will carry non demodulated
427 signal, and we will tell the hw to demodulate it itself */
428 ene_rx_select_input(dev, !dev->hw_use_gpio_0a);
429 dev->rx_fan_input_inuse = false;
430
431 /* Enable carrier demodulation */
432 ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
433
434 /* Enable carrier detection */
435 ene_write_reg(dev, ENE_CIRCAR_PULS, 0x63);
436 ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT,
437 dev->carrier_detect_enabled || debug);
438 } else {
439 if (dev->hw_fan_input)
440 dev->rx_fan_input_inuse = true;
441 else
442 ene_rx_select_input(dev, dev->hw_use_gpio_0a);
443
444 /* Disable carrier detection & demodulation */
445 ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
446 ene_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT);
447 }
448
449select_timeout:
450 if (dev->rx_fan_input_inuse) {
451 dev->props->rx_resolution = MS_TO_NS(ENE_FW_SAMPLE_PERIOD_FAN);
452
453 /* Fan input doesn't support timeouts, it just ends the
454 input with a maximum sample */
455 dev->props->min_timeout = dev->props->max_timeout =
456 MS_TO_NS(ENE_FW_SMPL_BUF_FAN_MSK *
457 ENE_FW_SAMPLE_PERIOD_FAN);
458 } else {
459 dev->props->rx_resolution = MS_TO_NS(sample_period);
460
461 /* Theoreticly timeout is unlimited, but we cap it
462 * because it was seen that on one device, it
463 * would stop sending spaces after around 250 msec.
464 * Besides, this is close to 2^32 anyway and timeout is u32.
465 */
466 dev->props->min_timeout = MS_TO_NS(127 * sample_period);
467 dev->props->max_timeout = MS_TO_NS(200000);
468 }
469
470 if (dev->hw_learning_and_tx_capable)
471 dev->props->tx_resolution = MS_TO_NS(sample_period);
472
473 if (dev->props->timeout > dev->props->max_timeout)
474 dev->props->timeout = dev->props->max_timeout;
475 if (dev->props->timeout < dev->props->min_timeout)
476 dev->props->timeout = dev->props->min_timeout;
477}
478
479/* Enable the device for receive */
480static void ene_rx_enable(struct ene_device *dev)
481{
482 u8 reg_value;
483
484 /* Enable system interrupt */
485 if (dev->hw_revision < ENE_HW_C) {
486 ene_write_reg(dev, ENEB_IRQ, dev->irq << 1);
487 ene_write_reg(dev, ENEB_IRQ_UNK1, 0x01);
488 } else {
489 reg_value = ene_read_reg(dev, ENE_IRQ) & 0xF0;
490 reg_value |= ENE_IRQ_UNK_EN;
491 reg_value &= ~ENE_IRQ_STATUS;
492 reg_value |= (dev->irq & ENE_IRQ_MASK);
493 ene_write_reg(dev, ENE_IRQ, reg_value);
494 }
495
496 /* Enable inputs */
497 ene_rx_enable_fan_input(dev, dev->rx_fan_input_inuse);
498 ene_rx_enable_cir_engine(dev, !dev->rx_fan_input_inuse);
499
500 /* ack any pending irqs - just in case */
501 ene_irq_status(dev);
502
503 /* enable firmware bits */
504 ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
505
506 /* enter idle mode */
507 ir_raw_event_set_idle(dev->idev, true);
508 dev->rx_enabled = true;
509}
510
511/* Disable the device receiver */
512static void ene_rx_disable(struct ene_device *dev)
513{
514 /* disable inputs */
515 ene_rx_enable_cir_engine(dev, false);
516 ene_rx_enable_fan_input(dev, false);
517
518 /* disable hardware IRQ and firmware flag */
519 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
520
521 ir_raw_event_set_idle(dev->idev, true);
522 dev->rx_enabled = false;
523}
524
525/* This resets the receiver. Usefull to stop stream of spaces at end of
526 * transmission
527 */
528static void ene_rx_reset(struct ene_device *dev)
529{
530 ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
531 ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
532}
533
534/* Set up the TX carrier frequency and duty cycle */
535static void ene_tx_set_carrier(struct ene_device *dev)
536{
537 u8 tx_puls_width;
538 unsigned long flags;
539
540 spin_lock_irqsave(&dev->hw_lock, flags);
541
542 ene_set_clear_reg_mask(dev, ENE_CIRCFG,
543 ENE_CIRCFG_TX_CARR, dev->tx_period > 0);
544
545 if (!dev->tx_period)
546 goto unlock;
547
548 BUG_ON(dev->tx_duty_cycle >= 100 || dev->tx_duty_cycle <= 0);
549
550 tx_puls_width = dev->tx_period / (100 / dev->tx_duty_cycle);
551
552 if (!tx_puls_width)
553 tx_puls_width = 1;
554
555 dbg("TX: pulse distance = %d * 500 ns", dev->tx_period);
556 dbg("TX: pulse width = %d * 500 ns", tx_puls_width);
557
558 ene_write_reg(dev, ENE_CIRMOD_PRD, dev->tx_period | ENE_CIRMOD_PRD_POL);
559 ene_write_reg(dev, ENE_CIRMOD_HPRD, tx_puls_width);
560unlock:
561 spin_unlock_irqrestore(&dev->hw_lock, flags);
562}
563
564/* Enable/disable transmitters */
565static void ene_tx_set_transmitters(struct ene_device *dev)
566{
567 unsigned long flags;
568
569 spin_lock_irqsave(&dev->hw_lock, flags);
570 ene_set_clear_reg_mask(dev, ENE_GPIOFS8, ENE_GPIOFS8_GPIO41,
571 !!(dev->transmitter_mask & 0x01));
572 ene_set_clear_reg_mask(dev, ENE_GPIOFS1, ENE_GPIOFS1_GPIO0D,
573 !!(dev->transmitter_mask & 0x02));
574 spin_unlock_irqrestore(&dev->hw_lock, flags);
575}
576
577/* prepare transmission */
578static void ene_tx_enable(struct ene_device *dev)
579{
580 u8 conf1 = ene_read_reg(dev, ENE_CIRCFG);
581 u8 fwreg2 = ene_read_reg(dev, ENE_FW2);
582
583 dev->saved_conf1 = conf1;
584
585 /* Show information about currently connected transmitter jacks */
586 if (fwreg2 & ENE_FW2_EMMITER1_CONN)
587 dbg("TX: Transmitter #1 is connected");
588
589 if (fwreg2 & ENE_FW2_EMMITER2_CONN)
590 dbg("TX: Transmitter #2 is connected");
591
592 if (!(fwreg2 & (ENE_FW2_EMMITER1_CONN | ENE_FW2_EMMITER2_CONN)))
593 ene_warn("TX: transmitter cable isn't connected!");
594
595 /* disable receive on revc */
596 if (dev->hw_revision == ENE_HW_C)
597 conf1 &= ~ENE_CIRCFG_RX_EN;
598
599 /* Enable TX engine */
600 conf1 |= ENE_CIRCFG_TX_EN | ENE_CIRCFG_TX_IRQ;
601 ene_write_reg(dev, ENE_CIRCFG, conf1);
602}
603
604/* end transmission */
605static void ene_tx_disable(struct ene_device *dev)
606{
607 ene_write_reg(dev, ENE_CIRCFG, dev->saved_conf1);
608 dev->tx_buffer = NULL;
609}
610
611
612/* TX one sample - must be called with dev->hw_lock*/
613static void ene_tx_sample(struct ene_device *dev)
614{
615 u8 raw_tx;
616 u32 sample;
617 bool pulse = dev->tx_sample_pulse;
618
619 if (!dev->tx_buffer) {
620 ene_warn("TX: BUG: attempt to transmit NULL buffer");
621 return;
622 }
623
624 /* Grab next TX sample */
625 if (!dev->tx_sample) {
626
627 if (dev->tx_pos == dev->tx_len) {
628 if (!dev->tx_done) {
629 dbg("TX: no more data to send");
630 dev->tx_done = true;
631 goto exit;
632 } else {
633 dbg("TX: last sample sent by hardware");
634 ene_tx_disable(dev);
635 complete(&dev->tx_complete);
636 return;
637 }
638 }
639
640 sample = dev->tx_buffer[dev->tx_pos++];
641 dev->tx_sample_pulse = !dev->tx_sample_pulse;
642
643 dev->tx_sample = DIV_ROUND_CLOSEST(sample, sample_period);
644
645 if (!dev->tx_sample)
646 dev->tx_sample = 1;
647 }
648
649 raw_tx = min(dev->tx_sample , (unsigned int)ENE_CIRRLC_OUT_MASK);
650 dev->tx_sample -= raw_tx;
651
652 dbg("TX: sample %8d (%s)", raw_tx * sample_period,
653 pulse ? "pulse" : "space");
654 if (pulse)
655 raw_tx |= ENE_CIRRLC_OUT_PULSE;
656
657 ene_write_reg(dev,
658 dev->tx_reg ? ENE_CIRRLC_OUT1 : ENE_CIRRLC_OUT0, raw_tx);
659
660 dev->tx_reg = !dev->tx_reg;
661exit:
662 /* simulate TX done interrupt */
663 if (txsim)
664 mod_timer(&dev->tx_sim_timer, jiffies + HZ / 500);
665}
666
667/* timer to simulate tx done interrupt */
668static void ene_tx_irqsim(unsigned long data)
669{
670 struct ene_device *dev = (struct ene_device *)data;
671 unsigned long flags;
672
673 spin_lock_irqsave(&dev->hw_lock, flags);
674 ene_tx_sample(dev);
675 spin_unlock_irqrestore(&dev->hw_lock, flags);
676}
677
678
679/* read irq status and ack it */
680static int ene_irq_status(struct ene_device *dev)
681{
682 u8 irq_status;
683 u8 fw_flags1, fw_flags2;
684 int retval = 0;
685
686 fw_flags2 = ene_read_reg(dev, ENE_FW2);
687
688 if (dev->hw_revision < ENE_HW_C) {
689 irq_status = ene_read_reg(dev, ENEB_IRQ_STATUS);
690
691 if (!(irq_status & ENEB_IRQ_STATUS_IR))
692 return 0;
693
694 ene_clear_reg_mask(dev, ENEB_IRQ_STATUS, ENEB_IRQ_STATUS_IR);
695 return ENE_IRQ_RX;
696 }
697
698 irq_status = ene_read_reg(dev, ENE_IRQ);
699 if (!(irq_status & ENE_IRQ_STATUS))
700 return 0;
701
702 /* original driver does that twice - a workaround ? */
703 ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS);
704 ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS);
705
706 /* check RX interrupt */
707 if (fw_flags2 & ENE_FW2_RXIRQ) {
708 retval |= ENE_IRQ_RX;
709 ene_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_RXIRQ);
710 }
711
712 /* check TX interrupt */
713 fw_flags1 = ene_read_reg(dev, ENE_FW1);
714 if (fw_flags1 & ENE_FW1_TXIRQ) {
715 ene_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ);
716 retval |= ENE_IRQ_TX;
717 }
718
719 return retval;
720}
721
722/* interrupt handler */
723static irqreturn_t ene_isr(int irq, void *data)
724{
725 u16 hw_value, reg;
726 int hw_sample, irq_status;
727 bool pulse;
728 unsigned long flags;
729 irqreturn_t retval = IRQ_NONE;
730 struct ene_device *dev = (struct ene_device *)data;
731 DEFINE_IR_RAW_EVENT(ev);
732
733 spin_lock_irqsave(&dev->hw_lock, flags);
734
735 dbg_verbose("ISR called");
736 ene_rx_read_hw_pointer(dev);
737 irq_status = ene_irq_status(dev);
738
739 if (!irq_status)
740 goto unlock;
741
742 retval = IRQ_HANDLED;
743
744 if (irq_status & ENE_IRQ_TX) {
745 dbg_verbose("TX interrupt");
746 if (!dev->hw_learning_and_tx_capable) {
747 dbg("TX interrupt on unsupported device!");
748 goto unlock;
749 }
750 ene_tx_sample(dev);
751 }
752
753 if (!(irq_status & ENE_IRQ_RX))
754 goto unlock;
755
756 dbg_verbose("RX interrupt");
757
758 if (dev->hw_learning_and_tx_capable)
759 ene_rx_sense_carrier(dev);
760
761 /* On hardware that don't support extra buffer we need to trust
762 the interrupt and not track the read pointer */
763 if (!dev->hw_extra_buffer)
764 dev->r_pointer = dev->w_pointer == 0 ? ENE_FW_PACKET_SIZE : 0;
765
766 while (1) {
767
768 reg = ene_rx_get_sample_reg(dev);
769
770 dbg_verbose("next sample to read at: %04x", reg);
771 if (!reg)
772 break;
773
774 hw_value = ene_read_reg(dev, reg);
775
776 if (dev->rx_fan_input_inuse) {
777
778 int offset = ENE_FW_SMPL_BUF_FAN - ENE_FW_SAMPLE_BUFFER;
779
780 /* read high part of the sample */
781 hw_value |= ene_read_reg(dev, reg + offset) << 8;
782 pulse = hw_value & ENE_FW_SMPL_BUF_FAN_PLS;
783
784 /* clear space bit, and other unused bits */
785 hw_value &= ENE_FW_SMPL_BUF_FAN_MSK;
786 hw_sample = hw_value * ENE_FW_SAMPLE_PERIOD_FAN;
787
788 } else {
789 pulse = !(hw_value & ENE_FW_SAMPLE_SPACE);
790 hw_value &= ~ENE_FW_SAMPLE_SPACE;
791 hw_sample = hw_value * sample_period;
792
793 if (dev->rx_period_adjust) {
794 hw_sample *= 100;
795 hw_sample /= (100 + dev->rx_period_adjust);
796 }
797 }
798
799 if (!dev->hw_extra_buffer && !hw_sample) {
800 dev->r_pointer = dev->w_pointer;
801 continue;
802 }
803
804 dbg("RX: %d (%s)", hw_sample, pulse ? "pulse" : "space");
805
806 ev.duration = MS_TO_NS(hw_sample);
807 ev.pulse = pulse;
808 ir_raw_event_store_with_filter(dev->idev, &ev);
809 }
810
811 ir_raw_event_handle(dev->idev);
812unlock:
813 spin_unlock_irqrestore(&dev->hw_lock, flags);
814 return retval;
815}
816
817/* Initialize default settings */
818static void ene_setup_default_settings(struct ene_device *dev)
819{
820 dev->tx_period = 32;
821 dev->tx_duty_cycle = 50; /*%*/
822 dev->transmitter_mask = 0x03;
823 dev->learning_mode_enabled = learning_mode_force;
824
825 /* Set reasonable default timeout */
826 dev->props->timeout = MS_TO_NS(150000);
827}
828
829/* Upload all hardware settings at once. Used at load and resume time */
830static void ene_setup_hw_settings(struct ene_device *dev)
831{
832 if (dev->hw_learning_and_tx_capable) {
833 ene_tx_set_carrier(dev);
834 ene_tx_set_transmitters(dev);
835 }
836
837 ene_rx_setup(dev);
838}
839
840/* outside interface: called on first open*/
841static int ene_open(void *data)
842{
843 struct ene_device *dev = (struct ene_device *)data;
844 unsigned long flags;
845
846 spin_lock_irqsave(&dev->hw_lock, flags);
847 ene_rx_enable(dev);
848 spin_unlock_irqrestore(&dev->hw_lock, flags);
849 return 0;
850}
851
852/* outside interface: called on device close*/
853static void ene_close(void *data)
854{
855 struct ene_device *dev = (struct ene_device *)data;
856 unsigned long flags;
857 spin_lock_irqsave(&dev->hw_lock, flags);
858
859 ene_rx_disable(dev);
860 spin_unlock_irqrestore(&dev->hw_lock, flags);
861}
862
863/* outside interface: set transmitter mask */
864static int ene_set_tx_mask(void *data, u32 tx_mask)
865{
866 struct ene_device *dev = (struct ene_device *)data;
867 dbg("TX: attempt to set transmitter mask %02x", tx_mask);
868
869 /* invalid txmask */
870 if (!tx_mask || tx_mask & ~0x03) {
871 dbg("TX: invalid mask");
872 /* return count of transmitters */
873 return 2;
874 }
875
876 dev->transmitter_mask = tx_mask;
877 ene_tx_set_transmitters(dev);
878 return 0;
879}
880
881/* outside interface : set tx carrier */
882static int ene_set_tx_carrier(void *data, u32 carrier)
883{
884 struct ene_device *dev = (struct ene_device *)data;
885 u32 period = 2000000 / carrier;
886
887 dbg("TX: attempt to set tx carrier to %d kHz", carrier);
888
889 if (period && (period > ENE_CIRMOD_PRD_MAX ||
890 period < ENE_CIRMOD_PRD_MIN)) {
891
892 dbg("TX: out of range %d-%d kHz carrier",
893 2000 / ENE_CIRMOD_PRD_MIN, 2000 / ENE_CIRMOD_PRD_MAX);
894 return -1;
895 }
896
897 dev->tx_period = period;
898 ene_tx_set_carrier(dev);
899 return 0;
900}
901
902/*outside interface : set tx duty cycle */
903static int ene_set_tx_duty_cycle(void *data, u32 duty_cycle)
904{
905 struct ene_device *dev = (struct ene_device *)data;
906 dbg("TX: setting duty cycle to %d%%", duty_cycle);
907 dev->tx_duty_cycle = duty_cycle;
908 ene_tx_set_carrier(dev);
909 return 0;
910}
911
912/* outside interface: enable learning mode */
913static int ene_set_learning_mode(void *data, int enable)
914{
915 struct ene_device *dev = (struct ene_device *)data;
916 unsigned long flags;
917 if (enable == dev->learning_mode_enabled)
918 return 0;
919
920 spin_lock_irqsave(&dev->hw_lock, flags);
921 dev->learning_mode_enabled = enable;
922 ene_rx_disable(dev);
923 ene_rx_setup(dev);
924 ene_rx_enable(dev);
925 spin_unlock_irqrestore(&dev->hw_lock, flags);
926 return 0;
927}
928
929static int ene_set_carrier_report(void *data, int enable)
930{
931 struct ene_device *dev = (struct ene_device *)data;
932 unsigned long flags;
933
934 if (enable == dev->carrier_detect_enabled)
935 return 0;
936
937 spin_lock_irqsave(&dev->hw_lock, flags);
938 dev->carrier_detect_enabled = enable;
939 ene_rx_disable(dev);
940 ene_rx_setup(dev);
941 ene_rx_enable(dev);
942 spin_unlock_irqrestore(&dev->hw_lock, flags);
943 return 0;
944}
945
946/* outside interface: enable or disable idle mode */
947static void ene_set_idle(void *data, bool idle)
948{
949 if (idle) {
950 ene_rx_reset((struct ene_device *)data);
951 dbg("RX: end of data");
952 }
953}
954
955/* outside interface: transmit */
956static int ene_transmit(void *data, int *buf, u32 n)
957{
958 struct ene_device *dev = (struct ene_device *)data;
959 unsigned long flags;
960
961 dev->tx_buffer = buf;
962 dev->tx_len = n / sizeof(int);
963 dev->tx_pos = 0;
964 dev->tx_reg = 0;
965 dev->tx_done = 0;
966 dev->tx_sample = 0;
967 dev->tx_sample_pulse = 0;
968
969 dbg("TX: %d samples", dev->tx_len);
970
971 spin_lock_irqsave(&dev->hw_lock, flags);
972
973 ene_tx_enable(dev);
974
975 /* Transmit first two samples */
976 ene_tx_sample(dev);
977 ene_tx_sample(dev);
978
979 spin_unlock_irqrestore(&dev->hw_lock, flags);
980
981 if (wait_for_completion_timeout(&dev->tx_complete, 2 * HZ) == 0) {
982 dbg("TX: timeout");
983 spin_lock_irqsave(&dev->hw_lock, flags);
984 ene_tx_disable(dev);
985 spin_unlock_irqrestore(&dev->hw_lock, flags);
986 } else
987 dbg("TX: done");
988 return n;
989}
990
991/* probe entry */
992static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
993{
994 int error = -ENOMEM;
995 struct ir_dev_props *ir_props;
996 struct input_dev *input_dev;
997 struct ene_device *dev;
998
999 /* allocate memory */
1000 input_dev = input_allocate_device();
1001 ir_props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
1002 dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
1003
1004 if (!input_dev || !ir_props || !dev)
1005 goto error1;
1006
1007 /* validate resources */
1008 error = -ENODEV;
1009
1010 if (!pnp_port_valid(pnp_dev, 0) ||
1011 pnp_port_len(pnp_dev, 0) < ENE_IO_SIZE)
1012 goto error;
1013
1014 if (!pnp_irq_valid(pnp_dev, 0))
1015 goto error;
1016
1017 spin_lock_init(&dev->hw_lock);
1018
1019 /* claim the resources */
1020 error = -EBUSY;
1021 dev->hw_io = pnp_port_start(pnp_dev, 0);
1022 if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
1023 dev->hw_io = -1;
1024 dev->irq = -1;
1025 goto error;
1026 }
1027
1028 dev->irq = pnp_irq(pnp_dev, 0);
1029 if (request_irq(dev->irq, ene_isr,
1030 IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
1031 dev->irq = -1;
1032 goto error;
1033 }
1034
1035 pnp_set_drvdata(pnp_dev, dev);
1036 dev->pnp_dev = pnp_dev;
1037
1038 /* don't allow too short/long sample periods */
1039 if (sample_period < 5 || sample_period > 0x7F)
1040 sample_period = ENE_DEFAULT_SAMPLE_PERIOD;
1041
1042 /* detect hardware version and features */
1043 error = ene_hw_detect(dev);
1044 if (error)
1045 goto error;
1046
1047 if (!dev->hw_learning_and_tx_capable && txsim) {
1048 dev->hw_learning_and_tx_capable = true;
1049 setup_timer(&dev->tx_sim_timer, ene_tx_irqsim,
1050 (long unsigned int)dev);
1051 ene_warn("Simulation of TX activated");
1052 }
1053
1054 if (!dev->hw_learning_and_tx_capable)
1055 learning_mode_force = false;
1056
1057 ir_props->driver_type = RC_DRIVER_IR_RAW;
1058 ir_props->allowed_protos = IR_TYPE_ALL;
1059 ir_props->priv = dev;
1060 ir_props->open = ene_open;
1061 ir_props->close = ene_close;
1062 ir_props->s_idle = ene_set_idle;
1063
1064 dev->props = ir_props;
1065 dev->idev = input_dev;
1066
1067 if (dev->hw_learning_and_tx_capable) {
1068 ir_props->s_learning_mode = ene_set_learning_mode;
1069 init_completion(&dev->tx_complete);
1070 ir_props->tx_ir = ene_transmit;
1071 ir_props->s_tx_mask = ene_set_tx_mask;
1072 ir_props->s_tx_carrier = ene_set_tx_carrier;
1073 ir_props->s_tx_duty_cycle = ene_set_tx_duty_cycle;
1074 ir_props->s_carrier_report = ene_set_carrier_report;
1075 }
1076
1077 ene_rx_setup_hw_buffer(dev);
1078 ene_setup_default_settings(dev);
1079 ene_setup_hw_settings(dev);
1080
1081 device_set_wakeup_capable(&pnp_dev->dev, true);
1082 device_set_wakeup_enable(&pnp_dev->dev, true);
1083
1084 if (dev->hw_learning_and_tx_capable)
1085 input_dev->name = "ENE eHome Infrared Remote Transceiver";
1086 else
1087 input_dev->name = "ENE eHome Infrared Remote Receiver";
1088
1089 error = -ENODEV;
1090 if (ir_input_register(input_dev, RC_MAP_RC6_MCE, ir_props,
1091 ENE_DRIVER_NAME))
1092 goto error;
1093
1094 ene_notice("driver has been succesfully loaded");
1095 return 0;
1096error:
1097 if (dev && dev->irq >= 0)
1098 free_irq(dev->irq, dev);
1099 if (dev && dev->hw_io >= 0)
1100 release_region(dev->hw_io, ENE_IO_SIZE);
1101error1:
1102 input_free_device(input_dev);
1103 kfree(ir_props);
1104 kfree(dev);
1105 return error;
1106}
1107
1108/* main unload function */
1109static void ene_remove(struct pnp_dev *pnp_dev)
1110{
1111 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
1112 unsigned long flags;
1113
1114 spin_lock_irqsave(&dev->hw_lock, flags);
1115 ene_rx_disable(dev);
1116 ene_rx_restore_hw_buffer(dev);
1117 spin_unlock_irqrestore(&dev->hw_lock, flags);
1118
1119 free_irq(dev->irq, dev);
1120 release_region(dev->hw_io, ENE_IO_SIZE);
1121 ir_input_unregister(dev->idev);
1122 kfree(dev->props);
1123 kfree(dev);
1124}
1125
1126/* enable wake on IR (wakes on specific button on original remote) */
1127static void ene_enable_wake(struct ene_device *dev, int enable)
1128{
1129 enable = enable && device_may_wakeup(&dev->pnp_dev->dev);
1130 dbg("wake on IR %s", enable ? "enabled" : "disabled");
1131 ene_set_clear_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, enable);
1132}
1133
1134#ifdef CONFIG_PM
1135static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
1136{
1137 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
1138 ene_enable_wake(dev, true);
1139
1140 /* TODO: add support for wake pattern */
1141 return 0;
1142}
1143
1144static int ene_resume(struct pnp_dev *pnp_dev)
1145{
1146 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
1147 ene_setup_hw_settings(dev);
1148
1149 if (dev->rx_enabled)
1150 ene_rx_enable(dev);
1151
1152 ene_enable_wake(dev, false);
1153 return 0;
1154}
1155#endif
1156
1157static void ene_shutdown(struct pnp_dev *pnp_dev)
1158{
1159 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
1160 ene_enable_wake(dev, true);
1161}
1162
1163static const struct pnp_device_id ene_ids[] = {
1164 {.id = "ENE0100",},
1165 {.id = "ENE0200",},
1166 {.id = "ENE0201",},
1167 {.id = "ENE0202",},
1168 {},
1169};
1170
1171static struct pnp_driver ene_driver = {
1172 .name = ENE_DRIVER_NAME,
1173 .id_table = ene_ids,
1174 .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
1175
1176 .probe = ene_probe,
1177 .remove = __devexit_p(ene_remove),
1178#ifdef CONFIG_PM
1179 .suspend = ene_suspend,
1180 .resume = ene_resume,
1181#endif
1182 .shutdown = ene_shutdown,
1183};
1184
1185static int __init ene_init(void)
1186{
1187 return pnp_register_driver(&ene_driver);
1188}
1189
1190static void ene_exit(void)
1191{
1192 pnp_unregister_driver(&ene_driver);
1193}
1194
1195module_param(sample_period, int, S_IRUGO);
1196MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)");
1197
1198module_param(learning_mode_force, bool, S_IRUGO);
1199MODULE_PARM_DESC(learning_mode_force, "Enable learning mode by default");
1200
1201module_param(debug, int, S_IRUGO | S_IWUSR);
1202MODULE_PARM_DESC(debug, "Debug level");
1203
1204module_param(txsim, bool, S_IRUGO);
1205MODULE_PARM_DESC(txsim,
1206 "Simulate TX features on unsupported hardware (dangerous)");
1207
1208MODULE_DEVICE_TABLE(pnp, ene_ids);
1209MODULE_DESCRIPTION
1210 ("Infrared input driver for KB3926B/C/D/E/F "
1211 "(aka ENE0100/ENE0200/ENE0201/ENE0202) CIR port");
1212
1213MODULE_AUTHOR("Maxim Levitsky");
1214MODULE_LICENSE("GPL");
1215
1216module_init(ene_init);
1217module_exit(ene_exit);
diff --git a/drivers/media/rc/ene_ir.h b/drivers/media/rc/ene_ir.h
new file mode 100644
index 000000000000..f5870667a433
--- /dev/null
+++ b/drivers/media/rc/ene_ir.h
@@ -0,0 +1,262 @@
1/*
2 * driver for ENE KB3926 B/C/D/E/F CIR (also known as ENE0XXX)
3 *
4 * Copyright (C) 2010 Maxim Levitsky <maximlevitsky@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 * USA
20 */
21#include <linux/spinlock.h>
22
23
24/* hardware address */
25#define ENE_STATUS 0 /* hardware status - unused */
26#define ENE_ADDR_HI 1 /* hi byte of register address */
27#define ENE_ADDR_LO 2 /* low byte of register address */
28#define ENE_IO 3 /* read/write window */
29#define ENE_IO_SIZE 4
30
31/* 8 bytes of samples, divided in 2 packets*/
32#define ENE_FW_SAMPLE_BUFFER 0xF8F0 /* sample buffer */
33#define ENE_FW_SAMPLE_SPACE 0x80 /* sample is space */
34#define ENE_FW_PACKET_SIZE 4
35
36/* first firmware flag register */
37#define ENE_FW1 0xF8F8 /* flagr */
38#define ENE_FW1_ENABLE 0x01 /* enable fw processing */
39#define ENE_FW1_TXIRQ 0x02 /* TX interrupt pending */
40#define ENE_FW1_HAS_EXTRA_BUF 0x04 /* fw uses extra buffer*/
41#define ENE_FW1_EXTRA_BUF_HND 0x08 /* extra buffer handshake bit*/
42#define ENE_FW1_LED_ON 0x10 /* turn on a led */
43
44#define ENE_FW1_WPATTERN 0x20 /* enable wake pattern */
45#define ENE_FW1_WAKE 0x40 /* enable wake from S3 */
46#define ENE_FW1_IRQ 0x80 /* enable interrupt */
47
48/* second firmware flag register */
49#define ENE_FW2 0xF8F9 /* flagw */
50#define ENE_FW2_BUF_WPTR 0x01 /* which half of the buffer to read */
51#define ENE_FW2_RXIRQ 0x04 /* RX IRQ pending*/
52#define ENE_FW2_GP0A 0x08 /* Use GPIO0A for demodulated input */
53#define ENE_FW2_EMMITER1_CONN 0x10 /* TX emmiter 1 connected */
54#define ENE_FW2_EMMITER2_CONN 0x20 /* TX emmiter 2 connected */
55
56#define ENE_FW2_FAN_INPUT 0x40 /* fan input used for demodulated data*/
57#define ENE_FW2_LEARNING 0x80 /* hardware supports learning and TX */
58
59/* firmware RX pointer for new style buffer */
60#define ENE_FW_RX_POINTER 0xF8FA
61
62/* high parts of samples for fan input (8 samples)*/
63#define ENE_FW_SMPL_BUF_FAN 0xF8FB
64#define ENE_FW_SMPL_BUF_FAN_PLS 0x8000 /* combined sample is pulse */
65#define ENE_FW_SMPL_BUF_FAN_MSK 0x0FFF /* combined sample maximum value */
66#define ENE_FW_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */
67
68/* transmitter ports */
69#define ENE_GPIOFS1 0xFC01
70#define ENE_GPIOFS1_GPIO0D 0x20 /* enable tx output on GPIO0D */
71#define ENE_GPIOFS8 0xFC08
72#define ENE_GPIOFS8_GPIO41 0x02 /* enable tx output on GPIO40 */
73
74/* IRQ registers block (for revision B) */
75#define ENEB_IRQ 0xFD09 /* IRQ number */
76#define ENEB_IRQ_UNK1 0xFD17 /* unknown setting = 1 */
77#define ENEB_IRQ_STATUS 0xFD80 /* irq status */
78#define ENEB_IRQ_STATUS_IR 0x20 /* IR irq */
79
80/* fan as input settings */
81#define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */
82#define ENE_FAN_AS_IN1_EN 0xCD
83#define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */
84#define ENE_FAN_AS_IN2_EN 0x03
85
86/* IRQ registers block (for revision C,D) */
87#define ENE_IRQ 0xFE9B /* new irq settings register */
88#define ENE_IRQ_MASK 0x0F /* irq number mask */
89#define ENE_IRQ_UNK_EN 0x10 /* always enabled */
90#define ENE_IRQ_STATUS 0x20 /* irq status and ACK */
91
92/* CIR Config register #1 */
93#define ENE_CIRCFG 0xFEC0
94#define ENE_CIRCFG_RX_EN 0x01 /* RX enable */
95#define ENE_CIRCFG_RX_IRQ 0x02 /* Enable hardware interrupt */
96#define ENE_CIRCFG_REV_POL 0x04 /* Input polarity reversed */
97#define ENE_CIRCFG_CARR_DEMOD 0x08 /* Enable carrier demodulator */
98
99#define ENE_CIRCFG_TX_EN 0x10 /* TX enable */
100#define ENE_CIRCFG_TX_IRQ 0x20 /* Send interrupt on TX done */
101#define ENE_CIRCFG_TX_POL_REV 0x40 /* TX polarity reversed */
102#define ENE_CIRCFG_TX_CARR 0x80 /* send TX carrier or not */
103
104/* CIR config register #2 */
105#define ENE_CIRCFG2 0xFEC1
106#define ENE_CIRCFG2_RLC 0x00
107#define ENE_CIRCFG2_RC5 0x01
108#define ENE_CIRCFG2_RC6 0x02
109#define ENE_CIRCFG2_NEC 0x03
110#define ENE_CIRCFG2_CARR_DETECT 0x10 /* Enable carrier detection */
111#define ENE_CIRCFG2_GPIO0A 0x20 /* Use GPIO0A instead of GPIO40 for input */
112#define ENE_CIRCFG2_FAST_SAMPL1 0x40 /* Fast leading pulse detection for RC6 */
113#define ENE_CIRCFG2_FAST_SAMPL2 0x80 /* Fast data detection for RC6 */
114
115/* Knobs for protocol decoding - will document when/if will use them */
116#define ENE_CIRPF 0xFEC2
117#define ENE_CIRHIGH 0xFEC3
118#define ENE_CIRBIT 0xFEC4
119#define ENE_CIRSTART 0xFEC5
120#define ENE_CIRSTART2 0xFEC6
121
122/* Actual register which contains RLC RX data - read by firmware */
123#define ENE_CIRDAT_IN 0xFEC7
124
125
126/* RLC configuration - sample period (1us resulution) + idle mode */
127#define ENE_CIRRLC_CFG 0xFEC8
128#define ENE_CIRRLC_CFG_OVERFLOW 0x80 /* interrupt on overflows if set */
129#define ENE_DEFAULT_SAMPLE_PERIOD 50
130
131/* Two byte RLC TX buffer */
132#define ENE_CIRRLC_OUT0 0xFEC9
133#define ENE_CIRRLC_OUT1 0xFECA
134#define ENE_CIRRLC_OUT_PULSE 0x80 /* Transmitted sample is pulse */
135#define ENE_CIRRLC_OUT_MASK 0x7F
136
137
138/* Carrier detect setting
139 * Low nibble - number of carrier pulses to average
140 * High nibble - number of initial carrier pulses to discard
141 */
142#define ENE_CIRCAR_PULS 0xFECB
143
144/* detected RX carrier period (resolution: 500 ns) */
145#define ENE_CIRCAR_PRD 0xFECC
146#define ENE_CIRCAR_PRD_VALID 0x80 /* data valid content valid */
147
148/* detected RX carrier pulse width (resolution: 500 ns) */
149#define ENE_CIRCAR_HPRD 0xFECD
150
151/* TX period (resolution: 500 ns, minimum 2)*/
152#define ENE_CIRMOD_PRD 0xFECE
153#define ENE_CIRMOD_PRD_POL 0x80 /* TX carrier polarity*/
154
155#define ENE_CIRMOD_PRD_MAX 0x7F /* 15.87 kHz */
156#define ENE_CIRMOD_PRD_MIN 0x02 /* 1 Mhz */
157
158/* TX pulse width (resolution: 500 ns)*/
159#define ENE_CIRMOD_HPRD 0xFECF
160
161/* Hardware versions */
162#define ENE_ECHV 0xFF00 /* hardware revision */
163#define ENE_PLLFRH 0xFF16
164#define ENE_PLLFRL 0xFF17
165#define ENE_DEFAULT_PLL_FREQ 1000
166
167#define ENE_ECSTS 0xFF1D
168#define ENE_ECSTS_RSRVD 0x04
169
170#define ENE_ECVER_MAJOR 0xFF1E /* chip version */
171#define ENE_ECVER_MINOR 0xFF1F
172#define ENE_HW_VER_OLD 0xFD00
173
174/******************************************************************************/
175
176#define ENE_DRIVER_NAME "ene_ir"
177
178#define ENE_IRQ_RX 1
179#define ENE_IRQ_TX 2
180
181#define ENE_HW_B 1 /* 3926B */
182#define ENE_HW_C 2 /* 3926C */
183#define ENE_HW_D 3 /* 3926D or later */
184
185#define ene_printk(level, text, ...) \
186 printk(level ENE_DRIVER_NAME ": " text "\n", ## __VA_ARGS__)
187
188#define ene_notice(text, ...) ene_printk(KERN_NOTICE, text, ## __VA_ARGS__)
189#define ene_warn(text, ...) ene_printk(KERN_WARNING, text, ## __VA_ARGS__)
190
191
192#define __dbg(level, format, ...) \
193 do { \
194 if (debug >= level) \
195 printk(KERN_DEBUG ENE_DRIVER_NAME \
196 ": " format "\n", ## __VA_ARGS__); \
197 } while (0)
198
199
200#define dbg(format, ...) __dbg(1, format, ## __VA_ARGS__)
201#define dbg_verbose(format, ...) __dbg(2, format, ## __VA_ARGS__)
202#define dbg_regs(format, ...) __dbg(3, format, ## __VA_ARGS__)
203
204#define MS_TO_NS(msec) ((msec) * 1000)
205
206struct ene_device {
207 struct pnp_dev *pnp_dev;
208 struct input_dev *idev;
209 struct ir_dev_props *props;
210
211 /* hw IO settings */
212 long hw_io;
213 int irq;
214 spinlock_t hw_lock;
215
216 /* HW features */
217 int hw_revision; /* hardware revision */
218 bool hw_use_gpio_0a; /* gpio0a is demodulated input*/
219 bool hw_extra_buffer; /* hardware has 'extra buffer' */
220 bool hw_fan_input; /* fan input is IR data source */
221 bool hw_learning_and_tx_capable; /* learning & tx capable */
222 int pll_freq;
223 int buffer_len;
224
225 /* Extra RX buffer location */
226 int extra_buf1_address;
227 int extra_buf1_len;
228 int extra_buf2_address;
229 int extra_buf2_len;
230
231 /* HW state*/
232 int r_pointer; /* pointer to next sample to read */
233 int w_pointer; /* pointer to next sample hw will write */
234 bool rx_fan_input_inuse; /* is fan input in use for rx*/
235 int tx_reg; /* current reg used for TX */
236 u8 saved_conf1; /* saved FEC0 reg */
237 unsigned int tx_sample; /* current sample for TX */
238 bool tx_sample_pulse; /* current sample is pulse */
239
240 /* TX buffer */
241 int *tx_buffer; /* input samples buffer*/
242 int tx_pos; /* position in that bufer */
243 int tx_len; /* current len of tx buffer */
244 int tx_done; /* done transmitting */
245 /* one more sample pending*/
246 struct completion tx_complete; /* TX completion */
247 struct timer_list tx_sim_timer;
248
249 /* TX settings */
250 int tx_period;
251 int tx_duty_cycle;
252 int transmitter_mask;
253
254 /* RX settings */
255 bool learning_mode_enabled; /* learning input enabled */
256 bool carrier_detect_enabled; /* carrier detect enabled */
257 int rx_period_adjust;
258 bool rx_enabled;
259};
260
261static int ene_irq_status(struct ene_device *dev);
262static void ene_rx_read_hw_pointer(struct ene_device *dev);
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
new file mode 100644
index 000000000000..79f4f58c2ea4
--- /dev/null
+++ b/drivers/media/rc/imon.c
@@ -0,0 +1,2465 @@
1/*
2 * imon.c: input and display driver for SoundGraph iMON IR/VFD/LCD
3 *
4 * Copyright(C) 2010 Jarod Wilson <jarod@wilsonet.com>
5 * Portions based on the original lirc_imon driver,
6 * Copyright(C) 2004 Venky Raju(dev@venky.ws)
7 *
8 * Huge thanks to R. Geoff Newbury for invaluable debugging on the
9 * 0xffdc iMON devices, and for sending me one to hack on, without
10 * which the support for them wouldn't be nearly as good. Thanks
11 * also to the numerous 0xffdc device owners that tested auto-config
12 * support for me and provided debug dumps from their devices.
13 *
14 * imon is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
30
31#include <linux/errno.h>
32#include <linux/init.h>
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/slab.h>
36#include <linux/uaccess.h>
37
38#include <linux/input.h>
39#include <linux/usb.h>
40#include <linux/usb/input.h>
41#include <media/ir-core.h>
42
43#include <linux/time.h>
44#include <linux/timer.h>
45
46#define MOD_AUTHOR "Jarod Wilson <jarod@wilsonet.com>"
47#define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display"
48#define MOD_NAME "imon"
49#define MOD_VERSION "0.9.2"
50
51#define DISPLAY_MINOR_BASE 144
52#define DEVICE_NAME "lcd%d"
53
54#define BUF_CHUNK_SIZE 8
55#define BUF_SIZE 128
56
57#define BIT_DURATION 250 /* each bit received is 250us */
58
59#define IMON_CLOCK_ENABLE_PACKETS 2
60
61/*** P R O T O T Y P E S ***/
62
63/* USB Callback prototypes */
64static int imon_probe(struct usb_interface *interface,
65 const struct usb_device_id *id);
66static void imon_disconnect(struct usb_interface *interface);
67static void usb_rx_callback_intf0(struct urb *urb);
68static void usb_rx_callback_intf1(struct urb *urb);
69static void usb_tx_callback(struct urb *urb);
70
71/* suspend/resume support */
72static int imon_resume(struct usb_interface *intf);
73static int imon_suspend(struct usb_interface *intf, pm_message_t message);
74
75/* Display file_operations function prototypes */
76static int display_open(struct inode *inode, struct file *file);
77static int display_close(struct inode *inode, struct file *file);
78
79/* VFD write operation */
80static ssize_t vfd_write(struct file *file, const char *buf,
81 size_t n_bytes, loff_t *pos);
82
83/* LCD file_operations override function prototypes */
84static ssize_t lcd_write(struct file *file, const char *buf,
85 size_t n_bytes, loff_t *pos);
86
87/*** G L O B A L S ***/
88
89struct imon_context {
90 struct device *dev;
91 struct ir_dev_props *props;
92 /* Newer devices have two interfaces */
93 struct usb_device *usbdev_intf0;
94 struct usb_device *usbdev_intf1;
95
96 bool display_supported; /* not all controllers do */
97 bool display_isopen; /* display port has been opened */
98 bool rf_device; /* true if iMON 2.4G LT/DT RF device */
99 bool rf_isassociating; /* RF remote associating */
100 bool dev_present_intf0; /* USB device presence, interface 0 */
101 bool dev_present_intf1; /* USB device presence, interface 1 */
102
103 struct mutex lock; /* to lock this object */
104 wait_queue_head_t remove_ok; /* For unexpected USB disconnects */
105
106 struct usb_endpoint_descriptor *rx_endpoint_intf0;
107 struct usb_endpoint_descriptor *rx_endpoint_intf1;
108 struct usb_endpoint_descriptor *tx_endpoint;
109 struct urb *rx_urb_intf0;
110 struct urb *rx_urb_intf1;
111 struct urb *tx_urb;
112 bool tx_control;
113 unsigned char usb_rx_buf[8];
114 unsigned char usb_tx_buf[8];
115
116 struct tx_t {
117 unsigned char data_buf[35]; /* user data buffer */
118 struct completion finished; /* wait for write to finish */
119 bool busy; /* write in progress */
120 int status; /* status of tx completion */
121 } tx;
122
123 u16 vendor; /* usb vendor ID */
124 u16 product; /* usb product ID */
125
126 struct input_dev *rdev; /* input device for remote */
127 struct input_dev *idev; /* input device for panel & IR mouse */
128 struct input_dev *touch; /* input device for touchscreen */
129
130 spinlock_t kc_lock; /* make sure we get keycodes right */
131 u32 kc; /* current input keycode */
132 u32 last_keycode; /* last reported input keycode */
133 u32 rc_scancode; /* the computed remote scancode */
134 u8 rc_toggle; /* the computed remote toggle bit */
135 u64 ir_type; /* iMON or MCE (RC6) IR protocol? */
136 bool release_code; /* some keys send a release code */
137
138 u8 display_type; /* store the display type */
139 bool pad_mouse; /* toggle kbd(0)/mouse(1) mode */
140
141 char name_rdev[128]; /* rc input device name */
142 char phys_rdev[64]; /* rc input device phys path */
143
144 char name_idev[128]; /* input device name */
145 char phys_idev[64]; /* input device phys path */
146
147 char name_touch[128]; /* touch screen name */
148 char phys_touch[64]; /* touch screen phys path */
149 struct timer_list ttimer; /* touch screen timer */
150 int touch_x; /* x coordinate on touchscreen */
151 int touch_y; /* y coordinate on touchscreen */
152};
153
154#define TOUCH_TIMEOUT (HZ/30)
155
156/* vfd character device file operations */
157static const struct file_operations vfd_fops = {
158 .owner = THIS_MODULE,
159 .open = &display_open,
160 .write = &vfd_write,
161 .release = &display_close,
162 .llseek = noop_llseek,
163};
164
165/* lcd character device file operations */
166static const struct file_operations lcd_fops = {
167 .owner = THIS_MODULE,
168 .open = &display_open,
169 .write = &lcd_write,
170 .release = &display_close,
171 .llseek = noop_llseek,
172};
173
174enum {
175 IMON_DISPLAY_TYPE_AUTO = 0,
176 IMON_DISPLAY_TYPE_VFD = 1,
177 IMON_DISPLAY_TYPE_LCD = 2,
178 IMON_DISPLAY_TYPE_VGA = 3,
179 IMON_DISPLAY_TYPE_NONE = 4,
180};
181
182enum {
183 IMON_KEY_IMON = 0,
184 IMON_KEY_MCE = 1,
185 IMON_KEY_PANEL = 2,
186};
187
188/*
189 * USB Device ID for iMON USB Control Boards
190 *
191 * The Windows drivers contain 6 different inf files, more or less one for
192 * each new device until the 0x0034-0x0046 devices, which all use the same
193 * driver. Some of the devices in the 34-46 range haven't been definitively
194 * identified yet. Early devices have either a TriGem Computer, Inc. or a
195 * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later
196 * devices use the SoundGraph vendor ID (0x15c2). This driver only supports
197 * the ffdc and later devices, which do onboard decoding.
198 */
199static struct usb_device_id imon_usb_id_table[] = {
200 /*
201 * Several devices with this same device ID, all use iMON_PAD.inf
202 * SoundGraph iMON PAD (IR & VFD)
203 * SoundGraph iMON PAD (IR & LCD)
204 * SoundGraph iMON Knob (IR only)
205 */
206 { USB_DEVICE(0x15c2, 0xffdc) },
207
208 /*
209 * Newer devices, all driven by the latest iMON Windows driver, full
210 * list of device IDs extracted via 'strings Setup/data1.hdr |grep 15c2'
211 * Need user input to fill in details on unknown devices.
212 */
213 /* SoundGraph iMON OEM Touch LCD (IR & 7" VGA LCD) */
214 { USB_DEVICE(0x15c2, 0x0034) },
215 /* SoundGraph iMON OEM Touch LCD (IR & 4.3" VGA LCD) */
216 { USB_DEVICE(0x15c2, 0x0035) },
217 /* SoundGraph iMON OEM VFD (IR & VFD) */
218 { USB_DEVICE(0x15c2, 0x0036) },
219 /* device specifics unknown */
220 { USB_DEVICE(0x15c2, 0x0037) },
221 /* SoundGraph iMON OEM LCD (IR & LCD) */
222 { USB_DEVICE(0x15c2, 0x0038) },
223 /* SoundGraph iMON UltraBay (IR & LCD) */
224 { USB_DEVICE(0x15c2, 0x0039) },
225 /* device specifics unknown */
226 { USB_DEVICE(0x15c2, 0x003a) },
227 /* device specifics unknown */
228 { USB_DEVICE(0x15c2, 0x003b) },
229 /* SoundGraph iMON OEM Inside (IR only) */
230 { USB_DEVICE(0x15c2, 0x003c) },
231 /* device specifics unknown */
232 { USB_DEVICE(0x15c2, 0x003d) },
233 /* device specifics unknown */
234 { USB_DEVICE(0x15c2, 0x003e) },
235 /* device specifics unknown */
236 { USB_DEVICE(0x15c2, 0x003f) },
237 /* device specifics unknown */
238 { USB_DEVICE(0x15c2, 0x0040) },
239 /* SoundGraph iMON MINI (IR only) */
240 { USB_DEVICE(0x15c2, 0x0041) },
241 /* Antec Veris Multimedia Station EZ External (IR only) */
242 { USB_DEVICE(0x15c2, 0x0042) },
243 /* Antec Veris Multimedia Station Basic Internal (IR only) */
244 { USB_DEVICE(0x15c2, 0x0043) },
245 /* Antec Veris Multimedia Station Elite (IR & VFD) */
246 { USB_DEVICE(0x15c2, 0x0044) },
247 /* Antec Veris Multimedia Station Premiere (IR & LCD) */
248 { USB_DEVICE(0x15c2, 0x0045) },
249 /* device specifics unknown */
250 { USB_DEVICE(0x15c2, 0x0046) },
251 {}
252};
253
254/* USB Device data */
255static struct usb_driver imon_driver = {
256 .name = MOD_NAME,
257 .probe = imon_probe,
258 .disconnect = imon_disconnect,
259 .suspend = imon_suspend,
260 .resume = imon_resume,
261 .id_table = imon_usb_id_table,
262};
263
264static struct usb_class_driver imon_vfd_class = {
265 .name = DEVICE_NAME,
266 .fops = &vfd_fops,
267 .minor_base = DISPLAY_MINOR_BASE,
268};
269
270static struct usb_class_driver imon_lcd_class = {
271 .name = DEVICE_NAME,
272 .fops = &lcd_fops,
273 .minor_base = DISPLAY_MINOR_BASE,
274};
275
276/* imon receiver front panel/knob key table */
277static const struct {
278 u64 hw_code;
279 u32 keycode;
280} imon_panel_key_table[] = {
281 { 0x000000000f00ffeell, KEY_PROG1 }, /* Go */
282 { 0x000000001f00ffeell, KEY_AUDIO },
283 { 0x000000002000ffeell, KEY_VIDEO },
284 { 0x000000002100ffeell, KEY_CAMERA },
285 { 0x000000002700ffeell, KEY_DVD },
286 { 0x000000002300ffeell, KEY_TV },
287 { 0x000000000500ffeell, KEY_PREVIOUS },
288 { 0x000000000700ffeell, KEY_REWIND },
289 { 0x000000000400ffeell, KEY_STOP },
290 { 0x000000003c00ffeell, KEY_PLAYPAUSE },
291 { 0x000000000800ffeell, KEY_FASTFORWARD },
292 { 0x000000000600ffeell, KEY_NEXT },
293 { 0x000000010000ffeell, KEY_RIGHT },
294 { 0x000001000000ffeell, KEY_LEFT },
295 { 0x000000003d00ffeell, KEY_SELECT },
296 { 0x000100000000ffeell, KEY_VOLUMEUP },
297 { 0x010000000000ffeell, KEY_VOLUMEDOWN },
298 { 0x000000000100ffeell, KEY_MUTE },
299 /* 0xffdc iMON MCE VFD */
300 { 0x00010000ffffffeell, KEY_VOLUMEUP },
301 { 0x01000000ffffffeell, KEY_VOLUMEDOWN },
302 /* iMON Knob values */
303 { 0x000100ffffffffeell, KEY_VOLUMEUP },
304 { 0x010000ffffffffeell, KEY_VOLUMEDOWN },
305 { 0x000008ffffffffeell, KEY_MUTE },
306};
307
308/* to prevent races between open() and disconnect(), probing, etc */
309static DEFINE_MUTEX(driver_lock);
310
311/* Module bookkeeping bits */
312MODULE_AUTHOR(MOD_AUTHOR);
313MODULE_DESCRIPTION(MOD_DESC);
314MODULE_VERSION(MOD_VERSION);
315MODULE_LICENSE("GPL");
316MODULE_DEVICE_TABLE(usb, imon_usb_id_table);
317
318static bool debug;
319module_param(debug, bool, S_IRUGO | S_IWUSR);
320MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)");
321
322/* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */
323static int display_type;
324module_param(display_type, int, S_IRUGO);
325MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, "
326 "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)");
327
328static int pad_stabilize = 1;
329module_param(pad_stabilize, int, S_IRUGO | S_IWUSR);
330MODULE_PARM_DESC(pad_stabilize, "Apply stabilization algorithm to iMON PAD "
331 "presses in arrow key mode. 0=disable, 1=enable (default).");
332
333/*
334 * In certain use cases, mouse mode isn't really helpful, and could actually
335 * cause confusion, so allow disabling it when the IR device is open.
336 */
337static bool nomouse;
338module_param(nomouse, bool, S_IRUGO | S_IWUSR);
339MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is "
340 "open. 0=don't disable, 1=disable. (default: don't disable)");
341
342/* threshold at which a pad push registers as an arrow key in kbd mode */
343static int pad_thresh;
344module_param(pad_thresh, int, S_IRUGO | S_IWUSR);
345MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an "
346 "arrow key in kbd mode (default: 28)");
347
348
349static void free_imon_context(struct imon_context *ictx)
350{
351 struct device *dev = ictx->dev;
352
353 usb_free_urb(ictx->tx_urb);
354 usb_free_urb(ictx->rx_urb_intf0);
355 usb_free_urb(ictx->rx_urb_intf1);
356 kfree(ictx);
357
358 dev_dbg(dev, "%s: iMON context freed\n", __func__);
359}
360
361/**
362 * Called when the Display device (e.g. /dev/lcd0)
363 * is opened by the application.
364 */
365static int display_open(struct inode *inode, struct file *file)
366{
367 struct usb_interface *interface;
368 struct imon_context *ictx = NULL;
369 int subminor;
370 int retval = 0;
371
372 /* prevent races with disconnect */
373 mutex_lock(&driver_lock);
374
375 subminor = iminor(inode);
376 interface = usb_find_interface(&imon_driver, subminor);
377 if (!interface) {
378 pr_err("could not find interface for minor %d\n", subminor);
379 retval = -ENODEV;
380 goto exit;
381 }
382 ictx = usb_get_intfdata(interface);
383
384 if (!ictx) {
385 pr_err("no context found for minor %d\n", subminor);
386 retval = -ENODEV;
387 goto exit;
388 }
389
390 mutex_lock(&ictx->lock);
391
392 if (!ictx->display_supported) {
393 pr_err("display not supported by device\n");
394 retval = -ENODEV;
395 } else if (ictx->display_isopen) {
396 pr_err("display port is already open\n");
397 retval = -EBUSY;
398 } else {
399 ictx->display_isopen = true;
400 file->private_data = ictx;
401 dev_dbg(ictx->dev, "display port opened\n");
402 }
403
404 mutex_unlock(&ictx->lock);
405
406exit:
407 mutex_unlock(&driver_lock);
408 return retval;
409}
410
411/**
412 * Called when the display device (e.g. /dev/lcd0)
413 * is closed by the application.
414 */
415static int display_close(struct inode *inode, struct file *file)
416{
417 struct imon_context *ictx = NULL;
418 int retval = 0;
419
420 ictx = file->private_data;
421
422 if (!ictx) {
423 pr_err("no context for device\n");
424 return -ENODEV;
425 }
426
427 mutex_lock(&ictx->lock);
428
429 if (!ictx->display_supported) {
430 pr_err("display not supported by device\n");
431 retval = -ENODEV;
432 } else if (!ictx->display_isopen) {
433 pr_err("display is not open\n");
434 retval = -EIO;
435 } else {
436 ictx->display_isopen = false;
437 dev_dbg(ictx->dev, "display port closed\n");
438 if (!ictx->dev_present_intf0) {
439 /*
440 * Device disconnected before close and IR port is not
441 * open. If IR port is open, context will be deleted by
442 * ir_close.
443 */
444 mutex_unlock(&ictx->lock);
445 free_imon_context(ictx);
446 return retval;
447 }
448 }
449
450 mutex_unlock(&ictx->lock);
451 return retval;
452}
453
454/**
455 * Sends a packet to the device -- this function must be called
456 * with ictx->lock held.
457 */
458static int send_packet(struct imon_context *ictx)
459{
460 unsigned int pipe;
461 unsigned long timeout;
462 int interval = 0;
463 int retval = 0;
464 struct usb_ctrlrequest *control_req = NULL;
465
466 /* Check if we need to use control or interrupt urb */
467 if (!ictx->tx_control) {
468 pipe = usb_sndintpipe(ictx->usbdev_intf0,
469 ictx->tx_endpoint->bEndpointAddress);
470 interval = ictx->tx_endpoint->bInterval;
471
472 usb_fill_int_urb(ictx->tx_urb, ictx->usbdev_intf0, pipe,
473 ictx->usb_tx_buf,
474 sizeof(ictx->usb_tx_buf),
475 usb_tx_callback, ictx, interval);
476
477 ictx->tx_urb->actual_length = 0;
478 } else {
479 /* fill request into kmalloc'ed space: */
480 control_req = kmalloc(sizeof(struct usb_ctrlrequest),
481 GFP_KERNEL);
482 if (control_req == NULL)
483 return -ENOMEM;
484
485 /* setup packet is '21 09 0200 0001 0008' */
486 control_req->bRequestType = 0x21;
487 control_req->bRequest = 0x09;
488 control_req->wValue = cpu_to_le16(0x0200);
489 control_req->wIndex = cpu_to_le16(0x0001);
490 control_req->wLength = cpu_to_le16(0x0008);
491
492 /* control pipe is endpoint 0x00 */
493 pipe = usb_sndctrlpipe(ictx->usbdev_intf0, 0);
494
495 /* build the control urb */
496 usb_fill_control_urb(ictx->tx_urb, ictx->usbdev_intf0,
497 pipe, (unsigned char *)control_req,
498 ictx->usb_tx_buf,
499 sizeof(ictx->usb_tx_buf),
500 usb_tx_callback, ictx);
501 ictx->tx_urb->actual_length = 0;
502 }
503
504 init_completion(&ictx->tx.finished);
505 ictx->tx.busy = true;
506 smp_rmb(); /* ensure later readers know we're busy */
507
508 retval = usb_submit_urb(ictx->tx_urb, GFP_KERNEL);
509 if (retval) {
510 ictx->tx.busy = false;
511 smp_rmb(); /* ensure later readers know we're not busy */
512 pr_err("error submitting urb(%d)\n", retval);
513 } else {
514 /* Wait for transmission to complete (or abort) */
515 mutex_unlock(&ictx->lock);
516 retval = wait_for_completion_interruptible(
517 &ictx->tx.finished);
518 if (retval)
519 pr_err("task interrupted\n");
520 mutex_lock(&ictx->lock);
521
522 retval = ictx->tx.status;
523 if (retval)
524 pr_err("packet tx failed (%d)\n", retval);
525 }
526
527 kfree(control_req);
528
529 /*
530 * Induce a mandatory 5ms delay before returning, as otherwise,
531 * send_packet can get called so rapidly as to overwhelm the device,
532 * particularly on faster systems and/or those with quirky usb.
533 */
534 timeout = msecs_to_jiffies(5);
535 set_current_state(TASK_UNINTERRUPTIBLE);
536 schedule_timeout(timeout);
537
538 return retval;
539}
540
541/**
542 * Sends an associate packet to the iMON 2.4G.
543 *
544 * This might not be such a good idea, since it has an id collision with
545 * some versions of the "IR & VFD" combo. The only way to determine if it
546 * is an RF version is to look at the product description string. (Which
547 * we currently do not fetch).
548 */
549static int send_associate_24g(struct imon_context *ictx)
550{
551 int retval;
552 const unsigned char packet[8] = { 0x01, 0x00, 0x00, 0x00,
553 0x00, 0x00, 0x00, 0x20 };
554
555 if (!ictx) {
556 pr_err("no context for device\n");
557 return -ENODEV;
558 }
559
560 if (!ictx->dev_present_intf0) {
561 pr_err("no iMON device present\n");
562 return -ENODEV;
563 }
564
565 memcpy(ictx->usb_tx_buf, packet, sizeof(packet));
566 retval = send_packet(ictx);
567
568 return retval;
569}
570
571/**
572 * Sends packets to setup and show clock on iMON display
573 *
574 * Arguments: year - last 2 digits of year, month - 1..12,
575 * day - 1..31, dow - day of the week (0-Sun...6-Sat),
576 * hour - 0..23, minute - 0..59, second - 0..59
577 */
578static int send_set_imon_clock(struct imon_context *ictx,
579 unsigned int year, unsigned int month,
580 unsigned int day, unsigned int dow,
581 unsigned int hour, unsigned int minute,
582 unsigned int second)
583{
584 unsigned char clock_enable_pkt[IMON_CLOCK_ENABLE_PACKETS][8];
585 int retval = 0;
586 int i;
587
588 if (!ictx) {
589 pr_err("no context for device\n");
590 return -ENODEV;
591 }
592
593 switch (ictx->display_type) {
594 case IMON_DISPLAY_TYPE_LCD:
595 clock_enable_pkt[0][0] = 0x80;
596 clock_enable_pkt[0][1] = year;
597 clock_enable_pkt[0][2] = month-1;
598 clock_enable_pkt[0][3] = day;
599 clock_enable_pkt[0][4] = hour;
600 clock_enable_pkt[0][5] = minute;
601 clock_enable_pkt[0][6] = second;
602
603 clock_enable_pkt[1][0] = 0x80;
604 clock_enable_pkt[1][1] = 0;
605 clock_enable_pkt[1][2] = 0;
606 clock_enable_pkt[1][3] = 0;
607 clock_enable_pkt[1][4] = 0;
608 clock_enable_pkt[1][5] = 0;
609 clock_enable_pkt[1][6] = 0;
610
611 if (ictx->product == 0xffdc) {
612 clock_enable_pkt[0][7] = 0x50;
613 clock_enable_pkt[1][7] = 0x51;
614 } else {
615 clock_enable_pkt[0][7] = 0x88;
616 clock_enable_pkt[1][7] = 0x8a;
617 }
618
619 break;
620
621 case IMON_DISPLAY_TYPE_VFD:
622 clock_enable_pkt[0][0] = year;
623 clock_enable_pkt[0][1] = month-1;
624 clock_enable_pkt[0][2] = day;
625 clock_enable_pkt[0][3] = dow;
626 clock_enable_pkt[0][4] = hour;
627 clock_enable_pkt[0][5] = minute;
628 clock_enable_pkt[0][6] = second;
629 clock_enable_pkt[0][7] = 0x40;
630
631 clock_enable_pkt[1][0] = 0;
632 clock_enable_pkt[1][1] = 0;
633 clock_enable_pkt[1][2] = 1;
634 clock_enable_pkt[1][3] = 0;
635 clock_enable_pkt[1][4] = 0;
636 clock_enable_pkt[1][5] = 0;
637 clock_enable_pkt[1][6] = 0;
638 clock_enable_pkt[1][7] = 0x42;
639
640 break;
641
642 default:
643 return -ENODEV;
644 }
645
646 for (i = 0; i < IMON_CLOCK_ENABLE_PACKETS; i++) {
647 memcpy(ictx->usb_tx_buf, clock_enable_pkt[i], 8);
648 retval = send_packet(ictx);
649 if (retval) {
650 pr_err("send_packet failed for packet %d\n", i);
651 break;
652 }
653 }
654
655 return retval;
656}
657
658/**
659 * These are the sysfs functions to handle the association on the iMON 2.4G LT.
660 */
661static ssize_t show_associate_remote(struct device *d,
662 struct device_attribute *attr,
663 char *buf)
664{
665 struct imon_context *ictx = dev_get_drvdata(d);
666
667 if (!ictx)
668 return -ENODEV;
669
670 mutex_lock(&ictx->lock);
671 if (ictx->rf_isassociating)
672 strcpy(buf, "associating\n");
673 else
674 strcpy(buf, "closed\n");
675
676 dev_info(d, "Visit http://www.lirc.org/html/imon-24g.html for "
677 "instructions on how to associate your iMON 2.4G DT/LT "
678 "remote\n");
679 mutex_unlock(&ictx->lock);
680 return strlen(buf);
681}
682
683static ssize_t store_associate_remote(struct device *d,
684 struct device_attribute *attr,
685 const char *buf, size_t count)
686{
687 struct imon_context *ictx;
688
689 ictx = dev_get_drvdata(d);
690
691 if (!ictx)
692 return -ENODEV;
693
694 mutex_lock(&ictx->lock);
695 ictx->rf_isassociating = true;
696 send_associate_24g(ictx);
697 mutex_unlock(&ictx->lock);
698
699 return count;
700}
701
702/**
703 * sysfs functions to control internal imon clock
704 */
705static ssize_t show_imon_clock(struct device *d,
706 struct device_attribute *attr, char *buf)
707{
708 struct imon_context *ictx = dev_get_drvdata(d);
709 size_t len;
710
711 if (!ictx)
712 return -ENODEV;
713
714 mutex_lock(&ictx->lock);
715
716 if (!ictx->display_supported) {
717 len = snprintf(buf, PAGE_SIZE, "Not supported.");
718 } else {
719 len = snprintf(buf, PAGE_SIZE,
720 "To set the clock on your iMON display:\n"
721 "# date \"+%%y %%m %%d %%w %%H %%M %%S\" > imon_clock\n"
722 "%s", ictx->display_isopen ?
723 "\nNOTE: imon device must be closed\n" : "");
724 }
725
726 mutex_unlock(&ictx->lock);
727
728 return len;
729}
730
731static ssize_t store_imon_clock(struct device *d,
732 struct device_attribute *attr,
733 const char *buf, size_t count)
734{
735 struct imon_context *ictx = dev_get_drvdata(d);
736 ssize_t retval;
737 unsigned int year, month, day, dow, hour, minute, second;
738
739 if (!ictx)
740 return -ENODEV;
741
742 mutex_lock(&ictx->lock);
743
744 if (!ictx->display_supported) {
745 retval = -ENODEV;
746 goto exit;
747 } else if (ictx->display_isopen) {
748 retval = -EBUSY;
749 goto exit;
750 }
751
752 if (sscanf(buf, "%u %u %u %u %u %u %u", &year, &month, &day, &dow,
753 &hour, &minute, &second) != 7) {
754 retval = -EINVAL;
755 goto exit;
756 }
757
758 if ((month < 1 || month > 12) ||
759 (day < 1 || day > 31) || (dow > 6) ||
760 (hour > 23) || (minute > 59) || (second > 59)) {
761 retval = -EINVAL;
762 goto exit;
763 }
764
765 retval = send_set_imon_clock(ictx, year, month, day, dow,
766 hour, minute, second);
767 if (retval)
768 goto exit;
769
770 retval = count;
771exit:
772 mutex_unlock(&ictx->lock);
773
774 return retval;
775}
776
777
778static DEVICE_ATTR(imon_clock, S_IWUSR | S_IRUGO, show_imon_clock,
779 store_imon_clock);
780
781static DEVICE_ATTR(associate_remote, S_IWUSR | S_IRUGO, show_associate_remote,
782 store_associate_remote);
783
784static struct attribute *imon_display_sysfs_entries[] = {
785 &dev_attr_imon_clock.attr,
786 NULL
787};
788
789static struct attribute_group imon_display_attr_group = {
790 .attrs = imon_display_sysfs_entries
791};
792
793static struct attribute *imon_rf_sysfs_entries[] = {
794 &dev_attr_associate_remote.attr,
795 NULL
796};
797
798static struct attribute_group imon_rf_attr_group = {
799 .attrs = imon_rf_sysfs_entries
800};
801
802/**
803 * Writes data to the VFD. The iMON VFD is 2x16 characters
804 * and requires data in 5 consecutive USB interrupt packets,
805 * each packet but the last carrying 7 bytes.
806 *
807 * I don't know if the VFD board supports features such as
808 * scrolling, clearing rows, blanking, etc. so at
809 * the caller must provide a full screen of data. If fewer
810 * than 32 bytes are provided spaces will be appended to
811 * generate a full screen.
812 */
813static ssize_t vfd_write(struct file *file, const char *buf,
814 size_t n_bytes, loff_t *pos)
815{
816 int i;
817 int offset;
818 int seq;
819 int retval = 0;
820 struct imon_context *ictx;
821 const unsigned char vfd_packet6[] = {
822 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
823
824 ictx = file->private_data;
825 if (!ictx) {
826 pr_err("no context for device\n");
827 return -ENODEV;
828 }
829
830 mutex_lock(&ictx->lock);
831
832 if (!ictx->dev_present_intf0) {
833 pr_err("no iMON device present\n");
834 retval = -ENODEV;
835 goto exit;
836 }
837
838 if (n_bytes <= 0 || n_bytes > 32) {
839 pr_err("invalid payload size\n");
840 retval = -EINVAL;
841 goto exit;
842 }
843
844 if (copy_from_user(ictx->tx.data_buf, buf, n_bytes)) {
845 retval = -EFAULT;
846 goto exit;
847 }
848
849 /* Pad with spaces */
850 for (i = n_bytes; i < 32; ++i)
851 ictx->tx.data_buf[i] = ' ';
852
853 for (i = 32; i < 35; ++i)
854 ictx->tx.data_buf[i] = 0xFF;
855
856 offset = 0;
857 seq = 0;
858
859 do {
860 memcpy(ictx->usb_tx_buf, ictx->tx.data_buf + offset, 7);
861 ictx->usb_tx_buf[7] = (unsigned char) seq;
862
863 retval = send_packet(ictx);
864 if (retval) {
865 pr_err("send packet failed for packet #%d\n", seq / 2);
866 goto exit;
867 } else {
868 seq += 2;
869 offset += 7;
870 }
871
872 } while (offset < 35);
873
874 /* Send packet #6 */
875 memcpy(ictx->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6));
876 ictx->usb_tx_buf[7] = (unsigned char) seq;
877 retval = send_packet(ictx);
878 if (retval)
879 pr_err("send packet failed for packet #%d\n", seq / 2);
880
881exit:
882 mutex_unlock(&ictx->lock);
883
884 return (!retval) ? n_bytes : retval;
885}
886
887/**
888 * Writes data to the LCD. The iMON OEM LCD screen expects 8-byte
889 * packets. We accept data as 16 hexadecimal digits, followed by a
890 * newline (to make it easy to drive the device from a command-line
891 * -- even though the actual binary data is a bit complicated).
892 *
893 * The device itself is not a "traditional" text-mode display. It's
894 * actually a 16x96 pixel bitmap display. That means if you want to
895 * display text, you've got to have your own "font" and translate the
896 * text into bitmaps for display. This is really flexible (you can
897 * display whatever diacritics you need, and so on), but it's also
898 * a lot more complicated than most LCDs...
899 */
900static ssize_t lcd_write(struct file *file, const char *buf,
901 size_t n_bytes, loff_t *pos)
902{
903 int retval = 0;
904 struct imon_context *ictx;
905
906 ictx = file->private_data;
907 if (!ictx) {
908 pr_err("no context for device\n");
909 return -ENODEV;
910 }
911
912 mutex_lock(&ictx->lock);
913
914 if (!ictx->display_supported) {
915 pr_err("no iMON display present\n");
916 retval = -ENODEV;
917 goto exit;
918 }
919
920 if (n_bytes != 8) {
921 pr_err("invalid payload size: %d (expected 8)\n", (int)n_bytes);
922 retval = -EINVAL;
923 goto exit;
924 }
925
926 if (copy_from_user(ictx->usb_tx_buf, buf, 8)) {
927 retval = -EFAULT;
928 goto exit;
929 }
930
931 retval = send_packet(ictx);
932 if (retval) {
933 pr_err("send packet failed!\n");
934 goto exit;
935 } else {
936 dev_dbg(ictx->dev, "%s: write %d bytes to LCD\n",
937 __func__, (int) n_bytes);
938 }
939exit:
940 mutex_unlock(&ictx->lock);
941 return (!retval) ? n_bytes : retval;
942}
943
944/**
945 * Callback function for USB core API: transmit data
946 */
947static void usb_tx_callback(struct urb *urb)
948{
949 struct imon_context *ictx;
950
951 if (!urb)
952 return;
953 ictx = (struct imon_context *)urb->context;
954 if (!ictx)
955 return;
956
957 ictx->tx.status = urb->status;
958
959 /* notify waiters that write has finished */
960 ictx->tx.busy = false;
961 smp_rmb(); /* ensure later readers know we're not busy */
962 complete(&ictx->tx.finished);
963}
964
965/**
966 * report touchscreen input
967 */
968static void imon_touch_display_timeout(unsigned long data)
969{
970 struct imon_context *ictx = (struct imon_context *)data;
971
972 if (ictx->display_type != IMON_DISPLAY_TYPE_VGA)
973 return;
974
975 input_report_abs(ictx->touch, ABS_X, ictx->touch_x);
976 input_report_abs(ictx->touch, ABS_Y, ictx->touch_y);
977 input_report_key(ictx->touch, BTN_TOUCH, 0x00);
978 input_sync(ictx->touch);
979}
980
981/**
982 * iMON IR receivers support two different signal sets -- those used by
983 * the iMON remotes, and those used by the Windows MCE remotes (which is
984 * really just RC-6), but only one or the other at a time, as the signals
985 * are decoded onboard the receiver.
986 */
987int imon_ir_change_protocol(void *priv, u64 ir_type)
988{
989 int retval;
990 struct imon_context *ictx = priv;
991 struct device *dev = ictx->dev;
992 bool pad_mouse;
993 unsigned char ir_proto_packet[] = {
994 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
995
996 if (ir_type && !(ir_type & ictx->props->allowed_protos))
997 dev_warn(dev, "Looks like you're trying to use an IR protocol "
998 "this device does not support\n");
999
1000 switch (ir_type) {
1001 case IR_TYPE_RC6:
1002 dev_dbg(dev, "Configuring IR receiver for MCE protocol\n");
1003 ir_proto_packet[0] = 0x01;
1004 pad_mouse = false;
1005 break;
1006 case IR_TYPE_UNKNOWN:
1007 case IR_TYPE_OTHER:
1008 dev_dbg(dev, "Configuring IR receiver for iMON protocol\n");
1009 if (pad_stabilize && !nomouse)
1010 pad_mouse = true;
1011 else {
1012 dev_dbg(dev, "PAD stabilize functionality disabled\n");
1013 pad_mouse = false;
1014 }
1015 /* ir_proto_packet[0] = 0x00; // already the default */
1016 ir_type = IR_TYPE_OTHER;
1017 break;
1018 default:
1019 dev_warn(dev, "Unsupported IR protocol specified, overriding "
1020 "to iMON IR protocol\n");
1021 if (pad_stabilize && !nomouse)
1022 pad_mouse = true;
1023 else {
1024 dev_dbg(dev, "PAD stabilize functionality disabled\n");
1025 pad_mouse = false;
1026 }
1027 /* ir_proto_packet[0] = 0x00; // already the default */
1028 ir_type = IR_TYPE_OTHER;
1029 break;
1030 }
1031
1032 memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
1033
1034 retval = send_packet(ictx);
1035 if (retval)
1036 goto out;
1037
1038 ictx->ir_type = ir_type;
1039 ictx->pad_mouse = pad_mouse;
1040
1041out:
1042 return retval;
1043}
1044
1045static inline int tv2int(const struct timeval *a, const struct timeval *b)
1046{
1047 int usecs = 0;
1048 int sec = 0;
1049
1050 if (b->tv_usec > a->tv_usec) {
1051 usecs = 1000000;
1052 sec--;
1053 }
1054
1055 usecs += a->tv_usec - b->tv_usec;
1056
1057 sec += a->tv_sec - b->tv_sec;
1058 sec *= 1000;
1059 usecs /= 1000;
1060 sec += usecs;
1061
1062 if (sec < 0)
1063 sec = 1000;
1064
1065 return sec;
1066}
1067
1068/**
1069 * The directional pad behaves a bit differently, depending on whether this is
1070 * one of the older ffdc devices or a newer device. Newer devices appear to
1071 * have a higher resolution matrix for more precise mouse movement, but it
1072 * makes things overly sensitive in keyboard mode, so we do some interesting
1073 * contortions to make it less touchy. Older devices run through the same
1074 * routine with shorter timeout and a smaller threshold.
1075 */
1076static int stabilize(int a, int b, u16 timeout, u16 threshold)
1077{
1078 struct timeval ct;
1079 static struct timeval prev_time = {0, 0};
1080 static struct timeval hit_time = {0, 0};
1081 static int x, y, prev_result, hits;
1082 int result = 0;
1083 int msec, msec_hit;
1084
1085 do_gettimeofday(&ct);
1086 msec = tv2int(&ct, &prev_time);
1087 msec_hit = tv2int(&ct, &hit_time);
1088
1089 if (msec > 100) {
1090 x = 0;
1091 y = 0;
1092 hits = 0;
1093 }
1094
1095 x += a;
1096 y += b;
1097
1098 prev_time = ct;
1099
1100 if (abs(x) > threshold || abs(y) > threshold) {
1101 if (abs(y) > abs(x))
1102 result = (y > 0) ? 0x7F : 0x80;
1103 else
1104 result = (x > 0) ? 0x7F00 : 0x8000;
1105
1106 x = 0;
1107 y = 0;
1108
1109 if (result == prev_result) {
1110 hits++;
1111
1112 if (hits > 3) {
1113 switch (result) {
1114 case 0x7F:
1115 y = 17 * threshold / 30;
1116 break;
1117 case 0x80:
1118 y -= 17 * threshold / 30;
1119 break;
1120 case 0x7F00:
1121 x = 17 * threshold / 30;
1122 break;
1123 case 0x8000:
1124 x -= 17 * threshold / 30;
1125 break;
1126 }
1127 }
1128
1129 if (hits == 2 && msec_hit < timeout) {
1130 result = 0;
1131 hits = 1;
1132 }
1133 } else {
1134 prev_result = result;
1135 hits = 1;
1136 hit_time = ct;
1137 }
1138 }
1139
1140 return result;
1141}
1142
1143static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 scancode)
1144{
1145 u32 keycode;
1146 u32 release;
1147 bool is_release_code = false;
1148
1149 /* Look for the initial press of a button */
1150 keycode = ir_g_keycode_from_table(ictx->rdev, scancode);
1151 ictx->rc_toggle = 0x0;
1152 ictx->rc_scancode = scancode;
1153
1154 /* Look for the release of a button */
1155 if (keycode == KEY_RESERVED) {
1156 release = scancode & ~0x4000;
1157 keycode = ir_g_keycode_from_table(ictx->rdev, release);
1158 if (keycode != KEY_RESERVED)
1159 is_release_code = true;
1160 }
1161
1162 ictx->release_code = is_release_code;
1163
1164 return keycode;
1165}
1166
1167static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 scancode)
1168{
1169 u32 keycode;
1170
1171#define MCE_KEY_MASK 0x7000
1172#define MCE_TOGGLE_BIT 0x8000
1173
1174 /*
1175 * On some receivers, mce keys decode to 0x8000f04xx and 0x8000f84xx
1176 * (the toggle bit flipping between alternating key presses), while
1177 * on other receivers, we see 0x8000f74xx and 0x8000ff4xx. To keep
1178 * the table trim, we always or in the bits to look up 0x8000ff4xx,
1179 * but we can't or them into all codes, as some keys are decoded in
1180 * a different way w/o the same use of the toggle bit...
1181 */
1182 if (scancode & 0x80000000)
1183 scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT;
1184
1185 ictx->rc_scancode = scancode;
1186 keycode = ir_g_keycode_from_table(ictx->rdev, scancode);
1187
1188 /* not used in mce mode, but make sure we know its false */
1189 ictx->release_code = false;
1190
1191 return keycode;
1192}
1193
1194static u32 imon_panel_key_lookup(u64 code)
1195{
1196 int i;
1197 u32 keycode = KEY_RESERVED;
1198
1199 for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) {
1200 if (imon_panel_key_table[i].hw_code == (code | 0xffee)) {
1201 keycode = imon_panel_key_table[i].keycode;
1202 break;
1203 }
1204 }
1205
1206 return keycode;
1207}
1208
1209static bool imon_mouse_event(struct imon_context *ictx,
1210 unsigned char *buf, int len)
1211{
1212 char rel_x = 0x00, rel_y = 0x00;
1213 u8 right_shift = 1;
1214 bool mouse_input = true;
1215 int dir = 0;
1216 unsigned long flags;
1217
1218 spin_lock_irqsave(&ictx->kc_lock, flags);
1219
1220 /* newer iMON device PAD or mouse button */
1221 if (ictx->product != 0xffdc && (buf[0] & 0x01) && len == 5) {
1222 rel_x = buf[2];
1223 rel_y = buf[3];
1224 right_shift = 1;
1225 /* 0xffdc iMON PAD or mouse button input */
1226 } else if (ictx->product == 0xffdc && (buf[0] & 0x40) &&
1227 !((buf[1] & 0x01) || ((buf[1] >> 2) & 0x01))) {
1228 rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 |
1229 (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6;
1230 if (buf[0] & 0x02)
1231 rel_x |= ~0x0f;
1232 rel_x = rel_x + rel_x / 2;
1233 rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 |
1234 (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6;
1235 if (buf[0] & 0x01)
1236 rel_y |= ~0x0f;
1237 rel_y = rel_y + rel_y / 2;
1238 right_shift = 2;
1239 /* some ffdc devices decode mouse buttons differently... */
1240 } else if (ictx->product == 0xffdc && (buf[0] == 0x68)) {
1241 right_shift = 2;
1242 /* ch+/- buttons, which we use for an emulated scroll wheel */
1243 } else if (ictx->kc == KEY_CHANNELUP && (buf[2] & 0x40) != 0x40) {
1244 dir = 1;
1245 } else if (ictx->kc == KEY_CHANNELDOWN && (buf[2] & 0x40) != 0x40) {
1246 dir = -1;
1247 } else
1248 mouse_input = false;
1249
1250 spin_unlock_irqrestore(&ictx->kc_lock, flags);
1251
1252 if (mouse_input) {
1253 dev_dbg(ictx->dev, "sending mouse data via input subsystem\n");
1254
1255 if (dir) {
1256 input_report_rel(ictx->idev, REL_WHEEL, dir);
1257 } else if (rel_x || rel_y) {
1258 input_report_rel(ictx->idev, REL_X, rel_x);
1259 input_report_rel(ictx->idev, REL_Y, rel_y);
1260 } else {
1261 input_report_key(ictx->idev, BTN_LEFT, buf[1] & 0x1);
1262 input_report_key(ictx->idev, BTN_RIGHT,
1263 buf[1] >> right_shift & 0x1);
1264 }
1265 input_sync(ictx->idev);
1266 spin_lock_irqsave(&ictx->kc_lock, flags);
1267 ictx->last_keycode = ictx->kc;
1268 spin_unlock_irqrestore(&ictx->kc_lock, flags);
1269 }
1270
1271 return mouse_input;
1272}
1273
1274static void imon_touch_event(struct imon_context *ictx, unsigned char *buf)
1275{
1276 mod_timer(&ictx->ttimer, jiffies + TOUCH_TIMEOUT);
1277 ictx->touch_x = (buf[0] << 4) | (buf[1] >> 4);
1278 ictx->touch_y = 0xfff - ((buf[2] << 4) | (buf[1] & 0xf));
1279 input_report_abs(ictx->touch, ABS_X, ictx->touch_x);
1280 input_report_abs(ictx->touch, ABS_Y, ictx->touch_y);
1281 input_report_key(ictx->touch, BTN_TOUCH, 0x01);
1282 input_sync(ictx->touch);
1283}
1284
1285static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
1286{
1287 int dir = 0;
1288 char rel_x = 0x00, rel_y = 0x00;
1289 u16 timeout, threshold;
1290 u32 scancode = KEY_RESERVED;
1291 unsigned long flags;
1292
1293 /*
1294 * The imon directional pad functions more like a touchpad. Bytes 3 & 4
1295 * contain a position coordinate (x,y), with each component ranging
1296 * from -14 to 14. We want to down-sample this to only 4 discrete values
1297 * for up/down/left/right arrow keys. Also, when you get too close to
1298 * diagonals, it has a tendancy to jump back and forth, so lets try to
1299 * ignore when they get too close.
1300 */
1301 if (ictx->product != 0xffdc) {
1302 /* first, pad to 8 bytes so it conforms with everything else */
1303 buf[5] = buf[6] = buf[7] = 0;
1304 timeout = 500; /* in msecs */
1305 /* (2*threshold) x (2*threshold) square */
1306 threshold = pad_thresh ? pad_thresh : 28;
1307 rel_x = buf[2];
1308 rel_y = buf[3];
1309
1310 if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) {
1311 if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) {
1312 dir = stabilize((int)rel_x, (int)rel_y,
1313 timeout, threshold);
1314 if (!dir) {
1315 spin_lock_irqsave(&ictx->kc_lock,
1316 flags);
1317 ictx->kc = KEY_UNKNOWN;
1318 spin_unlock_irqrestore(&ictx->kc_lock,
1319 flags);
1320 return;
1321 }
1322 buf[2] = dir & 0xFF;
1323 buf[3] = (dir >> 8) & 0xFF;
1324 scancode = be32_to_cpu(*((u32 *)buf));
1325 }
1326 } else {
1327 /*
1328 * Hack alert: instead of using keycodes, we have
1329 * to use hard-coded scancodes here...
1330 */
1331 if (abs(rel_y) > abs(rel_x)) {
1332 buf[2] = (rel_y > 0) ? 0x7F : 0x80;
1333 buf[3] = 0;
1334 if (rel_y > 0)
1335 scancode = 0x01007f00; /* KEY_DOWN */
1336 else
1337 scancode = 0x01008000; /* KEY_UP */
1338 } else {
1339 buf[2] = 0;
1340 buf[3] = (rel_x > 0) ? 0x7F : 0x80;
1341 if (rel_x > 0)
1342 scancode = 0x0100007f; /* KEY_RIGHT */
1343 else
1344 scancode = 0x01000080; /* KEY_LEFT */
1345 }
1346 }
1347
1348 /*
1349 * Handle on-board decoded pad events for e.g. older VFD/iMON-Pad
1350 * device (15c2:ffdc). The remote generates various codes from
1351 * 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button generates
1352 * 0x688301b7 and the right one 0x688481b7. All other keys generate
1353 * 0x2nnnnnnn. Position coordinate is encoded in buf[1] and buf[2] with
1354 * reversed endianess. Extract direction from buffer, rotate endianess,
1355 * adjust sign and feed the values into stabilize(). The resulting codes
1356 * will be 0x01008000, 0x01007F00, which match the newer devices.
1357 */
1358 } else {
1359 timeout = 10; /* in msecs */
1360 /* (2*threshold) x (2*threshold) square */
1361 threshold = pad_thresh ? pad_thresh : 15;
1362
1363 /* buf[1] is x */
1364 rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 |
1365 (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6;
1366 if (buf[0] & 0x02)
1367 rel_x |= ~0x10+1;
1368 /* buf[2] is y */
1369 rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 |
1370 (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6;
1371 if (buf[0] & 0x01)
1372 rel_y |= ~0x10+1;
1373
1374 buf[0] = 0x01;
1375 buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0;
1376
1377 if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) {
1378 dir = stabilize((int)rel_x, (int)rel_y,
1379 timeout, threshold);
1380 if (!dir) {
1381 spin_lock_irqsave(&ictx->kc_lock, flags);
1382 ictx->kc = KEY_UNKNOWN;
1383 spin_unlock_irqrestore(&ictx->kc_lock, flags);
1384 return;
1385 }
1386 buf[2] = dir & 0xFF;
1387 buf[3] = (dir >> 8) & 0xFF;
1388 scancode = be32_to_cpu(*((u32 *)buf));
1389 } else {
1390 /*
1391 * Hack alert: instead of using keycodes, we have
1392 * to use hard-coded scancodes here...
1393 */
1394 if (abs(rel_y) > abs(rel_x)) {
1395 buf[2] = (rel_y > 0) ? 0x7F : 0x80;
1396 buf[3] = 0;
1397 if (rel_y > 0)
1398 scancode = 0x01007f00; /* KEY_DOWN */
1399 else
1400 scancode = 0x01008000; /* KEY_UP */
1401 } else {
1402 buf[2] = 0;
1403 buf[3] = (rel_x > 0) ? 0x7F : 0x80;
1404 if (rel_x > 0)
1405 scancode = 0x0100007f; /* KEY_RIGHT */
1406 else
1407 scancode = 0x01000080; /* KEY_LEFT */
1408 }
1409 }
1410 }
1411
1412 if (scancode) {
1413 spin_lock_irqsave(&ictx->kc_lock, flags);
1414 ictx->kc = imon_remote_key_lookup(ictx, scancode);
1415 spin_unlock_irqrestore(&ictx->kc_lock, flags);
1416 }
1417}
1418
1419/**
1420 * figure out if these is a press or a release. We don't actually
1421 * care about repeats, as those will be auto-generated within the IR
1422 * subsystem for repeating scancodes.
1423 */
1424static int imon_parse_press_type(struct imon_context *ictx,
1425 unsigned char *buf, u8 ktype)
1426{
1427 int press_type = 0;
1428 unsigned long flags;
1429
1430 spin_lock_irqsave(&ictx->kc_lock, flags);
1431
1432 /* key release of 0x02XXXXXX key */
1433 if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00)
1434 ictx->kc = ictx->last_keycode;
1435
1436 /* mouse button release on (some) 0xffdc devices */
1437 else if (ictx->kc == KEY_RESERVED && buf[0] == 0x68 && buf[1] == 0x82 &&
1438 buf[2] == 0x81 && buf[3] == 0xb7)
1439 ictx->kc = ictx->last_keycode;
1440
1441 /* mouse button release on (some other) 0xffdc devices */
1442 else if (ictx->kc == KEY_RESERVED && buf[0] == 0x01 && buf[1] == 0x00 &&
1443 buf[2] == 0x81 && buf[3] == 0xb7)
1444 ictx->kc = ictx->last_keycode;
1445
1446 /* mce-specific button handling, no keyup events */
1447 else if (ktype == IMON_KEY_MCE) {
1448 ictx->rc_toggle = buf[2];
1449 press_type = 1;
1450
1451 /* incoherent or irrelevant data */
1452 } else if (ictx->kc == KEY_RESERVED)
1453 press_type = -EINVAL;
1454
1455 /* key release of 0xXXXXXXb7 key */
1456 else if (ictx->release_code)
1457 press_type = 0;
1458
1459 /* this is a button press */
1460 else
1461 press_type = 1;
1462
1463 spin_unlock_irqrestore(&ictx->kc_lock, flags);
1464
1465 return press_type;
1466}
1467
1468/**
1469 * Process the incoming packet
1470 */
1471static void imon_incoming_packet(struct imon_context *ictx,
1472 struct urb *urb, int intf)
1473{
1474 int len = urb->actual_length;
1475 unsigned char *buf = urb->transfer_buffer;
1476 struct device *dev = ictx->dev;
1477 unsigned long flags;
1478 u32 kc;
1479 bool norelease = false;
1480 int i;
1481 u64 scancode;
1482 int press_type = 0;
1483 int msec;
1484 struct timeval t;
1485 static struct timeval prev_time = { 0, 0 };
1486 u8 ktype;
1487
1488 /* filter out junk data on the older 0xffdc imon devices */
1489 if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff))
1490 return;
1491
1492 /* Figure out what key was pressed */
1493 if (len == 8 && buf[7] == 0xee) {
1494 scancode = be64_to_cpu(*((u64 *)buf));
1495 ktype = IMON_KEY_PANEL;
1496 kc = imon_panel_key_lookup(scancode);
1497 } else {
1498 scancode = be32_to_cpu(*((u32 *)buf));
1499 if (ictx->ir_type == IR_TYPE_RC6) {
1500 ktype = IMON_KEY_IMON;
1501 if (buf[0] == 0x80)
1502 ktype = IMON_KEY_MCE;
1503 kc = imon_mce_key_lookup(ictx, scancode);
1504 } else {
1505 ktype = IMON_KEY_IMON;
1506 kc = imon_remote_key_lookup(ictx, scancode);
1507 }
1508 }
1509
1510 spin_lock_irqsave(&ictx->kc_lock, flags);
1511 /* keyboard/mouse mode toggle button */
1512 if (kc == KEY_KEYBOARD && !ictx->release_code) {
1513 ictx->last_keycode = kc;
1514 if (!nomouse) {
1515 ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1;
1516 dev_dbg(dev, "toggling to %s mode\n",
1517 ictx->pad_mouse ? "mouse" : "keyboard");
1518 spin_unlock_irqrestore(&ictx->kc_lock, flags);
1519 return;
1520 } else {
1521 ictx->pad_mouse = 0;
1522 dev_dbg(dev, "mouse mode disabled, passing key value\n");
1523 }
1524 }
1525
1526 ictx->kc = kc;
1527 spin_unlock_irqrestore(&ictx->kc_lock, flags);
1528
1529 /* send touchscreen events through input subsystem if touchpad data */
1530 if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 &&
1531 buf[7] == 0x86) {
1532 imon_touch_event(ictx, buf);
1533 return;
1534
1535 /* look for mouse events with pad in mouse mode */
1536 } else if (ictx->pad_mouse) {
1537 if (imon_mouse_event(ictx, buf, len))
1538 return;
1539 }
1540
1541 /* Now for some special handling to convert pad input to arrow keys */
1542 if (((len == 5) && (buf[0] == 0x01) && (buf[4] == 0x00)) ||
1543 ((len == 8) && (buf[0] & 0x40) &&
1544 !(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) {
1545 len = 8;
1546 imon_pad_to_keys(ictx, buf);
1547 norelease = true;
1548 }
1549
1550 if (debug) {
1551 printk(KERN_INFO "intf%d decoded packet: ", intf);
1552 for (i = 0; i < len; ++i)
1553 printk("%02x ", buf[i]);
1554 printk("\n");
1555 }
1556
1557 press_type = imon_parse_press_type(ictx, buf, ktype);
1558 if (press_type < 0)
1559 goto not_input_data;
1560
1561 spin_lock_irqsave(&ictx->kc_lock, flags);
1562 if (ictx->kc == KEY_UNKNOWN)
1563 goto unknown_key;
1564 spin_unlock_irqrestore(&ictx->kc_lock, flags);
1565
1566 if (ktype != IMON_KEY_PANEL) {
1567 if (press_type == 0)
1568 ir_keyup(ictx->rdev);
1569 else {
1570 ir_keydown(ictx->rdev, ictx->rc_scancode, ictx->rc_toggle);
1571 spin_lock_irqsave(&ictx->kc_lock, flags);
1572 ictx->last_keycode = ictx->kc;
1573 spin_unlock_irqrestore(&ictx->kc_lock, flags);
1574 }
1575 return;
1576 }
1577
1578 /* Only panel type events left to process now */
1579 spin_lock_irqsave(&ictx->kc_lock, flags);
1580
1581 /* KEY_MUTE repeats from knob need to be suppressed */
1582 if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) {
1583 do_gettimeofday(&t);
1584 msec = tv2int(&t, &prev_time);
1585 prev_time = t;
1586 if (msec < ictx->idev->rep[REP_DELAY]) {
1587 spin_unlock_irqrestore(&ictx->kc_lock, flags);
1588 return;
1589 }
1590 }
1591 kc = ictx->kc;
1592
1593 spin_unlock_irqrestore(&ictx->kc_lock, flags);
1594
1595 input_report_key(ictx->idev, kc, press_type);
1596 input_sync(ictx->idev);
1597
1598 /* panel keys don't generate a release */
1599 input_report_key(ictx->idev, kc, 0);
1600 input_sync(ictx->idev);
1601
1602 ictx->last_keycode = kc;
1603
1604 return;
1605
1606unknown_key:
1607 spin_unlock_irqrestore(&ictx->kc_lock, flags);
1608 dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__,
1609 (long long)scancode);
1610 return;
1611
1612not_input_data:
1613 if (len != 8) {
1614 dev_warn(dev, "imon %s: invalid incoming packet "
1615 "size (len = %d, intf%d)\n", __func__, len, intf);
1616 return;
1617 }
1618
1619 /* iMON 2.4G associate frame */
1620 if (buf[0] == 0x00 &&
1621 buf[2] == 0xFF && /* REFID */
1622 buf[3] == 0xFF &&
1623 buf[4] == 0xFF &&
1624 buf[5] == 0xFF && /* iMON 2.4G */
1625 ((buf[6] == 0x4E && buf[7] == 0xDF) || /* LT */
1626 (buf[6] == 0x5E && buf[7] == 0xDF))) { /* DT */
1627 dev_warn(dev, "%s: remote associated refid=%02X\n",
1628 __func__, buf[1]);
1629 ictx->rf_isassociating = false;
1630 }
1631}
1632
1633/**
1634 * Callback function for USB core API: receive data
1635 */
1636static void usb_rx_callback_intf0(struct urb *urb)
1637{
1638 struct imon_context *ictx;
1639 int intfnum = 0;
1640
1641 if (!urb)
1642 return;
1643
1644 ictx = (struct imon_context *)urb->context;
1645 if (!ictx)
1646 return;
1647
1648 switch (urb->status) {
1649 case -ENOENT: /* usbcore unlink successful! */
1650 return;
1651
1652 case -ESHUTDOWN: /* transport endpoint was shut down */
1653 break;
1654
1655 case 0:
1656 imon_incoming_packet(ictx, urb, intfnum);
1657 break;
1658
1659 default:
1660 dev_warn(ictx->dev, "imon %s: status(%d): ignored\n",
1661 __func__, urb->status);
1662 break;
1663 }
1664
1665 usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC);
1666}
1667
1668static void usb_rx_callback_intf1(struct urb *urb)
1669{
1670 struct imon_context *ictx;
1671 int intfnum = 1;
1672
1673 if (!urb)
1674 return;
1675
1676 ictx = (struct imon_context *)urb->context;
1677 if (!ictx)
1678 return;
1679
1680 switch (urb->status) {
1681 case -ENOENT: /* usbcore unlink successful! */
1682 return;
1683
1684 case -ESHUTDOWN: /* transport endpoint was shut down */
1685 break;
1686
1687 case 0:
1688 imon_incoming_packet(ictx, urb, intfnum);
1689 break;
1690
1691 default:
1692 dev_warn(ictx->dev, "imon %s: status(%d): ignored\n",
1693 __func__, urb->status);
1694 break;
1695 }
1696
1697 usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC);
1698}
1699
1700/*
1701 * The 0x15c2:0xffdc device ID was used for umpteen different imon
1702 * devices, and all of them constantly spew interrupts, even when there
1703 * is no actual data to report. However, byte 6 of this buffer looks like
1704 * its unique across device variants, so we're trying to key off that to
1705 * figure out which display type (if any) and what IR protocol the device
1706 * actually supports. These devices have their IR protocol hard-coded into
1707 * their firmware, they can't be changed on the fly like the newer hardware.
1708 */
1709static void imon_get_ffdc_type(struct imon_context *ictx)
1710{
1711 u8 ffdc_cfg_byte = ictx->usb_rx_buf[6];
1712 u8 detected_display_type = IMON_DISPLAY_TYPE_NONE;
1713 u64 allowed_protos = IR_TYPE_OTHER;
1714
1715 switch (ffdc_cfg_byte) {
1716 /* iMON Knob, no display, iMON IR + vol knob */
1717 case 0x21:
1718 dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR");
1719 ictx->display_supported = false;
1720 break;
1721 /* iMON 2.4G LT (usb stick), no display, iMON RF */
1722 case 0x4e:
1723 dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF");
1724 ictx->display_supported = false;
1725 ictx->rf_device = true;
1726 break;
1727 /* iMON VFD, no IR (does have vol knob tho) */
1728 case 0x35:
1729 dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR");
1730 detected_display_type = IMON_DISPLAY_TYPE_VFD;
1731 break;
1732 /* iMON VFD, iMON IR */
1733 case 0x24:
1734 case 0x85:
1735 dev_info(ictx->dev, "0xffdc iMON VFD, iMON IR");
1736 detected_display_type = IMON_DISPLAY_TYPE_VFD;
1737 break;
1738 /* iMON VFD, MCE IR */
1739 case 0x9e:
1740 dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR");
1741 detected_display_type = IMON_DISPLAY_TYPE_VFD;
1742 allowed_protos = IR_TYPE_RC6;
1743 break;
1744 /* iMON LCD, MCE IR */
1745 case 0x9f:
1746 dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
1747 detected_display_type = IMON_DISPLAY_TYPE_LCD;
1748 allowed_protos = IR_TYPE_RC6;
1749 break;
1750 default:
1751 dev_info(ictx->dev, "Unknown 0xffdc device, "
1752 "defaulting to VFD and iMON IR");
1753 detected_display_type = IMON_DISPLAY_TYPE_VFD;
1754 break;
1755 }
1756
1757 printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte);
1758
1759 ictx->display_type = detected_display_type;
1760 ictx->props->allowed_protos = allowed_protos;
1761 ictx->ir_type = allowed_protos;
1762}
1763
1764static void imon_set_display_type(struct imon_context *ictx)
1765{
1766 u8 configured_display_type = IMON_DISPLAY_TYPE_VFD;
1767
1768 /*
1769 * Try to auto-detect the type of display if the user hasn't set
1770 * it by hand via the display_type modparam. Default is VFD.
1771 */
1772
1773 if (display_type == IMON_DISPLAY_TYPE_AUTO) {
1774 switch (ictx->product) {
1775 case 0xffdc:
1776 /* set in imon_get_ffdc_type() */
1777 configured_display_type = ictx->display_type;
1778 break;
1779 case 0x0034:
1780 case 0x0035:
1781 configured_display_type = IMON_DISPLAY_TYPE_VGA;
1782 break;
1783 case 0x0038:
1784 case 0x0039:
1785 case 0x0045:
1786 configured_display_type = IMON_DISPLAY_TYPE_LCD;
1787 break;
1788 case 0x003c:
1789 case 0x0041:
1790 case 0x0042:
1791 case 0x0043:
1792 configured_display_type = IMON_DISPLAY_TYPE_NONE;
1793 ictx->display_supported = false;
1794 break;
1795 case 0x0036:
1796 case 0x0044:
1797 default:
1798 configured_display_type = IMON_DISPLAY_TYPE_VFD;
1799 break;
1800 }
1801 } else {
1802 configured_display_type = display_type;
1803 if (display_type == IMON_DISPLAY_TYPE_NONE)
1804 ictx->display_supported = false;
1805 else
1806 ictx->display_supported = true;
1807 dev_info(ictx->dev, "%s: overriding display type to %d via "
1808 "modparam\n", __func__, display_type);
1809 }
1810
1811 ictx->display_type = configured_display_type;
1812}
1813
1814static struct input_dev *imon_init_rdev(struct imon_context *ictx)
1815{
1816 struct input_dev *rdev;
1817 struct ir_dev_props *props;
1818 int ret;
1819 char *ir_codes = NULL;
1820 const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00,
1821 0x00, 0x00, 0x00, 0x88 };
1822
1823 rdev = input_allocate_device();
1824 props = kzalloc(sizeof(*props), GFP_KERNEL);
1825 if (!rdev || !props) {
1826 dev_err(ictx->dev, "remote control dev allocation failed\n");
1827 goto out;
1828 }
1829
1830 snprintf(ictx->name_rdev, sizeof(ictx->name_rdev),
1831 "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product);
1832 usb_make_path(ictx->usbdev_intf0, ictx->phys_rdev,
1833 sizeof(ictx->phys_rdev));
1834 strlcat(ictx->phys_rdev, "/input0", sizeof(ictx->phys_rdev));
1835
1836 rdev->name = ictx->name_rdev;
1837 rdev->phys = ictx->phys_rdev;
1838 usb_to_input_id(ictx->usbdev_intf0, &rdev->id);
1839 rdev->dev.parent = ictx->dev;
1840 rdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
1841 input_set_drvdata(rdev, ictx);
1842
1843 props->priv = ictx;
1844 props->driver_type = RC_DRIVER_SCANCODE;
1845 props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; /* iMON PAD or MCE */
1846 props->change_protocol = imon_ir_change_protocol;
1847 ictx->props = props;
1848
1849 /* Enable front-panel buttons and/or knobs */
1850 memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet));
1851 ret = send_packet(ictx);
1852 /* Not fatal, but warn about it */
1853 if (ret)
1854 dev_info(ictx->dev, "panel buttons/knobs setup failed\n");
1855
1856 if (ictx->product == 0xffdc)
1857 imon_get_ffdc_type(ictx);
1858
1859 imon_set_display_type(ictx);
1860
1861 if (ictx->ir_type == IR_TYPE_RC6)
1862 ir_codes = RC_MAP_IMON_MCE;
1863 else
1864 ir_codes = RC_MAP_IMON_PAD;
1865
1866 ret = ir_input_register(rdev, ir_codes, props, MOD_NAME);
1867 if (ret < 0) {
1868 dev_err(ictx->dev, "remote input dev register failed\n");
1869 goto out;
1870 }
1871
1872 return rdev;
1873
1874out:
1875 kfree(props);
1876 input_free_device(rdev);
1877 return NULL;
1878}
1879
1880static struct input_dev *imon_init_idev(struct imon_context *ictx)
1881{
1882 struct input_dev *idev;
1883 int ret, i;
1884
1885 idev = input_allocate_device();
1886 if (!idev) {
1887 dev_err(ictx->dev, "input dev allocation failed\n");
1888 goto out;
1889 }
1890
1891 snprintf(ictx->name_idev, sizeof(ictx->name_idev),
1892 "iMON Panel, Knob and Mouse(%04x:%04x)",
1893 ictx->vendor, ictx->product);
1894 idev->name = ictx->name_idev;
1895
1896 usb_make_path(ictx->usbdev_intf0, ictx->phys_idev,
1897 sizeof(ictx->phys_idev));
1898 strlcat(ictx->phys_idev, "/input1", sizeof(ictx->phys_idev));
1899 idev->phys = ictx->phys_idev;
1900
1901 idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_REL);
1902
1903 idev->keybit[BIT_WORD(BTN_MOUSE)] =
1904 BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);
1905 idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) |
1906 BIT_MASK(REL_WHEEL);
1907
1908 /* panel and/or knob code support */
1909 for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) {
1910 u32 kc = imon_panel_key_table[i].keycode;
1911 __set_bit(kc, idev->keybit);
1912 }
1913
1914 usb_to_input_id(ictx->usbdev_intf0, &idev->id);
1915 idev->dev.parent = ictx->dev;
1916 input_set_drvdata(idev, ictx);
1917
1918 ret = input_register_device(idev);
1919 if (ret < 0) {
1920 dev_err(ictx->dev, "input dev register failed\n");
1921 goto out;
1922 }
1923
1924 return idev;
1925
1926out:
1927 input_free_device(idev);
1928 return NULL;
1929}
1930
1931static struct input_dev *imon_init_touch(struct imon_context *ictx)
1932{
1933 struct input_dev *touch;
1934 int ret;
1935
1936 touch = input_allocate_device();
1937 if (!touch) {
1938 dev_err(ictx->dev, "touchscreen input dev allocation failed\n");
1939 goto touch_alloc_failed;
1940 }
1941
1942 snprintf(ictx->name_touch, sizeof(ictx->name_touch),
1943 "iMON USB Touchscreen (%04x:%04x)",
1944 ictx->vendor, ictx->product);
1945 touch->name = ictx->name_touch;
1946
1947 usb_make_path(ictx->usbdev_intf1, ictx->phys_touch,
1948 sizeof(ictx->phys_touch));
1949 strlcat(ictx->phys_touch, "/input2", sizeof(ictx->phys_touch));
1950 touch->phys = ictx->phys_touch;
1951
1952 touch->evbit[0] =
1953 BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
1954 touch->keybit[BIT_WORD(BTN_TOUCH)] =
1955 BIT_MASK(BTN_TOUCH);
1956 input_set_abs_params(touch, ABS_X,
1957 0x00, 0xfff, 0, 0);
1958 input_set_abs_params(touch, ABS_Y,
1959 0x00, 0xfff, 0, 0);
1960
1961 input_set_drvdata(touch, ictx);
1962
1963 usb_to_input_id(ictx->usbdev_intf1, &touch->id);
1964 touch->dev.parent = ictx->dev;
1965 ret = input_register_device(touch);
1966 if (ret < 0) {
1967 dev_info(ictx->dev, "touchscreen input dev register failed\n");
1968 goto touch_register_failed;
1969 }
1970
1971 return touch;
1972
1973touch_register_failed:
1974 input_free_device(ictx->touch);
1975
1976touch_alloc_failed:
1977 return NULL;
1978}
1979
1980static bool imon_find_endpoints(struct imon_context *ictx,
1981 struct usb_host_interface *iface_desc)
1982{
1983 struct usb_endpoint_descriptor *ep;
1984 struct usb_endpoint_descriptor *rx_endpoint = NULL;
1985 struct usb_endpoint_descriptor *tx_endpoint = NULL;
1986 int ifnum = iface_desc->desc.bInterfaceNumber;
1987 int num_endpts = iface_desc->desc.bNumEndpoints;
1988 int i, ep_dir, ep_type;
1989 bool ir_ep_found = false;
1990 bool display_ep_found = false;
1991 bool tx_control = false;
1992
1993 /*
1994 * Scan the endpoint list and set:
1995 * first input endpoint = IR endpoint
1996 * first output endpoint = display endpoint
1997 */
1998 for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) {
1999 ep = &iface_desc->endpoint[i].desc;
2000 ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK;
2001 ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
2002
2003 if (!ir_ep_found && ep_dir == USB_DIR_IN &&
2004 ep_type == USB_ENDPOINT_XFER_INT) {
2005
2006 rx_endpoint = ep;
2007 ir_ep_found = true;
2008 dev_dbg(ictx->dev, "%s: found IR endpoint\n", __func__);
2009
2010 } else if (!display_ep_found && ep_dir == USB_DIR_OUT &&
2011 ep_type == USB_ENDPOINT_XFER_INT) {
2012 tx_endpoint = ep;
2013 display_ep_found = true;
2014 dev_dbg(ictx->dev, "%s: found display endpoint\n", __func__);
2015 }
2016 }
2017
2018 if (ifnum == 0) {
2019 ictx->rx_endpoint_intf0 = rx_endpoint;
2020 /*
2021 * tx is used to send characters to lcd/vfd, associate RF
2022 * remotes, set IR protocol, and maybe more...
2023 */
2024 ictx->tx_endpoint = tx_endpoint;
2025 } else {
2026 ictx->rx_endpoint_intf1 = rx_endpoint;
2027 }
2028
2029 /*
2030 * If we didn't find a display endpoint, this is probably one of the
2031 * newer iMON devices that use control urb instead of interrupt
2032 */
2033 if (!display_ep_found) {
2034 tx_control = true;
2035 display_ep_found = true;
2036 dev_dbg(ictx->dev, "%s: device uses control endpoint, not "
2037 "interface OUT endpoint\n", __func__);
2038 }
2039
2040 /*
2041 * Some iMON receivers have no display. Unfortunately, it seems
2042 * that SoundGraph recycles device IDs between devices both with
2043 * and without... :\
2044 */
2045 if (ictx->display_type == IMON_DISPLAY_TYPE_NONE) {
2046 display_ep_found = false;
2047 dev_dbg(ictx->dev, "%s: device has no display\n", __func__);
2048 }
2049
2050 /*
2051 * iMON Touch devices have a VGA touchscreen, but no "display", as
2052 * that refers to e.g. /dev/lcd0 (a character device LCD or VFD).
2053 */
2054 if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) {
2055 display_ep_found = false;
2056 dev_dbg(ictx->dev, "%s: iMON Touch device found\n", __func__);
2057 }
2058
2059 /* Input endpoint is mandatory */
2060 if (!ir_ep_found)
2061 pr_err("no valid input (IR) endpoint found\n");
2062
2063 ictx->tx_control = tx_control;
2064
2065 if (display_ep_found)
2066 ictx->display_supported = true;
2067
2068 return ir_ep_found;
2069
2070}
2071
2072static struct imon_context *imon_init_intf0(struct usb_interface *intf)
2073{
2074 struct imon_context *ictx;
2075 struct urb *rx_urb;
2076 struct urb *tx_urb;
2077 struct device *dev = &intf->dev;
2078 struct usb_host_interface *iface_desc;
2079 int ret = -ENOMEM;
2080
2081 ictx = kzalloc(sizeof(struct imon_context), GFP_KERNEL);
2082 if (!ictx) {
2083 dev_err(dev, "%s: kzalloc failed for context", __func__);
2084 goto exit;
2085 }
2086 rx_urb = usb_alloc_urb(0, GFP_KERNEL);
2087 if (!rx_urb) {
2088 dev_err(dev, "%s: usb_alloc_urb failed for IR urb", __func__);
2089 goto rx_urb_alloc_failed;
2090 }
2091 tx_urb = usb_alloc_urb(0, GFP_KERNEL);
2092 if (!tx_urb) {
2093 dev_err(dev, "%s: usb_alloc_urb failed for display urb",
2094 __func__);
2095 goto tx_urb_alloc_failed;
2096 }
2097
2098 mutex_init(&ictx->lock);
2099 spin_lock_init(&ictx->kc_lock);
2100
2101 mutex_lock(&ictx->lock);
2102
2103 ictx->dev = dev;
2104 ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf));
2105 ictx->dev_present_intf0 = true;
2106 ictx->rx_urb_intf0 = rx_urb;
2107 ictx->tx_urb = tx_urb;
2108 ictx->rf_device = false;
2109
2110 ictx->vendor = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor);
2111 ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct);
2112
2113 ret = -ENODEV;
2114 iface_desc = intf->cur_altsetting;
2115 if (!imon_find_endpoints(ictx, iface_desc)) {
2116 goto find_endpoint_failed;
2117 }
2118
2119 ictx->idev = imon_init_idev(ictx);
2120 if (!ictx->idev) {
2121 dev_err(dev, "%s: input device setup failed\n", __func__);
2122 goto idev_setup_failed;
2123 }
2124
2125 ictx->rdev = imon_init_rdev(ictx);
2126 if (!ictx->rdev) {
2127 dev_err(dev, "%s: rc device setup failed\n", __func__);
2128 goto rdev_setup_failed;
2129 }
2130
2131 usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0,
2132 usb_rcvintpipe(ictx->usbdev_intf0,
2133 ictx->rx_endpoint_intf0->bEndpointAddress),
2134 ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf),
2135 usb_rx_callback_intf0, ictx,
2136 ictx->rx_endpoint_intf0->bInterval);
2137
2138 ret = usb_submit_urb(ictx->rx_urb_intf0, GFP_KERNEL);
2139 if (ret) {
2140 pr_err("usb_submit_urb failed for intf0 (%d)\n", ret);
2141 goto urb_submit_failed;
2142 }
2143
2144 return ictx;
2145
2146urb_submit_failed:
2147 ir_input_unregister(ictx->rdev);
2148rdev_setup_failed:
2149 input_unregister_device(ictx->idev);
2150idev_setup_failed:
2151find_endpoint_failed:
2152 mutex_unlock(&ictx->lock);
2153 usb_free_urb(tx_urb);
2154tx_urb_alloc_failed:
2155 usb_free_urb(rx_urb);
2156rx_urb_alloc_failed:
2157 kfree(ictx);
2158exit:
2159 dev_err(dev, "unable to initialize intf0, err %d\n", ret);
2160
2161 return NULL;
2162}
2163
2164static struct imon_context *imon_init_intf1(struct usb_interface *intf,
2165 struct imon_context *ictx)
2166{
2167 struct urb *rx_urb;
2168 struct usb_host_interface *iface_desc;
2169 int ret = -ENOMEM;
2170
2171 rx_urb = usb_alloc_urb(0, GFP_KERNEL);
2172 if (!rx_urb) {
2173 pr_err("usb_alloc_urb failed for IR urb\n");
2174 goto rx_urb_alloc_failed;
2175 }
2176
2177 mutex_lock(&ictx->lock);
2178
2179 if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) {
2180 init_timer(&ictx->ttimer);
2181 ictx->ttimer.data = (unsigned long)ictx;
2182 ictx->ttimer.function = imon_touch_display_timeout;
2183 }
2184
2185 ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf));
2186 ictx->dev_present_intf1 = true;
2187 ictx->rx_urb_intf1 = rx_urb;
2188
2189 ret = -ENODEV;
2190 iface_desc = intf->cur_altsetting;
2191 if (!imon_find_endpoints(ictx, iface_desc))
2192 goto find_endpoint_failed;
2193
2194 if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) {
2195 ictx->touch = imon_init_touch(ictx);
2196 if (!ictx->touch)
2197 goto touch_setup_failed;
2198 } else
2199 ictx->touch = NULL;
2200
2201 usb_fill_int_urb(ictx->rx_urb_intf1, ictx->usbdev_intf1,
2202 usb_rcvintpipe(ictx->usbdev_intf1,
2203 ictx->rx_endpoint_intf1->bEndpointAddress),
2204 ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf),
2205 usb_rx_callback_intf1, ictx,
2206 ictx->rx_endpoint_intf1->bInterval);
2207
2208 ret = usb_submit_urb(ictx->rx_urb_intf1, GFP_KERNEL);
2209
2210 if (ret) {
2211 pr_err("usb_submit_urb failed for intf1 (%d)\n", ret);
2212 goto urb_submit_failed;
2213 }
2214
2215 return ictx;
2216
2217urb_submit_failed:
2218 if (ictx->touch)
2219 input_unregister_device(ictx->touch);
2220touch_setup_failed:
2221find_endpoint_failed:
2222 mutex_unlock(&ictx->lock);
2223 usb_free_urb(rx_urb);
2224rx_urb_alloc_failed:
2225 dev_err(ictx->dev, "unable to initialize intf0, err %d\n", ret);
2226
2227 return NULL;
2228}
2229
2230static void imon_init_display(struct imon_context *ictx,
2231 struct usb_interface *intf)
2232{
2233 int ret;
2234
2235 dev_dbg(ictx->dev, "Registering iMON display with sysfs\n");
2236
2237 /* set up sysfs entry for built-in clock */
2238 ret = sysfs_create_group(&intf->dev.kobj, &imon_display_attr_group);
2239 if (ret)
2240 dev_err(ictx->dev, "Could not create display sysfs "
2241 "entries(%d)", ret);
2242
2243 if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
2244 ret = usb_register_dev(intf, &imon_lcd_class);
2245 else
2246 ret = usb_register_dev(intf, &imon_vfd_class);
2247 if (ret)
2248 /* Not a fatal error, so ignore */
2249 dev_info(ictx->dev, "could not get a minor number for "
2250 "display\n");
2251
2252}
2253
2254/**
2255 * Callback function for USB core API: Probe
2256 */
2257static int __devinit imon_probe(struct usb_interface *interface,
2258 const struct usb_device_id *id)
2259{
2260 struct usb_device *usbdev = NULL;
2261 struct usb_host_interface *iface_desc = NULL;
2262 struct usb_interface *first_if;
2263 struct device *dev = &interface->dev;
2264 int ifnum, code_length, sysfs_err;
2265 int ret = 0;
2266 struct imon_context *ictx = NULL;
2267 struct imon_context *first_if_ctx = NULL;
2268 u16 vendor, product;
2269
2270 code_length = BUF_CHUNK_SIZE * 8;
2271
2272 usbdev = usb_get_dev(interface_to_usbdev(interface));
2273 iface_desc = interface->cur_altsetting;
2274 ifnum = iface_desc->desc.bInterfaceNumber;
2275 vendor = le16_to_cpu(usbdev->descriptor.idVendor);
2276 product = le16_to_cpu(usbdev->descriptor.idProduct);
2277
2278 dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n",
2279 __func__, vendor, product, ifnum);
2280
2281 /* prevent races probing devices w/multiple interfaces */
2282 mutex_lock(&driver_lock);
2283
2284 first_if = usb_ifnum_to_if(usbdev, 0);
2285 first_if_ctx = (struct imon_context *)usb_get_intfdata(first_if);
2286
2287 if (ifnum == 0) {
2288 ictx = imon_init_intf0(interface);
2289 if (!ictx) {
2290 pr_err("failed to initialize context!\n");
2291 ret = -ENODEV;
2292 goto fail;
2293 }
2294
2295 } else {
2296 /* this is the secondary interface on the device */
2297 ictx = imon_init_intf1(interface, first_if_ctx);
2298 if (!ictx) {
2299 pr_err("failed to attach to context!\n");
2300 ret = -ENODEV;
2301 goto fail;
2302 }
2303
2304 }
2305
2306 usb_set_intfdata(interface, ictx);
2307
2308 if (ifnum == 0) {
2309 if (product == 0xffdc && ictx->rf_device) {
2310 sysfs_err = sysfs_create_group(&interface->dev.kobj,
2311 &imon_rf_attr_group);
2312 if (sysfs_err)
2313 pr_err("Could not create RF sysfs entries(%d)\n",
2314 sysfs_err);
2315 }
2316
2317 if (ictx->display_supported)
2318 imon_init_display(ictx, interface);
2319 }
2320
2321 dev_info(dev, "iMON device (%04x:%04x, intf%d) on "
2322 "usb<%d:%d> initialized\n", vendor, product, ifnum,
2323 usbdev->bus->busnum, usbdev->devnum);
2324
2325 mutex_unlock(&ictx->lock);
2326 mutex_unlock(&driver_lock);
2327
2328 return 0;
2329
2330fail:
2331 mutex_unlock(&driver_lock);
2332 dev_err(dev, "unable to register, err %d\n", ret);
2333
2334 return ret;
2335}
2336
2337/**
2338 * Callback function for USB core API: disconnect
2339 */
2340static void __devexit imon_disconnect(struct usb_interface *interface)
2341{
2342 struct imon_context *ictx;
2343 struct device *dev;
2344 int ifnum;
2345
2346 /* prevent races with multi-interface device probing and display_open */
2347 mutex_lock(&driver_lock);
2348
2349 ictx = usb_get_intfdata(interface);
2350 dev = ictx->dev;
2351 ifnum = interface->cur_altsetting->desc.bInterfaceNumber;
2352
2353 mutex_lock(&ictx->lock);
2354
2355 /*
2356 * sysfs_remove_group is safe to call even if sysfs_create_group
2357 * hasn't been called
2358 */
2359 sysfs_remove_group(&interface->dev.kobj, &imon_display_attr_group);
2360 sysfs_remove_group(&interface->dev.kobj, &imon_rf_attr_group);
2361
2362 usb_set_intfdata(interface, NULL);
2363
2364 /* Abort ongoing write */
2365 if (ictx->tx.busy) {
2366 usb_kill_urb(ictx->tx_urb);
2367 complete_all(&ictx->tx.finished);
2368 }
2369
2370 if (ifnum == 0) {
2371 ictx->dev_present_intf0 = false;
2372 usb_kill_urb(ictx->rx_urb_intf0);
2373 input_unregister_device(ictx->idev);
2374 ir_input_unregister(ictx->rdev);
2375 if (ictx->display_supported) {
2376 if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
2377 usb_deregister_dev(interface, &imon_lcd_class);
2378 else
2379 usb_deregister_dev(interface, &imon_vfd_class);
2380 }
2381 } else {
2382 ictx->dev_present_intf1 = false;
2383 usb_kill_urb(ictx->rx_urb_intf1);
2384 if (ictx->display_type == IMON_DISPLAY_TYPE_VGA)
2385 input_unregister_device(ictx->touch);
2386 }
2387
2388 if (!ictx->dev_present_intf0 && !ictx->dev_present_intf1) {
2389 if (ictx->display_type == IMON_DISPLAY_TYPE_VGA)
2390 del_timer_sync(&ictx->ttimer);
2391 mutex_unlock(&ictx->lock);
2392 if (!ictx->display_isopen)
2393 free_imon_context(ictx);
2394 } else
2395 mutex_unlock(&ictx->lock);
2396
2397 mutex_unlock(&driver_lock);
2398
2399 dev_dbg(dev, "%s: iMON device (intf%d) disconnected\n",
2400 __func__, ifnum);
2401}
2402
2403static int imon_suspend(struct usb_interface *intf, pm_message_t message)
2404{
2405 struct imon_context *ictx = usb_get_intfdata(intf);
2406 int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
2407
2408 if (ifnum == 0)
2409 usb_kill_urb(ictx->rx_urb_intf0);
2410 else
2411 usb_kill_urb(ictx->rx_urb_intf1);
2412
2413 return 0;
2414}
2415
2416static int imon_resume(struct usb_interface *intf)
2417{
2418 int rc = 0;
2419 struct imon_context *ictx = usb_get_intfdata(intf);
2420 int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
2421
2422 if (ifnum == 0) {
2423 usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0,
2424 usb_rcvintpipe(ictx->usbdev_intf0,
2425 ictx->rx_endpoint_intf0->bEndpointAddress),
2426 ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf),
2427 usb_rx_callback_intf0, ictx,
2428 ictx->rx_endpoint_intf0->bInterval);
2429
2430 rc = usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC);
2431
2432 } else {
2433 usb_fill_int_urb(ictx->rx_urb_intf1, ictx->usbdev_intf1,
2434 usb_rcvintpipe(ictx->usbdev_intf1,
2435 ictx->rx_endpoint_intf1->bEndpointAddress),
2436 ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf),
2437 usb_rx_callback_intf1, ictx,
2438 ictx->rx_endpoint_intf1->bInterval);
2439
2440 rc = usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC);
2441 }
2442
2443 return rc;
2444}
2445
2446static int __init imon_init(void)
2447{
2448 int rc;
2449
2450 rc = usb_register(&imon_driver);
2451 if (rc) {
2452 pr_err("usb register failed(%d)\n", rc);
2453 rc = -ENODEV;
2454 }
2455
2456 return rc;
2457}
2458
2459static void __exit imon_exit(void)
2460{
2461 usb_deregister(&imon_driver);
2462}
2463
2464module_init(imon_init);
2465module_exit(imon_exit);
diff --git a/drivers/media/rc/ir-core-priv.h b/drivers/media/rc/ir-core-priv.h
new file mode 100644
index 000000000000..81c936bd793f
--- /dev/null
+++ b/drivers/media/rc/ir-core-priv.h
@@ -0,0 +1,203 @@
1/*
2 * Remote Controller core raw events header
3 *
4 * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#ifndef _IR_RAW_EVENT
17#define _IR_RAW_EVENT
18
19#include <linux/slab.h>
20#include <linux/spinlock.h>
21#include <media/ir-core.h>
22
23struct ir_raw_handler {
24 struct list_head list;
25
26 u64 protocols; /* which are handled by this handler */
27 int (*decode)(struct input_dev *input_dev, struct ir_raw_event event);
28
29 /* These two should only be used by the lirc decoder */
30 int (*raw_register)(struct input_dev *input_dev);
31 int (*raw_unregister)(struct input_dev *input_dev);
32};
33
34struct ir_raw_event_ctrl {
35 struct list_head list; /* to keep track of raw clients */
36 struct task_struct *thread;
37 spinlock_t lock;
38 struct kfifo kfifo; /* fifo for the pulse/space durations */
39 ktime_t last_event; /* when last event occurred */
40 enum raw_event_type last_type; /* last event type */
41 struct input_dev *input_dev; /* pointer to the parent input_dev */
42 u64 enabled_protocols; /* enabled raw protocol decoders */
43
44 /* raw decoder state follows */
45 struct ir_raw_event prev_ev;
46 struct ir_raw_event this_ev;
47 struct nec_dec {
48 int state;
49 unsigned count;
50 u32 bits;
51 bool is_nec_x;
52 bool necx_repeat;
53 } nec;
54 struct rc5_dec {
55 int state;
56 u32 bits;
57 unsigned count;
58 unsigned wanted_bits;
59 } rc5;
60 struct rc6_dec {
61 int state;
62 u8 header;
63 u32 body;
64 bool toggle;
65 unsigned count;
66 unsigned wanted_bits;
67 } rc6;
68 struct sony_dec {
69 int state;
70 u32 bits;
71 unsigned count;
72 } sony;
73 struct jvc_dec {
74 int state;
75 u16 bits;
76 u16 old_bits;
77 unsigned count;
78 bool first;
79 bool toggle;
80 } jvc;
81 struct rc5_sz_dec {
82 int state;
83 u32 bits;
84 unsigned count;
85 unsigned wanted_bits;
86 } rc5_sz;
87 struct lirc_codec {
88 struct ir_input_dev *ir_dev;
89 struct lirc_driver *drv;
90 int carrier_low;
91
92 ktime_t gap_start;
93 u64 gap_duration;
94 bool gap;
95 bool send_timeout_reports;
96
97 } lirc;
98};
99
100/* macros for IR decoders */
101static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin)
102{
103 return d1 > (d2 - margin);
104}
105
106static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin)
107{
108 return ((d1 > (d2 - margin)) && (d1 < (d2 + margin)));
109}
110
111static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y)
112{
113 return x->pulse != y->pulse;
114}
115
116static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration)
117{
118 if (duration > ev->duration)
119 ev->duration = 0;
120 else
121 ev->duration -= duration;
122}
123
124/* Returns true if event is normal pulse/space event */
125static inline bool is_timing_event(struct ir_raw_event ev)
126{
127 return !ev.carrier_report && !ev.reset;
128}
129
130#define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000)
131#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space")
132/*
133 * Routines from ir-sysfs.c - Meant to be called only internally inside
134 * ir-core
135 */
136int ir_register_input(struct input_dev *input_dev);
137
138int ir_register_class(struct input_dev *input_dev);
139void ir_unregister_class(struct input_dev *input_dev);
140
141/*
142 * Routines from ir-raw-event.c to be used internally and by decoders
143 */
144u64 ir_raw_get_allowed_protocols(void);
145int ir_raw_event_register(struct input_dev *input_dev);
146void ir_raw_event_unregister(struct input_dev *input_dev);
147int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
148void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
149void ir_raw_init(void);
150
151int ir_rcmap_init(void);
152void ir_rcmap_cleanup(void);
153/*
154 * Decoder initialization code
155 *
156 * Those load logic are called during ir-core init, and automatically
157 * loads the compiled decoders for their usage with IR raw events
158 */
159
160/* from ir-nec-decoder.c */
161#ifdef CONFIG_IR_NEC_DECODER_MODULE
162#define load_nec_decode() request_module("ir-nec-decoder")
163#else
164#define load_nec_decode() 0
165#endif
166
167/* from ir-rc5-decoder.c */
168#ifdef CONFIG_IR_RC5_DECODER_MODULE
169#define load_rc5_decode() request_module("ir-rc5-decoder")
170#else
171#define load_rc5_decode() 0
172#endif
173
174/* from ir-rc6-decoder.c */
175#ifdef CONFIG_IR_RC6_DECODER_MODULE
176#define load_rc6_decode() request_module("ir-rc6-decoder")
177#else
178#define load_rc6_decode() 0
179#endif
180
181/* from ir-jvc-decoder.c */
182#ifdef CONFIG_IR_JVC_DECODER_MODULE
183#define load_jvc_decode() request_module("ir-jvc-decoder")
184#else
185#define load_jvc_decode() 0
186#endif
187
188/* from ir-sony-decoder.c */
189#ifdef CONFIG_IR_SONY_DECODER_MODULE
190#define load_sony_decode() request_module("ir-sony-decoder")
191#else
192#define load_sony_decode() 0
193#endif
194
195/* from ir-lirc-codec.c */
196#ifdef CONFIG_IR_LIRC_CODEC_MODULE
197#define load_lirc_codec() request_module("ir-lirc-codec")
198#else
199#define load_lirc_codec() 0
200#endif
201
202
203#endif /* _IR_RAW_EVENT */
diff --git a/drivers/media/rc/ir-functions.c b/drivers/media/rc/ir-functions.c
new file mode 100644
index 000000000000..ec021c92527a
--- /dev/null
+++ b/drivers/media/rc/ir-functions.c
@@ -0,0 +1,120 @@
1/*
2 * some common functions to handle infrared remote protocol decoding for
3 * drivers which have not yet been (or can't be) converted to use the
4 * regular protocol decoders...
5 *
6 * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <linux/module.h>
24#include <linux/string.h>
25#include <linux/jiffies.h>
26#include <media/ir-common.h>
27#include "ir-core-priv.h"
28
29/* -------------------------------------------------------------------------- */
30
31MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
32MODULE_LICENSE("GPL");
33
34/* RC5 decoding stuff, moved from bttv-input.c to share it with
35 * saa7134 */
36
37/* decode raw bit pattern to RC5 code */
38static u32 ir_rc5_decode(unsigned int code)
39{
40 unsigned int org_code = code;
41 unsigned int pair;
42 unsigned int rc5 = 0;
43 int i;
44
45 for (i = 0; i < 14; ++i) {
46 pair = code & 0x3;
47 code >>= 2;
48
49 rc5 <<= 1;
50 switch (pair) {
51 case 0:
52 case 2:
53 break;
54 case 1:
55 rc5 |= 1;
56 break;
57 case 3:
58 IR_dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);
59 return 0;
60 }
61 }
62 IR_dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
63 "instr=%x\n", rc5, org_code, RC5_START(rc5),
64 RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
65 return rc5;
66}
67
68void ir_rc5_timer_end(unsigned long data)
69{
70 struct card_ir *ir = (struct card_ir *)data;
71 struct timeval tv;
72 unsigned long current_jiffies;
73 u32 gap;
74 u32 rc5 = 0;
75
76 /* get time */
77 current_jiffies = jiffies;
78 do_gettimeofday(&tv);
79
80 /* avoid overflow with gap >1s */
81 if (tv.tv_sec - ir->base_time.tv_sec > 1) {
82 gap = 200000;
83 } else {
84 gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
85 tv.tv_usec - ir->base_time.tv_usec;
86 }
87
88 /* signal we're ready to start a new code */
89 ir->active = 0;
90
91 /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */
92 if (gap < 28000) {
93 IR_dprintk(1, "ir-common: spurious timer_end\n");
94 return;
95 }
96
97 if (ir->last_bit < 20) {
98 /* ignore spurious codes (caused by light/other remotes) */
99 IR_dprintk(1, "ir-common: short code: %x\n", ir->code);
100 } else {
101 ir->code = (ir->code << ir->shift_by) | 1;
102 rc5 = ir_rc5_decode(ir->code);
103
104 /* two start bits? */
105 if (RC5_START(rc5) != ir->start) {
106 IR_dprintk(1, "ir-common: rc5 start bits invalid: %u\n", RC5_START(rc5));
107
108 /* right address? */
109 } else if (RC5_ADDR(rc5) == ir->addr) {
110 u32 toggle = RC5_TOGGLE(rc5);
111 u32 instr = RC5_INSTR(rc5);
112
113 /* Good code */
114 ir_keydown(ir->dev, instr, toggle);
115 IR_dprintk(1, "ir-common: instruction %x, toggle %x\n",
116 instr, toggle);
117 }
118 }
119}
120EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c
new file mode 100644
index 000000000000..63dca6e5458b
--- /dev/null
+++ b/drivers/media/rc/ir-jvc-decoder.c
@@ -0,0 +1,199 @@
1/* ir-jvc-decoder.c - handle JVC IR Pulse/Space protocol
2 *
3 * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/bitrev.h>
16#include "ir-core-priv.h"
17
18#define JVC_NBITS 16 /* dev(8) + func(8) */
19#define JVC_UNIT 525000 /* ns */
20#define JVC_HEADER_PULSE (16 * JVC_UNIT) /* lack of header -> repeat */
21#define JVC_HEADER_SPACE (8 * JVC_UNIT)
22#define JVC_BIT_PULSE (1 * JVC_UNIT)
23#define JVC_BIT_0_SPACE (1 * JVC_UNIT)
24#define JVC_BIT_1_SPACE (3 * JVC_UNIT)
25#define JVC_TRAILER_PULSE (1 * JVC_UNIT)
26#define JVC_TRAILER_SPACE (35 * JVC_UNIT)
27
28enum jvc_state {
29 STATE_INACTIVE,
30 STATE_HEADER_SPACE,
31 STATE_BIT_PULSE,
32 STATE_BIT_SPACE,
33 STATE_TRAILER_PULSE,
34 STATE_TRAILER_SPACE,
35 STATE_CHECK_REPEAT,
36};
37
38/**
39 * ir_jvc_decode() - Decode one JVC pulse or space
40 * @input_dev: the struct input_dev descriptor of the device
41 * @duration: the struct ir_raw_event descriptor of the pulse/space
42 *
43 * This function returns -EINVAL if the pulse violates the state machine
44 */
45static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
46{
47 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
48 struct jvc_dec *data = &ir_dev->raw->jvc;
49
50 if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC))
51 return 0;
52
53 if (!is_timing_event(ev)) {
54 if (ev.reset)
55 data->state = STATE_INACTIVE;
56 return 0;
57 }
58
59 if (!geq_margin(ev.duration, JVC_UNIT, JVC_UNIT / 2))
60 goto out;
61
62 IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n",
63 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
64
65again:
66 switch (data->state) {
67
68 case STATE_INACTIVE:
69 if (!ev.pulse)
70 break;
71
72 if (!eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
73 break;
74
75 data->count = 0;
76 data->first = true;
77 data->toggle = !data->toggle;
78 data->state = STATE_HEADER_SPACE;
79 return 0;
80
81 case STATE_HEADER_SPACE:
82 if (ev.pulse)
83 break;
84
85 if (!eq_margin(ev.duration, JVC_HEADER_SPACE, JVC_UNIT / 2))
86 break;
87
88 data->state = STATE_BIT_PULSE;
89 return 0;
90
91 case STATE_BIT_PULSE:
92 if (!ev.pulse)
93 break;
94
95 if (!eq_margin(ev.duration, JVC_BIT_PULSE, JVC_UNIT / 2))
96 break;
97
98 data->state = STATE_BIT_SPACE;
99 return 0;
100
101 case STATE_BIT_SPACE:
102 if (ev.pulse)
103 break;
104
105 data->bits <<= 1;
106 if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) {
107 data->bits |= 1;
108 decrease_duration(&ev, JVC_BIT_1_SPACE);
109 } else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2))
110 decrease_duration(&ev, JVC_BIT_0_SPACE);
111 else
112 break;
113 data->count++;
114
115 if (data->count == JVC_NBITS)
116 data->state = STATE_TRAILER_PULSE;
117 else
118 data->state = STATE_BIT_PULSE;
119 return 0;
120
121 case STATE_TRAILER_PULSE:
122 if (!ev.pulse)
123 break;
124
125 if (!eq_margin(ev.duration, JVC_TRAILER_PULSE, JVC_UNIT / 2))
126 break;
127
128 data->state = STATE_TRAILER_SPACE;
129 return 0;
130
131 case STATE_TRAILER_SPACE:
132 if (ev.pulse)
133 break;
134
135 if (!geq_margin(ev.duration, JVC_TRAILER_SPACE, JVC_UNIT / 2))
136 break;
137
138 if (data->first) {
139 u32 scancode;
140 scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) |
141 (bitrev8((data->bits >> 0) & 0xff) << 0);
142 IR_dprintk(1, "JVC scancode 0x%04x\n", scancode);
143 ir_keydown(input_dev, scancode, data->toggle);
144 data->first = false;
145 data->old_bits = data->bits;
146 } else if (data->bits == data->old_bits) {
147 IR_dprintk(1, "JVC repeat\n");
148 ir_repeat(input_dev);
149 } else {
150 IR_dprintk(1, "JVC invalid repeat msg\n");
151 break;
152 }
153
154 data->count = 0;
155 data->state = STATE_CHECK_REPEAT;
156 return 0;
157
158 case STATE_CHECK_REPEAT:
159 if (!ev.pulse)
160 break;
161
162 if (eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
163 data->state = STATE_INACTIVE;
164 else
165 data->state = STATE_BIT_PULSE;
166 goto again;
167 }
168
169out:
170 IR_dprintk(1, "JVC decode failed at state %d (%uus %s)\n",
171 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
172 data->state = STATE_INACTIVE;
173 return -EINVAL;
174}
175
176static struct ir_raw_handler jvc_handler = {
177 .protocols = IR_TYPE_JVC,
178 .decode = ir_jvc_decode,
179};
180
181static int __init ir_jvc_decode_init(void)
182{
183 ir_raw_handler_register(&jvc_handler);
184
185 printk(KERN_INFO "IR JVC protocol handler initialized\n");
186 return 0;
187}
188
189static void __exit ir_jvc_decode_exit(void)
190{
191 ir_raw_handler_unregister(&jvc_handler);
192}
193
194module_init(ir_jvc_decode_init);
195module_exit(ir_jvc_decode_exit);
196
197MODULE_LICENSE("GPL");
198MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
199MODULE_DESCRIPTION("JVC IR protocol decoder");
diff --git a/drivers/media/rc/ir-keytable.c b/drivers/media/rc/ir-keytable.c
new file mode 100644
index 000000000000..8039110350d3
--- /dev/null
+++ b/drivers/media/rc/ir-keytable.c
@@ -0,0 +1,766 @@
1/* ir-keytable.c - handle IR scancode->keycode tables
2 *
3 * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15
16#include <linux/input.h>
17#include <linux/slab.h>
18#include "ir-core-priv.h"
19
20/* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */
21#define IR_TAB_MIN_SIZE 256
22#define IR_TAB_MAX_SIZE 8192
23
24/* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */
25#define IR_KEYPRESS_TIMEOUT 250
26
27/**
28 * ir_create_table() - initializes a scancode table
29 * @rc_tab: the ir_scancode_table to initialize
30 * @name: name to assign to the table
31 * @ir_type: ir type to assign to the new table
32 * @size: initial size of the table
33 * @return: zero on success or a negative error code
34 *
35 * This routine will initialize the ir_scancode_table and will allocate
36 * memory to hold at least the specified number elements.
37 */
38static int ir_create_table(struct ir_scancode_table *rc_tab,
39 const char *name, u64 ir_type, size_t size)
40{
41 rc_tab->name = name;
42 rc_tab->ir_type = ir_type;
43 rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode));
44 rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode);
45 rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL);
46 if (!rc_tab->scan)
47 return -ENOMEM;
48
49 IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
50 rc_tab->size, rc_tab->alloc);
51 return 0;
52}
53
54/**
55 * ir_free_table() - frees memory allocated by a scancode table
56 * @rc_tab: the table whose mappings need to be freed
57 *
58 * This routine will free memory alloctaed for key mappings used by given
59 * scancode table.
60 */
61static void ir_free_table(struct ir_scancode_table *rc_tab)
62{
63 rc_tab->size = 0;
64 kfree(rc_tab->scan);
65 rc_tab->scan = NULL;
66}
67
68/**
69 * ir_resize_table() - resizes a scancode table if necessary
70 * @rc_tab: the ir_scancode_table to resize
71 * @gfp_flags: gfp flags to use when allocating memory
72 * @return: zero on success or a negative error code
73 *
74 * This routine will shrink the ir_scancode_table if it has lots of
75 * unused entries and grow it if it is full.
76 */
77static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags)
78{
79 unsigned int oldalloc = rc_tab->alloc;
80 unsigned int newalloc = oldalloc;
81 struct ir_scancode *oldscan = rc_tab->scan;
82 struct ir_scancode *newscan;
83
84 if (rc_tab->size == rc_tab->len) {
85 /* All entries in use -> grow keytable */
86 if (rc_tab->alloc >= IR_TAB_MAX_SIZE)
87 return -ENOMEM;
88
89 newalloc *= 2;
90 IR_dprintk(1, "Growing table to %u bytes\n", newalloc);
91 }
92
93 if ((rc_tab->len * 3 < rc_tab->size) && (oldalloc > IR_TAB_MIN_SIZE)) {
94 /* Less than 1/3 of entries in use -> shrink keytable */
95 newalloc /= 2;
96 IR_dprintk(1, "Shrinking table to %u bytes\n", newalloc);
97 }
98
99 if (newalloc == oldalloc)
100 return 0;
101
102 newscan = kmalloc(newalloc, gfp_flags);
103 if (!newscan) {
104 IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc);
105 return -ENOMEM;
106 }
107
108 memcpy(newscan, rc_tab->scan, rc_tab->len * sizeof(struct ir_scancode));
109 rc_tab->scan = newscan;
110 rc_tab->alloc = newalloc;
111 rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode);
112 kfree(oldscan);
113 return 0;
114}
115
116/**
117 * ir_update_mapping() - set a keycode in the scancode->keycode table
118 * @dev: the struct input_dev device descriptor
119 * @rc_tab: scancode table to be adjusted
120 * @index: index of the mapping that needs to be updated
121 * @keycode: the desired keycode
122 * @return: previous keycode assigned to the mapping
123 *
124 * This routine is used to update scancode->keycopde mapping at given
125 * position.
126 */
127static unsigned int ir_update_mapping(struct input_dev *dev,
128 struct ir_scancode_table *rc_tab,
129 unsigned int index,
130 unsigned int new_keycode)
131{
132 int old_keycode = rc_tab->scan[index].keycode;
133 int i;
134
135 /* Did the user wish to remove the mapping? */
136 if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) {
137 IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
138 index, rc_tab->scan[index].scancode);
139 rc_tab->len--;
140 memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1],
141 (rc_tab->len - index) * sizeof(struct ir_scancode));
142 } else {
143 IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n",
144 index,
145 old_keycode == KEY_RESERVED ? "New" : "Replacing",
146 rc_tab->scan[index].scancode, new_keycode);
147 rc_tab->scan[index].keycode = new_keycode;
148 __set_bit(new_keycode, dev->keybit);
149 }
150
151 if (old_keycode != KEY_RESERVED) {
152 /* A previous mapping was updated... */
153 __clear_bit(old_keycode, dev->keybit);
154 /* ... but another scancode might use the same keycode */
155 for (i = 0; i < rc_tab->len; i++) {
156 if (rc_tab->scan[i].keycode == old_keycode) {
157 __set_bit(old_keycode, dev->keybit);
158 break;
159 }
160 }
161
162 /* Possibly shrink the keytable, failure is not a problem */
163 ir_resize_table(rc_tab, GFP_ATOMIC);
164 }
165
166 return old_keycode;
167}
168
169/**
170 * ir_locate_scancode() - set a keycode in the scancode->keycode table
171 * @ir_dev: the struct ir_input_dev device descriptor
172 * @rc_tab: scancode table to be searched
173 * @scancode: the desired scancode
174 * @resize: controls whether we allowed to resize the table to
175 * accomodate not yet present scancodes
176 * @return: index of the mapping containing scancode in question
177 * or -1U in case of failure.
178 *
179 * This routine is used to locate given scancode in ir_scancode_table.
180 * If scancode is not yet present the routine will allocate a new slot
181 * for it.
182 */
183static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev,
184 struct ir_scancode_table *rc_tab,
185 unsigned int scancode,
186 bool resize)
187{
188 unsigned int i;
189
190 /*
191 * Unfortunately, some hardware-based IR decoders don't provide
192 * all bits for the complete IR code. In general, they provide only
193 * the command part of the IR code. Yet, as it is possible to replace
194 * the provided IR with another one, it is needed to allow loading
195 * IR tables from other remotes. So,
196 */
197 if (ir_dev->props && ir_dev->props->scanmask)
198 scancode &= ir_dev->props->scanmask;
199
200 /* First check if we already have a mapping for this ir command */
201 for (i = 0; i < rc_tab->len; i++) {
202 if (rc_tab->scan[i].scancode == scancode)
203 return i;
204
205 /* Keytable is sorted from lowest to highest scancode */
206 if (rc_tab->scan[i].scancode >= scancode)
207 break;
208 }
209
210 /* No previous mapping found, we might need to grow the table */
211 if (rc_tab->size == rc_tab->len) {
212 if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC))
213 return -1U;
214 }
215
216 /* i is the proper index to insert our new keycode */
217 if (i < rc_tab->len)
218 memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i],
219 (rc_tab->len - i) * sizeof(struct ir_scancode));
220 rc_tab->scan[i].scancode = scancode;
221 rc_tab->scan[i].keycode = KEY_RESERVED;
222 rc_tab->len++;
223
224 return i;
225}
226
227/**
228 * ir_setkeycode() - set a keycode in the scancode->keycode table
229 * @dev: the struct input_dev device descriptor
230 * @scancode: the desired scancode
231 * @keycode: result
232 * @return: -EINVAL if the keycode could not be inserted, otherwise zero.
233 *
234 * This routine is used to handle evdev EVIOCSKEY ioctl.
235 */
236static int ir_setkeycode(struct input_dev *dev,
237 const struct input_keymap_entry *ke,
238 unsigned int *old_keycode)
239{
240 struct ir_input_dev *ir_dev = input_get_drvdata(dev);
241 struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
242 unsigned int index;
243 unsigned int scancode;
244 int retval;
245 unsigned long flags;
246
247 spin_lock_irqsave(&rc_tab->lock, flags);
248
249 if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
250 index = ke->index;
251 if (index >= rc_tab->len) {
252 retval = -EINVAL;
253 goto out;
254 }
255 } else {
256 retval = input_scancode_to_scalar(ke, &scancode);
257 if (retval)
258 goto out;
259
260 index = ir_establish_scancode(ir_dev, rc_tab, scancode, true);
261 if (index >= rc_tab->len) {
262 retval = -ENOMEM;
263 goto out;
264 }
265 }
266
267 *old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode);
268
269out:
270 spin_unlock_irqrestore(&rc_tab->lock, flags);
271 return retval;
272}
273
274/**
275 * ir_setkeytable() - sets several entries in the scancode->keycode table
276 * @dev: the struct input_dev device descriptor
277 * @to: the struct ir_scancode_table to copy entries to
278 * @from: the struct ir_scancode_table to copy entries from
279 * @return: -ENOMEM if all keycodes could not be inserted, otherwise zero.
280 *
281 * This routine is used to handle table initialization.
282 */
283static int ir_setkeytable(struct ir_input_dev *ir_dev,
284 const struct ir_scancode_table *from)
285{
286 struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
287 unsigned int i, index;
288 int rc;
289
290 rc = ir_create_table(&ir_dev->rc_tab,
291 from->name, from->ir_type, from->size);
292 if (rc)
293 return rc;
294
295 IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
296 rc_tab->size, rc_tab->alloc);
297
298 for (i = 0; i < from->size; i++) {
299 index = ir_establish_scancode(ir_dev, rc_tab,
300 from->scan[i].scancode, false);
301 if (index >= rc_tab->len) {
302 rc = -ENOMEM;
303 break;
304 }
305
306 ir_update_mapping(ir_dev->input_dev, rc_tab, index,
307 from->scan[i].keycode);
308 }
309
310 if (rc)
311 ir_free_table(rc_tab);
312
313 return rc;
314}
315
316/**
317 * ir_lookup_by_scancode() - locate mapping by scancode
318 * @rc_tab: the &struct ir_scancode_table to search
319 * @scancode: scancode to look for in the table
320 * @return: index in the table, -1U if not found
321 *
322 * This routine performs binary search in RC keykeymap table for
323 * given scancode.
324 */
325static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab,
326 unsigned int scancode)
327{
328 int start = 0;
329 int end = rc_tab->len - 1;
330 int mid;
331
332 while (start <= end) {
333 mid = (start + end) / 2;
334 if (rc_tab->scan[mid].scancode < scancode)
335 start = mid + 1;
336 else if (rc_tab->scan[mid].scancode > scancode)
337 end = mid - 1;
338 else
339 return mid;
340 }
341
342 return -1U;
343}
344
345/**
346 * ir_getkeycode() - get a keycode from the scancode->keycode table
347 * @dev: the struct input_dev device descriptor
348 * @scancode: the desired scancode
349 * @keycode: used to return the keycode, if found, or KEY_RESERVED
350 * @return: always returns zero.
351 *
352 * This routine is used to handle evdev EVIOCGKEY ioctl.
353 */
354static int ir_getkeycode(struct input_dev *dev,
355 struct input_keymap_entry *ke)
356{
357 struct ir_input_dev *ir_dev = input_get_drvdata(dev);
358 struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
359 struct ir_scancode *entry;
360 unsigned long flags;
361 unsigned int index;
362 unsigned int scancode;
363 int retval;
364
365 spin_lock_irqsave(&rc_tab->lock, flags);
366
367 if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
368 index = ke->index;
369 } else {
370 retval = input_scancode_to_scalar(ke, &scancode);
371 if (retval)
372 goto out;
373
374 index = ir_lookup_by_scancode(rc_tab, scancode);
375 }
376
377 if (index >= rc_tab->len) {
378 if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
379 IR_dprintk(1, "unknown key for scancode 0x%04x\n",
380 scancode);
381 retval = -EINVAL;
382 goto out;
383 }
384
385 entry = &rc_tab->scan[index];
386
387 ke->index = index;
388 ke->keycode = entry->keycode;
389 ke->len = sizeof(entry->scancode);
390 memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode));
391
392 retval = 0;
393
394out:
395 spin_unlock_irqrestore(&rc_tab->lock, flags);
396 return retval;
397}
398
399/**
400 * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode
401 * @input_dev: the struct input_dev descriptor of the device
402 * @scancode: the scancode that we're seeking
403 *
404 * This routine is used by the input routines when a key is pressed at the
405 * IR. The scancode is received and needs to be converted into a keycode.
406 * If the key is not found, it returns KEY_RESERVED. Otherwise, returns the
407 * corresponding keycode from the table.
408 */
409u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
410{
411 struct ir_input_dev *ir_dev = input_get_drvdata(dev);
412 struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
413 unsigned int keycode;
414 unsigned int index;
415 unsigned long flags;
416
417 spin_lock_irqsave(&rc_tab->lock, flags);
418
419 index = ir_lookup_by_scancode(rc_tab, scancode);
420 keycode = index < rc_tab->len ?
421 rc_tab->scan[index].keycode : KEY_RESERVED;
422
423 spin_unlock_irqrestore(&rc_tab->lock, flags);
424
425 if (keycode != KEY_RESERVED)
426 IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
427 dev->name, scancode, keycode);
428
429 return keycode;
430}
431EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
432
433/**
434 * ir_do_keyup() - internal function to signal the release of a keypress
435 * @ir: the struct ir_input_dev descriptor of the device
436 *
437 * This function is used internally to release a keypress, it must be
438 * called with keylock held.
439 */
440static void ir_do_keyup(struct ir_input_dev *ir)
441{
442 if (!ir->keypressed)
443 return;
444
445 IR_dprintk(1, "keyup key 0x%04x\n", ir->last_keycode);
446 input_report_key(ir->input_dev, ir->last_keycode, 0);
447 input_sync(ir->input_dev);
448 ir->keypressed = false;
449}
450
451/**
452 * ir_keyup() - generates input event to signal the release of a keypress
453 * @dev: the struct input_dev descriptor of the device
454 *
455 * This routine is used to signal that a key has been released on the
456 * remote control.
457 */
458void ir_keyup(struct input_dev *dev)
459{
460 unsigned long flags;
461 struct ir_input_dev *ir = input_get_drvdata(dev);
462
463 spin_lock_irqsave(&ir->keylock, flags);
464 ir_do_keyup(ir);
465 spin_unlock_irqrestore(&ir->keylock, flags);
466}
467EXPORT_SYMBOL_GPL(ir_keyup);
468
469/**
470 * ir_timer_keyup() - generates a keyup event after a timeout
471 * @cookie: a pointer to struct ir_input_dev passed to setup_timer()
472 *
473 * This routine will generate a keyup event some time after a keydown event
474 * is generated when no further activity has been detected.
475 */
476static void ir_timer_keyup(unsigned long cookie)
477{
478 struct ir_input_dev *ir = (struct ir_input_dev *)cookie;
479 unsigned long flags;
480
481 /*
482 * ir->keyup_jiffies is used to prevent a race condition if a
483 * hardware interrupt occurs at this point and the keyup timer
484 * event is moved further into the future as a result.
485 *
486 * The timer will then be reactivated and this function called
487 * again in the future. We need to exit gracefully in that case
488 * to allow the input subsystem to do its auto-repeat magic or
489 * a keyup event might follow immediately after the keydown.
490 */
491 spin_lock_irqsave(&ir->keylock, flags);
492 if (time_is_before_eq_jiffies(ir->keyup_jiffies))
493 ir_do_keyup(ir);
494 spin_unlock_irqrestore(&ir->keylock, flags);
495}
496
497/**
498 * ir_repeat() - notifies the IR core that a key is still pressed
499 * @dev: the struct input_dev descriptor of the device
500 *
501 * This routine is used by IR decoders when a repeat message which does
502 * not include the necessary bits to reproduce the scancode has been
503 * received.
504 */
505void ir_repeat(struct input_dev *dev)
506{
507 unsigned long flags;
508 struct ir_input_dev *ir = input_get_drvdata(dev);
509
510 spin_lock_irqsave(&ir->keylock, flags);
511
512 input_event(dev, EV_MSC, MSC_SCAN, ir->last_scancode);
513
514 if (!ir->keypressed)
515 goto out;
516
517 ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT);
518 mod_timer(&ir->timer_keyup, ir->keyup_jiffies);
519
520out:
521 spin_unlock_irqrestore(&ir->keylock, flags);
522}
523EXPORT_SYMBOL_GPL(ir_repeat);
524
525/**
526 * ir_do_keydown() - internal function to process a keypress
527 * @dev: the struct input_dev descriptor of the device
528 * @scancode: the scancode of the keypress
529 * @keycode: the keycode of the keypress
530 * @toggle: the toggle value of the keypress
531 *
532 * This function is used internally to register a keypress, it must be
533 * called with keylock held.
534 */
535static void ir_do_keydown(struct input_dev *dev, int scancode,
536 u32 keycode, u8 toggle)
537{
538 struct ir_input_dev *ir = input_get_drvdata(dev);
539
540 input_event(dev, EV_MSC, MSC_SCAN, scancode);
541
542 /* Repeat event? */
543 if (ir->keypressed &&
544 ir->last_scancode == scancode &&
545 ir->last_toggle == toggle)
546 return;
547
548 /* Release old keypress */
549 ir_do_keyup(ir);
550
551 ir->last_scancode = scancode;
552 ir->last_toggle = toggle;
553 ir->last_keycode = keycode;
554
555 if (keycode == KEY_RESERVED)
556 return;
557
558 /* Register a keypress */
559 ir->keypressed = true;
560 IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n",
561 dev->name, keycode, scancode);
562 input_report_key(dev, ir->last_keycode, 1);
563 input_sync(dev);
564}
565
566/**
567 * ir_keydown() - generates input event for a key press
568 * @dev: the struct input_dev descriptor of the device
569 * @scancode: the scancode that we're seeking
570 * @toggle: the toggle value (protocol dependent, if the protocol doesn't
571 * support toggle values, this should be set to zero)
572 *
573 * This routine is used by the input routines when a key is pressed at the
574 * IR. It gets the keycode for a scancode and reports an input event via
575 * input_report_key().
576 */
577void ir_keydown(struct input_dev *dev, int scancode, u8 toggle)
578{
579 unsigned long flags;
580 struct ir_input_dev *ir = input_get_drvdata(dev);
581 u32 keycode = ir_g_keycode_from_table(dev, scancode);
582
583 spin_lock_irqsave(&ir->keylock, flags);
584 ir_do_keydown(dev, scancode, keycode, toggle);
585
586 if (ir->keypressed) {
587 ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT);
588 mod_timer(&ir->timer_keyup, ir->keyup_jiffies);
589 }
590 spin_unlock_irqrestore(&ir->keylock, flags);
591}
592EXPORT_SYMBOL_GPL(ir_keydown);
593
594/**
595 * ir_keydown_notimeout() - generates input event for a key press without
596 * an automatic keyup event at a later time
597 * @dev: the struct input_dev descriptor of the device
598 * @scancode: the scancode that we're seeking
599 * @toggle: the toggle value (protocol dependent, if the protocol doesn't
600 * support toggle values, this should be set to zero)
601 *
602 * This routine is used by the input routines when a key is pressed at the
603 * IR. It gets the keycode for a scancode and reports an input event via
604 * input_report_key(). The driver must manually call ir_keyup() at a later
605 * stage.
606 */
607void ir_keydown_notimeout(struct input_dev *dev, int scancode, u8 toggle)
608{
609 unsigned long flags;
610 struct ir_input_dev *ir = input_get_drvdata(dev);
611 u32 keycode = ir_g_keycode_from_table(dev, scancode);
612
613 spin_lock_irqsave(&ir->keylock, flags);
614 ir_do_keydown(dev, scancode, keycode, toggle);
615 spin_unlock_irqrestore(&ir->keylock, flags);
616}
617EXPORT_SYMBOL_GPL(ir_keydown_notimeout);
618
619static int ir_open(struct input_dev *input_dev)
620{
621 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
622
623 return ir_dev->props->open(ir_dev->props->priv);
624}
625
626static void ir_close(struct input_dev *input_dev)
627{
628 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
629
630 ir_dev->props->close(ir_dev->props->priv);
631}
632
633/**
634 * __ir_input_register() - sets the IR keycode table and add the handlers
635 * for keymap table get/set
636 * @input_dev: the struct input_dev descriptor of the device
637 * @rc_tab: the struct ir_scancode_table table of scancode/keymap
638 *
639 * This routine is used to initialize the input infrastructure
640 * to work with an IR.
641 * It will register the input/evdev interface for the device and
642 * register the syfs code for IR class
643 */
644int __ir_input_register(struct input_dev *input_dev,
645 const struct ir_scancode_table *rc_tab,
646 struct ir_dev_props *props,
647 const char *driver_name)
648{
649 struct ir_input_dev *ir_dev;
650 int rc;
651
652 if (rc_tab->scan == NULL || !rc_tab->size)
653 return -EINVAL;
654
655 ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL);
656 if (!ir_dev)
657 return -ENOMEM;
658
659 ir_dev->driver_name = kasprintf(GFP_KERNEL, "%s", driver_name);
660 if (!ir_dev->driver_name) {
661 rc = -ENOMEM;
662 goto out_dev;
663 }
664
665 input_dev->getkeycode_new = ir_getkeycode;
666 input_dev->setkeycode_new = ir_setkeycode;
667 input_set_drvdata(input_dev, ir_dev);
668 ir_dev->input_dev = input_dev;
669
670 spin_lock_init(&ir_dev->rc_tab.lock);
671 spin_lock_init(&ir_dev->keylock);
672 setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev);
673
674 if (props) {
675 ir_dev->props = props;
676 if (props->open)
677 input_dev->open = ir_open;
678 if (props->close)
679 input_dev->close = ir_close;
680 }
681
682 set_bit(EV_KEY, input_dev->evbit);
683 set_bit(EV_REP, input_dev->evbit);
684 set_bit(EV_MSC, input_dev->evbit);
685 set_bit(MSC_SCAN, input_dev->mscbit);
686
687 rc = ir_setkeytable(ir_dev, rc_tab);
688 if (rc)
689 goto out_name;
690
691 rc = ir_register_class(input_dev);
692 if (rc < 0)
693 goto out_table;
694
695 if (ir_dev->props)
696 if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) {
697 rc = ir_raw_event_register(input_dev);
698 if (rc < 0)
699 goto out_event;
700 }
701
702 rc = ir_register_input(input_dev);
703 if (rc < 0)
704 goto out_event;
705
706 IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
707 driver_name, rc_tab->name,
708 (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
709 " in raw mode" : "");
710
711 /*
712 * Default delay of 250ms is too short for some protocols, expecially
713 * since the timeout is currently set to 250ms. Increase it to 500ms,
714 * to avoid wrong repetition of the keycodes.
715 */
716 input_dev->rep[REP_DELAY] = 500;
717
718 return 0;
719
720out_event:
721 ir_unregister_class(input_dev);
722out_table:
723 ir_free_table(&ir_dev->rc_tab);
724out_name:
725 kfree(ir_dev->driver_name);
726out_dev:
727 kfree(ir_dev);
728 return rc;
729}
730EXPORT_SYMBOL_GPL(__ir_input_register);
731
732/**
733 * ir_input_unregister() - unregisters IR and frees resources
734 * @input_dev: the struct input_dev descriptor of the device
735
736 * This routine is used to free memory and de-register interfaces.
737 */
738void ir_input_unregister(struct input_dev *input_dev)
739{
740 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
741
742 if (!ir_dev)
743 return;
744
745 IR_dprintk(1, "Freed keycode table\n");
746
747 del_timer_sync(&ir_dev->timer_keyup);
748 if (ir_dev->props)
749 if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
750 ir_raw_event_unregister(input_dev);
751
752 ir_free_table(&ir_dev->rc_tab);
753
754 ir_unregister_class(input_dev);
755
756 kfree(ir_dev->driver_name);
757 kfree(ir_dev);
758}
759EXPORT_SYMBOL_GPL(ir_input_unregister);
760
761int ir_core_debug; /* ir_debug level (0,1,2) */
762EXPORT_SYMBOL_GPL(ir_core_debug);
763module_param_named(debug, ir_core_debug, int, 0644);
764
765MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
766MODULE_LICENSE("GPL");
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
new file mode 100644
index 000000000000..9fc0db9d344d
--- /dev/null
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -0,0 +1,410 @@
1/* ir-lirc-codec.c - ir-core to classic lirc interface bridge
2 *
3 * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/sched.h>
16#include <linux/wait.h>
17#include <media/lirc.h>
18#include <media/lirc_dev.h>
19#include <media/ir-core.h>
20#include "ir-core-priv.h"
21
22#define LIRCBUF_SIZE 256
23
24/**
25 * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the
26 * lircd userspace daemon for decoding.
27 * @input_dev: the struct input_dev descriptor of the device
28 * @duration: the struct ir_raw_event descriptor of the pulse/space
29 *
30 * This function returns -EINVAL if the lirc interfaces aren't wired up.
31 */
32static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
33{
34 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
35 struct lirc_codec *lirc = &ir_dev->raw->lirc;
36 int sample;
37
38 if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
39 return 0;
40
41 if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
42 return -EINVAL;
43
44 /* Packet start */
45 if (ev.reset)
46 return 0;
47
48 /* Carrier reports */
49 if (ev.carrier_report) {
50 sample = LIRC_FREQUENCY(ev.carrier);
51
52 /* Packet end */
53 } else if (ev.timeout) {
54
55 if (lirc->gap)
56 return 0;
57
58 lirc->gap_start = ktime_get();
59 lirc->gap = true;
60 lirc->gap_duration = ev.duration;
61
62 if (!lirc->send_timeout_reports)
63 return 0;
64
65 sample = LIRC_TIMEOUT(ev.duration / 1000);
66
67 /* Normal sample */
68 } else {
69
70 if (lirc->gap) {
71 int gap_sample;
72
73 lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
74 lirc->gap_start));
75
76 /* Convert to ms and cap by LIRC_VALUE_MASK */
77 do_div(lirc->gap_duration, 1000);
78 lirc->gap_duration = min(lirc->gap_duration,
79 (u64)LIRC_VALUE_MASK);
80
81 gap_sample = LIRC_SPACE(lirc->gap_duration);
82 lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
83 (unsigned char *) &gap_sample);
84 lirc->gap = false;
85 }
86
87 sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) :
88 LIRC_SPACE(ev.duration / 1000);
89 }
90
91 lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
92 (unsigned char *) &sample);
93 wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
94
95 return 0;
96}
97
98static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,
99 size_t n, loff_t *ppos)
100{
101 struct lirc_codec *lirc;
102 struct ir_input_dev *ir_dev;
103 int *txbuf; /* buffer with values to transmit */
104 int ret = 0, count;
105
106 lirc = lirc_get_pdata(file);
107 if (!lirc)
108 return -EFAULT;
109
110 if (n % sizeof(int))
111 return -EINVAL;
112
113 count = n / sizeof(int);
114 if (count > LIRCBUF_SIZE || count % 2 == 0)
115 return -EINVAL;
116
117 txbuf = memdup_user(buf, n);
118 if (IS_ERR(txbuf))
119 return PTR_ERR(txbuf);
120
121 ir_dev = lirc->ir_dev;
122 if (!ir_dev) {
123 ret = -EFAULT;
124 goto out;
125 }
126
127 if (ir_dev->props && ir_dev->props->tx_ir)
128 ret = ir_dev->props->tx_ir(ir_dev->props->priv, txbuf, (u32)n);
129
130out:
131 kfree(txbuf);
132 return ret;
133}
134
135static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
136 unsigned long __user arg)
137{
138 struct lirc_codec *lirc;
139 struct ir_input_dev *ir_dev;
140 int ret = 0;
141 void *drv_data;
142 __u32 val = 0, tmp;
143
144 lirc = lirc_get_pdata(filep);
145 if (!lirc)
146 return -EFAULT;
147
148 ir_dev = lirc->ir_dev;
149 if (!ir_dev || !ir_dev->props || !ir_dev->props->priv)
150 return -EFAULT;
151
152 drv_data = ir_dev->props->priv;
153
154 if (_IOC_DIR(cmd) & _IOC_WRITE) {
155 ret = get_user(val, (__u32 *)arg);
156 if (ret)
157 return ret;
158 }
159
160 switch (cmd) {
161
162 /* legacy support */
163 case LIRC_GET_SEND_MODE:
164 val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
165 break;
166
167 case LIRC_SET_SEND_MODE:
168 if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
169 return -EINVAL;
170 return 0;
171
172 /* TX settings */
173 case LIRC_SET_TRANSMITTER_MASK:
174 if (!ir_dev->props->s_tx_mask)
175 return -EINVAL;
176
177 return ir_dev->props->s_tx_mask(drv_data, val);
178
179 case LIRC_SET_SEND_CARRIER:
180 if (!ir_dev->props->s_tx_carrier)
181 return -EINVAL;
182
183 return ir_dev->props->s_tx_carrier(drv_data, val);
184
185 case LIRC_SET_SEND_DUTY_CYCLE:
186 if (!ir_dev->props->s_tx_duty_cycle)
187 return -ENOSYS;
188
189 if (val <= 0 || val >= 100)
190 return -EINVAL;
191
192 return ir_dev->props->s_tx_duty_cycle(drv_data, val);
193
194 /* RX settings */
195 case LIRC_SET_REC_CARRIER:
196 if (!ir_dev->props->s_rx_carrier_range)
197 return -ENOSYS;
198
199 if (val <= 0)
200 return -EINVAL;
201
202 return ir_dev->props->s_rx_carrier_range(drv_data,
203 ir_dev->raw->lirc.carrier_low, val);
204
205 case LIRC_SET_REC_CARRIER_RANGE:
206 if (val <= 0)
207 return -EINVAL;
208
209 ir_dev->raw->lirc.carrier_low = val;
210 return 0;
211
212 case LIRC_GET_REC_RESOLUTION:
213 val = ir_dev->props->rx_resolution;
214 break;
215
216 case LIRC_SET_WIDEBAND_RECEIVER:
217 if (!ir_dev->props->s_learning_mode)
218 return -ENOSYS;
219
220 return ir_dev->props->s_learning_mode(drv_data, !!val);
221
222 case LIRC_SET_MEASURE_CARRIER_MODE:
223 if (!ir_dev->props->s_carrier_report)
224 return -ENOSYS;
225
226 return ir_dev->props->s_carrier_report(drv_data, !!val);
227
228 /* Generic timeout support */
229 case LIRC_GET_MIN_TIMEOUT:
230 if (!ir_dev->props->max_timeout)
231 return -ENOSYS;
232 val = ir_dev->props->min_timeout / 1000;
233 break;
234
235 case LIRC_GET_MAX_TIMEOUT:
236 if (!ir_dev->props->max_timeout)
237 return -ENOSYS;
238 val = ir_dev->props->max_timeout / 1000;
239 break;
240
241 case LIRC_SET_REC_TIMEOUT:
242 if (!ir_dev->props->max_timeout)
243 return -ENOSYS;
244
245 tmp = val * 1000;
246
247 if (tmp < ir_dev->props->min_timeout ||
248 tmp > ir_dev->props->max_timeout)
249 return -EINVAL;
250
251 ir_dev->props->timeout = tmp;
252 break;
253
254 case LIRC_SET_REC_TIMEOUT_REPORTS:
255 lirc->send_timeout_reports = !!val;
256 break;
257
258 default:
259 return lirc_dev_fop_ioctl(filep, cmd, arg);
260 }
261
262 if (_IOC_DIR(cmd) & _IOC_READ)
263 ret = put_user(val, (__u32 *)arg);
264
265 return ret;
266}
267
268static int ir_lirc_open(void *data)
269{
270 return 0;
271}
272
273static void ir_lirc_close(void *data)
274{
275 return;
276}
277
278static struct file_operations lirc_fops = {
279 .owner = THIS_MODULE,
280 .write = ir_lirc_transmit_ir,
281 .unlocked_ioctl = ir_lirc_ioctl,
282#ifdef CONFIG_COMPAT
283 .compat_ioctl = ir_lirc_ioctl,
284#endif
285 .read = lirc_dev_fop_read,
286 .poll = lirc_dev_fop_poll,
287 .open = lirc_dev_fop_open,
288 .release = lirc_dev_fop_close,
289 .llseek = no_llseek,
290};
291
292static int ir_lirc_register(struct input_dev *input_dev)
293{
294 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
295 struct lirc_driver *drv;
296 struct lirc_buffer *rbuf;
297 int rc = -ENOMEM;
298 unsigned long features;
299
300 drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
301 if (!drv)
302 return rc;
303
304 rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
305 if (!rbuf)
306 goto rbuf_alloc_failed;
307
308 rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE);
309 if (rc)
310 goto rbuf_init_failed;
311
312 features = LIRC_CAN_REC_MODE2;
313 if (ir_dev->props->tx_ir) {
314
315 features |= LIRC_CAN_SEND_PULSE;
316 if (ir_dev->props->s_tx_mask)
317 features |= LIRC_CAN_SET_TRANSMITTER_MASK;
318 if (ir_dev->props->s_tx_carrier)
319 features |= LIRC_CAN_SET_SEND_CARRIER;
320
321 if (ir_dev->props->s_tx_duty_cycle)
322 features |= LIRC_CAN_SET_SEND_DUTY_CYCLE;
323 }
324
325 if (ir_dev->props->s_rx_carrier_range)
326 features |= LIRC_CAN_SET_REC_CARRIER |
327 LIRC_CAN_SET_REC_CARRIER_RANGE;
328
329 if (ir_dev->props->s_learning_mode)
330 features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
331
332 if (ir_dev->props->s_carrier_report)
333 features |= LIRC_CAN_MEASURE_CARRIER;
334
335
336 if (ir_dev->props->max_timeout)
337 features |= LIRC_CAN_SET_REC_TIMEOUT;
338
339
340 snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
341 ir_dev->driver_name);
342 drv->minor = -1;
343 drv->features = features;
344 drv->data = &ir_dev->raw->lirc;
345 drv->rbuf = rbuf;
346 drv->set_use_inc = &ir_lirc_open;
347 drv->set_use_dec = &ir_lirc_close;
348 drv->code_length = sizeof(struct ir_raw_event) * 8;
349 drv->fops = &lirc_fops;
350 drv->dev = &ir_dev->dev;
351 drv->owner = THIS_MODULE;
352
353 drv->minor = lirc_register_driver(drv);
354 if (drv->minor < 0) {
355 rc = -ENODEV;
356 goto lirc_register_failed;
357 }
358
359 ir_dev->raw->lirc.drv = drv;
360 ir_dev->raw->lirc.ir_dev = ir_dev;
361 return 0;
362
363lirc_register_failed:
364rbuf_init_failed:
365 kfree(rbuf);
366rbuf_alloc_failed:
367 kfree(drv);
368
369 return rc;
370}
371
372static int ir_lirc_unregister(struct input_dev *input_dev)
373{
374 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
375 struct lirc_codec *lirc = &ir_dev->raw->lirc;
376
377 lirc_unregister_driver(lirc->drv->minor);
378 lirc_buffer_free(lirc->drv->rbuf);
379 kfree(lirc->drv);
380
381 return 0;
382}
383
384static struct ir_raw_handler lirc_handler = {
385 .protocols = IR_TYPE_LIRC,
386 .decode = ir_lirc_decode,
387 .raw_register = ir_lirc_register,
388 .raw_unregister = ir_lirc_unregister,
389};
390
391static int __init ir_lirc_codec_init(void)
392{
393 ir_raw_handler_register(&lirc_handler);
394
395 printk(KERN_INFO "IR LIRC bridge handler initialized\n");
396 return 0;
397}
398
399static void __exit ir_lirc_codec_exit(void)
400{
401 ir_raw_handler_unregister(&lirc_handler);
402}
403
404module_init(ir_lirc_codec_init);
405module_exit(ir_lirc_codec_exit);
406
407MODULE_LICENSE("GPL");
408MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
409MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
410MODULE_DESCRIPTION("LIRC IR handler bridge");
diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
new file mode 100644
index 000000000000..70993f79c8a2
--- /dev/null
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -0,0 +1,217 @@
1/* ir-nec-decoder.c - handle NEC IR Pulse/Space protocol
2 *
3 * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/bitrev.h>
16#include "ir-core-priv.h"
17
18#define NEC_NBITS 32
19#define NEC_UNIT 562500 /* ns */
20#define NEC_HEADER_PULSE (16 * NEC_UNIT)
21#define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */
22#define NEC_HEADER_SPACE (8 * NEC_UNIT)
23#define NEC_REPEAT_SPACE (4 * NEC_UNIT)
24#define NEC_BIT_PULSE (1 * NEC_UNIT)
25#define NEC_BIT_0_SPACE (1 * NEC_UNIT)
26#define NEC_BIT_1_SPACE (3 * NEC_UNIT)
27#define NEC_TRAILER_PULSE (1 * NEC_UNIT)
28#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */
29#define NECX_REPEAT_BITS 1
30
31enum nec_state {
32 STATE_INACTIVE,
33 STATE_HEADER_SPACE,
34 STATE_BIT_PULSE,
35 STATE_BIT_SPACE,
36 STATE_TRAILER_PULSE,
37 STATE_TRAILER_SPACE,
38};
39
40/**
41 * ir_nec_decode() - Decode one NEC pulse or space
42 * @input_dev: the struct input_dev descriptor of the device
43 * @duration: the struct ir_raw_event descriptor of the pulse/space
44 *
45 * This function returns -EINVAL if the pulse violates the state machine
46 */
47static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
48{
49 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
50 struct nec_dec *data = &ir_dev->raw->nec;
51 u32 scancode;
52 u8 address, not_address, command, not_command;
53
54 if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC))
55 return 0;
56
57 if (!is_timing_event(ev)) {
58 if (ev.reset)
59 data->state = STATE_INACTIVE;
60 return 0;
61 }
62
63 IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n",
64 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
65
66 switch (data->state) {
67
68 case STATE_INACTIVE:
69 if (!ev.pulse)
70 break;
71
72 if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2)) {
73 data->is_nec_x = false;
74 data->necx_repeat = false;
75 } else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
76 data->is_nec_x = true;
77 else
78 break;
79
80 data->count = 0;
81 data->state = STATE_HEADER_SPACE;
82 return 0;
83
84 case STATE_HEADER_SPACE:
85 if (ev.pulse)
86 break;
87
88 if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT / 2)) {
89 data->state = STATE_BIT_PULSE;
90 return 0;
91 } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) {
92 ir_repeat(input_dev);
93 IR_dprintk(1, "Repeat last key\n");
94 data->state = STATE_TRAILER_PULSE;
95 return 0;
96 }
97
98 break;
99
100 case STATE_BIT_PULSE:
101 if (!ev.pulse)
102 break;
103
104 if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2))
105 break;
106
107 data->state = STATE_BIT_SPACE;
108 return 0;
109
110 case STATE_BIT_SPACE:
111 if (ev.pulse)
112 break;
113
114 if (data->necx_repeat && data->count == NECX_REPEAT_BITS &&
115 geq_margin(ev.duration,
116 NEC_TRAILER_SPACE, NEC_UNIT / 2)) {
117 IR_dprintk(1, "Repeat last key\n");
118 ir_repeat(input_dev);
119 data->state = STATE_INACTIVE;
120 return 0;
121
122 } else if (data->count > NECX_REPEAT_BITS)
123 data->necx_repeat = false;
124
125 data->bits <<= 1;
126 if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
127 data->bits |= 1;
128 else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))
129 break;
130 data->count++;
131
132 if (data->count == NEC_NBITS)
133 data->state = STATE_TRAILER_PULSE;
134 else
135 data->state = STATE_BIT_PULSE;
136
137 return 0;
138
139 case STATE_TRAILER_PULSE:
140 if (!ev.pulse)
141 break;
142
143 if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2))
144 break;
145
146 data->state = STATE_TRAILER_SPACE;
147 return 0;
148
149 case STATE_TRAILER_SPACE:
150 if (ev.pulse)
151 break;
152
153 if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))
154 break;
155
156 address = bitrev8((data->bits >> 24) & 0xff);
157 not_address = bitrev8((data->bits >> 16) & 0xff);
158 command = bitrev8((data->bits >> 8) & 0xff);
159 not_command = bitrev8((data->bits >> 0) & 0xff);
160
161 if ((command ^ not_command) != 0xff) {
162 IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
163 data->bits);
164 break;
165 }
166
167 if ((address ^ not_address) != 0xff) {
168 /* Extended NEC */
169 scancode = address << 16 |
170 not_address << 8 |
171 command;
172 IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode);
173 } else {
174 /* Normal NEC */
175 scancode = address << 8 | command;
176 IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
177 }
178
179 if (data->is_nec_x)
180 data->necx_repeat = true;
181
182 ir_keydown(input_dev, scancode, 0);
183 data->state = STATE_INACTIVE;
184 return 0;
185 }
186
187 IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n",
188 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
189 data->state = STATE_INACTIVE;
190 return -EINVAL;
191}
192
193static struct ir_raw_handler nec_handler = {
194 .protocols = IR_TYPE_NEC,
195 .decode = ir_nec_decode,
196};
197
198static int __init ir_nec_decode_init(void)
199{
200 ir_raw_handler_register(&nec_handler);
201
202 printk(KERN_INFO "IR NEC protocol handler initialized\n");
203 return 0;
204}
205
206static void __exit ir_nec_decode_exit(void)
207{
208 ir_raw_handler_unregister(&nec_handler);
209}
210
211module_init(ir_nec_decode_init);
212module_exit(ir_nec_decode_exit);
213
214MODULE_LICENSE("GPL");
215MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
216MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
217MODULE_DESCRIPTION("NEC IR protocol decoder");
diff --git a/drivers/media/rc/ir-raw-event.c b/drivers/media/rc/ir-raw-event.c
new file mode 100644
index 000000000000..a06a07e4e0b1
--- /dev/null
+++ b/drivers/media/rc/ir-raw-event.c
@@ -0,0 +1,382 @@
1/* ir-raw-event.c - handle IR Pulse/Space event
2 *
3 * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/kthread.h>
16#include <linux/mutex.h>
17#include <linux/sched.h>
18#include <linux/freezer.h>
19#include "ir-core-priv.h"
20
21/* Define the max number of pulse/space transitions to buffer */
22#define MAX_IR_EVENT_SIZE 512
23
24/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
25static LIST_HEAD(ir_raw_client_list);
26
27/* Used to handle IR raw handler extensions */
28static DEFINE_MUTEX(ir_raw_handler_lock);
29static LIST_HEAD(ir_raw_handler_list);
30static u64 available_protocols;
31
32#ifdef MODULE
33/* Used to load the decoders */
34static struct work_struct wq_load;
35#endif
36
37static int ir_raw_event_thread(void *data)
38{
39 struct ir_raw_event ev;
40 struct ir_raw_handler *handler;
41 struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
42 int retval;
43
44 while (!kthread_should_stop()) {
45
46 spin_lock_irq(&raw->lock);
47 retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev));
48
49 if (!retval) {
50 set_current_state(TASK_INTERRUPTIBLE);
51
52 if (kthread_should_stop())
53 set_current_state(TASK_RUNNING);
54
55 spin_unlock_irq(&raw->lock);
56 schedule();
57 continue;
58 }
59
60 spin_unlock_irq(&raw->lock);
61
62
63 BUG_ON(retval != sizeof(ev));
64
65 mutex_lock(&ir_raw_handler_lock);
66 list_for_each_entry(handler, &ir_raw_handler_list, list)
67 handler->decode(raw->input_dev, ev);
68 raw->prev_ev = ev;
69 mutex_unlock(&ir_raw_handler_lock);
70 }
71
72 return 0;
73}
74
75/**
76 * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders
77 * @input_dev: the struct input_dev device descriptor
78 * @ev: the struct ir_raw_event descriptor of the pulse/space
79 *
80 * This routine (which may be called from an interrupt context) stores a
81 * pulse/space duration for the raw ir decoding state machines. Pulses are
82 * signalled as positive values and spaces as negative values. A zero value
83 * will reset the decoding state machines.
84 */
85int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev)
86{
87 struct ir_input_dev *ir = input_get_drvdata(input_dev);
88
89 if (!ir->raw)
90 return -EINVAL;
91
92 IR_dprintk(2, "sample: (%05dus %s)\n",
93 TO_US(ev->duration), TO_STR(ev->pulse));
94
95 if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
96 return -ENOMEM;
97
98 return 0;
99}
100EXPORT_SYMBOL_GPL(ir_raw_event_store);
101
102/**
103 * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space
104 * @input_dev: the struct input_dev device descriptor
105 * @type: the type of the event that has occurred
106 *
107 * This routine (which may be called from an interrupt context) is used to
108 * store the beginning of an ir pulse or space (or the start/end of ir
109 * reception) for the raw ir decoding state machines. This is used by
110 * hardware which does not provide durations directly but only interrupts
111 * (or similar events) on state change.
112 */
113int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type)
114{
115 struct ir_input_dev *ir = input_get_drvdata(input_dev);
116 ktime_t now;
117 s64 delta; /* ns */
118 struct ir_raw_event ev;
119 int rc = 0;
120
121 if (!ir->raw)
122 return -EINVAL;
123
124 now = ktime_get();
125 delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event));
126
127 /* Check for a long duration since last event or if we're
128 * being called for the first time, note that delta can't
129 * possibly be negative.
130 */
131 ev.duration = 0;
132 if (delta > IR_MAX_DURATION || !ir->raw->last_type)
133 type |= IR_START_EVENT;
134 else
135 ev.duration = delta;
136
137 if (type & IR_START_EVENT)
138 ir_raw_event_reset(input_dev);
139 else if (ir->raw->last_type & IR_SPACE) {
140 ev.pulse = false;
141 rc = ir_raw_event_store(input_dev, &ev);
142 } else if (ir->raw->last_type & IR_PULSE) {
143 ev.pulse = true;
144 rc = ir_raw_event_store(input_dev, &ev);
145 } else
146 return 0;
147
148 ir->raw->last_event = now;
149 ir->raw->last_type = type;
150 return rc;
151}
152EXPORT_SYMBOL_GPL(ir_raw_event_store_edge);
153
154/**
155 * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing
156 * @input_dev: the struct input_dev device descriptor
157 * @type: the type of the event that has occurred
158 *
159 * This routine (which may be called from an interrupt context) works
160 * in similiar manner to ir_raw_event_store_edge.
161 * This routine is intended for devices with limited internal buffer
162 * It automerges samples of same type, and handles timeouts
163 */
164int ir_raw_event_store_with_filter(struct input_dev *input_dev,
165 struct ir_raw_event *ev)
166{
167 struct ir_input_dev *ir = input_get_drvdata(input_dev);
168 struct ir_raw_event_ctrl *raw = ir->raw;
169
170 if (!raw || !ir->props)
171 return -EINVAL;
172
173 /* Ignore spaces in idle mode */
174 if (ir->idle && !ev->pulse)
175 return 0;
176 else if (ir->idle)
177 ir_raw_event_set_idle(input_dev, false);
178
179 if (!raw->this_ev.duration) {
180 raw->this_ev = *ev;
181 } else if (ev->pulse == raw->this_ev.pulse) {
182 raw->this_ev.duration += ev->duration;
183 } else {
184 ir_raw_event_store(input_dev, &raw->this_ev);
185 raw->this_ev = *ev;
186 }
187
188 /* Enter idle mode if nessesary */
189 if (!ev->pulse && ir->props->timeout &&
190 raw->this_ev.duration >= ir->props->timeout) {
191 ir_raw_event_set_idle(input_dev, true);
192 }
193 return 0;
194}
195EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
196
197/**
198 * ir_raw_event_set_idle() - hint the ir core if device is receiving
199 * IR data or not
200 * @input_dev: the struct input_dev device descriptor
201 * @idle: the hint value
202 */
203void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle)
204{
205 struct ir_input_dev *ir = input_get_drvdata(input_dev);
206 struct ir_raw_event_ctrl *raw = ir->raw;
207
208 if (!ir->props || !ir->raw)
209 return;
210
211 IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave");
212
213 if (idle) {
214 raw->this_ev.timeout = true;
215 ir_raw_event_store(input_dev, &raw->this_ev);
216 init_ir_raw_event(&raw->this_ev);
217 }
218
219 if (ir->props->s_idle)
220 ir->props->s_idle(ir->props->priv, idle);
221 ir->idle = idle;
222}
223EXPORT_SYMBOL_GPL(ir_raw_event_set_idle);
224
225/**
226 * ir_raw_event_handle() - schedules the decoding of stored ir data
227 * @input_dev: the struct input_dev device descriptor
228 *
229 * This routine will signal the workqueue to start decoding stored ir data.
230 */
231void ir_raw_event_handle(struct input_dev *input_dev)
232{
233 struct ir_input_dev *ir = input_get_drvdata(input_dev);
234 unsigned long flags;
235
236 if (!ir->raw)
237 return;
238
239 spin_lock_irqsave(&ir->raw->lock, flags);
240 wake_up_process(ir->raw->thread);
241 spin_unlock_irqrestore(&ir->raw->lock, flags);
242}
243EXPORT_SYMBOL_GPL(ir_raw_event_handle);
244
245/* used internally by the sysfs interface */
246u64
247ir_raw_get_allowed_protocols()
248{
249 u64 protocols;
250 mutex_lock(&ir_raw_handler_lock);
251 protocols = available_protocols;
252 mutex_unlock(&ir_raw_handler_lock);
253 return protocols;
254}
255
256/*
257 * Used to (un)register raw event clients
258 */
259int ir_raw_event_register(struct input_dev *input_dev)
260{
261 struct ir_input_dev *ir = input_get_drvdata(input_dev);
262 int rc;
263 struct ir_raw_handler *handler;
264
265 ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
266 if (!ir->raw)
267 return -ENOMEM;
268
269 ir->raw->input_dev = input_dev;
270
271 ir->raw->enabled_protocols = ~0;
272 rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
273 GFP_KERNEL);
274 if (rc < 0) {
275 kfree(ir->raw);
276 ir->raw = NULL;
277 return rc;
278 }
279
280 spin_lock_init(&ir->raw->lock);
281 ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw,
282 "rc%u", (unsigned int)ir->devno);
283
284 if (IS_ERR(ir->raw->thread)) {
285 int ret = PTR_ERR(ir->raw->thread);
286
287 kfree(ir->raw);
288 ir->raw = NULL;
289 return ret;
290 }
291
292 mutex_lock(&ir_raw_handler_lock);
293 list_add_tail(&ir->raw->list, &ir_raw_client_list);
294 list_for_each_entry(handler, &ir_raw_handler_list, list)
295 if (handler->raw_register)
296 handler->raw_register(ir->raw->input_dev);
297 mutex_unlock(&ir_raw_handler_lock);
298
299 return 0;
300}
301
302void ir_raw_event_unregister(struct input_dev *input_dev)
303{
304 struct ir_input_dev *ir = input_get_drvdata(input_dev);
305 struct ir_raw_handler *handler;
306
307 if (!ir->raw)
308 return;
309
310 kthread_stop(ir->raw->thread);
311
312 mutex_lock(&ir_raw_handler_lock);
313 list_del(&ir->raw->list);
314 list_for_each_entry(handler, &ir_raw_handler_list, list)
315 if (handler->raw_unregister)
316 handler->raw_unregister(ir->raw->input_dev);
317 mutex_unlock(&ir_raw_handler_lock);
318
319 kfifo_free(&ir->raw->kfifo);
320 kfree(ir->raw);
321 ir->raw = NULL;
322}
323
324/*
325 * Extension interface - used to register the IR decoders
326 */
327
328int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
329{
330 struct ir_raw_event_ctrl *raw;
331
332 mutex_lock(&ir_raw_handler_lock);
333 list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
334 if (ir_raw_handler->raw_register)
335 list_for_each_entry(raw, &ir_raw_client_list, list)
336 ir_raw_handler->raw_register(raw->input_dev);
337 available_protocols |= ir_raw_handler->protocols;
338 mutex_unlock(&ir_raw_handler_lock);
339
340 return 0;
341}
342EXPORT_SYMBOL(ir_raw_handler_register);
343
344void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
345{
346 struct ir_raw_event_ctrl *raw;
347
348 mutex_lock(&ir_raw_handler_lock);
349 list_del(&ir_raw_handler->list);
350 if (ir_raw_handler->raw_unregister)
351 list_for_each_entry(raw, &ir_raw_client_list, list)
352 ir_raw_handler->raw_unregister(raw->input_dev);
353 available_protocols &= ~ir_raw_handler->protocols;
354 mutex_unlock(&ir_raw_handler_lock);
355}
356EXPORT_SYMBOL(ir_raw_handler_unregister);
357
358#ifdef MODULE
359static void init_decoders(struct work_struct *work)
360{
361 /* Load the decoder modules */
362
363 load_nec_decode();
364 load_rc5_decode();
365 load_rc6_decode();
366 load_jvc_decode();
367 load_sony_decode();
368 load_lirc_codec();
369
370 /* If needed, we may later add some init code. In this case,
371 it is needed to change the CONFIG_MODULE test at ir-core.h
372 */
373}
374#endif
375
376void ir_raw_init(void)
377{
378#ifdef MODULE
379 INIT_WORK(&wq_load, init_decoders);
380 schedule_work(&wq_load);
381#endif
382}
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
new file mode 100644
index 000000000000..572ed4ca8c68
--- /dev/null
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -0,0 +1,190 @@
1/* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol
2 *
3 * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15/*
16 * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols.
17 * There are other variants that use a different number of bits.
18 * This is currently unsupported.
19 * It considers a carrier of 36 kHz, with a total of 14/20 bits, where
20 * the first two bits are start bits, and a third one is a filing bit
21 */
22
23#include "ir-core-priv.h"
24
25#define RC5_NBITS 14
26#define RC5X_NBITS 20
27#define CHECK_RC5X_NBITS 8
28#define RC5_UNIT 888888 /* ns */
29#define RC5_BIT_START (1 * RC5_UNIT)
30#define RC5_BIT_END (1 * RC5_UNIT)
31#define RC5X_SPACE (4 * RC5_UNIT)
32
33enum rc5_state {
34 STATE_INACTIVE,
35 STATE_BIT_START,
36 STATE_BIT_END,
37 STATE_CHECK_RC5X,
38 STATE_FINISHED,
39};
40
41/**
42 * ir_rc5_decode() - Decode one RC-5 pulse or space
43 * @input_dev: the struct input_dev descriptor of the device
44 * @ev: the struct ir_raw_event descriptor of the pulse/space
45 *
46 * This function returns -EINVAL if the pulse violates the state machine
47 */
48static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
49{
50 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
51 struct rc5_dec *data = &ir_dev->raw->rc5;
52 u8 toggle;
53 u32 scancode;
54
55 if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5))
56 return 0;
57
58 if (!is_timing_event(ev)) {
59 if (ev.reset)
60 data->state = STATE_INACTIVE;
61 return 0;
62 }
63
64 if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
65 goto out;
66
67again:
68 IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n",
69 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
70
71 if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
72 return 0;
73
74 switch (data->state) {
75
76 case STATE_INACTIVE:
77 if (!ev.pulse)
78 break;
79
80 data->state = STATE_BIT_START;
81 data->count = 1;
82 /* We just need enough bits to get to STATE_CHECK_RC5X */
83 data->wanted_bits = RC5X_NBITS;
84 decrease_duration(&ev, RC5_BIT_START);
85 goto again;
86
87 case STATE_BIT_START:
88 if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
89 break;
90
91 data->bits <<= 1;
92 if (!ev.pulse)
93 data->bits |= 1;
94 data->count++;
95 data->state = STATE_BIT_END;
96 return 0;
97
98 case STATE_BIT_END:
99 if (!is_transition(&ev, &ir_dev->raw->prev_ev))
100 break;
101
102 if (data->count == data->wanted_bits)
103 data->state = STATE_FINISHED;
104 else if (data->count == CHECK_RC5X_NBITS)
105 data->state = STATE_CHECK_RC5X;
106 else
107 data->state = STATE_BIT_START;
108
109 decrease_duration(&ev, RC5_BIT_END);
110 goto again;
111
112 case STATE_CHECK_RC5X:
113 if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) {
114 /* RC5X */
115 data->wanted_bits = RC5X_NBITS;
116 decrease_duration(&ev, RC5X_SPACE);
117 } else {
118 /* RC5 */
119 data->wanted_bits = RC5_NBITS;
120 }
121 data->state = STATE_BIT_START;
122 goto again;
123
124 case STATE_FINISHED:
125 if (ev.pulse)
126 break;
127
128 if (data->wanted_bits == RC5X_NBITS) {
129 /* RC5X */
130 u8 xdata, command, system;
131 xdata = (data->bits & 0x0003F) >> 0;
132 command = (data->bits & 0x00FC0) >> 6;
133 system = (data->bits & 0x1F000) >> 12;
134 toggle = (data->bits & 0x20000) ? 1 : 0;
135 command += (data->bits & 0x01000) ? 0 : 0x40;
136 scancode = system << 16 | command << 8 | xdata;
137
138 IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
139 scancode, toggle);
140
141 } else {
142 /* RC5 */
143 u8 command, system;
144 command = (data->bits & 0x0003F) >> 0;
145 system = (data->bits & 0x007C0) >> 6;
146 toggle = (data->bits & 0x00800) ? 1 : 0;
147 command += (data->bits & 0x01000) ? 0 : 0x40;
148 scancode = system << 8 | command;
149
150 IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
151 scancode, toggle);
152 }
153
154 ir_keydown(input_dev, scancode, toggle);
155 data->state = STATE_INACTIVE;
156 return 0;
157 }
158
159out:
160 IR_dprintk(1, "RC5(x) decode failed at state %i (%uus %s)\n",
161 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
162 data->state = STATE_INACTIVE;
163 return -EINVAL;
164}
165
166static struct ir_raw_handler rc5_handler = {
167 .protocols = IR_TYPE_RC5,
168 .decode = ir_rc5_decode,
169};
170
171static int __init ir_rc5_decode_init(void)
172{
173 ir_raw_handler_register(&rc5_handler);
174
175 printk(KERN_INFO "IR RC5(x) protocol handler initialized\n");
176 return 0;
177}
178
179static void __exit ir_rc5_decode_exit(void)
180{
181 ir_raw_handler_unregister(&rc5_handler);
182}
183
184module_init(ir_rc5_decode_init);
185module_exit(ir_rc5_decode_exit);
186
187MODULE_LICENSE("GPL");
188MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
189MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
190MODULE_DESCRIPTION("RC5(x) IR protocol decoder");
diff --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c
new file mode 100644
index 000000000000..7c413501a3f7
--- /dev/null
+++ b/drivers/media/rc/ir-rc5-sz-decoder.c
@@ -0,0 +1,154 @@
1/* ir-rc5-sz-decoder.c - handle RC5 Streamzap IR Pulse/Space protocol
2 *
3 * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16/*
17 * This code handles the 15 bit RC5-ish protocol used by the Streamzap
18 * PC Remote.
19 * It considers a carrier of 36 kHz, with a total of 15 bits, where
20 * the first two bits are start bits, and a third one is a filing bit
21 */
22
23#include "ir-core-priv.h"
24
25#define RC5_SZ_NBITS 15
26#define RC5_UNIT 888888 /* ns */
27#define RC5_BIT_START (1 * RC5_UNIT)
28#define RC5_BIT_END (1 * RC5_UNIT)
29
30enum rc5_sz_state {
31 STATE_INACTIVE,
32 STATE_BIT_START,
33 STATE_BIT_END,
34 STATE_FINISHED,
35};
36
37/**
38 * ir_rc5_sz_decode() - Decode one RC-5 Streamzap pulse or space
39 * @input_dev: the struct input_dev descriptor of the device
40 * @ev: the struct ir_raw_event descriptor of the pulse/space
41 *
42 * This function returns -EINVAL if the pulse violates the state machine
43 */
44static int ir_rc5_sz_decode(struct input_dev *input_dev, struct ir_raw_event ev)
45{
46 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
47 struct rc5_sz_dec *data = &ir_dev->raw->rc5_sz;
48 u8 toggle, command, system;
49 u32 scancode;
50
51 if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5_SZ))
52 return 0;
53
54 if (!is_timing_event(ev)) {
55 if (ev.reset)
56 data->state = STATE_INACTIVE;
57 return 0;
58 }
59
60 if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
61 goto out;
62
63again:
64 IR_dprintk(2, "RC5-sz decode started at state %i (%uus %s)\n",
65 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
66
67 if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
68 return 0;
69
70 switch (data->state) {
71
72 case STATE_INACTIVE:
73 if (!ev.pulse)
74 break;
75
76 data->state = STATE_BIT_START;
77 data->count = 1;
78 data->wanted_bits = RC5_SZ_NBITS;
79 decrease_duration(&ev, RC5_BIT_START);
80 goto again;
81
82 case STATE_BIT_START:
83 if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
84 break;
85
86 data->bits <<= 1;
87 if (!ev.pulse)
88 data->bits |= 1;
89 data->count++;
90 data->state = STATE_BIT_END;
91 return 0;
92
93 case STATE_BIT_END:
94 if (!is_transition(&ev, &ir_dev->raw->prev_ev))
95 break;
96
97 if (data->count == data->wanted_bits)
98 data->state = STATE_FINISHED;
99 else
100 data->state = STATE_BIT_START;
101
102 decrease_duration(&ev, RC5_BIT_END);
103 goto again;
104
105 case STATE_FINISHED:
106 if (ev.pulse)
107 break;
108
109 /* RC5-sz */
110 command = (data->bits & 0x0003F) >> 0;
111 system = (data->bits & 0x02FC0) >> 6;
112 toggle = (data->bits & 0x01000) ? 1 : 0;
113 scancode = system << 6 | command;
114
115 IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n",
116 scancode, toggle);
117
118 ir_keydown(input_dev, scancode, toggle);
119 data->state = STATE_INACTIVE;
120 return 0;
121 }
122
123out:
124 IR_dprintk(1, "RC5-sz decode failed at state %i (%uus %s)\n",
125 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
126 data->state = STATE_INACTIVE;
127 return -EINVAL;
128}
129
130static struct ir_raw_handler rc5_sz_handler = {
131 .protocols = IR_TYPE_RC5_SZ,
132 .decode = ir_rc5_sz_decode,
133};
134
135static int __init ir_rc5_sz_decode_init(void)
136{
137 ir_raw_handler_register(&rc5_sz_handler);
138
139 printk(KERN_INFO "IR RC5 (streamzap) protocol handler initialized\n");
140 return 0;
141}
142
143static void __exit ir_rc5_sz_decode_exit(void)
144{
145 ir_raw_handler_unregister(&rc5_sz_handler);
146}
147
148module_init(ir_rc5_sz_decode_init);
149module_exit(ir_rc5_sz_decode_exit);
150
151MODULE_LICENSE("GPL");
152MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
153MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
154MODULE_DESCRIPTION("RC5 (streamzap) IR protocol decoder");
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
new file mode 100644
index 000000000000..d25da91f44ff
--- /dev/null
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -0,0 +1,281 @@
1/* ir-rc6-decoder.c - A decoder for the RC6 IR protocol
2 *
3 * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include "ir-core-priv.h"
16
17/*
18 * This decoder currently supports:
19 * RC6-0-16 (standard toggle bit in header)
20 * RC6-6A-24 (no toggle bit)
21 * RC6-6A-32 (MCE version with toggle bit in body)
22 */
23
24#define RC6_UNIT 444444 /* us */
25#define RC6_HEADER_NBITS 4 /* not including toggle bit */
26#define RC6_0_NBITS 16
27#define RC6_6A_SMALL_NBITS 24
28#define RC6_6A_LARGE_NBITS 32
29#define RC6_PREFIX_PULSE (6 * RC6_UNIT)
30#define RC6_PREFIX_SPACE (2 * RC6_UNIT)
31#define RC6_BIT_START (1 * RC6_UNIT)
32#define RC6_BIT_END (1 * RC6_UNIT)
33#define RC6_TOGGLE_START (2 * RC6_UNIT)
34#define RC6_TOGGLE_END (2 * RC6_UNIT)
35#define RC6_MODE_MASK 0x07 /* for the header bits */
36#define RC6_STARTBIT_MASK 0x08 /* for the header bits */
37#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */
38
39enum rc6_mode {
40 RC6_MODE_0,
41 RC6_MODE_6A,
42 RC6_MODE_UNKNOWN,
43};
44
45enum rc6_state {
46 STATE_INACTIVE,
47 STATE_PREFIX_SPACE,
48 STATE_HEADER_BIT_START,
49 STATE_HEADER_BIT_END,
50 STATE_TOGGLE_START,
51 STATE_TOGGLE_END,
52 STATE_BODY_BIT_START,
53 STATE_BODY_BIT_END,
54 STATE_FINISHED,
55};
56
57static enum rc6_mode rc6_mode(struct rc6_dec *data)
58{
59 switch (data->header & RC6_MODE_MASK) {
60 case 0:
61 return RC6_MODE_0;
62 case 6:
63 if (!data->toggle)
64 return RC6_MODE_6A;
65 /* fall through */
66 default:
67 return RC6_MODE_UNKNOWN;
68 }
69}
70
71/**
72 * ir_rc6_decode() - Decode one RC6 pulse or space
73 * @input_dev: the struct input_dev descriptor of the device
74 * @ev: the struct ir_raw_event descriptor of the pulse/space
75 *
76 * This function returns -EINVAL if the pulse violates the state machine
77 */
78static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
79{
80 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
81 struct rc6_dec *data = &ir_dev->raw->rc6;
82 u32 scancode;
83 u8 toggle;
84
85 if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
86 return 0;
87
88 if (!is_timing_event(ev)) {
89 if (ev.reset)
90 data->state = STATE_INACTIVE;
91 return 0;
92 }
93
94 if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
95 goto out;
96
97again:
98 IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n",
99 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
100
101 if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
102 return 0;
103
104 switch (data->state) {
105
106 case STATE_INACTIVE:
107 if (!ev.pulse)
108 break;
109
110 /* Note: larger margin on first pulse since each RC6_UNIT
111 is quite short and some hardware takes some time to
112 adjust to the signal */
113 if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT))
114 break;
115
116 data->state = STATE_PREFIX_SPACE;
117 data->count = 0;
118 return 0;
119
120 case STATE_PREFIX_SPACE:
121 if (ev.pulse)
122 break;
123
124 if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2))
125 break;
126
127 data->state = STATE_HEADER_BIT_START;
128 return 0;
129
130 case STATE_HEADER_BIT_START:
131 if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
132 break;
133
134 data->header <<= 1;
135 if (ev.pulse)
136 data->header |= 1;
137 data->count++;
138 data->state = STATE_HEADER_BIT_END;
139 return 0;
140
141 case STATE_HEADER_BIT_END:
142 if (!is_transition(&ev, &ir_dev->raw->prev_ev))
143 break;
144
145 if (data->count == RC6_HEADER_NBITS)
146 data->state = STATE_TOGGLE_START;
147 else
148 data->state = STATE_HEADER_BIT_START;
149
150 decrease_duration(&ev, RC6_BIT_END);
151 goto again;
152
153 case STATE_TOGGLE_START:
154 if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
155 break;
156
157 data->toggle = ev.pulse;
158 data->state = STATE_TOGGLE_END;
159 return 0;
160
161 case STATE_TOGGLE_END:
162 if (!is_transition(&ev, &ir_dev->raw->prev_ev) ||
163 !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
164 break;
165
166 if (!(data->header & RC6_STARTBIT_MASK)) {
167 IR_dprintk(1, "RC6 invalid start bit\n");
168 break;
169 }
170
171 data->state = STATE_BODY_BIT_START;
172 decrease_duration(&ev, RC6_TOGGLE_END);
173 data->count = 0;
174
175 switch (rc6_mode(data)) {
176 case RC6_MODE_0:
177 data->wanted_bits = RC6_0_NBITS;
178 break;
179 case RC6_MODE_6A:
180 /* This might look weird, but we basically
181 check the value of the first body bit to
182 determine the number of bits in mode 6A */
183 if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) ||
184 geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
185 data->wanted_bits = RC6_6A_LARGE_NBITS;
186 else
187 data->wanted_bits = RC6_6A_SMALL_NBITS;
188 break;
189 default:
190 IR_dprintk(1, "RC6 unknown mode\n");
191 goto out;
192 }
193 goto again;
194
195 case STATE_BODY_BIT_START:
196 if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
197 break;
198
199 data->body <<= 1;
200 if (ev.pulse)
201 data->body |= 1;
202 data->count++;
203 data->state = STATE_BODY_BIT_END;
204 return 0;
205
206 case STATE_BODY_BIT_END:
207 if (!is_transition(&ev, &ir_dev->raw->prev_ev))
208 break;
209
210 if (data->count == data->wanted_bits)
211 data->state = STATE_FINISHED;
212 else
213 data->state = STATE_BODY_BIT_START;
214
215 decrease_duration(&ev, RC6_BIT_END);
216 goto again;
217
218 case STATE_FINISHED:
219 if (ev.pulse)
220 break;
221
222 switch (rc6_mode(data)) {
223 case RC6_MODE_0:
224 scancode = data->body & 0xffff;
225 toggle = data->toggle;
226 IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
227 scancode, toggle);
228 break;
229 case RC6_MODE_6A:
230 if (data->wanted_bits == RC6_6A_LARGE_NBITS) {
231 toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0;
232 scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK;
233 } else {
234 toggle = 0;
235 scancode = data->body & 0xffffff;
236 }
237
238 IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
239 scancode, toggle);
240 break;
241 default:
242 IR_dprintk(1, "RC6 unknown mode\n");
243 goto out;
244 }
245
246 ir_keydown(input_dev, scancode, toggle);
247 data->state = STATE_INACTIVE;
248 return 0;
249 }
250
251out:
252 IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n",
253 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
254 data->state = STATE_INACTIVE;
255 return -EINVAL;
256}
257
258static struct ir_raw_handler rc6_handler = {
259 .protocols = IR_TYPE_RC6,
260 .decode = ir_rc6_decode,
261};
262
263static int __init ir_rc6_decode_init(void)
264{
265 ir_raw_handler_register(&rc6_handler);
266
267 printk(KERN_INFO "IR RC6 protocol handler initialized\n");
268 return 0;
269}
270
271static void __exit ir_rc6_decode_exit(void)
272{
273 ir_raw_handler_unregister(&rc6_handler);
274}
275
276module_init(ir_rc6_decode_init);
277module_exit(ir_rc6_decode_exit);
278
279MODULE_LICENSE("GPL");
280MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
281MODULE_DESCRIPTION("RC6 IR protocol decoder");
diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c
new file mode 100644
index 000000000000..2d15730822bc
--- /dev/null
+++ b/drivers/media/rc/ir-sony-decoder.c
@@ -0,0 +1,182 @@
1/* ir-sony-decoder.c - handle Sony IR Pulse/Space protocol
2 *
3 * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/bitrev.h>
16#include "ir-core-priv.h"
17
18#define SONY_UNIT 600000 /* ns */
19#define SONY_HEADER_PULSE (4 * SONY_UNIT)
20#define SONY_HEADER_SPACE (1 * SONY_UNIT)
21#define SONY_BIT_0_PULSE (1 * SONY_UNIT)
22#define SONY_BIT_1_PULSE (2 * SONY_UNIT)
23#define SONY_BIT_SPACE (1 * SONY_UNIT)
24#define SONY_TRAILER_SPACE (10 * SONY_UNIT) /* minimum */
25
26enum sony_state {
27 STATE_INACTIVE,
28 STATE_HEADER_SPACE,
29 STATE_BIT_PULSE,
30 STATE_BIT_SPACE,
31 STATE_FINISHED,
32};
33
34/**
35 * ir_sony_decode() - Decode one Sony pulse or space
36 * @input_dev: the struct input_dev descriptor of the device
37 * @ev: the struct ir_raw_event descriptor of the pulse/space
38 *
39 * This function returns -EINVAL if the pulse violates the state machine
40 */
41static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
42{
43 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
44 struct sony_dec *data = &ir_dev->raw->sony;
45 u32 scancode;
46 u8 device, subdevice, function;
47
48 if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
49 return 0;
50
51 if (!is_timing_event(ev)) {
52 if (ev.reset)
53 data->state = STATE_INACTIVE;
54 return 0;
55 }
56
57 if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2))
58 goto out;
59
60 IR_dprintk(2, "Sony decode started at state %d (%uus %s)\n",
61 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
62
63 switch (data->state) {
64
65 case STATE_INACTIVE:
66 if (!ev.pulse)
67 break;
68
69 if (!eq_margin(ev.duration, SONY_HEADER_PULSE, SONY_UNIT / 2))
70 break;
71
72 data->count = 0;
73 data->state = STATE_HEADER_SPACE;
74 return 0;
75
76 case STATE_HEADER_SPACE:
77 if (ev.pulse)
78 break;
79
80 if (!eq_margin(ev.duration, SONY_HEADER_SPACE, SONY_UNIT / 2))
81 break;
82
83 data->state = STATE_BIT_PULSE;
84 return 0;
85
86 case STATE_BIT_PULSE:
87 if (!ev.pulse)
88 break;
89
90 data->bits <<= 1;
91 if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2))
92 data->bits |= 1;
93 else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2))
94 break;
95
96 data->count++;
97 data->state = STATE_BIT_SPACE;
98 return 0;
99
100 case STATE_BIT_SPACE:
101 if (ev.pulse)
102 break;
103
104 if (!geq_margin(ev.duration, SONY_BIT_SPACE, SONY_UNIT / 2))
105 break;
106
107 decrease_duration(&ev, SONY_BIT_SPACE);
108
109 if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) {
110 data->state = STATE_BIT_PULSE;
111 return 0;
112 }
113
114 data->state = STATE_FINISHED;
115 /* Fall through */
116
117 case STATE_FINISHED:
118 if (ev.pulse)
119 break;
120
121 if (!geq_margin(ev.duration, SONY_TRAILER_SPACE, SONY_UNIT / 2))
122 break;
123
124 switch (data->count) {
125 case 12:
126 device = bitrev8((data->bits << 3) & 0xF8);
127 subdevice = 0;
128 function = bitrev8((data->bits >> 4) & 0xFE);
129 break;
130 case 15:
131 device = bitrev8((data->bits >> 0) & 0xFF);
132 subdevice = 0;
133 function = bitrev8((data->bits >> 7) & 0xFD);
134 break;
135 case 20:
136 device = bitrev8((data->bits >> 5) & 0xF8);
137 subdevice = bitrev8((data->bits >> 0) & 0xFF);
138 function = bitrev8((data->bits >> 12) & 0xFE);
139 break;
140 default:
141 IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
142 goto out;
143 }
144
145 scancode = device << 16 | subdevice << 8 | function;
146 IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode);
147 ir_keydown(input_dev, scancode, 0);
148 data->state = STATE_INACTIVE;
149 return 0;
150 }
151
152out:
153 IR_dprintk(1, "Sony decode failed at state %d (%uus %s)\n",
154 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
155 data->state = STATE_INACTIVE;
156 return -EINVAL;
157}
158
159static struct ir_raw_handler sony_handler = {
160 .protocols = IR_TYPE_SONY,
161 .decode = ir_sony_decode,
162};
163
164static int __init ir_sony_decode_init(void)
165{
166 ir_raw_handler_register(&sony_handler);
167
168 printk(KERN_INFO "IR Sony protocol handler initialized\n");
169 return 0;
170}
171
172static void __exit ir_sony_decode_exit(void)
173{
174 ir_raw_handler_unregister(&sony_handler);
175}
176
177module_init(ir_sony_decode_init);
178module_exit(ir_sony_decode_exit);
179
180MODULE_LICENSE("GPL");
181MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
182MODULE_DESCRIPTION("Sony IR protocol decoder");
diff --git a/drivers/media/rc/ir-sysfs.c b/drivers/media/rc/ir-sysfs.c
new file mode 100644
index 000000000000..38423a8da871
--- /dev/null
+++ b/drivers/media/rc/ir-sysfs.c
@@ -0,0 +1,362 @@
1/* ir-sysfs.c - sysfs interface for RC devices (/sys/class/rc)
2 *
3 * Copyright (C) 2009-2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/slab.h>
16#include <linux/input.h>
17#include <linux/device.h>
18#include "ir-core-priv.h"
19
20#define IRRCV_NUM_DEVICES 256
21
22/* bit array to represent IR sysfs device number */
23static unsigned long ir_core_dev_number;
24
25/* class for /sys/class/rc */
26static char *ir_devnode(struct device *dev, mode_t *mode)
27{
28 return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev));
29}
30
31static struct class ir_input_class = {
32 .name = "rc",
33 .devnode = ir_devnode,
34};
35
36static struct {
37 u64 type;
38 char *name;
39} proto_names[] = {
40 { IR_TYPE_UNKNOWN, "unknown" },
41 { IR_TYPE_RC5, "rc-5" },
42 { IR_TYPE_NEC, "nec" },
43 { IR_TYPE_RC6, "rc-6" },
44 { IR_TYPE_JVC, "jvc" },
45 { IR_TYPE_SONY, "sony" },
46 { IR_TYPE_RC5_SZ, "rc-5-sz" },
47 { IR_TYPE_LIRC, "lirc" },
48};
49
50#define PROTO_NONE "none"
51
52/**
53 * show_protocols() - shows the current IR protocol(s)
54 * @d: the device descriptor
55 * @mattr: the device attribute struct (unused)
56 * @buf: a pointer to the output buffer
57 *
58 * This routine is a callback routine for input read the IR protocol type(s).
59 * it is trigged by reading /sys/class/rc/rc?/protocols.
60 * It returns the protocol names of supported protocols.
61 * Enabled protocols are printed in brackets.
62 */
63static ssize_t show_protocols(struct device *d,
64 struct device_attribute *mattr, char *buf)
65{
66 struct ir_input_dev *ir_dev = dev_get_drvdata(d);
67 u64 allowed, enabled;
68 char *tmp = buf;
69 int i;
70
71 /* Device is being removed */
72 if (!ir_dev)
73 return -EINVAL;
74
75 if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
76 enabled = ir_dev->rc_tab.ir_type;
77 allowed = ir_dev->props->allowed_protos;
78 } else if (ir_dev->raw) {
79 enabled = ir_dev->raw->enabled_protocols;
80 allowed = ir_raw_get_allowed_protocols();
81 } else
82 return sprintf(tmp, "[builtin]\n");
83
84 IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
85 (long long)allowed,
86 (long long)enabled);
87
88 for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
89 if (allowed & enabled & proto_names[i].type)
90 tmp += sprintf(tmp, "[%s] ", proto_names[i].name);
91 else if (allowed & proto_names[i].type)
92 tmp += sprintf(tmp, "%s ", proto_names[i].name);
93 }
94
95 if (tmp != buf)
96 tmp--;
97 *tmp = '\n';
98 return tmp + 1 - buf;
99}
100
101/**
102 * store_protocols() - changes the current IR protocol(s)
103 * @d: the device descriptor
104 * @mattr: the device attribute struct (unused)
105 * @buf: a pointer to the input buffer
106 * @len: length of the input buffer
107 *
108 * This routine is a callback routine for changing the IR protocol type.
109 * It is trigged by writing to /sys/class/rc/rc?/protocols.
110 * Writing "+proto" will add a protocol to the list of enabled protocols.
111 * Writing "-proto" will remove a protocol from the list of enabled protocols.
112 * Writing "proto" will enable only "proto".
113 * Writing "none" will disable all protocols.
114 * Returns -EINVAL if an invalid protocol combination or unknown protocol name
115 * is used, otherwise @len.
116 */
117static ssize_t store_protocols(struct device *d,
118 struct device_attribute *mattr,
119 const char *data,
120 size_t len)
121{
122 struct ir_input_dev *ir_dev = dev_get_drvdata(d);
123 bool enable, disable;
124 const char *tmp;
125 u64 type;
126 u64 mask;
127 int rc, i, count = 0;
128 unsigned long flags;
129
130 /* Device is being removed */
131 if (!ir_dev)
132 return -EINVAL;
133
134 if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
135 type = ir_dev->rc_tab.ir_type;
136 else if (ir_dev->raw)
137 type = ir_dev->raw->enabled_protocols;
138 else {
139 IR_dprintk(1, "Protocol switching not supported\n");
140 return -EINVAL;
141 }
142
143 while ((tmp = strsep((char **) &data, " \n")) != NULL) {
144 if (!*tmp)
145 break;
146
147 if (*tmp == '+') {
148 enable = true;
149 disable = false;
150 tmp++;
151 } else if (*tmp == '-') {
152 enable = false;
153 disable = true;
154 tmp++;
155 } else {
156 enable = false;
157 disable = false;
158 }
159
160 if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) {
161 tmp += sizeof(PROTO_NONE);
162 mask = 0;
163 count++;
164 } else {
165 for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
166 if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) {
167 tmp += strlen(proto_names[i].name);
168 mask = proto_names[i].type;
169 break;
170 }
171 }
172 if (i == ARRAY_SIZE(proto_names)) {
173 IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
174 return -EINVAL;
175 }
176 count++;
177 }
178
179 if (enable)
180 type |= mask;
181 else if (disable)
182 type &= ~mask;
183 else
184 type = mask;
185 }
186
187 if (!count) {
188 IR_dprintk(1, "Protocol not specified\n");
189 return -EINVAL;
190 }
191
192 if (ir_dev->props && ir_dev->props->change_protocol) {
193 rc = ir_dev->props->change_protocol(ir_dev->props->priv,
194 type);
195 if (rc < 0) {
196 IR_dprintk(1, "Error setting protocols to 0x%llx\n",
197 (long long)type);
198 return -EINVAL;
199 }
200 }
201
202 if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
203 spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
204 ir_dev->rc_tab.ir_type = type;
205 spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
206 } else {
207 ir_dev->raw->enabled_protocols = type;
208 }
209
210 IR_dprintk(1, "Current protocol(s): 0x%llx\n",
211 (long long)type);
212
213 return len;
214}
215
216#define ADD_HOTPLUG_VAR(fmt, val...) \
217 do { \
218 int err = add_uevent_var(env, fmt, val); \
219 if (err) \
220 return err; \
221 } while (0)
222
223static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
224{
225 struct ir_input_dev *ir_dev = dev_get_drvdata(device);
226
227 if (ir_dev->rc_tab.name)
228 ADD_HOTPLUG_VAR("NAME=%s", ir_dev->rc_tab.name);
229 if (ir_dev->driver_name)
230 ADD_HOTPLUG_VAR("DRV_NAME=%s", ir_dev->driver_name);
231
232 return 0;
233}
234
235/*
236 * Static device attribute struct with the sysfs attributes for IR's
237 */
238static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR,
239 show_protocols, store_protocols);
240
241static struct attribute *rc_dev_attrs[] = {
242 &dev_attr_protocols.attr,
243 NULL,
244};
245
246static struct attribute_group rc_dev_attr_grp = {
247 .attrs = rc_dev_attrs,
248};
249
250static const struct attribute_group *rc_dev_attr_groups[] = {
251 &rc_dev_attr_grp,
252 NULL
253};
254
255static struct device_type rc_dev_type = {
256 .groups = rc_dev_attr_groups,
257 .uevent = rc_dev_uevent,
258};
259
260/**
261 * ir_register_class() - creates the sysfs for /sys/class/rc/rc?
262 * @input_dev: the struct input_dev descriptor of the device
263 *
264 * This routine is used to register the syfs code for IR class
265 */
266int ir_register_class(struct input_dev *input_dev)
267{
268 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
269 int devno = find_first_zero_bit(&ir_core_dev_number,
270 IRRCV_NUM_DEVICES);
271
272 if (unlikely(devno < 0))
273 return devno;
274
275 ir_dev->dev.type = &rc_dev_type;
276 ir_dev->devno = devno;
277
278 ir_dev->dev.class = &ir_input_class;
279 ir_dev->dev.parent = input_dev->dev.parent;
280 input_dev->dev.parent = &ir_dev->dev;
281 dev_set_name(&ir_dev->dev, "rc%d", devno);
282 dev_set_drvdata(&ir_dev->dev, ir_dev);
283 return device_register(&ir_dev->dev);
284};
285
286/**
287 * ir_register_input - registers ir input device with input subsystem
288 * @input_dev: the struct input_dev descriptor of the device
289 */
290
291int ir_register_input(struct input_dev *input_dev)
292{
293 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
294 int rc;
295 const char *path;
296
297
298 rc = input_register_device(input_dev);
299 if (rc < 0) {
300 device_del(&ir_dev->dev);
301 return rc;
302 }
303
304 __module_get(THIS_MODULE);
305
306 path = kobject_get_path(&ir_dev->dev.kobj, GFP_KERNEL);
307 printk(KERN_INFO "%s: %s as %s\n",
308 dev_name(&ir_dev->dev),
309 input_dev->name ? input_dev->name : "Unspecified device",
310 path ? path : "N/A");
311 kfree(path);
312
313 set_bit(ir_dev->devno, &ir_core_dev_number);
314 return 0;
315}
316
317/**
318 * ir_unregister_class() - removes the sysfs for sysfs for
319 * /sys/class/rc/rc?
320 * @input_dev: the struct input_dev descriptor of the device
321 *
322 * This routine is used to unregister the syfs code for IR class
323 */
324void ir_unregister_class(struct input_dev *input_dev)
325{
326 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
327
328 input_set_drvdata(input_dev, NULL);
329 clear_bit(ir_dev->devno, &ir_core_dev_number);
330 input_unregister_device(input_dev);
331 device_del(&ir_dev->dev);
332
333 module_put(THIS_MODULE);
334}
335
336/*
337 * Init/exit code for the module. Basically, creates/removes /sys/class/rc
338 */
339
340static int __init ir_core_init(void)
341{
342 int rc = class_register(&ir_input_class);
343 if (rc) {
344 printk(KERN_ERR "ir_core: unable to register rc class\n");
345 return rc;
346 }
347
348 /* Initialize/load the decoders/keymap code that will be used */
349 ir_raw_init();
350 ir_rcmap_init();
351
352 return 0;
353}
354
355static void __exit ir_core_exit(void)
356{
357 class_unregister(&ir_input_class);
358 ir_rcmap_cleanup();
359}
360
361module_init(ir_core_init);
362module_exit(ir_core_exit);
diff --git a/drivers/media/rc/keymaps/Kconfig b/drivers/media/rc/keymaps/Kconfig
new file mode 100644
index 000000000000..14b22f58f823
--- /dev/null
+++ b/drivers/media/rc/keymaps/Kconfig
@@ -0,0 +1,15 @@
1config RC_MAP
2 tristate "Compile Remote Controller keymap modules"
3 depends on IR_CORE
4 default y
5
6 ---help---
7 This option enables the compilation of lots of Remote
8 Controller tables. They are short tables, but if you
9 don't use a remote controller, or prefer to load the
10 tables on userspace, you should disable it.
11
12 The ir-keytable program, available at v4l-utils package
13 provide the tool and the same RC maps for load from
14 userspace. Its available at
15 http://git.linuxtv.org/v4l-utils
diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile
new file mode 100644
index 000000000000..3194d391bbd4
--- /dev/null
+++ b/drivers/media/rc/keymaps/Makefile
@@ -0,0 +1,86 @@
1obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
2 rc-alink-dtu-m.o \
3 rc-anysee.o \
4 rc-apac-viewcomp.o \
5 rc-asus-pc39.o \
6 rc-ati-tv-wonder-hd-600.o \
7 rc-avermedia-a16d.o \
8 rc-avermedia.o \
9 rc-avermedia-cardbus.o \
10 rc-avermedia-dvbt.o \
11 rc-avermedia-m135a.o \
12 rc-avermedia-m733a-rm-k6.o \
13 rc-avermedia-rm-ks.o \
14 rc-avertv-303.o \
15 rc-azurewave-ad-tu700.o \
16 rc-behold.o \
17 rc-behold-columbus.o \
18 rc-budget-ci-old.o \
19 rc-cinergy-1400.o \
20 rc-cinergy.o \
21 rc-dib0700-nec.o \
22 rc-dib0700-rc5.o \
23 rc-digitalnow-tinytwin.o \
24 rc-digittrade.o \
25 rc-dm1105-nec.o \
26 rc-dntv-live-dvb-t.o \
27 rc-dntv-live-dvbt-pro.o \
28 rc-em-terratec.o \
29 rc-encore-enltv2.o \
30 rc-encore-enltv.o \
31 rc-encore-enltv-fm53.o \
32 rc-evga-indtube.o \
33 rc-eztv.o \
34 rc-flydvb.o \
35 rc-flyvideo.o \
36 rc-fusionhdtv-mce.o \
37 rc-gadmei-rm008z.o \
38 rc-genius-tvgo-a11mce.o \
39 rc-gotview7135.o \
40 rc-hauppauge-new.o \
41 rc-imon-mce.o \
42 rc-imon-pad.o \
43 rc-iodata-bctv7e.o \
44 rc-kaiomy.o \
45 rc-kworld-315u.o \
46 rc-kworld-plus-tv-analog.o \
47 rc-leadtek-y04g0051.o \
48 rc-lirc.o \
49 rc-lme2510.o \
50 rc-manli.o \
51 rc-msi-digivox-ii.o \
52 rc-msi-digivox-iii.o \
53 rc-msi-tvanywhere.o \
54 rc-msi-tvanywhere-plus.o \
55 rc-nebula.o \
56 rc-nec-terratec-cinergy-xs.o \
57 rc-norwood.o \
58 rc-npgtech.o \
59 rc-pctv-sedna.o \
60 rc-pinnacle-color.o \
61 rc-pinnacle-grey.o \
62 rc-pinnacle-pctv-hd.o \
63 rc-pixelview.o \
64 rc-pixelview-mk12.o \
65 rc-pixelview-new.o \
66 rc-powercolor-real-angel.o \
67 rc-proteus-2309.o \
68 rc-purpletv.o \
69 rc-pv951.o \
70 rc-rc5-hauppauge-new.o \
71 rc-rc5-tv.o \
72 rc-rc6-mce.o \
73 rc-real-audio-220-32-keys.o \
74 rc-streamzap.o \
75 rc-tbs-nec.o \
76 rc-terratec-cinergy-xs.o \
77 rc-terratec-slim.o \
78 rc-tevii-nec.o \
79 rc-total-media-in-hand.o \
80 rc-trekstor.o \
81 rc-tt-1500.o \
82 rc-twinhan1027.o \
83 rc-videomate-s350.o \
84 rc-videomate-tv-pvr.o \
85 rc-winfast.o \
86 rc-winfast-usbii-deluxe.o
diff --git a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c
new file mode 100644
index 000000000000..b17283176ecd
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c
@@ -0,0 +1,89 @@
1/* adstech-dvb-t-pci.h - Keytable for adstech_dvb_t_pci Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* ADS Tech Instant TV DVB-T PCI Remote */
16
17static struct ir_scancode adstech_dvb_t_pci[] = {
18 /* Keys 0 to 9 */
19 { 0x4d, KEY_0 },
20 { 0x57, KEY_1 },
21 { 0x4f, KEY_2 },
22 { 0x53, KEY_3 },
23 { 0x56, KEY_4 },
24 { 0x4e, KEY_5 },
25 { 0x5e, KEY_6 },
26 { 0x54, KEY_7 },
27 { 0x4c, KEY_8 },
28 { 0x5c, KEY_9 },
29
30 { 0x5b, KEY_POWER },
31 { 0x5f, KEY_MUTE },
32 { 0x55, KEY_GOTO },
33 { 0x5d, KEY_SEARCH },
34 { 0x17, KEY_EPG }, /* Guide */
35 { 0x1f, KEY_MENU },
36 { 0x0f, KEY_UP },
37 { 0x46, KEY_DOWN },
38 { 0x16, KEY_LEFT },
39 { 0x1e, KEY_RIGHT },
40 { 0x0e, KEY_SELECT }, /* Enter */
41 { 0x5a, KEY_INFO },
42 { 0x52, KEY_EXIT },
43 { 0x59, KEY_PREVIOUS },
44 { 0x51, KEY_NEXT },
45 { 0x58, KEY_REWIND },
46 { 0x50, KEY_FORWARD },
47 { 0x44, KEY_PLAYPAUSE },
48 { 0x07, KEY_STOP },
49 { 0x1b, KEY_RECORD },
50 { 0x13, KEY_TUNER }, /* Live */
51 { 0x0a, KEY_A },
52 { 0x12, KEY_B },
53 { 0x03, KEY_PROG1 }, /* 1 */
54 { 0x01, KEY_PROG2 }, /* 2 */
55 { 0x00, KEY_PROG3 }, /* 3 */
56 { 0x06, KEY_DVD },
57 { 0x48, KEY_AUX }, /* Photo */
58 { 0x40, KEY_VIDEO },
59 { 0x19, KEY_AUDIO }, /* Music */
60 { 0x0b, KEY_CHANNELUP },
61 { 0x08, KEY_CHANNELDOWN },
62 { 0x15, KEY_VOLUMEUP },
63 { 0x1c, KEY_VOLUMEDOWN },
64};
65
66static struct rc_keymap adstech_dvb_t_pci_map = {
67 .map = {
68 .scan = adstech_dvb_t_pci,
69 .size = ARRAY_SIZE(adstech_dvb_t_pci),
70 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
71 .name = RC_MAP_ADSTECH_DVB_T_PCI,
72 }
73};
74
75static int __init init_rc_map_adstech_dvb_t_pci(void)
76{
77 return ir_register_map(&adstech_dvb_t_pci_map);
78}
79
80static void __exit exit_rc_map_adstech_dvb_t_pci(void)
81{
82 ir_unregister_map(&adstech_dvb_t_pci_map);
83}
84
85module_init(init_rc_map_adstech_dvb_t_pci)
86module_exit(exit_rc_map_adstech_dvb_t_pci)
87
88MODULE_LICENSE("GPL");
89MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-alink-dtu-m.c b/drivers/media/rc/keymaps/rc-alink-dtu-m.c
new file mode 100644
index 000000000000..ddfee7f8093d
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-alink-dtu-m.c
@@ -0,0 +1,68 @@
1/*
2 * A-Link DTU(m) remote controller keytable
3 *
4 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <media/rc-map.h>
22
23/* A-Link DTU(m) slim remote, 6 rows, 3 columns. */
24static struct ir_scancode alink_dtu_m[] = {
25 { 0x0800, KEY_VOLUMEUP },
26 { 0x0801, KEY_1 },
27 { 0x0802, KEY_3 },
28 { 0x0803, KEY_7 },
29 { 0x0804, KEY_9 },
30 { 0x0805, KEY_NEW }, /* symbol: PIP */
31 { 0x0806, KEY_0 },
32 { 0x0807, KEY_CHANNEL }, /* JUMP */
33 { 0x080d, KEY_5 },
34 { 0x080f, KEY_2 },
35 { 0x0812, KEY_POWER2 },
36 { 0x0814, KEY_CHANNELUP },
37 { 0x0816, KEY_VOLUMEDOWN },
38 { 0x0818, KEY_6 },
39 { 0x081a, KEY_MUTE },
40 { 0x081b, KEY_8 },
41 { 0x081c, KEY_4 },
42 { 0x081d, KEY_CHANNELDOWN },
43};
44
45static struct rc_keymap alink_dtu_m_map = {
46 .map = {
47 .scan = alink_dtu_m,
48 .size = ARRAY_SIZE(alink_dtu_m),
49 .ir_type = IR_TYPE_NEC,
50 .name = RC_MAP_ALINK_DTU_M,
51 }
52};
53
54static int __init init_rc_map_alink_dtu_m(void)
55{
56 return ir_register_map(&alink_dtu_m_map);
57}
58
59static void __exit exit_rc_map_alink_dtu_m(void)
60{
61 ir_unregister_map(&alink_dtu_m_map);
62}
63
64module_init(init_rc_map_alink_dtu_m)
65module_exit(exit_rc_map_alink_dtu_m)
66
67MODULE_LICENSE("GPL");
68MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff --git a/drivers/media/rc/keymaps/rc-anysee.c b/drivers/media/rc/keymaps/rc-anysee.c
new file mode 100644
index 000000000000..30d70498cfed
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-anysee.c
@@ -0,0 +1,93 @@
1/*
2 * Anysee remote controller keytable
3 *
4 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <media/rc-map.h>
22
23static struct ir_scancode anysee[] = {
24 { 0x0800, KEY_0 },
25 { 0x0801, KEY_1 },
26 { 0x0802, KEY_2 },
27 { 0x0803, KEY_3 },
28 { 0x0804, KEY_4 },
29 { 0x0805, KEY_5 },
30 { 0x0806, KEY_6 },
31 { 0x0807, KEY_7 },
32 { 0x0808, KEY_8 },
33 { 0x0809, KEY_9 },
34 { 0x080a, KEY_POWER2 }, /* [red power button] */
35 { 0x080b, KEY_VIDEO }, /* [*] MODE */
36 { 0x080c, KEY_CHANNEL }, /* [symbol counterclockwise arrow] */
37 { 0x080d, KEY_NEXT }, /* [>>|] */
38 { 0x080e, KEY_MENU }, /* MENU */
39 { 0x080f, KEY_EPG }, /* [EPG] */
40 { 0x0810, KEY_CLEAR }, /* EXIT */
41 { 0x0811, KEY_CHANNELUP },
42 { 0x0812, KEY_VOLUMEDOWN },
43 { 0x0813, KEY_VOLUMEUP },
44 { 0x0814, KEY_CHANNELDOWN },
45 { 0x0815, KEY_OK },
46 { 0x0816, KEY_RADIO }, /* [symbol TV/radio] */
47 { 0x0817, KEY_INFO }, /* [i] */
48 { 0x0818, KEY_PREVIOUS }, /* [|<<] */
49 { 0x0819, KEY_FAVORITES }, /* FAV. */
50 { 0x081a, KEY_SUBTITLE }, /* Subtitle */
51 { 0x081b, KEY_CAMERA }, /* [symbol camera] */
52 { 0x081c, KEY_YELLOW },
53 { 0x081d, KEY_RED },
54 { 0x081e, KEY_LANGUAGE }, /* [symbol Second Audio Program] */
55 { 0x081f, KEY_GREEN },
56 { 0x0820, KEY_SLEEP }, /* Sleep */
57 { 0x0821, KEY_SCREEN }, /* 16:9 / 4:3 */
58 { 0x0822, KEY_ZOOM }, /* SIZE */
59 { 0x0824, KEY_FN }, /* [F1] */
60 { 0x0825, KEY_FN }, /* [F2] */
61 { 0x0842, KEY_MUTE }, /* symbol mute */
62 { 0x0844, KEY_BLUE },
63 { 0x0847, KEY_TEXT }, /* TEXT */
64 { 0x0848, KEY_STOP },
65 { 0x0849, KEY_RECORD },
66 { 0x0850, KEY_PLAY },
67 { 0x0851, KEY_PAUSE },
68};
69
70static struct rc_keymap anysee_map = {
71 .map = {
72 .scan = anysee,
73 .size = ARRAY_SIZE(anysee),
74 .ir_type = IR_TYPE_NEC,
75 .name = RC_MAP_ANYSEE,
76 }
77};
78
79static int __init init_rc_map_anysee(void)
80{
81 return ir_register_map(&anysee_map);
82}
83
84static void __exit exit_rc_map_anysee(void)
85{
86 ir_unregister_map(&anysee_map);
87}
88
89module_init(init_rc_map_anysee)
90module_exit(exit_rc_map_anysee)
91
92MODULE_LICENSE("GPL");
93MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff --git a/drivers/media/rc/keymaps/rc-apac-viewcomp.c b/drivers/media/rc/keymaps/rc-apac-viewcomp.c
new file mode 100644
index 000000000000..0ef2b562baf0
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-apac-viewcomp.c
@@ -0,0 +1,80 @@
1/* apac-viewcomp.h - Keytable for apac_viewcomp Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Attila Kondoros <attila.kondoros@chello.hu> */
16
17static struct ir_scancode apac_viewcomp[] = {
18
19 { 0x01, KEY_1 },
20 { 0x02, KEY_2 },
21 { 0x03, KEY_3 },
22 { 0x04, KEY_4 },
23 { 0x05, KEY_5 },
24 { 0x06, KEY_6 },
25 { 0x07, KEY_7 },
26 { 0x08, KEY_8 },
27 { 0x09, KEY_9 },
28 { 0x00, KEY_0 },
29 { 0x17, KEY_LAST }, /* +100 */
30 { 0x0a, KEY_LIST }, /* recall */
31
32
33 { 0x1c, KEY_TUNER }, /* TV/FM */
34 { 0x15, KEY_SEARCH }, /* scan */
35 { 0x12, KEY_POWER }, /* power */
36 { 0x1f, KEY_VOLUMEDOWN }, /* vol up */
37 { 0x1b, KEY_VOLUMEUP }, /* vol down */
38 { 0x1e, KEY_CHANNELDOWN }, /* chn up */
39 { 0x1a, KEY_CHANNELUP }, /* chn down */
40
41 { 0x11, KEY_VIDEO }, /* video */
42 { 0x0f, KEY_ZOOM }, /* full screen */
43 { 0x13, KEY_MUTE }, /* mute/unmute */
44 { 0x10, KEY_TEXT }, /* min */
45
46 { 0x0d, KEY_STOP }, /* freeze */
47 { 0x0e, KEY_RECORD }, /* record */
48 { 0x1d, KEY_PLAYPAUSE }, /* stop */
49 { 0x19, KEY_PLAY }, /* play */
50
51 { 0x16, KEY_GOTO }, /* osd */
52 { 0x14, KEY_REFRESH }, /* default */
53 { 0x0c, KEY_KPPLUS }, /* fine tune >>>> */
54 { 0x18, KEY_KPMINUS }, /* fine tune <<<< */
55};
56
57static struct rc_keymap apac_viewcomp_map = {
58 .map = {
59 .scan = apac_viewcomp,
60 .size = ARRAY_SIZE(apac_viewcomp),
61 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
62 .name = RC_MAP_APAC_VIEWCOMP,
63 }
64};
65
66static int __init init_rc_map_apac_viewcomp(void)
67{
68 return ir_register_map(&apac_viewcomp_map);
69}
70
71static void __exit exit_rc_map_apac_viewcomp(void)
72{
73 ir_unregister_map(&apac_viewcomp_map);
74}
75
76module_init(init_rc_map_apac_viewcomp)
77module_exit(exit_rc_map_apac_viewcomp)
78
79MODULE_LICENSE("GPL");
80MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-asus-pc39.c b/drivers/media/rc/keymaps/rc-asus-pc39.c
new file mode 100644
index 000000000000..2996e0a3b8d5
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-asus-pc39.c
@@ -0,0 +1,91 @@
1/* asus-pc39.h - Keytable for asus_pc39 Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/*
16 * Marc Fargas <telenieko@telenieko.com>
17 * this is the remote control that comes with the asus p7131
18 * which has a label saying is "Model PC-39"
19 */
20
21static struct ir_scancode asus_pc39[] = {
22 /* Keys 0 to 9 */
23 { 0x082a, KEY_0 },
24 { 0x0816, KEY_1 },
25 { 0x0812, KEY_2 },
26 { 0x0814, KEY_3 },
27 { 0x0836, KEY_4 },
28 { 0x0832, KEY_5 },
29 { 0x0834, KEY_6 },
30 { 0x080e, KEY_7 },
31 { 0x080a, KEY_8 },
32 { 0x080c, KEY_9 },
33
34 { 0x0801, KEY_RADIO }, /* radio */
35 { 0x083c, KEY_MENU }, /* dvd/menu */
36 { 0x0815, KEY_VOLUMEUP },
37 { 0x0826, KEY_VOLUMEDOWN },
38 { 0x0808, KEY_UP },
39 { 0x0804, KEY_DOWN },
40 { 0x0818, KEY_LEFT },
41 { 0x0810, KEY_RIGHT },
42 { 0x081a, KEY_VIDEO }, /* video */
43 { 0x0806, KEY_AUDIO }, /* music */
44
45 { 0x081e, KEY_TV }, /* tv */
46 { 0x0822, KEY_EXIT }, /* back */
47 { 0x0835, KEY_CHANNELUP }, /* channel / program + */
48 { 0x0824, KEY_CHANNELDOWN }, /* channel / program - */
49 { 0x0825, KEY_ENTER }, /* enter */
50
51 { 0x0839, KEY_PAUSE }, /* play/pause */
52 { 0x0821, KEY_PREVIOUS }, /* rew */
53 { 0x0819, KEY_NEXT }, /* forward */
54 { 0x0831, KEY_REWIND }, /* backward << */
55 { 0x0805, KEY_FASTFORWARD }, /* forward >> */
56 { 0x0809, KEY_STOP },
57 { 0x0811, KEY_RECORD }, /* recording */
58 { 0x0829, KEY_POWER }, /* the button that reads "close" */
59
60 { 0x082e, KEY_ZOOM }, /* full screen */
61 { 0x082c, KEY_MACRO }, /* recall */
62 { 0x081c, KEY_HOME }, /* home */
63 { 0x083a, KEY_PVR }, /* picture */
64 { 0x0802, KEY_MUTE }, /* mute */
65 { 0x083e, KEY_DVD }, /* dvd */
66};
67
68static struct rc_keymap asus_pc39_map = {
69 .map = {
70 .scan = asus_pc39,
71 .size = ARRAY_SIZE(asus_pc39),
72 .ir_type = IR_TYPE_RC5,
73 .name = RC_MAP_ASUS_PC39,
74 }
75};
76
77static int __init init_rc_map_asus_pc39(void)
78{
79 return ir_register_map(&asus_pc39_map);
80}
81
82static void __exit exit_rc_map_asus_pc39(void)
83{
84 ir_unregister_map(&asus_pc39_map);
85}
86
87module_init(init_rc_map_asus_pc39)
88module_exit(exit_rc_map_asus_pc39)
89
90MODULE_LICENSE("GPL");
91MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c b/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c
new file mode 100644
index 000000000000..8edfd293d010
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c
@@ -0,0 +1,69 @@
1/* ati-tv-wonder-hd-600.h - Keytable for ati_tv_wonder_hd_600 Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* ATI TV Wonder HD 600 USB
16 Devin Heitmueller <devin.heitmueller@gmail.com>
17 */
18
19static struct ir_scancode ati_tv_wonder_hd_600[] = {
20 { 0x00, KEY_RECORD}, /* Row 1 */
21 { 0x01, KEY_PLAYPAUSE},
22 { 0x02, KEY_STOP},
23 { 0x03, KEY_POWER},
24 { 0x04, KEY_PREVIOUS}, /* Row 2 */
25 { 0x05, KEY_REWIND},
26 { 0x06, KEY_FORWARD},
27 { 0x07, KEY_NEXT},
28 { 0x08, KEY_EPG}, /* Row 3 */
29 { 0x09, KEY_HOME},
30 { 0x0a, KEY_MENU},
31 { 0x0b, KEY_CHANNELUP},
32 { 0x0c, KEY_BACK}, /* Row 4 */
33 { 0x0d, KEY_UP},
34 { 0x0e, KEY_INFO},
35 { 0x0f, KEY_CHANNELDOWN},
36 { 0x10, KEY_LEFT}, /* Row 5 */
37 { 0x11, KEY_SELECT},
38 { 0x12, KEY_RIGHT},
39 { 0x13, KEY_VOLUMEUP},
40 { 0x14, KEY_LAST}, /* Row 6 */
41 { 0x15, KEY_DOWN},
42 { 0x16, KEY_MUTE},
43 { 0x17, KEY_VOLUMEDOWN},
44};
45
46static struct rc_keymap ati_tv_wonder_hd_600_map = {
47 .map = {
48 .scan = ati_tv_wonder_hd_600,
49 .size = ARRAY_SIZE(ati_tv_wonder_hd_600),
50 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
51 .name = RC_MAP_ATI_TV_WONDER_HD_600,
52 }
53};
54
55static int __init init_rc_map_ati_tv_wonder_hd_600(void)
56{
57 return ir_register_map(&ati_tv_wonder_hd_600_map);
58}
59
60static void __exit exit_rc_map_ati_tv_wonder_hd_600(void)
61{
62 ir_unregister_map(&ati_tv_wonder_hd_600_map);
63}
64
65module_init(init_rc_map_ati_tv_wonder_hd_600)
66module_exit(exit_rc_map_ati_tv_wonder_hd_600)
67
68MODULE_LICENSE("GPL");
69MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-avermedia-a16d.c b/drivers/media/rc/keymaps/rc-avermedia-a16d.c
new file mode 100644
index 000000000000..12f043587f2e
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avermedia-a16d.c
@@ -0,0 +1,75 @@
1/* avermedia-a16d.h - Keytable for avermedia_a16d Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode avermedia_a16d[] = {
16 { 0x20, KEY_LIST},
17 { 0x00, KEY_POWER},
18 { 0x28, KEY_1},
19 { 0x18, KEY_2},
20 { 0x38, KEY_3},
21 { 0x24, KEY_4},
22 { 0x14, KEY_5},
23 { 0x34, KEY_6},
24 { 0x2c, KEY_7},
25 { 0x1c, KEY_8},
26 { 0x3c, KEY_9},
27 { 0x12, KEY_SUBTITLE},
28 { 0x22, KEY_0},
29 { 0x32, KEY_REWIND},
30 { 0x3a, KEY_SHUFFLE},
31 { 0x02, KEY_PRINT},
32 { 0x11, KEY_CHANNELDOWN},
33 { 0x31, KEY_CHANNELUP},
34 { 0x0c, KEY_ZOOM},
35 { 0x1e, KEY_VOLUMEDOWN},
36 { 0x3e, KEY_VOLUMEUP},
37 { 0x0a, KEY_MUTE},
38 { 0x04, KEY_AUDIO},
39 { 0x26, KEY_RECORD},
40 { 0x06, KEY_PLAY},
41 { 0x36, KEY_STOP},
42 { 0x16, KEY_PAUSE},
43 { 0x2e, KEY_REWIND},
44 { 0x0e, KEY_FASTFORWARD},
45 { 0x30, KEY_TEXT},
46 { 0x21, KEY_GREEN},
47 { 0x01, KEY_BLUE},
48 { 0x08, KEY_EPG},
49 { 0x2a, KEY_MENU},
50};
51
52static struct rc_keymap avermedia_a16d_map = {
53 .map = {
54 .scan = avermedia_a16d,
55 .size = ARRAY_SIZE(avermedia_a16d),
56 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
57 .name = RC_MAP_AVERMEDIA_A16D,
58 }
59};
60
61static int __init init_rc_map_avermedia_a16d(void)
62{
63 return ir_register_map(&avermedia_a16d_map);
64}
65
66static void __exit exit_rc_map_avermedia_a16d(void)
67{
68 ir_unregister_map(&avermedia_a16d_map);
69}
70
71module_init(init_rc_map_avermedia_a16d)
72module_exit(exit_rc_map_avermedia_a16d)
73
74MODULE_LICENSE("GPL");
75MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c
new file mode 100644
index 000000000000..2a945b02e8ca
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c
@@ -0,0 +1,97 @@
1/* avermedia-cardbus.h - Keytable for avermedia_cardbus Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Oldrich Jedlicka <oldium.pro@seznam.cz> */
16
17static struct ir_scancode avermedia_cardbus[] = {
18 { 0x00, KEY_POWER },
19 { 0x01, KEY_TUNER }, /* TV/FM */
20 { 0x03, KEY_TEXT }, /* Teletext */
21 { 0x04, KEY_EPG },
22 { 0x05, KEY_1 },
23 { 0x06, KEY_2 },
24 { 0x07, KEY_3 },
25 { 0x08, KEY_AUDIO },
26 { 0x09, KEY_4 },
27 { 0x0a, KEY_5 },
28 { 0x0b, KEY_6 },
29 { 0x0c, KEY_ZOOM }, /* Full screen */
30 { 0x0d, KEY_7 },
31 { 0x0e, KEY_8 },
32 { 0x0f, KEY_9 },
33 { 0x10, KEY_PAGEUP }, /* 16-CH PREV */
34 { 0x11, KEY_0 },
35 { 0x12, KEY_INFO },
36 { 0x13, KEY_AGAIN }, /* CH RTN - channel return */
37 { 0x14, KEY_MUTE },
38 { 0x15, KEY_EDIT }, /* Autoscan */
39 { 0x17, KEY_SAVE }, /* Screenshot */
40 { 0x18, KEY_PLAYPAUSE },
41 { 0x19, KEY_RECORD },
42 { 0x1a, KEY_PLAY },
43 { 0x1b, KEY_STOP },
44 { 0x1c, KEY_FASTFORWARD },
45 { 0x1d, KEY_REWIND },
46 { 0x1e, KEY_VOLUMEDOWN },
47 { 0x1f, KEY_VOLUMEUP },
48 { 0x22, KEY_SLEEP }, /* Sleep */
49 { 0x23, KEY_ZOOM }, /* Aspect */
50 { 0x26, KEY_SCREEN }, /* Pos */
51 { 0x27, KEY_ANGLE }, /* Size */
52 { 0x28, KEY_SELECT }, /* Select */
53 { 0x29, KEY_BLUE }, /* Blue/Picture */
54 { 0x2a, KEY_BACKSPACE }, /* Back */
55 { 0x2b, KEY_MEDIA }, /* PIP (Picture-in-picture) */
56 { 0x2c, KEY_DOWN },
57 { 0x2e, KEY_DOT },
58 { 0x2f, KEY_TV }, /* Live TV */
59 { 0x32, KEY_LEFT },
60 { 0x33, KEY_CLEAR }, /* Clear */
61 { 0x35, KEY_RED }, /* Red/TV */
62 { 0x36, KEY_UP },
63 { 0x37, KEY_HOME }, /* Home */
64 { 0x39, KEY_GREEN }, /* Green/Video */
65 { 0x3d, KEY_YELLOW }, /* Yellow/Music */
66 { 0x3e, KEY_OK }, /* Ok */
67 { 0x3f, KEY_RIGHT },
68 { 0x40, KEY_NEXT }, /* Next */
69 { 0x41, KEY_PREVIOUS }, /* Previous */
70 { 0x42, KEY_CHANNELDOWN }, /* Channel down */
71 { 0x43, KEY_CHANNELUP }, /* Channel up */
72};
73
74static struct rc_keymap avermedia_cardbus_map = {
75 .map = {
76 .scan = avermedia_cardbus,
77 .size = ARRAY_SIZE(avermedia_cardbus),
78 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
79 .name = RC_MAP_AVERMEDIA_CARDBUS,
80 }
81};
82
83static int __init init_rc_map_avermedia_cardbus(void)
84{
85 return ir_register_map(&avermedia_cardbus_map);
86}
87
88static void __exit exit_rc_map_avermedia_cardbus(void)
89{
90 ir_unregister_map(&avermedia_cardbus_map);
91}
92
93module_init(init_rc_map_avermedia_cardbus)
94module_exit(exit_rc_map_avermedia_cardbus)
95
96MODULE_LICENSE("GPL");
97MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c
new file mode 100644
index 000000000000..39dde6222875
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c
@@ -0,0 +1,78 @@
1/* avermedia-dvbt.h - Keytable for avermedia_dvbt Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Matt Jesson <dvb@jesson.eclipse.co.uk */
16
17static struct ir_scancode avermedia_dvbt[] = {
18 { 0x28, KEY_0 }, /* '0' / 'enter' */
19 { 0x22, KEY_1 }, /* '1' */
20 { 0x12, KEY_2 }, /* '2' / 'up arrow' */
21 { 0x32, KEY_3 }, /* '3' */
22 { 0x24, KEY_4 }, /* '4' / 'left arrow' */
23 { 0x14, KEY_5 }, /* '5' */
24 { 0x34, KEY_6 }, /* '6' / 'right arrow' */
25 { 0x26, KEY_7 }, /* '7' */
26 { 0x16, KEY_8 }, /* '8' / 'down arrow' */
27 { 0x36, KEY_9 }, /* '9' */
28
29 { 0x20, KEY_LIST }, /* 'source' */
30 { 0x10, KEY_TEXT }, /* 'teletext' */
31 { 0x00, KEY_POWER }, /* 'power' */
32 { 0x04, KEY_AUDIO }, /* 'audio' */
33 { 0x06, KEY_ZOOM }, /* 'full screen' */
34 { 0x18, KEY_VIDEO }, /* 'display' */
35 { 0x38, KEY_SEARCH }, /* 'loop' */
36 { 0x08, KEY_INFO }, /* 'preview' */
37 { 0x2a, KEY_REWIND }, /* 'backward <<' */
38 { 0x1a, KEY_FASTFORWARD }, /* 'forward >>' */
39 { 0x3a, KEY_RECORD }, /* 'capture' */
40 { 0x0a, KEY_MUTE }, /* 'mute' */
41 { 0x2c, KEY_RECORD }, /* 'record' */
42 { 0x1c, KEY_PAUSE }, /* 'pause' */
43 { 0x3c, KEY_STOP }, /* 'stop' */
44 { 0x0c, KEY_PLAY }, /* 'play' */
45 { 0x2e, KEY_RED }, /* 'red' */
46 { 0x01, KEY_BLUE }, /* 'blue' / 'cancel' */
47 { 0x0e, KEY_YELLOW }, /* 'yellow' / 'ok' */
48 { 0x21, KEY_GREEN }, /* 'green' */
49 { 0x11, KEY_CHANNELDOWN }, /* 'channel -' */
50 { 0x31, KEY_CHANNELUP }, /* 'channel +' */
51 { 0x1e, KEY_VOLUMEDOWN }, /* 'volume -' */
52 { 0x3e, KEY_VOLUMEUP }, /* 'volume +' */
53};
54
55static struct rc_keymap avermedia_dvbt_map = {
56 .map = {
57 .scan = avermedia_dvbt,
58 .size = ARRAY_SIZE(avermedia_dvbt),
59 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
60 .name = RC_MAP_AVERMEDIA_DVBT,
61 }
62};
63
64static int __init init_rc_map_avermedia_dvbt(void)
65{
66 return ir_register_map(&avermedia_dvbt_map);
67}
68
69static void __exit exit_rc_map_avermedia_dvbt(void)
70{
71 ir_unregister_map(&avermedia_dvbt_map);
72}
73
74module_init(init_rc_map_avermedia_dvbt)
75module_exit(exit_rc_map_avermedia_dvbt)
76
77MODULE_LICENSE("GPL");
78MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-avermedia-m135a.c b/drivers/media/rc/keymaps/rc-avermedia-m135a.c
new file mode 100644
index 000000000000..e4471fb2ad1e
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avermedia-m135a.c
@@ -0,0 +1,147 @@
1/* avermedia-m135a.c - Keytable for Avermedia M135A Remote Controllers
2 *
3 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 * Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <media/rc-map.h>
13
14/*
15 * Avermedia M135A with RM-JX and RM-K6 remote controls
16 *
17 * On Avermedia M135A with IR model RM-JX, the same codes exist on both
18 * Positivo (BR) and original IR, initial version and remote control codes
19 * added by Mauro Carvalho Chehab <mchehab@infradead.org>
20 *
21 * Positivo also ships Avermedia M135A with model RM-K6, extra control
22 * codes added by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
23 */
24
25static struct ir_scancode avermedia_m135a[] = {
26 /* RM-JX */
27 { 0x0200, KEY_POWER2 },
28 { 0x022e, KEY_DOT }, /* '.' */
29 { 0x0201, KEY_MODE }, /* TV/FM or SOURCE */
30
31 { 0x0205, KEY_1 },
32 { 0x0206, KEY_2 },
33 { 0x0207, KEY_3 },
34 { 0x0209, KEY_4 },
35 { 0x020a, KEY_5 },
36 { 0x020b, KEY_6 },
37 { 0x020d, KEY_7 },
38 { 0x020e, KEY_8 },
39 { 0x020f, KEY_9 },
40 { 0x0211, KEY_0 },
41
42 { 0x0213, KEY_RIGHT }, /* -> or L */
43 { 0x0212, KEY_LEFT }, /* <- or R */
44
45 { 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */
46 { 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */
47
48 { 0x0303, KEY_CHANNELUP },
49 { 0x0302, KEY_CHANNELDOWN },
50 { 0x021f, KEY_VOLUMEUP },
51 { 0x021e, KEY_VOLUMEDOWN },
52 { 0x020c, KEY_ENTER }, /* Full Screen */
53
54 { 0x0214, KEY_MUTE },
55 { 0x0208, KEY_AUDIO },
56
57 { 0x0203, KEY_TEXT }, /* Teletext */
58 { 0x0204, KEY_EPG },
59 { 0x022b, KEY_TV2 }, /* TV2 or PIP */
60
61 { 0x021d, KEY_RED },
62 { 0x021c, KEY_YELLOW },
63 { 0x0301, KEY_GREEN },
64 { 0x0300, KEY_BLUE },
65
66 { 0x021a, KEY_PLAYPAUSE },
67 { 0x0219, KEY_RECORD },
68 { 0x0218, KEY_PLAY },
69 { 0x021b, KEY_STOP },
70
71 /* RM-K6 */
72 { 0x0401, KEY_POWER2 },
73 { 0x0406, KEY_MUTE },
74 { 0x0408, KEY_MODE }, /* TV/FM */
75
76 { 0x0409, KEY_1 },
77 { 0x040a, KEY_2 },
78 { 0x040b, KEY_3 },
79 { 0x040c, KEY_4 },
80 { 0x040d, KEY_5 },
81 { 0x040e, KEY_6 },
82 { 0x040f, KEY_7 },
83 { 0x0410, KEY_8 },
84 { 0x0411, KEY_9 },
85 { 0x044c, KEY_DOT }, /* '.' */
86 { 0x0412, KEY_0 },
87 { 0x0407, KEY_REFRESH }, /* Refresh/Reload */
88
89 { 0x0413, KEY_AUDIO },
90 { 0x0440, KEY_SCREEN }, /* Full Screen toggle */
91 { 0x0441, KEY_HOME },
92 { 0x0442, KEY_BACK },
93 { 0x0447, KEY_UP },
94 { 0x0448, KEY_DOWN },
95 { 0x0449, KEY_LEFT },
96 { 0x044a, KEY_RIGHT },
97 { 0x044b, KEY_OK },
98 { 0x0404, KEY_VOLUMEUP },
99 { 0x0405, KEY_VOLUMEDOWN },
100 { 0x0402, KEY_CHANNELUP },
101 { 0x0403, KEY_CHANNELDOWN },
102
103 { 0x0443, KEY_RED },
104 { 0x0444, KEY_GREEN },
105 { 0x0445, KEY_YELLOW },
106 { 0x0446, KEY_BLUE },
107
108 { 0x0414, KEY_TEXT },
109 { 0x0415, KEY_EPG },
110 { 0x041a, KEY_TV2 }, /* PIP */
111 { 0x041b, KEY_MHP }, /* Snapshot */
112
113 { 0x0417, KEY_RECORD },
114 { 0x0416, KEY_PLAYPAUSE },
115 { 0x0418, KEY_STOP },
116 { 0x0419, KEY_PAUSE },
117
118 { 0x041f, KEY_PREVIOUS },
119 { 0x041c, KEY_REWIND },
120 { 0x041d, KEY_FORWARD },
121 { 0x041e, KEY_NEXT },
122};
123
124static struct rc_keymap avermedia_m135a_map = {
125 .map = {
126 .scan = avermedia_m135a,
127 .size = ARRAY_SIZE(avermedia_m135a),
128 .ir_type = IR_TYPE_NEC,
129 .name = RC_MAP_AVERMEDIA_M135A,
130 }
131};
132
133static int __init init_rc_map_avermedia_m135a(void)
134{
135 return ir_register_map(&avermedia_m135a_map);
136}
137
138static void __exit exit_rc_map_avermedia_m135a(void)
139{
140 ir_unregister_map(&avermedia_m135a_map);
141}
142
143module_init(init_rc_map_avermedia_m135a)
144module_exit(exit_rc_map_avermedia_m135a)
145
146MODULE_LICENSE("GPL");
147MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c
new file mode 100644
index 000000000000..cf8d45717cb3
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c
@@ -0,0 +1,95 @@
1/* avermedia-m733a-rm-k6.h - Keytable for avermedia_m733a_rm_k6 Remote Controller
2 *
3 * Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 */
10
11#include <media/rc-map.h>
12
13/*
14 * Avermedia M733A with IR model RM-K6
15 * This is the stock remote controller used with Positivo machines with M733A
16 * Herton Ronaldo Krzesinski <herton@mandriva.com.br>
17 */
18
19static struct ir_scancode avermedia_m733a_rm_k6[] = {
20 { 0x0401, KEY_POWER2 },
21 { 0x0406, KEY_MUTE },
22 { 0x0408, KEY_MODE }, /* TV/FM */
23
24 { 0x0409, KEY_1 },
25 { 0x040a, KEY_2 },
26 { 0x040b, KEY_3 },
27 { 0x040c, KEY_4 },
28 { 0x040d, KEY_5 },
29 { 0x040e, KEY_6 },
30 { 0x040f, KEY_7 },
31 { 0x0410, KEY_8 },
32 { 0x0411, KEY_9 },
33 { 0x044c, KEY_DOT }, /* '.' */
34 { 0x0412, KEY_0 },
35 { 0x0407, KEY_REFRESH }, /* Refresh/Reload */
36
37 { 0x0413, KEY_AUDIO },
38 { 0x0440, KEY_SCREEN }, /* Full Screen toggle */
39 { 0x0441, KEY_HOME },
40 { 0x0442, KEY_BACK },
41 { 0x0447, KEY_UP },
42 { 0x0448, KEY_DOWN },
43 { 0x0449, KEY_LEFT },
44 { 0x044a, KEY_RIGHT },
45 { 0x044b, KEY_OK },
46 { 0x0404, KEY_VOLUMEUP },
47 { 0x0405, KEY_VOLUMEDOWN },
48 { 0x0402, KEY_CHANNELUP },
49 { 0x0403, KEY_CHANNELDOWN },
50
51 { 0x0443, KEY_RED },
52 { 0x0444, KEY_GREEN },
53 { 0x0445, KEY_YELLOW },
54 { 0x0446, KEY_BLUE },
55
56 { 0x0414, KEY_TEXT },
57 { 0x0415, KEY_EPG },
58 { 0x041a, KEY_TV2 }, /* PIP */
59 { 0x041b, KEY_MHP }, /* Snapshot */
60
61 { 0x0417, KEY_RECORD },
62 { 0x0416, KEY_PLAYPAUSE },
63 { 0x0418, KEY_STOP },
64 { 0x0419, KEY_PAUSE },
65
66 { 0x041f, KEY_PREVIOUS },
67 { 0x041c, KEY_REWIND },
68 { 0x041d, KEY_FORWARD },
69 { 0x041e, KEY_NEXT },
70};
71
72static struct rc_keymap avermedia_m733a_rm_k6_map = {
73 .map = {
74 .scan = avermedia_m733a_rm_k6,
75 .size = ARRAY_SIZE(avermedia_m733a_rm_k6),
76 .ir_type = IR_TYPE_NEC,
77 .name = RC_MAP_AVERMEDIA_M733A_RM_K6,
78 }
79};
80
81static int __init init_rc_map_avermedia_m733a_rm_k6(void)
82{
83 return ir_register_map(&avermedia_m733a_rm_k6_map);
84}
85
86static void __exit exit_rc_map_avermedia_m733a_rm_k6(void)
87{
88 ir_unregister_map(&avermedia_m733a_rm_k6_map);
89}
90
91module_init(init_rc_map_avermedia_m733a_rm_k6)
92module_exit(exit_rc_map_avermedia_m733a_rm_k6)
93
94MODULE_LICENSE("GPL");
95MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c
new file mode 100644
index 000000000000..9ee60906c861
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c
@@ -0,0 +1,79 @@
1/*
2 * AverMedia RM-KS remote controller keytable
3 *
4 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <media/rc-map.h>
22
23/* Initial keytable is from Jose Alberto Reguero <jareguero@telefonica.net>
24 and Felipe Morales Moreno <felipe.morales.moreno@gmail.com> */
25/* FIXME: mappings are not 100% correct? */
26static struct ir_scancode avermedia_rm_ks[] = {
27 { 0x0501, KEY_POWER2 },
28 { 0x0502, KEY_CHANNELUP },
29 { 0x0503, KEY_CHANNELDOWN },
30 { 0x0504, KEY_VOLUMEUP },
31 { 0x0505, KEY_VOLUMEDOWN },
32 { 0x0506, KEY_MUTE },
33 { 0x0507, KEY_RIGHT },
34 { 0x0508, KEY_PROG1 },
35 { 0x0509, KEY_1 },
36 { 0x050a, KEY_2 },
37 { 0x050b, KEY_3 },
38 { 0x050c, KEY_4 },
39 { 0x050d, KEY_5 },
40 { 0x050e, KEY_6 },
41 { 0x050f, KEY_7 },
42 { 0x0510, KEY_8 },
43 { 0x0511, KEY_9 },
44 { 0x0512, KEY_0 },
45 { 0x0513, KEY_AUDIO },
46 { 0x0515, KEY_EPG },
47 { 0x0516, KEY_PLAY },
48 { 0x0517, KEY_RECORD },
49 { 0x0518, KEY_STOP },
50 { 0x051c, KEY_BACK },
51 { 0x051d, KEY_FORWARD },
52 { 0x054d, KEY_LEFT },
53 { 0x0556, KEY_ZOOM },
54};
55
56static struct rc_keymap avermedia_rm_ks_map = {
57 .map = {
58 .scan = avermedia_rm_ks,
59 .size = ARRAY_SIZE(avermedia_rm_ks),
60 .ir_type = IR_TYPE_NEC,
61 .name = RC_MAP_AVERMEDIA_RM_KS,
62 }
63};
64
65static int __init init_rc_map_avermedia_rm_ks(void)
66{
67 return ir_register_map(&avermedia_rm_ks_map);
68}
69
70static void __exit exit_rc_map_avermedia_rm_ks(void)
71{
72 ir_unregister_map(&avermedia_rm_ks_map);
73}
74
75module_init(init_rc_map_avermedia_rm_ks)
76module_exit(exit_rc_map_avermedia_rm_ks)
77
78MODULE_LICENSE("GPL");
79MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff --git a/drivers/media/rc/keymaps/rc-avermedia.c b/drivers/media/rc/keymaps/rc-avermedia.c
new file mode 100644
index 000000000000..21effd5bfb0d
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avermedia.c
@@ -0,0 +1,86 @@
1/* avermedia.h - Keytable for avermedia Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Alex Hermann <gaaf@gmx.net> */
16
17static struct ir_scancode avermedia[] = {
18 { 0x28, KEY_1 },
19 { 0x18, KEY_2 },
20 { 0x38, KEY_3 },
21 { 0x24, KEY_4 },
22 { 0x14, KEY_5 },
23 { 0x34, KEY_6 },
24 { 0x2c, KEY_7 },
25 { 0x1c, KEY_8 },
26 { 0x3c, KEY_9 },
27 { 0x22, KEY_0 },
28
29 { 0x20, KEY_TV }, /* TV/FM */
30 { 0x10, KEY_CD }, /* CD */
31 { 0x30, KEY_TEXT }, /* TELETEXT */
32 { 0x00, KEY_POWER }, /* POWER */
33
34 { 0x08, KEY_VIDEO }, /* VIDEO */
35 { 0x04, KEY_AUDIO }, /* AUDIO */
36 { 0x0c, KEY_ZOOM }, /* FULL SCREEN */
37
38 { 0x12, KEY_SUBTITLE }, /* DISPLAY */
39 { 0x32, KEY_REWIND }, /* LOOP */
40 { 0x02, KEY_PRINT }, /* PREVIEW */
41
42 { 0x2a, KEY_SEARCH }, /* AUTOSCAN */
43 { 0x1a, KEY_SLEEP }, /* FREEZE */
44 { 0x3a, KEY_CAMERA }, /* SNAPSHOT */
45 { 0x0a, KEY_MUTE }, /* MUTE */
46
47 { 0x26, KEY_RECORD }, /* RECORD */
48 { 0x16, KEY_PAUSE }, /* PAUSE */
49 { 0x36, KEY_STOP }, /* STOP */
50 { 0x06, KEY_PLAY }, /* PLAY */
51
52 { 0x2e, KEY_RED }, /* RED */
53 { 0x21, KEY_GREEN }, /* GREEN */
54 { 0x0e, KEY_YELLOW }, /* YELLOW */
55 { 0x01, KEY_BLUE }, /* BLUE */
56
57 { 0x1e, KEY_VOLUMEDOWN }, /* VOLUME- */
58 { 0x3e, KEY_VOLUMEUP }, /* VOLUME+ */
59 { 0x11, KEY_CHANNELDOWN }, /* CHANNEL/PAGE- */
60 { 0x31, KEY_CHANNELUP } /* CHANNEL/PAGE+ */
61};
62
63static struct rc_keymap avermedia_map = {
64 .map = {
65 .scan = avermedia,
66 .size = ARRAY_SIZE(avermedia),
67 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
68 .name = RC_MAP_AVERMEDIA,
69 }
70};
71
72static int __init init_rc_map_avermedia(void)
73{
74 return ir_register_map(&avermedia_map);
75}
76
77static void __exit exit_rc_map_avermedia(void)
78{
79 ir_unregister_map(&avermedia_map);
80}
81
82module_init(init_rc_map_avermedia)
83module_exit(exit_rc_map_avermedia)
84
85MODULE_LICENSE("GPL");
86MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-avertv-303.c b/drivers/media/rc/keymaps/rc-avertv-303.c
new file mode 100644
index 000000000000..971c59d6f9d6
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avertv-303.c
@@ -0,0 +1,85 @@
1/* avertv-303.h - Keytable for avertv_303 Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* AVERTV STUDIO 303 Remote */
16
17static struct ir_scancode avertv_303[] = {
18 { 0x2a, KEY_1 },
19 { 0x32, KEY_2 },
20 { 0x3a, KEY_3 },
21 { 0x4a, KEY_4 },
22 { 0x52, KEY_5 },
23 { 0x5a, KEY_6 },
24 { 0x6a, KEY_7 },
25 { 0x72, KEY_8 },
26 { 0x7a, KEY_9 },
27 { 0x0e, KEY_0 },
28
29 { 0x02, KEY_POWER },
30 { 0x22, KEY_VIDEO },
31 { 0x42, KEY_AUDIO },
32 { 0x62, KEY_ZOOM },
33 { 0x0a, KEY_TV },
34 { 0x12, KEY_CD },
35 { 0x1a, KEY_TEXT },
36
37 { 0x16, KEY_SUBTITLE },
38 { 0x1e, KEY_REWIND },
39 { 0x06, KEY_PRINT },
40
41 { 0x2e, KEY_SEARCH },
42 { 0x36, KEY_SLEEP },
43 { 0x3e, KEY_SHUFFLE },
44 { 0x26, KEY_MUTE },
45
46 { 0x4e, KEY_RECORD },
47 { 0x56, KEY_PAUSE },
48 { 0x5e, KEY_STOP },
49 { 0x46, KEY_PLAY },
50
51 { 0x6e, KEY_RED },
52 { 0x0b, KEY_GREEN },
53 { 0x66, KEY_YELLOW },
54 { 0x03, KEY_BLUE },
55
56 { 0x76, KEY_LEFT },
57 { 0x7e, KEY_RIGHT },
58 { 0x13, KEY_DOWN },
59 { 0x1b, KEY_UP },
60};
61
62static struct rc_keymap avertv_303_map = {
63 .map = {
64 .scan = avertv_303,
65 .size = ARRAY_SIZE(avertv_303),
66 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
67 .name = RC_MAP_AVERTV_303,
68 }
69};
70
71static int __init init_rc_map_avertv_303(void)
72{
73 return ir_register_map(&avertv_303_map);
74}
75
76static void __exit exit_rc_map_avertv_303(void)
77{
78 ir_unregister_map(&avertv_303_map);
79}
80
81module_init(init_rc_map_avertv_303)
82module_exit(exit_rc_map_avertv_303)
83
84MODULE_LICENSE("GPL");
85MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c b/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c
new file mode 100644
index 000000000000..e0876147d471
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c
@@ -0,0 +1,102 @@
1/*
2 * TwinHan AzureWave AD-TU700(704J) remote controller keytable
3 *
4 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <media/rc-map.h>
22
23static struct ir_scancode azurewave_ad_tu700[] = {
24 { 0x0000, KEY_TAB }, /* Tab */
25 { 0x0001, KEY_2 },
26 { 0x0002, KEY_CHANNELDOWN },
27 { 0x0003, KEY_1 },
28 { 0x0004, KEY_MENU }, /* Record List */
29 { 0x0005, KEY_CHANNELUP },
30 { 0x0006, KEY_3 },
31 { 0x0007, KEY_SLEEP }, /* Hibernate */
32 { 0x0008, KEY_VIDEO }, /* A/V */
33 { 0x0009, KEY_4 },
34 { 0x000a, KEY_VOLUMEDOWN },
35 { 0x000c, KEY_CANCEL }, /* Cancel */
36 { 0x000d, KEY_7 },
37 { 0x000e, KEY_AGAIN }, /* Recall */
38 { 0x000f, KEY_TEXT }, /* Teletext */
39 { 0x0010, KEY_MUTE },
40 { 0x0011, KEY_RECORD },
41 { 0x0012, KEY_FASTFORWARD }, /* FF >> */
42 { 0x0013, KEY_BACK }, /* Back */
43 { 0x0014, KEY_PLAY },
44 { 0x0015, KEY_0 },
45 { 0x0016, KEY_POWER2 }, /* [red power button] */
46 { 0x0017, KEY_FAVORITES }, /* Favorite List */
47 { 0x0018, KEY_RED },
48 { 0x0019, KEY_8 },
49 { 0x001a, KEY_STOP },
50 { 0x001b, KEY_9 },
51 { 0x001c, KEY_EPG }, /* Info/EPG */
52 { 0x001d, KEY_5 },
53 { 0x001e, KEY_VOLUMEUP },
54 { 0x001f, KEY_6 },
55 { 0x0040, KEY_REWIND }, /* FR << */
56 { 0x0041, KEY_PREVIOUS }, /* Replay */
57 { 0x0042, KEY_NEXT }, /* Skip */
58 { 0x0043, KEY_SUBTITLE }, /* Subtitle / CC */
59 { 0x0045, KEY_KPPLUS }, /* Zoom+ */
60 { 0x0046, KEY_KPMINUS }, /* Zoom- */
61 { 0x0047, KEY_NEW }, /* PIP */
62 { 0x0048, KEY_INFO }, /* Preview */
63 { 0x0049, KEY_MODE }, /* L/R */
64 { 0x004a, KEY_CLEAR }, /* Clear */
65 { 0x004b, KEY_UP }, /* up arrow */
66 { 0x004c, KEY_PAUSE },
67 { 0x004d, KEY_ZOOM }, /* Full Screen */
68 { 0x004e, KEY_LEFT }, /* left arrow */
69 { 0x004f, KEY_OK }, /* Enter / ok */
70 { 0x0050, KEY_LANGUAGE }, /* SAP */
71 { 0x0051, KEY_DOWN }, /* down arrow */
72 { 0x0052, KEY_RIGHT }, /* right arrow */
73 { 0x0053, KEY_GREEN },
74 { 0x0054, KEY_CAMERA }, /* Capture */
75 { 0x005e, KEY_YELLOW },
76 { 0x005f, KEY_BLUE },
77};
78
79static struct rc_keymap azurewave_ad_tu700_map = {
80 .map = {
81 .scan = azurewave_ad_tu700,
82 .size = ARRAY_SIZE(azurewave_ad_tu700),
83 .ir_type = IR_TYPE_NEC,
84 .name = RC_MAP_AZUREWAVE_AD_TU700,
85 }
86};
87
88static int __init init_rc_map_azurewave_ad_tu700(void)
89{
90 return ir_register_map(&azurewave_ad_tu700_map);
91}
92
93static void __exit exit_rc_map_azurewave_ad_tu700(void)
94{
95 ir_unregister_map(&azurewave_ad_tu700_map);
96}
97
98module_init(init_rc_map_azurewave_ad_tu700)
99module_exit(exit_rc_map_azurewave_ad_tu700)
100
101MODULE_LICENSE("GPL");
102MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff --git a/drivers/media/rc/keymaps/rc-behold-columbus.c b/drivers/media/rc/keymaps/rc-behold-columbus.c
new file mode 100644
index 000000000000..9f56c98fef5b
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-behold-columbus.c
@@ -0,0 +1,108 @@
1/* behold-columbus.h - Keytable for behold_columbus Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Beholder Intl. Ltd. 2008
16 * Dmitry Belimov d.belimov@google.com
17 * Keytable is used by BeholdTV Columbus
18 * The "ascii-art picture" below (in comments, first row
19 * is the keycode in hex, and subsequent row(s) shows
20 * the button labels (several variants when appropriate)
21 * helps to descide which keycodes to assign to the buttons.
22 */
23
24static struct ir_scancode behold_columbus[] = {
25
26 /* 0x13 0x11 0x1C 0x12 *
27 * Mute Source TV/FM Power *
28 * */
29
30 { 0x13, KEY_MUTE },
31 { 0x11, KEY_PROPS },
32 { 0x1C, KEY_TUNER }, /* KEY_TV/KEY_RADIO */
33 { 0x12, KEY_POWER },
34
35 /* 0x01 0x02 0x03 0x0D *
36 * 1 2 3 Stereo *
37 * *
38 * 0x04 0x05 0x06 0x19 *
39 * 4 5 6 Snapshot *
40 * *
41 * 0x07 0x08 0x09 0x10 *
42 * 7 8 9 Zoom *
43 * */
44 { 0x01, KEY_1 },
45 { 0x02, KEY_2 },
46 { 0x03, KEY_3 },
47 { 0x0D, KEY_SETUP }, /* Setup key */
48 { 0x04, KEY_4 },
49 { 0x05, KEY_5 },
50 { 0x06, KEY_6 },
51 { 0x19, KEY_CAMERA }, /* Snapshot key */
52 { 0x07, KEY_7 },
53 { 0x08, KEY_8 },
54 { 0x09, KEY_9 },
55 { 0x10, KEY_ZOOM },
56
57 /* 0x0A 0x00 0x0B 0x0C *
58 * RECALL 0 ChannelUp VolumeUp *
59 * */
60 { 0x0A, KEY_AGAIN },
61 { 0x00, KEY_0 },
62 { 0x0B, KEY_CHANNELUP },
63 { 0x0C, KEY_VOLUMEUP },
64
65 /* 0x1B 0x1D 0x15 0x18 *
66 * Timeshift Record ChannelDown VolumeDown *
67 * */
68
69 { 0x1B, KEY_TIME },
70 { 0x1D, KEY_RECORD },
71 { 0x15, KEY_CHANNELDOWN },
72 { 0x18, KEY_VOLUMEDOWN },
73
74 /* 0x0E 0x1E 0x0F 0x1A *
75 * Stop Pause Previouse Next *
76 * */
77
78 { 0x0E, KEY_STOP },
79 { 0x1E, KEY_PAUSE },
80 { 0x0F, KEY_PREVIOUS },
81 { 0x1A, KEY_NEXT },
82
83};
84
85static struct rc_keymap behold_columbus_map = {
86 .map = {
87 .scan = behold_columbus,
88 .size = ARRAY_SIZE(behold_columbus),
89 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
90 .name = RC_MAP_BEHOLD_COLUMBUS,
91 }
92};
93
94static int __init init_rc_map_behold_columbus(void)
95{
96 return ir_register_map(&behold_columbus_map);
97}
98
99static void __exit exit_rc_map_behold_columbus(void)
100{
101 ir_unregister_map(&behold_columbus_map);
102}
103
104module_init(init_rc_map_behold_columbus)
105module_exit(exit_rc_map_behold_columbus)
106
107MODULE_LICENSE("GPL");
108MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-behold.c b/drivers/media/rc/keymaps/rc-behold.c
new file mode 100644
index 000000000000..abc140b2098b
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-behold.c
@@ -0,0 +1,141 @@
1/* behold.h - Keytable for behold Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/*
16 * Igor Kuznetsov <igk72@ya.ru>
17 * Andrey J. Melnikov <temnota@kmv.ru>
18 *
19 * Keytable is used by BeholdTV 60x series, M6 series at
20 * least, and probably other cards too.
21 * The "ascii-art picture" below (in comments, first row
22 * is the keycode in hex, and subsequent row(s) shows
23 * the button labels (several variants when appropriate)
24 * helps to descide which keycodes to assign to the buttons.
25 */
26
27static struct ir_scancode behold[] = {
28
29 /* 0x1c 0x12 *
30 * TV/FM POWER *
31 * */
32 { 0x1c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */
33 { 0x12, KEY_POWER },
34
35 /* 0x01 0x02 0x03 *
36 * 1 2 3 *
37 * *
38 * 0x04 0x05 0x06 *
39 * 4 5 6 *
40 * *
41 * 0x07 0x08 0x09 *
42 * 7 8 9 *
43 * */
44 { 0x01, KEY_1 },
45 { 0x02, KEY_2 },
46 { 0x03, KEY_3 },
47 { 0x04, KEY_4 },
48 { 0x05, KEY_5 },
49 { 0x06, KEY_6 },
50 { 0x07, KEY_7 },
51 { 0x08, KEY_8 },
52 { 0x09, KEY_9 },
53
54 /* 0x0a 0x00 0x17 *
55 * RECALL 0 MODE *
56 * */
57 { 0x0a, KEY_AGAIN },
58 { 0x00, KEY_0 },
59 { 0x17, KEY_MODE },
60
61 /* 0x14 0x10 *
62 * ASPECT FULLSCREEN *
63 * */
64 { 0x14, KEY_SCREEN },
65 { 0x10, KEY_ZOOM },
66
67 /* 0x0b *
68 * Up *
69 * *
70 * 0x18 0x16 0x0c *
71 * Left Ok Right *
72 * *
73 * 0x015 *
74 * Down *
75 * */
76 { 0x0b, KEY_CHANNELUP },
77 { 0x18, KEY_VOLUMEDOWN },
78 { 0x16, KEY_OK }, /* XXX KEY_ENTER */
79 { 0x0c, KEY_VOLUMEUP },
80 { 0x15, KEY_CHANNELDOWN },
81
82 /* 0x11 0x0d *
83 * MUTE INFO *
84 * */
85 { 0x11, KEY_MUTE },
86 { 0x0d, KEY_INFO },
87
88 /* 0x0f 0x1b 0x1a *
89 * RECORD PLAY/PAUSE STOP *
90 * *
91 * 0x0e 0x1f 0x1e *
92 *TELETEXT AUDIO SOURCE *
93 * RED YELLOW *
94 * */
95 { 0x0f, KEY_RECORD },
96 { 0x1b, KEY_PLAYPAUSE },
97 { 0x1a, KEY_STOP },
98 { 0x0e, KEY_TEXT },
99 { 0x1f, KEY_RED }, /*XXX KEY_AUDIO */
100 { 0x1e, KEY_YELLOW }, /*XXX KEY_SOURCE */
101
102 /* 0x1d 0x13 0x19 *
103 * SLEEP PREVIEW DVB *
104 * GREEN BLUE *
105 * */
106 { 0x1d, KEY_SLEEP },
107 { 0x13, KEY_GREEN },
108 { 0x19, KEY_BLUE }, /* XXX KEY_SAT */
109
110 /* 0x58 0x5c *
111 * FREEZE SNAPSHOT *
112 * */
113 { 0x58, KEY_SLOW },
114 { 0x5c, KEY_CAMERA },
115
116};
117
118static struct rc_keymap behold_map = {
119 .map = {
120 .scan = behold,
121 .size = ARRAY_SIZE(behold),
122 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
123 .name = RC_MAP_BEHOLD,
124 }
125};
126
127static int __init init_rc_map_behold(void)
128{
129 return ir_register_map(&behold_map);
130}
131
132static void __exit exit_rc_map_behold(void)
133{
134 ir_unregister_map(&behold_map);
135}
136
137module_init(init_rc_map_behold)
138module_exit(exit_rc_map_behold)
139
140MODULE_LICENSE("GPL");
141MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-budget-ci-old.c b/drivers/media/rc/keymaps/rc-budget-ci-old.c
new file mode 100644
index 000000000000..64c2ac913338
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-budget-ci-old.c
@@ -0,0 +1,92 @@
1/* budget-ci-old.h - Keytable for budget_ci_old Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* From reading the following remotes:
16 * Zenith Universal 7 / TV Mode 807 / VCR Mode 837
17 * Hauppauge (from NOVA-CI-s box product)
18 * This is a "middle of the road" approach, differences are noted
19 */
20
21static struct ir_scancode budget_ci_old[] = {
22 { 0x00, KEY_0 },
23 { 0x01, KEY_1 },
24 { 0x02, KEY_2 },
25 { 0x03, KEY_3 },
26 { 0x04, KEY_4 },
27 { 0x05, KEY_5 },
28 { 0x06, KEY_6 },
29 { 0x07, KEY_7 },
30 { 0x08, KEY_8 },
31 { 0x09, KEY_9 },
32 { 0x0a, KEY_ENTER },
33 { 0x0b, KEY_RED },
34 { 0x0c, KEY_POWER }, /* RADIO on Hauppauge */
35 { 0x0d, KEY_MUTE },
36 { 0x0f, KEY_A }, /* TV on Hauppauge */
37 { 0x10, KEY_VOLUMEUP },
38 { 0x11, KEY_VOLUMEDOWN },
39 { 0x14, KEY_B },
40 { 0x1c, KEY_UP },
41 { 0x1d, KEY_DOWN },
42 { 0x1e, KEY_OPTION }, /* RESERVED on Hauppauge */
43 { 0x1f, KEY_BREAK },
44 { 0x20, KEY_CHANNELUP },
45 { 0x21, KEY_CHANNELDOWN },
46 { 0x22, KEY_PREVIOUS }, /* Prev Ch on Zenith, SOURCE on Hauppauge */
47 { 0x24, KEY_RESTART },
48 { 0x25, KEY_OK },
49 { 0x26, KEY_CYCLEWINDOWS }, /* MINIMIZE on Hauppauge */
50 { 0x28, KEY_ENTER }, /* VCR mode on Zenith */
51 { 0x29, KEY_PAUSE },
52 { 0x2b, KEY_RIGHT },
53 { 0x2c, KEY_LEFT },
54 { 0x2e, KEY_MENU }, /* FULL SCREEN on Hauppauge */
55 { 0x30, KEY_SLOW },
56 { 0x31, KEY_PREVIOUS }, /* VCR mode on Zenith */
57 { 0x32, KEY_REWIND },
58 { 0x34, KEY_FASTFORWARD },
59 { 0x35, KEY_PLAY },
60 { 0x36, KEY_STOP },
61 { 0x37, KEY_RECORD },
62 { 0x38, KEY_TUNER }, /* TV/VCR on Zenith */
63 { 0x3a, KEY_C },
64 { 0x3c, KEY_EXIT },
65 { 0x3d, KEY_POWER2 },
66 { 0x3e, KEY_TUNER },
67};
68
69static struct rc_keymap budget_ci_old_map = {
70 .map = {
71 .scan = budget_ci_old,
72 .size = ARRAY_SIZE(budget_ci_old),
73 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
74 .name = RC_MAP_BUDGET_CI_OLD,
75 }
76};
77
78static int __init init_rc_map_budget_ci_old(void)
79{
80 return ir_register_map(&budget_ci_old_map);
81}
82
83static void __exit exit_rc_map_budget_ci_old(void)
84{
85 ir_unregister_map(&budget_ci_old_map);
86}
87
88module_init(init_rc_map_budget_ci_old)
89module_exit(exit_rc_map_budget_ci_old)
90
91MODULE_LICENSE("GPL");
92MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-cinergy-1400.c b/drivers/media/rc/keymaps/rc-cinergy-1400.c
new file mode 100644
index 000000000000..074f2c2c2c61
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-cinergy-1400.c
@@ -0,0 +1,84 @@
1/* cinergy-1400.h - Keytable for cinergy_1400 Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Cinergy 1400 DVB-T */
16
17static struct ir_scancode cinergy_1400[] = {
18 { 0x01, KEY_POWER },
19 { 0x02, KEY_1 },
20 { 0x03, KEY_2 },
21 { 0x04, KEY_3 },
22 { 0x05, KEY_4 },
23 { 0x06, KEY_5 },
24 { 0x07, KEY_6 },
25 { 0x08, KEY_7 },
26 { 0x09, KEY_8 },
27 { 0x0a, KEY_9 },
28 { 0x0c, KEY_0 },
29
30 { 0x0b, KEY_VIDEO },
31 { 0x0d, KEY_REFRESH },
32 { 0x0e, KEY_SELECT },
33 { 0x0f, KEY_EPG },
34 { 0x10, KEY_UP },
35 { 0x11, KEY_LEFT },
36 { 0x12, KEY_OK },
37 { 0x13, KEY_RIGHT },
38 { 0x14, KEY_DOWN },
39 { 0x15, KEY_TEXT },
40 { 0x16, KEY_INFO },
41
42 { 0x17, KEY_RED },
43 { 0x18, KEY_GREEN },
44 { 0x19, KEY_YELLOW },
45 { 0x1a, KEY_BLUE },
46
47 { 0x1b, KEY_CHANNELUP },
48 { 0x1c, KEY_VOLUMEUP },
49 { 0x1d, KEY_MUTE },
50 { 0x1e, KEY_VOLUMEDOWN },
51 { 0x1f, KEY_CHANNELDOWN },
52
53 { 0x40, KEY_PAUSE },
54 { 0x4c, KEY_PLAY },
55 { 0x58, KEY_RECORD },
56 { 0x54, KEY_PREVIOUS },
57 { 0x48, KEY_STOP },
58 { 0x5c, KEY_NEXT },
59};
60
61static struct rc_keymap cinergy_1400_map = {
62 .map = {
63 .scan = cinergy_1400,
64 .size = ARRAY_SIZE(cinergy_1400),
65 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
66 .name = RC_MAP_CINERGY_1400,
67 }
68};
69
70static int __init init_rc_map_cinergy_1400(void)
71{
72 return ir_register_map(&cinergy_1400_map);
73}
74
75static void __exit exit_rc_map_cinergy_1400(void)
76{
77 ir_unregister_map(&cinergy_1400_map);
78}
79
80module_init(init_rc_map_cinergy_1400)
81module_exit(exit_rc_map_cinergy_1400)
82
83MODULE_LICENSE("GPL");
84MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-cinergy.c b/drivers/media/rc/keymaps/rc-cinergy.c
new file mode 100644
index 000000000000..cf84c3dba742
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-cinergy.c
@@ -0,0 +1,78 @@
1/* cinergy.h - Keytable for cinergy Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode cinergy[] = {
16 { 0x00, KEY_0 },
17 { 0x01, KEY_1 },
18 { 0x02, KEY_2 },
19 { 0x03, KEY_3 },
20 { 0x04, KEY_4 },
21 { 0x05, KEY_5 },
22 { 0x06, KEY_6 },
23 { 0x07, KEY_7 },
24 { 0x08, KEY_8 },
25 { 0x09, KEY_9 },
26
27 { 0x0a, KEY_POWER },
28 { 0x0b, KEY_PROG1 }, /* app */
29 { 0x0c, KEY_ZOOM }, /* zoom/fullscreen */
30 { 0x0d, KEY_CHANNELUP }, /* channel */
31 { 0x0e, KEY_CHANNELDOWN }, /* channel- */
32 { 0x0f, KEY_VOLUMEUP },
33 { 0x10, KEY_VOLUMEDOWN },
34 { 0x11, KEY_TUNER }, /* AV */
35 { 0x12, KEY_NUMLOCK }, /* -/-- */
36 { 0x13, KEY_AUDIO }, /* audio */
37 { 0x14, KEY_MUTE },
38 { 0x15, KEY_UP },
39 { 0x16, KEY_DOWN },
40 { 0x17, KEY_LEFT },
41 { 0x18, KEY_RIGHT },
42 { 0x19, BTN_LEFT, },
43 { 0x1a, BTN_RIGHT, },
44 { 0x1b, KEY_WWW }, /* text */
45 { 0x1c, KEY_REWIND },
46 { 0x1d, KEY_FORWARD },
47 { 0x1e, KEY_RECORD },
48 { 0x1f, KEY_PLAY },
49 { 0x20, KEY_PREVIOUSSONG },
50 { 0x21, KEY_NEXTSONG },
51 { 0x22, KEY_PAUSE },
52 { 0x23, KEY_STOP },
53};
54
55static struct rc_keymap cinergy_map = {
56 .map = {
57 .scan = cinergy,
58 .size = ARRAY_SIZE(cinergy),
59 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
60 .name = RC_MAP_CINERGY,
61 }
62};
63
64static int __init init_rc_map_cinergy(void)
65{
66 return ir_register_map(&cinergy_map);
67}
68
69static void __exit exit_rc_map_cinergy(void)
70{
71 ir_unregister_map(&cinergy_map);
72}
73
74module_init(init_rc_map_cinergy)
75module_exit(exit_rc_map_cinergy)
76
77MODULE_LICENSE("GPL");
78MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-dib0700-nec.c b/drivers/media/rc/keymaps/rc-dib0700-nec.c
new file mode 100644
index 000000000000..ae1832038fbe
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-dib0700-nec.c
@@ -0,0 +1,124 @@
1/* rc-dvb0700-big.c - Keytable for devices in dvb0700
2 *
3 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 *
5 * TODO: This table is a real mess, as it merges RC codes from several
6 * devices into a big table. It also has both RC-5 and NEC codes inside.
7 * It should be broken into small tables, and the protocols should properly
8 * be indentificated.
9 *
10 * The table were imported from dib0700_devices.c.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 */
17
18#include <media/rc-map.h>
19
20static struct ir_scancode dib0700_nec_table[] = {
21 /* Key codes for the Pixelview SBTVD remote */
22 { 0x8613, KEY_MUTE },
23 { 0x8612, KEY_POWER },
24 { 0x8601, KEY_1 },
25 { 0x8602, KEY_2 },
26 { 0x8603, KEY_3 },
27 { 0x8604, KEY_4 },
28 { 0x8605, KEY_5 },
29 { 0x8606, KEY_6 },
30 { 0x8607, KEY_7 },
31 { 0x8608, KEY_8 },
32 { 0x8609, KEY_9 },
33 { 0x8600, KEY_0 },
34 { 0x860d, KEY_CHANNELUP },
35 { 0x8619, KEY_CHANNELDOWN },
36 { 0x8610, KEY_VOLUMEUP },
37 { 0x860c, KEY_VOLUMEDOWN },
38
39 { 0x860a, KEY_CAMERA },
40 { 0x860b, KEY_ZOOM },
41 { 0x861b, KEY_BACKSPACE },
42 { 0x8615, KEY_ENTER },
43
44 { 0x861d, KEY_UP },
45 { 0x861e, KEY_DOWN },
46 { 0x860e, KEY_LEFT },
47 { 0x860f, KEY_RIGHT },
48
49 { 0x8618, KEY_RECORD },
50 { 0x861a, KEY_STOP },
51
52 /* Key codes for the EvolutePC TVWay+ remote */
53 { 0x7a00, KEY_MENU },
54 { 0x7a01, KEY_RECORD },
55 { 0x7a02, KEY_PLAY },
56 { 0x7a03, KEY_STOP },
57 { 0x7a10, KEY_CHANNELUP },
58 { 0x7a11, KEY_CHANNELDOWN },
59 { 0x7a12, KEY_VOLUMEUP },
60 { 0x7a13, KEY_VOLUMEDOWN },
61 { 0x7a40, KEY_POWER },
62 { 0x7a41, KEY_MUTE },
63
64 /* Key codes for the Elgato EyeTV Diversity silver remote */
65 { 0x4501, KEY_POWER },
66 { 0x4502, KEY_MUTE },
67 { 0x4503, KEY_1 },
68 { 0x4504, KEY_2 },
69 { 0x4505, KEY_3 },
70 { 0x4506, KEY_4 },
71 { 0x4507, KEY_5 },
72 { 0x4508, KEY_6 },
73 { 0x4509, KEY_7 },
74 { 0x450a, KEY_8 },
75 { 0x450b, KEY_9 },
76 { 0x450c, KEY_LAST },
77 { 0x450d, KEY_0 },
78 { 0x450e, KEY_ENTER },
79 { 0x450f, KEY_RED },
80 { 0x4510, KEY_CHANNELUP },
81 { 0x4511, KEY_GREEN },
82 { 0x4512, KEY_VOLUMEDOWN },
83 { 0x4513, KEY_OK },
84 { 0x4514, KEY_VOLUMEUP },
85 { 0x4515, KEY_YELLOW },
86 { 0x4516, KEY_CHANNELDOWN },
87 { 0x4517, KEY_BLUE },
88 { 0x4518, KEY_LEFT }, /* Skip backwards */
89 { 0x4519, KEY_PLAYPAUSE },
90 { 0x451a, KEY_RIGHT }, /* Skip forward */
91 { 0x451b, KEY_REWIND },
92 { 0x451c, KEY_L }, /* Live */
93 { 0x451d, KEY_FASTFORWARD },
94 { 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */
95 { 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */
96 { 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */
97 { 0x4541, KEY_SCREEN }, /* Full screen toggle, 'Hold' for Teletext */
98 { 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */
99};
100
101static struct rc_keymap dib0700_nec_map = {
102 .map = {
103 .scan = dib0700_nec_table,
104 .size = ARRAY_SIZE(dib0700_nec_table),
105 .ir_type = IR_TYPE_NEC,
106 .name = RC_MAP_DIB0700_NEC_TABLE,
107 }
108};
109
110static int __init init_rc_map(void)
111{
112 return ir_register_map(&dib0700_nec_map);
113}
114
115static void __exit exit_rc_map(void)
116{
117 ir_unregister_map(&dib0700_nec_map);
118}
119
120module_init(init_rc_map)
121module_exit(exit_rc_map)
122
123MODULE_LICENSE("GPL");
124MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-dib0700-rc5.c b/drivers/media/rc/keymaps/rc-dib0700-rc5.c
new file mode 100644
index 000000000000..4a4797cfd77d
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-dib0700-rc5.c
@@ -0,0 +1,235 @@
1/* rc-dvb0700-big.c - Keytable for devices in dvb0700
2 *
3 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 *
5 * TODO: This table is a real mess, as it merges RC codes from several
6 * devices into a big table. It also has both RC-5 and NEC codes inside.
7 * It should be broken into small tables, and the protocols should properly
8 * be indentificated.
9 *
10 * The table were imported from dib0700_devices.c.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 */
17
18#include <media/rc-map.h>
19
20static struct ir_scancode dib0700_rc5_table[] = {
21 /* Key codes for the tiny Pinnacle remote*/
22 { 0x0700, KEY_MUTE },
23 { 0x0701, KEY_MENU }, /* Pinnacle logo */
24 { 0x0739, KEY_POWER },
25 { 0x0703, KEY_VOLUMEUP },
26 { 0x0709, KEY_VOLUMEDOWN },
27 { 0x0706, KEY_CHANNELUP },
28 { 0x070c, KEY_CHANNELDOWN },
29 { 0x070f, KEY_1 },
30 { 0x0715, KEY_2 },
31 { 0x0710, KEY_3 },
32 { 0x0718, KEY_4 },
33 { 0x071b, KEY_5 },
34 { 0x071e, KEY_6 },
35 { 0x0711, KEY_7 },
36 { 0x0721, KEY_8 },
37 { 0x0712, KEY_9 },
38 { 0x0727, KEY_0 },
39 { 0x0724, KEY_SCREEN }, /* 'Square' key */
40 { 0x072a, KEY_TEXT }, /* 'T' key */
41 { 0x072d, KEY_REWIND },
42 { 0x0730, KEY_PLAY },
43 { 0x0733, KEY_FASTFORWARD },
44 { 0x0736, KEY_RECORD },
45 { 0x073c, KEY_STOP },
46 { 0x073f, KEY_CANCEL }, /* '?' key */
47
48 /* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
49 { 0xeb01, KEY_POWER },
50 { 0xeb02, KEY_1 },
51 { 0xeb03, KEY_2 },
52 { 0xeb04, KEY_3 },
53 { 0xeb05, KEY_4 },
54 { 0xeb06, KEY_5 },
55 { 0xeb07, KEY_6 },
56 { 0xeb08, KEY_7 },
57 { 0xeb09, KEY_8 },
58 { 0xeb0a, KEY_9 },
59 { 0xeb0b, KEY_VIDEO },
60 { 0xeb0c, KEY_0 },
61 { 0xeb0d, KEY_REFRESH },
62 { 0xeb0f, KEY_EPG },
63 { 0xeb10, KEY_UP },
64 { 0xeb11, KEY_LEFT },
65 { 0xeb12, KEY_OK },
66 { 0xeb13, KEY_RIGHT },
67 { 0xeb14, KEY_DOWN },
68 { 0xeb16, KEY_INFO },
69 { 0xeb17, KEY_RED },
70 { 0xeb18, KEY_GREEN },
71 { 0xeb19, KEY_YELLOW },
72 { 0xeb1a, KEY_BLUE },
73 { 0xeb1b, KEY_CHANNELUP },
74 { 0xeb1c, KEY_VOLUMEUP },
75 { 0xeb1d, KEY_MUTE },
76 { 0xeb1e, KEY_VOLUMEDOWN },
77 { 0xeb1f, KEY_CHANNELDOWN },
78 { 0xeb40, KEY_PAUSE },
79 { 0xeb41, KEY_HOME },
80 { 0xeb42, KEY_MENU }, /* DVD Menu */
81 { 0xeb43, KEY_SUBTITLE },
82 { 0xeb44, KEY_TEXT }, /* Teletext */
83 { 0xeb45, KEY_DELETE },
84 { 0xeb46, KEY_TV },
85 { 0xeb47, KEY_DVD },
86 { 0xeb48, KEY_STOP },
87 { 0xeb49, KEY_VIDEO },
88 { 0xeb4a, KEY_AUDIO }, /* Music */
89 { 0xeb4b, KEY_SCREEN }, /* Pic */
90 { 0xeb4c, KEY_PLAY },
91 { 0xeb4d, KEY_BACK },
92 { 0xeb4e, KEY_REWIND },
93 { 0xeb4f, KEY_FASTFORWARD },
94 { 0xeb54, KEY_PREVIOUS },
95 { 0xeb58, KEY_RECORD },
96 { 0xeb5c, KEY_NEXT },
97
98 /* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */
99 { 0x1e00, KEY_0 },
100 { 0x1e01, KEY_1 },
101 { 0x1e02, KEY_2 },
102 { 0x1e03, KEY_3 },
103 { 0x1e04, KEY_4 },
104 { 0x1e05, KEY_5 },
105 { 0x1e06, KEY_6 },
106 { 0x1e07, KEY_7 },
107 { 0x1e08, KEY_8 },
108 { 0x1e09, KEY_9 },
109 { 0x1e0a, KEY_KPASTERISK },
110 { 0x1e0b, KEY_RED },
111 { 0x1e0c, KEY_RADIO },
112 { 0x1e0d, KEY_MENU },
113 { 0x1e0e, KEY_GRAVE }, /* # */
114 { 0x1e0f, KEY_MUTE },
115 { 0x1e10, KEY_VOLUMEUP },
116 { 0x1e11, KEY_VOLUMEDOWN },
117 { 0x1e12, KEY_CHANNEL },
118 { 0x1e14, KEY_UP },
119 { 0x1e15, KEY_DOWN },
120 { 0x1e16, KEY_LEFT },
121 { 0x1e17, KEY_RIGHT },
122 { 0x1e18, KEY_VIDEO },
123 { 0x1e19, KEY_AUDIO },
124 { 0x1e1a, KEY_MEDIA },
125 { 0x1e1b, KEY_EPG },
126 { 0x1e1c, KEY_TV },
127 { 0x1e1e, KEY_NEXT },
128 { 0x1e1f, KEY_BACK },
129 { 0x1e20, KEY_CHANNELUP },
130 { 0x1e21, KEY_CHANNELDOWN },
131 { 0x1e24, KEY_LAST }, /* Skip backwards */
132 { 0x1e25, KEY_OK },
133 { 0x1e29, KEY_BLUE},
134 { 0x1e2e, KEY_GREEN },
135 { 0x1e30, KEY_PAUSE },
136 { 0x1e32, KEY_REWIND },
137 { 0x1e34, KEY_FASTFORWARD },
138 { 0x1e35, KEY_PLAY },
139 { 0x1e36, KEY_STOP },
140 { 0x1e37, KEY_RECORD },
141 { 0x1e38, KEY_YELLOW },
142 { 0x1e3b, KEY_GOTO },
143 { 0x1e3d, KEY_POWER },
144
145 /* Key codes for the Leadtek Winfast DTV Dongle */
146 { 0x0042, KEY_POWER },
147 { 0x077c, KEY_TUNER },
148 { 0x0f4e, KEY_PRINT }, /* PREVIEW */
149 { 0x0840, KEY_SCREEN }, /* full screen toggle*/
150 { 0x0f71, KEY_DOT }, /* frequency */
151 { 0x0743, KEY_0 },
152 { 0x0c41, KEY_1 },
153 { 0x0443, KEY_2 },
154 { 0x0b7f, KEY_3 },
155 { 0x0e41, KEY_4 },
156 { 0x0643, KEY_5 },
157 { 0x097f, KEY_6 },
158 { 0x0d7e, KEY_7 },
159 { 0x057c, KEY_8 },
160 { 0x0a40, KEY_9 },
161 { 0x0e4e, KEY_CLEAR },
162 { 0x047c, KEY_CHANNEL }, /* show channel number */
163 { 0x0f41, KEY_LAST }, /* recall */
164 { 0x0342, KEY_MUTE },
165 { 0x064c, KEY_RESERVED }, /* PIP button*/
166 { 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */
167 { 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */
168 { 0x0b70, KEY_RECORD },
169 { 0x037d, KEY_VOLUMEUP },
170 { 0x017d, KEY_VOLUMEDOWN },
171 { 0x0242, KEY_CHANNELUP },
172 { 0x007d, KEY_CHANNELDOWN },
173
174 /* Key codes for Nova-TD "credit card" remote control. */
175 { 0x1d00, KEY_0 },
176 { 0x1d01, KEY_1 },
177 { 0x1d02, KEY_2 },
178 { 0x1d03, KEY_3 },
179 { 0x1d04, KEY_4 },
180 { 0x1d05, KEY_5 },
181 { 0x1d06, KEY_6 },
182 { 0x1d07, KEY_7 },
183 { 0x1d08, KEY_8 },
184 { 0x1d09, KEY_9 },
185 { 0x1d0a, KEY_TEXT },
186 { 0x1d0d, KEY_MENU },
187 { 0x1d0f, KEY_MUTE },
188 { 0x1d10, KEY_VOLUMEUP },
189 { 0x1d11, KEY_VOLUMEDOWN },
190 { 0x1d12, KEY_CHANNEL },
191 { 0x1d14, KEY_UP },
192 { 0x1d15, KEY_DOWN },
193 { 0x1d16, KEY_LEFT },
194 { 0x1d17, KEY_RIGHT },
195 { 0x1d1c, KEY_TV },
196 { 0x1d1e, KEY_NEXT },
197 { 0x1d1f, KEY_BACK },
198 { 0x1d20, KEY_CHANNELUP },
199 { 0x1d21, KEY_CHANNELDOWN },
200 { 0x1d24, KEY_LAST },
201 { 0x1d25, KEY_OK },
202 { 0x1d30, KEY_PAUSE },
203 { 0x1d32, KEY_REWIND },
204 { 0x1d34, KEY_FASTFORWARD },
205 { 0x1d35, KEY_PLAY },
206 { 0x1d36, KEY_STOP },
207 { 0x1d37, KEY_RECORD },
208 { 0x1d3b, KEY_GOTO },
209 { 0x1d3d, KEY_POWER },
210};
211
212static struct rc_keymap dib0700_rc5_map = {
213 .map = {
214 .scan = dib0700_rc5_table,
215 .size = ARRAY_SIZE(dib0700_rc5_table),
216 .ir_type = IR_TYPE_RC5,
217 .name = RC_MAP_DIB0700_RC5_TABLE,
218 }
219};
220
221static int __init init_rc_map(void)
222{
223 return ir_register_map(&dib0700_rc5_map);
224}
225
226static void __exit exit_rc_map(void)
227{
228 ir_unregister_map(&dib0700_rc5_map);
229}
230
231module_init(init_rc_map)
232module_exit(exit_rc_map)
233
234MODULE_LICENSE("GPL");
235MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c b/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c
new file mode 100644
index 000000000000..63e469e2dd21
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c
@@ -0,0 +1,98 @@
1/*
2 * DigitalNow TinyTwin remote controller keytable
3 *
4 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <media/rc-map.h>
22
23static struct ir_scancode digitalnow_tinytwin[] = {
24 { 0x0000, KEY_MUTE }, /* [symbol speaker] */
25 { 0x0001, KEY_VOLUMEUP },
26 { 0x0002, KEY_POWER2 }, /* TV [power button] */
27 { 0x0003, KEY_2 },
28 { 0x0004, KEY_3 },
29 { 0x0005, KEY_4 },
30 { 0x0006, KEY_6 },
31 { 0x0007, KEY_7 },
32 { 0x0008, KEY_8 },
33 { 0x0009, KEY_NUMERIC_STAR }, /* [*] */
34 { 0x000a, KEY_0 },
35 { 0x000b, KEY_NUMERIC_POUND }, /* [#] */
36 { 0x000c, KEY_RIGHT }, /* [right arrow] */
37 { 0x000d, KEY_HOMEPAGE }, /* [symbol home] Start */
38 { 0x000e, KEY_RED }, /* [red] Videos */
39 { 0x0010, KEY_POWER }, /* PC [power button] */
40 { 0x0011, KEY_YELLOW }, /* [yellow] Pictures */
41 { 0x0012, KEY_DOWN }, /* [down arrow] */
42 { 0x0013, KEY_GREEN }, /* [green] Music */
43 { 0x0014, KEY_CYCLEWINDOWS }, /* BACK */
44 { 0x0015, KEY_FAVORITES }, /* MORE */
45 { 0x0016, KEY_UP }, /* [up arrow] */
46 { 0x0017, KEY_LEFT }, /* [left arrow] */
47 { 0x0018, KEY_OK }, /* OK */
48 { 0x0019, KEY_BLUE }, /* [blue] MyTV */
49 { 0x001a, KEY_REWIND }, /* REW [<<] */
50 { 0x001b, KEY_PLAY }, /* PLAY */
51 { 0x001c, KEY_5 },
52 { 0x001d, KEY_9 },
53 { 0x001e, KEY_VOLUMEDOWN },
54 { 0x001f, KEY_1 },
55 { 0x0040, KEY_STOP }, /* STOP */
56 { 0x0042, KEY_PAUSE }, /* PAUSE */
57 { 0x0043, KEY_SCREEN }, /* Aspect */
58 { 0x0044, KEY_FORWARD }, /* FWD [>>] */
59 { 0x0045, KEY_NEXT }, /* SKIP */
60 { 0x0048, KEY_RECORD }, /* RECORD */
61 { 0x0049, KEY_VIDEO }, /* RTV */
62 { 0x004a, KEY_EPG }, /* Guide */
63 { 0x004b, KEY_CHANNELUP },
64 { 0x004c, KEY_HELP }, /* Help */
65 { 0x004d, KEY_RADIO }, /* Radio */
66 { 0x004f, KEY_CHANNELDOWN },
67 { 0x0050, KEY_DVD }, /* DVD */
68 { 0x0051, KEY_AUDIO }, /* Audio */
69 { 0x0052, KEY_TITLE }, /* Title */
70 { 0x0053, KEY_NEW }, /* [symbol PIP?] */
71 { 0x0057, KEY_MENU }, /* Mouse */
72 { 0x005a, KEY_PREVIOUS }, /* REPLAY */
73};
74
75static struct rc_keymap digitalnow_tinytwin_map = {
76 .map = {
77 .scan = digitalnow_tinytwin,
78 .size = ARRAY_SIZE(digitalnow_tinytwin),
79 .ir_type = IR_TYPE_NEC,
80 .name = RC_MAP_DIGITALNOW_TINYTWIN,
81 }
82};
83
84static int __init init_rc_map_digitalnow_tinytwin(void)
85{
86 return ir_register_map(&digitalnow_tinytwin_map);
87}
88
89static void __exit exit_rc_map_digitalnow_tinytwin(void)
90{
91 ir_unregister_map(&digitalnow_tinytwin_map);
92}
93
94module_init(init_rc_map_digitalnow_tinytwin)
95module_exit(exit_rc_map_digitalnow_tinytwin)
96
97MODULE_LICENSE("GPL");
98MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff --git a/drivers/media/rc/keymaps/rc-digittrade.c b/drivers/media/rc/keymaps/rc-digittrade.c
new file mode 100644
index 000000000000..5dece78e19c5
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-digittrade.c
@@ -0,0 +1,82 @@
1/*
2 * Digittrade DVB-T USB Stick remote controller keytable
3 *
4 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <media/rc-map.h>
22
23/* Digittrade DVB-T USB Stick remote controller. */
24/* Imported from af9015.h.
25 Initial keytable was from Alain Kalker <miki@dds.nl> */
26
27/* Digittrade DVB-T USB Stick */
28static struct ir_scancode digittrade[] = {
29 { 0x0000, KEY_9 },
30 { 0x0001, KEY_EPG }, /* EPG */
31 { 0x0002, KEY_VOLUMEDOWN }, /* Vol Dn */
32 { 0x0003, KEY_TEXT }, /* TELETEXT */
33 { 0x0004, KEY_8 },
34 { 0x0005, KEY_MUTE }, /* MUTE */
35 { 0x0006, KEY_POWER2 }, /* POWER */
36 { 0x0009, KEY_ZOOM }, /* FULLSCREEN */
37 { 0x000a, KEY_RECORD }, /* RECORD */
38 { 0x000d, KEY_SUBTITLE }, /* SUBTITLE */
39 { 0x000e, KEY_STOP }, /* STOP */
40 { 0x0010, KEY_OK }, /* RETURN */
41 { 0x0011, KEY_2 },
42 { 0x0012, KEY_4 },
43 { 0x0015, KEY_3 },
44 { 0x0016, KEY_5 },
45 { 0x0017, KEY_CHANNELDOWN }, /* Ch Dn */
46 { 0x0019, KEY_CHANNELUP }, /* CH Up */
47 { 0x001a, KEY_PAUSE }, /* PAUSE */
48 { 0x001b, KEY_1 },
49 { 0x001d, KEY_AUDIO }, /* DUAL SOUND */
50 { 0x001e, KEY_PLAY }, /* PLAY */
51 { 0x001f, KEY_CAMERA }, /* SNAPSHOT */
52 { 0x0040, KEY_VOLUMEUP }, /* Vol Up */
53 { 0x0048, KEY_7 },
54 { 0x004c, KEY_6 },
55 { 0x004d, KEY_PLAYPAUSE }, /* TIMESHIFT */
56 { 0x0054, KEY_0 },
57};
58
59static struct rc_keymap digittrade_map = {
60 .map = {
61 .scan = digittrade,
62 .size = ARRAY_SIZE(digittrade),
63 .ir_type = IR_TYPE_NEC,
64 .name = RC_MAP_DIGITTRADE,
65 }
66};
67
68static int __init init_rc_map_digittrade(void)
69{
70 return ir_register_map(&digittrade_map);
71}
72
73static void __exit exit_rc_map_digittrade(void)
74{
75 ir_unregister_map(&digittrade_map);
76}
77
78module_init(init_rc_map_digittrade)
79module_exit(exit_rc_map_digittrade)
80
81MODULE_LICENSE("GPL");
82MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff --git a/drivers/media/rc/keymaps/rc-dm1105-nec.c b/drivers/media/rc/keymaps/rc-dm1105-nec.c
new file mode 100644
index 000000000000..90684d0efea3
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-dm1105-nec.c
@@ -0,0 +1,76 @@
1/* dm1105-nec.h - Keytable for dm1105_nec Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* DVBWorld remotes
16 Igor M. Liplianin <liplianin@me.by>
17 */
18
19static struct ir_scancode dm1105_nec[] = {
20 { 0x0a, KEY_POWER2}, /* power */
21 { 0x0c, KEY_MUTE}, /* mute */
22 { 0x11, KEY_1},
23 { 0x12, KEY_2},
24 { 0x13, KEY_3},
25 { 0x14, KEY_4},
26 { 0x15, KEY_5},
27 { 0x16, KEY_6},
28 { 0x17, KEY_7},
29 { 0x18, KEY_8},
30 { 0x19, KEY_9},
31 { 0x10, KEY_0},
32 { 0x1c, KEY_CHANNELUP}, /* ch+ */
33 { 0x0f, KEY_CHANNELDOWN}, /* ch- */
34 { 0x1a, KEY_VOLUMEUP}, /* vol+ */
35 { 0x0e, KEY_VOLUMEDOWN}, /* vol- */
36 { 0x04, KEY_RECORD}, /* rec */
37 { 0x09, KEY_CHANNEL}, /* fav */
38 { 0x08, KEY_BACKSPACE}, /* rewind */
39 { 0x07, KEY_FASTFORWARD}, /* fast */
40 { 0x0b, KEY_PAUSE}, /* pause */
41 { 0x02, KEY_ESC}, /* cancel */
42 { 0x03, KEY_TAB}, /* tab */
43 { 0x00, KEY_UP}, /* up */
44 { 0x1f, KEY_ENTER}, /* ok */
45 { 0x01, KEY_DOWN}, /* down */
46 { 0x05, KEY_RECORD}, /* cap */
47 { 0x06, KEY_STOP}, /* stop */
48 { 0x40, KEY_ZOOM}, /* full */
49 { 0x1e, KEY_TV}, /* tvmode */
50 { 0x1b, KEY_B}, /* recall */
51};
52
53static struct rc_keymap dm1105_nec_map = {
54 .map = {
55 .scan = dm1105_nec,
56 .size = ARRAY_SIZE(dm1105_nec),
57 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
58 .name = RC_MAP_DM1105_NEC,
59 }
60};
61
62static int __init init_rc_map_dm1105_nec(void)
63{
64 return ir_register_map(&dm1105_nec_map);
65}
66
67static void __exit exit_rc_map_dm1105_nec(void)
68{
69 ir_unregister_map(&dm1105_nec_map);
70}
71
72module_init(init_rc_map_dm1105_nec)
73module_exit(exit_rc_map_dm1105_nec)
74
75MODULE_LICENSE("GPL");
76MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c
new file mode 100644
index 000000000000..8a4027af964a
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c
@@ -0,0 +1,78 @@
1/* dntv-live-dvb-t.h - Keytable for dntv_live_dvb_t Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* DigitalNow DNTV Live DVB-T Remote */
16
17static struct ir_scancode dntv_live_dvb_t[] = {
18 { 0x00, KEY_ESC }, /* 'go up a level?' */
19 /* Keys 0 to 9 */
20 { 0x0a, KEY_0 },
21 { 0x01, KEY_1 },
22 { 0x02, KEY_2 },
23 { 0x03, KEY_3 },
24 { 0x04, KEY_4 },
25 { 0x05, KEY_5 },
26 { 0x06, KEY_6 },
27 { 0x07, KEY_7 },
28 { 0x08, KEY_8 },
29 { 0x09, KEY_9 },
30
31 { 0x0b, KEY_TUNER }, /* tv/fm */
32 { 0x0c, KEY_SEARCH }, /* scan */
33 { 0x0d, KEY_STOP },
34 { 0x0e, KEY_PAUSE },
35 { 0x0f, KEY_LIST }, /* source */
36
37 { 0x10, KEY_MUTE },
38 { 0x11, KEY_REWIND }, /* backward << */
39 { 0x12, KEY_POWER },
40 { 0x13, KEY_CAMERA }, /* snap */
41 { 0x14, KEY_AUDIO }, /* stereo */
42 { 0x15, KEY_CLEAR }, /* reset */
43 { 0x16, KEY_PLAY },
44 { 0x17, KEY_ENTER },
45 { 0x18, KEY_ZOOM }, /* full screen */
46 { 0x19, KEY_FASTFORWARD }, /* forward >> */
47 { 0x1a, KEY_CHANNELUP },
48 { 0x1b, KEY_VOLUMEUP },
49 { 0x1c, KEY_INFO }, /* preview */
50 { 0x1d, KEY_RECORD }, /* record */
51 { 0x1e, KEY_CHANNELDOWN },
52 { 0x1f, KEY_VOLUMEDOWN },
53};
54
55static struct rc_keymap dntv_live_dvb_t_map = {
56 .map = {
57 .scan = dntv_live_dvb_t,
58 .size = ARRAY_SIZE(dntv_live_dvb_t),
59 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
60 .name = RC_MAP_DNTV_LIVE_DVB_T,
61 }
62};
63
64static int __init init_rc_map_dntv_live_dvb_t(void)
65{
66 return ir_register_map(&dntv_live_dvb_t_map);
67}
68
69static void __exit exit_rc_map_dntv_live_dvb_t(void)
70{
71 ir_unregister_map(&dntv_live_dvb_t_map);
72}
73
74module_init(init_rc_map_dntv_live_dvb_t)
75module_exit(exit_rc_map_dntv_live_dvb_t)
76
77MODULE_LICENSE("GPL");
78MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c b/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c
new file mode 100644
index 000000000000..6f4d60764d59
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c
@@ -0,0 +1,97 @@
1/* dntv-live-dvbt-pro.h - Keytable for dntv_live_dvbt_pro Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* DigitalNow DNTV Live! DVB-T Pro Remote */
16
17static struct ir_scancode dntv_live_dvbt_pro[] = {
18 { 0x16, KEY_POWER },
19 { 0x5b, KEY_HOME },
20
21 { 0x55, KEY_TV }, /* live tv */
22 { 0x58, KEY_TUNER }, /* digital Radio */
23 { 0x5a, KEY_RADIO }, /* FM radio */
24 { 0x59, KEY_DVD }, /* dvd menu */
25 { 0x03, KEY_1 },
26 { 0x01, KEY_2 },
27 { 0x06, KEY_3 },
28 { 0x09, KEY_4 },
29 { 0x1d, KEY_5 },
30 { 0x1f, KEY_6 },
31 { 0x0d, KEY_7 },
32 { 0x19, KEY_8 },
33 { 0x1b, KEY_9 },
34 { 0x0c, KEY_CANCEL },
35 { 0x15, KEY_0 },
36 { 0x4a, KEY_CLEAR },
37 { 0x13, KEY_BACK },
38 { 0x00, KEY_TAB },
39 { 0x4b, KEY_UP },
40 { 0x4e, KEY_LEFT },
41 { 0x4f, KEY_OK },
42 { 0x52, KEY_RIGHT },
43 { 0x51, KEY_DOWN },
44 { 0x1e, KEY_VOLUMEUP },
45 { 0x0a, KEY_VOLUMEDOWN },
46 { 0x02, KEY_CHANNELDOWN },
47 { 0x05, KEY_CHANNELUP },
48 { 0x11, KEY_RECORD },
49 { 0x14, KEY_PLAY },
50 { 0x4c, KEY_PAUSE },
51 { 0x1a, KEY_STOP },
52 { 0x40, KEY_REWIND },
53 { 0x12, KEY_FASTFORWARD },
54 { 0x41, KEY_PREVIOUSSONG }, /* replay |< */
55 { 0x42, KEY_NEXTSONG }, /* skip >| */
56 { 0x54, KEY_CAMERA }, /* capture */
57 { 0x50, KEY_LANGUAGE }, /* sap */
58 { 0x47, KEY_TV2 }, /* pip */
59 { 0x4d, KEY_SCREEN },
60 { 0x43, KEY_SUBTITLE },
61 { 0x10, KEY_MUTE },
62 { 0x49, KEY_AUDIO }, /* l/r */
63 { 0x07, KEY_SLEEP },
64 { 0x08, KEY_VIDEO }, /* a/v */
65 { 0x0e, KEY_PREVIOUS }, /* recall */
66 { 0x45, KEY_ZOOM }, /* zoom + */
67 { 0x46, KEY_ANGLE }, /* zoom - */
68 { 0x56, KEY_RED },
69 { 0x57, KEY_GREEN },
70 { 0x5c, KEY_YELLOW },
71 { 0x5d, KEY_BLUE },
72};
73
74static struct rc_keymap dntv_live_dvbt_pro_map = {
75 .map = {
76 .scan = dntv_live_dvbt_pro,
77 .size = ARRAY_SIZE(dntv_live_dvbt_pro),
78 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
79 .name = RC_MAP_DNTV_LIVE_DVBT_PRO,
80 }
81};
82
83static int __init init_rc_map_dntv_live_dvbt_pro(void)
84{
85 return ir_register_map(&dntv_live_dvbt_pro_map);
86}
87
88static void __exit exit_rc_map_dntv_live_dvbt_pro(void)
89{
90 ir_unregister_map(&dntv_live_dvbt_pro_map);
91}
92
93module_init(init_rc_map_dntv_live_dvbt_pro)
94module_exit(exit_rc_map_dntv_live_dvbt_pro)
95
96MODULE_LICENSE("GPL");
97MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-em-terratec.c b/drivers/media/rc/keymaps/rc-em-terratec.c
new file mode 100644
index 000000000000..3130c9c29e6b
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-em-terratec.c
@@ -0,0 +1,69 @@
1/* em-terratec.h - Keytable for em_terratec Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode em_terratec[] = {
16 { 0x01, KEY_CHANNEL },
17 { 0x02, KEY_SELECT },
18 { 0x03, KEY_MUTE },
19 { 0x04, KEY_POWER },
20 { 0x05, KEY_1 },
21 { 0x06, KEY_2 },
22 { 0x07, KEY_3 },
23 { 0x08, KEY_CHANNELUP },
24 { 0x09, KEY_4 },
25 { 0x0a, KEY_5 },
26 { 0x0b, KEY_6 },
27 { 0x0c, KEY_CHANNELDOWN },
28 { 0x0d, KEY_7 },
29 { 0x0e, KEY_8 },
30 { 0x0f, KEY_9 },
31 { 0x10, KEY_VOLUMEUP },
32 { 0x11, KEY_0 },
33 { 0x12, KEY_MENU },
34 { 0x13, KEY_PRINT },
35 { 0x14, KEY_VOLUMEDOWN },
36 { 0x16, KEY_PAUSE },
37 { 0x18, KEY_RECORD },
38 { 0x19, KEY_REWIND },
39 { 0x1a, KEY_PLAY },
40 { 0x1b, KEY_FORWARD },
41 { 0x1c, KEY_BACKSPACE },
42 { 0x1e, KEY_STOP },
43 { 0x40, KEY_ZOOM },
44};
45
46static struct rc_keymap em_terratec_map = {
47 .map = {
48 .scan = em_terratec,
49 .size = ARRAY_SIZE(em_terratec),
50 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
51 .name = RC_MAP_EM_TERRATEC,
52 }
53};
54
55static int __init init_rc_map_em_terratec(void)
56{
57 return ir_register_map(&em_terratec_map);
58}
59
60static void __exit exit_rc_map_em_terratec(void)
61{
62 ir_unregister_map(&em_terratec_map);
63}
64
65module_init(init_rc_map_em_terratec)
66module_exit(exit_rc_map_em_terratec)
67
68MODULE_LICENSE("GPL");
69MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c b/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c
new file mode 100644
index 000000000000..4b816967877e
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c
@@ -0,0 +1,81 @@
1/* encore-enltv-fm53.h - Keytable for encore_enltv_fm53 Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Encore ENLTV-FM v5.3
16 Mauro Carvalho Chehab <mchehab@infradead.org>
17 */
18
19static struct ir_scancode encore_enltv_fm53[] = {
20 { 0x10, KEY_POWER2},
21 { 0x06, KEY_MUTE},
22
23 { 0x09, KEY_1},
24 { 0x1d, KEY_2},
25 { 0x1f, KEY_3},
26 { 0x19, KEY_4},
27 { 0x1b, KEY_5},
28 { 0x11, KEY_6},
29 { 0x17, KEY_7},
30 { 0x12, KEY_8},
31 { 0x16, KEY_9},
32 { 0x48, KEY_0},
33
34 { 0x04, KEY_LIST}, /* -/-- */
35 { 0x40, KEY_LAST}, /* recall */
36
37 { 0x02, KEY_MODE}, /* TV/AV */
38 { 0x05, KEY_CAMERA}, /* SNAPSHOT */
39
40 { 0x4c, KEY_CHANNELUP}, /* UP */
41 { 0x00, KEY_CHANNELDOWN}, /* DOWN */
42 { 0x0d, KEY_VOLUMEUP}, /* RIGHT */
43 { 0x15, KEY_VOLUMEDOWN}, /* LEFT */
44 { 0x49, KEY_ENTER}, /* OK */
45
46 { 0x54, KEY_RECORD},
47 { 0x4d, KEY_PLAY}, /* pause */
48
49 { 0x1e, KEY_MENU}, /* video setting */
50 { 0x0e, KEY_RIGHT}, /* <- */
51 { 0x1a, KEY_LEFT}, /* -> */
52
53 { 0x0a, KEY_CLEAR}, /* video default */
54 { 0x0c, KEY_ZOOM}, /* hide pannel */
55 { 0x47, KEY_SLEEP}, /* shutdown */
56};
57
58static struct rc_keymap encore_enltv_fm53_map = {
59 .map = {
60 .scan = encore_enltv_fm53,
61 .size = ARRAY_SIZE(encore_enltv_fm53),
62 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
63 .name = RC_MAP_ENCORE_ENLTV_FM53,
64 }
65};
66
67static int __init init_rc_map_encore_enltv_fm53(void)
68{
69 return ir_register_map(&encore_enltv_fm53_map);
70}
71
72static void __exit exit_rc_map_encore_enltv_fm53(void)
73{
74 ir_unregister_map(&encore_enltv_fm53_map);
75}
76
77module_init(init_rc_map_encore_enltv_fm53)
78module_exit(exit_rc_map_encore_enltv_fm53)
79
80MODULE_LICENSE("GPL");
81MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-encore-enltv.c b/drivers/media/rc/keymaps/rc-encore-enltv.c
new file mode 100644
index 000000000000..9fabffd28cc9
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-encore-enltv.c
@@ -0,0 +1,112 @@
1/* encore-enltv.h - Keytable for encore_enltv Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons
16 Juan Pablo Sormani <sorman@gmail.com> */
17
18static struct ir_scancode encore_enltv[] = {
19
20 /* Power button does nothing, neither in Windows app,
21 although it sends data (used for BIOS wakeup?) */
22 { 0x0d, KEY_MUTE },
23
24 { 0x1e, KEY_TV },
25 { 0x00, KEY_VIDEO },
26 { 0x01, KEY_AUDIO }, /* music */
27 { 0x02, KEY_MHP }, /* picture */
28
29 { 0x1f, KEY_1 },
30 { 0x03, KEY_2 },
31 { 0x04, KEY_3 },
32 { 0x05, KEY_4 },
33 { 0x1c, KEY_5 },
34 { 0x06, KEY_6 },
35 { 0x07, KEY_7 },
36 { 0x08, KEY_8 },
37 { 0x1d, KEY_9 },
38 { 0x0a, KEY_0 },
39
40 { 0x09, KEY_LIST }, /* -/-- */
41 { 0x0b, KEY_LAST }, /* recall */
42
43 { 0x14, KEY_HOME }, /* win start menu */
44 { 0x15, KEY_EXIT }, /* exit */
45 { 0x16, KEY_CHANNELUP }, /* UP */
46 { 0x12, KEY_CHANNELDOWN }, /* DOWN */
47 { 0x0c, KEY_VOLUMEUP }, /* RIGHT */
48 { 0x17, KEY_VOLUMEDOWN }, /* LEFT */
49
50 { 0x18, KEY_ENTER }, /* OK */
51
52 { 0x0e, KEY_ESC },
53 { 0x13, KEY_CYCLEWINDOWS }, /* desktop */
54 { 0x11, KEY_TAB },
55 { 0x19, KEY_SWITCHVIDEOMODE }, /* switch */
56
57 { 0x1a, KEY_MENU },
58 { 0x1b, KEY_ZOOM }, /* fullscreen */
59 { 0x44, KEY_TIME }, /* time shift */
60 { 0x40, KEY_MODE }, /* source */
61
62 { 0x5a, KEY_RECORD },
63 { 0x42, KEY_PLAY }, /* play/pause */
64 { 0x45, KEY_STOP },
65 { 0x43, KEY_CAMERA }, /* camera icon */
66
67 { 0x48, KEY_REWIND },
68 { 0x4a, KEY_FASTFORWARD },
69 { 0x49, KEY_PREVIOUS },
70 { 0x4b, KEY_NEXT },
71
72 { 0x4c, KEY_FAVORITES }, /* tv wall */
73 { 0x4d, KEY_SOUND }, /* DVD sound */
74 { 0x4e, KEY_LANGUAGE }, /* DVD lang */
75 { 0x4f, KEY_TEXT }, /* DVD text */
76
77 { 0x50, KEY_SLEEP }, /* shutdown */
78 { 0x51, KEY_MODE }, /* stereo > main */
79 { 0x52, KEY_SELECT }, /* stereo > sap */
80 { 0x53, KEY_PROG1 }, /* teletext */
81
82
83 { 0x59, KEY_RED }, /* AP1 */
84 { 0x41, KEY_GREEN }, /* AP2 */
85 { 0x47, KEY_YELLOW }, /* AP3 */
86 { 0x57, KEY_BLUE }, /* AP4 */
87};
88
89static struct rc_keymap encore_enltv_map = {
90 .map = {
91 .scan = encore_enltv,
92 .size = ARRAY_SIZE(encore_enltv),
93 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
94 .name = RC_MAP_ENCORE_ENLTV,
95 }
96};
97
98static int __init init_rc_map_encore_enltv(void)
99{
100 return ir_register_map(&encore_enltv_map);
101}
102
103static void __exit exit_rc_map_encore_enltv(void)
104{
105 ir_unregister_map(&encore_enltv_map);
106}
107
108module_init(init_rc_map_encore_enltv)
109module_exit(exit_rc_map_encore_enltv)
110
111MODULE_LICENSE("GPL");
112MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-encore-enltv2.c b/drivers/media/rc/keymaps/rc-encore-enltv2.c
new file mode 100644
index 000000000000..efefd5166618
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-encore-enltv2.c
@@ -0,0 +1,90 @@
1/* encore-enltv2.h - Keytable for encore_enltv2 Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton
16 Mauro Carvalho Chehab <mchehab@infradead.org> */
17
18static struct ir_scancode encore_enltv2[] = {
19 { 0x4c, KEY_POWER2 },
20 { 0x4a, KEY_TUNER },
21 { 0x40, KEY_1 },
22 { 0x60, KEY_2 },
23 { 0x50, KEY_3 },
24 { 0x70, KEY_4 },
25 { 0x48, KEY_5 },
26 { 0x68, KEY_6 },
27 { 0x58, KEY_7 },
28 { 0x78, KEY_8 },
29 { 0x44, KEY_9 },
30 { 0x54, KEY_0 },
31
32 { 0x64, KEY_LAST }, /* +100 */
33 { 0x4e, KEY_AGAIN }, /* Recall */
34
35 { 0x6c, KEY_SWITCHVIDEOMODE }, /* Video Source */
36 { 0x5e, KEY_MENU },
37 { 0x56, KEY_SCREEN },
38 { 0x7a, KEY_SETUP },
39
40 { 0x46, KEY_MUTE },
41 { 0x5c, KEY_MODE }, /* Stereo */
42 { 0x74, KEY_INFO },
43 { 0x7c, KEY_CLEAR },
44
45 { 0x55, KEY_UP },
46 { 0x49, KEY_DOWN },
47 { 0x7e, KEY_LEFT },
48 { 0x59, KEY_RIGHT },
49 { 0x6a, KEY_ENTER },
50
51 { 0x42, KEY_VOLUMEUP },
52 { 0x62, KEY_VOLUMEDOWN },
53 { 0x52, KEY_CHANNELUP },
54 { 0x72, KEY_CHANNELDOWN },
55
56 { 0x41, KEY_RECORD },
57 { 0x51, KEY_CAMERA }, /* Snapshot */
58 { 0x75, KEY_TIME }, /* Timeshift */
59 { 0x71, KEY_TV2 }, /* PIP */
60
61 { 0x45, KEY_REWIND },
62 { 0x6f, KEY_PAUSE },
63 { 0x7d, KEY_FORWARD },
64 { 0x79, KEY_STOP },
65};
66
67static struct rc_keymap encore_enltv2_map = {
68 .map = {
69 .scan = encore_enltv2,
70 .size = ARRAY_SIZE(encore_enltv2),
71 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
72 .name = RC_MAP_ENCORE_ENLTV2,
73 }
74};
75
76static int __init init_rc_map_encore_enltv2(void)
77{
78 return ir_register_map(&encore_enltv2_map);
79}
80
81static void __exit exit_rc_map_encore_enltv2(void)
82{
83 ir_unregister_map(&encore_enltv2_map);
84}
85
86module_init(init_rc_map_encore_enltv2)
87module_exit(exit_rc_map_encore_enltv2)
88
89MODULE_LICENSE("GPL");
90MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-evga-indtube.c b/drivers/media/rc/keymaps/rc-evga-indtube.c
new file mode 100644
index 000000000000..3f3fb13813b3
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-evga-indtube.c
@@ -0,0 +1,61 @@
1/* evga-indtube.h - Keytable for evga_indtube Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* EVGA inDtube
16 Devin Heitmueller <devin.heitmueller@gmail.com>
17 */
18
19static struct ir_scancode evga_indtube[] = {
20 { 0x12, KEY_POWER},
21 { 0x02, KEY_MODE}, /* TV */
22 { 0x14, KEY_MUTE},
23 { 0x1a, KEY_CHANNELUP},
24 { 0x16, KEY_TV2}, /* PIP */
25 { 0x1d, KEY_VOLUMEUP},
26 { 0x05, KEY_CHANNELDOWN},
27 { 0x0f, KEY_PLAYPAUSE},
28 { 0x19, KEY_VOLUMEDOWN},
29 { 0x1c, KEY_REWIND},
30 { 0x0d, KEY_RECORD},
31 { 0x18, KEY_FORWARD},
32 { 0x1e, KEY_PREVIOUS},
33 { 0x1b, KEY_STOP},
34 { 0x1f, KEY_NEXT},
35 { 0x13, KEY_CAMERA},
36};
37
38static struct rc_keymap evga_indtube_map = {
39 .map = {
40 .scan = evga_indtube,
41 .size = ARRAY_SIZE(evga_indtube),
42 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
43 .name = RC_MAP_EVGA_INDTUBE,
44 }
45};
46
47static int __init init_rc_map_evga_indtube(void)
48{
49 return ir_register_map(&evga_indtube_map);
50}
51
52static void __exit exit_rc_map_evga_indtube(void)
53{
54 ir_unregister_map(&evga_indtube_map);
55}
56
57module_init(init_rc_map_evga_indtube)
58module_exit(exit_rc_map_evga_indtube)
59
60MODULE_LICENSE("GPL");
61MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-eztv.c b/drivers/media/rc/keymaps/rc-eztv.c
new file mode 100644
index 000000000000..660907a78db9
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-eztv.c
@@ -0,0 +1,96 @@
1/* eztv.h - Keytable for eztv Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Alfons Geser <a.geser@cox.net>
16 * updates from Job D. R. Borges <jobdrb@ig.com.br> */
17
18static struct ir_scancode eztv[] = {
19 { 0x12, KEY_POWER },
20 { 0x01, KEY_TV }, /* DVR */
21 { 0x15, KEY_DVD }, /* DVD */
22 { 0x17, KEY_AUDIO }, /* music */
23 /* DVR mode / DVD mode / music mode */
24
25 { 0x1b, KEY_MUTE }, /* mute */
26 { 0x02, KEY_LANGUAGE }, /* MTS/SAP / audio / autoseek */
27 { 0x1e, KEY_SUBTITLE }, /* closed captioning / subtitle / seek */
28 { 0x16, KEY_ZOOM }, /* full screen */
29 { 0x1c, KEY_VIDEO }, /* video source / eject / delall */
30 { 0x1d, KEY_RESTART }, /* playback / angle / del */
31 { 0x2f, KEY_SEARCH }, /* scan / menu / playlist */
32 { 0x30, KEY_CHANNEL }, /* CH surfing / bookmark / memo */
33
34 { 0x31, KEY_HELP }, /* help */
35 { 0x32, KEY_MODE }, /* num/memo */
36 { 0x33, KEY_ESC }, /* cancel */
37
38 { 0x0c, KEY_UP }, /* up */
39 { 0x10, KEY_DOWN }, /* down */
40 { 0x08, KEY_LEFT }, /* left */
41 { 0x04, KEY_RIGHT }, /* right */
42 { 0x03, KEY_SELECT }, /* select */
43
44 { 0x1f, KEY_REWIND }, /* rewind */
45 { 0x20, KEY_PLAYPAUSE },/* play/pause */
46 { 0x29, KEY_FORWARD }, /* forward */
47 { 0x14, KEY_AGAIN }, /* repeat */
48 { 0x2b, KEY_RECORD }, /* recording */
49 { 0x2c, KEY_STOP }, /* stop */
50 { 0x2d, KEY_PLAY }, /* play */
51 { 0x2e, KEY_CAMERA }, /* snapshot / shuffle */
52
53 { 0x00, KEY_0 },
54 { 0x05, KEY_1 },
55 { 0x06, KEY_2 },
56 { 0x07, KEY_3 },
57 { 0x09, KEY_4 },
58 { 0x0a, KEY_5 },
59 { 0x0b, KEY_6 },
60 { 0x0d, KEY_7 },
61 { 0x0e, KEY_8 },
62 { 0x0f, KEY_9 },
63
64 { 0x2a, KEY_VOLUMEUP },
65 { 0x11, KEY_VOLUMEDOWN },
66 { 0x18, KEY_CHANNELUP },/* CH.tracking up */
67 { 0x19, KEY_CHANNELDOWN },/* CH.tracking down */
68
69 { 0x13, KEY_ENTER }, /* enter */
70 { 0x21, KEY_DOT }, /* . (decimal dot) */
71};
72
73static struct rc_keymap eztv_map = {
74 .map = {
75 .scan = eztv,
76 .size = ARRAY_SIZE(eztv),
77 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
78 .name = RC_MAP_EZTV,
79 }
80};
81
82static int __init init_rc_map_eztv(void)
83{
84 return ir_register_map(&eztv_map);
85}
86
87static void __exit exit_rc_map_eztv(void)
88{
89 ir_unregister_map(&eztv_map);
90}
91
92module_init(init_rc_map_eztv)
93module_exit(exit_rc_map_eztv)
94
95MODULE_LICENSE("GPL");
96MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-flydvb.c b/drivers/media/rc/keymaps/rc-flydvb.c
new file mode 100644
index 000000000000..a173c81035f4
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-flydvb.c
@@ -0,0 +1,77 @@
1/* flydvb.h - Keytable for flydvb Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode flydvb[] = {
16 { 0x01, KEY_ZOOM }, /* Full Screen */
17 { 0x00, KEY_POWER }, /* Power */
18
19 { 0x03, KEY_1 },
20 { 0x04, KEY_2 },
21 { 0x05, KEY_3 },
22 { 0x07, KEY_4 },
23 { 0x08, KEY_5 },
24 { 0x09, KEY_6 },
25 { 0x0b, KEY_7 },
26 { 0x0c, KEY_8 },
27 { 0x0d, KEY_9 },
28 { 0x06, KEY_AGAIN }, /* Recall */
29 { 0x0f, KEY_0 },
30 { 0x10, KEY_MUTE }, /* Mute */
31 { 0x02, KEY_RADIO }, /* TV/Radio */
32 { 0x1b, KEY_LANGUAGE }, /* SAP (Second Audio Program) */
33
34 { 0x14, KEY_VOLUMEUP }, /* VOL+ */
35 { 0x17, KEY_VOLUMEDOWN }, /* VOL- */
36 { 0x12, KEY_CHANNELUP }, /* CH+ */
37 { 0x13, KEY_CHANNELDOWN }, /* CH- */
38 { 0x1d, KEY_ENTER }, /* Enter */
39
40 { 0x1a, KEY_MODE }, /* PIP */
41 { 0x18, KEY_TUNER }, /* Source */
42
43 { 0x1e, KEY_RECORD }, /* Record/Pause */
44 { 0x15, KEY_ANGLE }, /* Swap (no label on key) */
45 { 0x1c, KEY_PAUSE }, /* Timeshift/Pause */
46 { 0x19, KEY_BACK }, /* Rewind << */
47 { 0x0a, KEY_PLAYPAUSE }, /* Play/Pause */
48 { 0x1f, KEY_FORWARD }, /* Forward >> */
49 { 0x16, KEY_PREVIOUS }, /* Back |<< */
50 { 0x11, KEY_STOP }, /* Stop */
51 { 0x0e, KEY_NEXT }, /* End >>| */
52};
53
54static struct rc_keymap flydvb_map = {
55 .map = {
56 .scan = flydvb,
57 .size = ARRAY_SIZE(flydvb),
58 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
59 .name = RC_MAP_FLYDVB,
60 }
61};
62
63static int __init init_rc_map_flydvb(void)
64{
65 return ir_register_map(&flydvb_map);
66}
67
68static void __exit exit_rc_map_flydvb(void)
69{
70 ir_unregister_map(&flydvb_map);
71}
72
73module_init(init_rc_map_flydvb)
74module_exit(exit_rc_map_flydvb)
75
76MODULE_LICENSE("GPL");
77MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-flyvideo.c b/drivers/media/rc/keymaps/rc-flyvideo.c
new file mode 100644
index 000000000000..9c73043cbdba
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-flyvideo.c
@@ -0,0 +1,70 @@
1/* flyvideo.h - Keytable for flyvideo Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode flyvideo[] = {
16 { 0x0f, KEY_0 },
17 { 0x03, KEY_1 },
18 { 0x04, KEY_2 },
19 { 0x05, KEY_3 },
20 { 0x07, KEY_4 },
21 { 0x08, KEY_5 },
22 { 0x09, KEY_6 },
23 { 0x0b, KEY_7 },
24 { 0x0c, KEY_8 },
25 { 0x0d, KEY_9 },
26
27 { 0x0e, KEY_MODE }, /* Air/Cable */
28 { 0x11, KEY_VIDEO }, /* Video */
29 { 0x15, KEY_AUDIO }, /* Audio */
30 { 0x00, KEY_POWER }, /* Power */
31 { 0x18, KEY_TUNER }, /* AV Source */
32 { 0x02, KEY_ZOOM }, /* Fullscreen */
33 { 0x1a, KEY_LANGUAGE }, /* Stereo */
34 { 0x1b, KEY_MUTE }, /* Mute */
35 { 0x14, KEY_VOLUMEUP }, /* Volume + */
36 { 0x17, KEY_VOLUMEDOWN },/* Volume - */
37 { 0x12, KEY_CHANNELUP },/* Channel + */
38 { 0x13, KEY_CHANNELDOWN },/* Channel - */
39 { 0x06, KEY_AGAIN }, /* Recall */
40 { 0x10, KEY_ENTER }, /* Enter */
41
42 { 0x19, KEY_BACK }, /* Rewind ( <<< ) */
43 { 0x1f, KEY_FORWARD }, /* Forward ( >>> ) */
44 { 0x0a, KEY_ANGLE }, /* no label, may be used as the PAUSE button */
45};
46
47static struct rc_keymap flyvideo_map = {
48 .map = {
49 .scan = flyvideo,
50 .size = ARRAY_SIZE(flyvideo),
51 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
52 .name = RC_MAP_FLYVIDEO,
53 }
54};
55
56static int __init init_rc_map_flyvideo(void)
57{
58 return ir_register_map(&flyvideo_map);
59}
60
61static void __exit exit_rc_map_flyvideo(void)
62{
63 ir_unregister_map(&flyvideo_map);
64}
65
66module_init(init_rc_map_flyvideo)
67module_exit(exit_rc_map_flyvideo)
68
69MODULE_LICENSE("GPL");
70MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c b/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c
new file mode 100644
index 000000000000..cdb10389b10e
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c
@@ -0,0 +1,98 @@
1/* fusionhdtv-mce.h - Keytable for fusionhdtv_mce Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* DViCO FUSION HDTV MCE remote */
16
17static struct ir_scancode fusionhdtv_mce[] = {
18
19 { 0x0b, KEY_1 },
20 { 0x17, KEY_2 },
21 { 0x1b, KEY_3 },
22 { 0x07, KEY_4 },
23 { 0x50, KEY_5 },
24 { 0x54, KEY_6 },
25 { 0x48, KEY_7 },
26 { 0x4c, KEY_8 },
27 { 0x58, KEY_9 },
28 { 0x03, KEY_0 },
29
30 { 0x5e, KEY_OK },
31 { 0x51, KEY_UP },
32 { 0x53, KEY_DOWN },
33 { 0x5b, KEY_LEFT },
34 { 0x5f, KEY_RIGHT },
35
36 { 0x02, KEY_TV }, /* Labeled DTV on remote */
37 { 0x0e, KEY_MP3 },
38 { 0x1a, KEY_DVD },
39 { 0x1e, KEY_FAVORITES }, /* Labeled CPF on remote */
40 { 0x16, KEY_SETUP },
41 { 0x46, KEY_POWER2 }, /* TV On/Off button on remote */
42 { 0x0a, KEY_EPG }, /* Labeled Guide on remote */
43
44 { 0x49, KEY_BACK },
45 { 0x59, KEY_INFO }, /* Labeled MORE on remote */
46 { 0x4d, KEY_MENU }, /* Labeled DVDMENU on remote */
47 { 0x55, KEY_CYCLEWINDOWS }, /* Labeled ALT-TAB on remote */
48
49 { 0x0f, KEY_PREVIOUSSONG }, /* Labeled |<< REPLAY on remote */
50 { 0x12, KEY_NEXTSONG }, /* Labeled >>| SKIP on remote */
51 { 0x42, KEY_ENTER }, /* Labeled START with a green
52 MS windows logo on remote */
53
54 { 0x15, KEY_VOLUMEUP },
55 { 0x05, KEY_VOLUMEDOWN },
56 { 0x11, KEY_CHANNELUP },
57 { 0x09, KEY_CHANNELDOWN },
58
59 { 0x52, KEY_CAMERA },
60 { 0x5a, KEY_TUNER },
61 { 0x19, KEY_OPEN },
62
63 { 0x13, KEY_MODE }, /* 4:3 16:9 select */
64 { 0x1f, KEY_ZOOM },
65
66 { 0x43, KEY_REWIND },
67 { 0x47, KEY_PLAYPAUSE },
68 { 0x4f, KEY_FASTFORWARD },
69 { 0x57, KEY_MUTE },
70 { 0x0d, KEY_STOP },
71 { 0x01, KEY_RECORD },
72 { 0x4e, KEY_POWER },
73};
74
75static struct rc_keymap fusionhdtv_mce_map = {
76 .map = {
77 .scan = fusionhdtv_mce,
78 .size = ARRAY_SIZE(fusionhdtv_mce),
79 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
80 .name = RC_MAP_FUSIONHDTV_MCE,
81 }
82};
83
84static int __init init_rc_map_fusionhdtv_mce(void)
85{
86 return ir_register_map(&fusionhdtv_mce_map);
87}
88
89static void __exit exit_rc_map_fusionhdtv_mce(void)
90{
91 ir_unregister_map(&fusionhdtv_mce_map);
92}
93
94module_init(init_rc_map_fusionhdtv_mce)
95module_exit(exit_rc_map_fusionhdtv_mce)
96
97MODULE_LICENSE("GPL");
98MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-gadmei-rm008z.c b/drivers/media/rc/keymaps/rc-gadmei-rm008z.c
new file mode 100644
index 000000000000..c16c0d1263ac
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-gadmei-rm008z.c
@@ -0,0 +1,81 @@
1/* gadmei-rm008z.h - Keytable for gadmei_rm008z Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* GADMEI UTV330+ RM008Z remote
16 Shine Liu <shinel@foxmail.com>
17 */
18
19static struct ir_scancode gadmei_rm008z[] = {
20 { 0x14, KEY_POWER2}, /* POWER OFF */
21 { 0x0c, KEY_MUTE}, /* MUTE */
22
23 { 0x18, KEY_TV}, /* TV */
24 { 0x0e, KEY_VIDEO}, /* AV */
25 { 0x0b, KEY_AUDIO}, /* SV */
26 { 0x0f, KEY_RADIO}, /* FM */
27
28 { 0x00, KEY_1},
29 { 0x01, KEY_2},
30 { 0x02, KEY_3},
31 { 0x03, KEY_4},
32 { 0x04, KEY_5},
33 { 0x05, KEY_6},
34 { 0x06, KEY_7},
35 { 0x07, KEY_8},
36 { 0x08, KEY_9},
37 { 0x09, KEY_0},
38 { 0x0a, KEY_INFO}, /* OSD */
39 { 0x1c, KEY_BACKSPACE}, /* LAST */
40
41 { 0x0d, KEY_PLAY}, /* PLAY */
42 { 0x1e, KEY_CAMERA}, /* SNAPSHOT */
43 { 0x1a, KEY_RECORD}, /* RECORD */
44 { 0x17, KEY_STOP}, /* STOP */
45
46 { 0x1f, KEY_UP}, /* UP */
47 { 0x44, KEY_DOWN}, /* DOWN */
48 { 0x46, KEY_TAB}, /* BACK */
49 { 0x4a, KEY_ZOOM}, /* FULLSECREEN */
50
51 { 0x10, KEY_VOLUMEUP}, /* VOLUMEUP */
52 { 0x11, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */
53 { 0x12, KEY_CHANNELUP}, /* CHANNELUP */
54 { 0x13, KEY_CHANNELDOWN}, /* CHANNELDOWN */
55 { 0x15, KEY_ENTER}, /* OK */
56};
57
58static struct rc_keymap gadmei_rm008z_map = {
59 .map = {
60 .scan = gadmei_rm008z,
61 .size = ARRAY_SIZE(gadmei_rm008z),
62 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
63 .name = RC_MAP_GADMEI_RM008Z,
64 }
65};
66
67static int __init init_rc_map_gadmei_rm008z(void)
68{
69 return ir_register_map(&gadmei_rm008z_map);
70}
71
72static void __exit exit_rc_map_gadmei_rm008z(void)
73{
74 ir_unregister_map(&gadmei_rm008z_map);
75}
76
77module_init(init_rc_map_gadmei_rm008z)
78module_exit(exit_rc_map_gadmei_rm008z)
79
80MODULE_LICENSE("GPL");
81MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c b/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c
new file mode 100644
index 000000000000..89f8e384e52a
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c
@@ -0,0 +1,84 @@
1/* genius-tvgo-a11mce.h - Keytable for genius_tvgo_a11mce Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/*
16 * Remote control for the Genius TVGO A11MCE
17 * Adrian Pardini <pardo.bsso@gmail.com>
18 */
19
20static struct ir_scancode genius_tvgo_a11mce[] = {
21 /* Keys 0 to 9 */
22 { 0x48, KEY_0 },
23 { 0x09, KEY_1 },
24 { 0x1d, KEY_2 },
25 { 0x1f, KEY_3 },
26 { 0x19, KEY_4 },
27 { 0x1b, KEY_5 },
28 { 0x11, KEY_6 },
29 { 0x17, KEY_7 },
30 { 0x12, KEY_8 },
31 { 0x16, KEY_9 },
32
33 { 0x54, KEY_RECORD }, /* recording */
34 { 0x06, KEY_MUTE }, /* mute */
35 { 0x10, KEY_POWER },
36 { 0x40, KEY_LAST }, /* recall */
37 { 0x4c, KEY_CHANNELUP }, /* channel / program + */
38 { 0x00, KEY_CHANNELDOWN }, /* channel / program - */
39 { 0x0d, KEY_VOLUMEUP },
40 { 0x15, KEY_VOLUMEDOWN },
41 { 0x4d, KEY_OK }, /* also labeled as Pause */
42 { 0x1c, KEY_ZOOM }, /* full screen and Stop*/
43 { 0x02, KEY_MODE }, /* AV Source or Rewind*/
44 { 0x04, KEY_LIST }, /* -/-- */
45 /* small arrows above numbers */
46 { 0x1a, KEY_NEXT }, /* also Fast Forward */
47 { 0x0e, KEY_PREVIOUS }, /* also Rewind */
48 /* these are in a rather non standard layout and have
49 an alternate name written */
50 { 0x1e, KEY_UP }, /* Video Setting */
51 { 0x0a, KEY_DOWN }, /* Video Default */
52 { 0x05, KEY_CAMERA }, /* Snapshot */
53 { 0x0c, KEY_RIGHT }, /* Hide Panel */
54 /* Four buttons without label */
55 { 0x49, KEY_RED },
56 { 0x0b, KEY_GREEN },
57 { 0x13, KEY_YELLOW },
58 { 0x50, KEY_BLUE },
59};
60
61static struct rc_keymap genius_tvgo_a11mce_map = {
62 .map = {
63 .scan = genius_tvgo_a11mce,
64 .size = ARRAY_SIZE(genius_tvgo_a11mce),
65 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
66 .name = RC_MAP_GENIUS_TVGO_A11MCE,
67 }
68};
69
70static int __init init_rc_map_genius_tvgo_a11mce(void)
71{
72 return ir_register_map(&genius_tvgo_a11mce_map);
73}
74
75static void __exit exit_rc_map_genius_tvgo_a11mce(void)
76{
77 ir_unregister_map(&genius_tvgo_a11mce_map);
78}
79
80module_init(init_rc_map_genius_tvgo_a11mce)
81module_exit(exit_rc_map_genius_tvgo_a11mce)
82
83MODULE_LICENSE("GPL");
84MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-gotview7135.c b/drivers/media/rc/keymaps/rc-gotview7135.c
new file mode 100644
index 000000000000..52f025bb35f6
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-gotview7135.c
@@ -0,0 +1,79 @@
1/* gotview7135.h - Keytable for gotview7135 Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Mike Baikov <mike@baikov.com> */
16
17static struct ir_scancode gotview7135[] = {
18
19 { 0x11, KEY_POWER },
20 { 0x35, KEY_TV },
21 { 0x1b, KEY_0 },
22 { 0x29, KEY_1 },
23 { 0x19, KEY_2 },
24 { 0x39, KEY_3 },
25 { 0x1f, KEY_4 },
26 { 0x2c, KEY_5 },
27 { 0x21, KEY_6 },
28 { 0x24, KEY_7 },
29 { 0x18, KEY_8 },
30 { 0x2b, KEY_9 },
31 { 0x3b, KEY_AGAIN }, /* LOOP */
32 { 0x06, KEY_AUDIO },
33 { 0x31, KEY_PRINT }, /* PREVIEW */
34 { 0x3e, KEY_VIDEO },
35 { 0x10, KEY_CHANNELUP },
36 { 0x20, KEY_CHANNELDOWN },
37 { 0x0c, KEY_VOLUMEDOWN },
38 { 0x28, KEY_VOLUMEUP },
39 { 0x08, KEY_MUTE },
40 { 0x26, KEY_SEARCH }, /* SCAN */
41 { 0x3f, KEY_CAMERA }, /* SNAPSHOT */
42 { 0x12, KEY_RECORD },
43 { 0x32, KEY_STOP },
44 { 0x3c, KEY_PLAY },
45 { 0x1d, KEY_REWIND },
46 { 0x2d, KEY_PAUSE },
47 { 0x0d, KEY_FORWARD },
48 { 0x05, KEY_ZOOM }, /*FULL*/
49
50 { 0x2a, KEY_F21 }, /* LIVE TIMESHIFT */
51 { 0x0e, KEY_F22 }, /* MIN TIMESHIFT */
52 { 0x1e, KEY_TIME }, /* TIMESHIFT */
53 { 0x38, KEY_F24 }, /* NORMAL TIMESHIFT */
54};
55
56static struct rc_keymap gotview7135_map = {
57 .map = {
58 .scan = gotview7135,
59 .size = ARRAY_SIZE(gotview7135),
60 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
61 .name = RC_MAP_GOTVIEW7135,
62 }
63};
64
65static int __init init_rc_map_gotview7135(void)
66{
67 return ir_register_map(&gotview7135_map);
68}
69
70static void __exit exit_rc_map_gotview7135(void)
71{
72 ir_unregister_map(&gotview7135_map);
73}
74
75module_init(init_rc_map_gotview7135)
76module_exit(exit_rc_map_gotview7135)
77
78MODULE_LICENSE("GPL");
79MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-hauppauge-new.c b/drivers/media/rc/keymaps/rc-hauppauge-new.c
new file mode 100644
index 000000000000..c6f8cd7c5186
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-hauppauge-new.c
@@ -0,0 +1,100 @@
1/* hauppauge-new.h - Keytable for hauppauge_new Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Hauppauge: the newer, gray remotes (seems there are multiple
16 * slightly different versions), shipped with cx88+ivtv cards.
17 * almost rc5 coding, but some non-standard keys */
18
19static struct ir_scancode hauppauge_new[] = {
20 /* Keys 0 to 9 */
21 { 0x00, KEY_0 },
22 { 0x01, KEY_1 },
23 { 0x02, KEY_2 },
24 { 0x03, KEY_3 },
25 { 0x04, KEY_4 },
26 { 0x05, KEY_5 },
27 { 0x06, KEY_6 },
28 { 0x07, KEY_7 },
29 { 0x08, KEY_8 },
30 { 0x09, KEY_9 },
31
32 { 0x0a, KEY_TEXT }, /* keypad asterisk as well */
33 { 0x0b, KEY_RED }, /* red button */
34 { 0x0c, KEY_RADIO },
35 { 0x0d, KEY_MENU },
36 { 0x0e, KEY_SUBTITLE }, /* also the # key */
37 { 0x0f, KEY_MUTE },
38 { 0x10, KEY_VOLUMEUP },
39 { 0x11, KEY_VOLUMEDOWN },
40 { 0x12, KEY_PREVIOUS }, /* previous channel */
41 { 0x14, KEY_UP },
42 { 0x15, KEY_DOWN },
43 { 0x16, KEY_LEFT },
44 { 0x17, KEY_RIGHT },
45 { 0x18, KEY_VIDEO }, /* Videos */
46 { 0x19, KEY_AUDIO }, /* Music */
47 /* 0x1a: Pictures - presume this means
48 "Multimedia Home Platform" -
49 no "PICTURES" key in input.h
50 */
51 { 0x1a, KEY_MHP },
52
53 { 0x1b, KEY_EPG }, /* Guide */
54 { 0x1c, KEY_TV },
55 { 0x1e, KEY_NEXTSONG }, /* skip >| */
56 { 0x1f, KEY_EXIT }, /* back/exit */
57 { 0x20, KEY_CHANNELUP }, /* channel / program + */
58 { 0x21, KEY_CHANNELDOWN }, /* channel / program - */
59 { 0x22, KEY_CHANNEL }, /* source (old black remote) */
60 { 0x24, KEY_PREVIOUSSONG }, /* replay |< */
61 { 0x25, KEY_ENTER }, /* OK */
62 { 0x26, KEY_SLEEP }, /* minimize (old black remote) */
63 { 0x29, KEY_BLUE }, /* blue key */
64 { 0x2e, KEY_GREEN }, /* green button */
65 { 0x30, KEY_PAUSE }, /* pause */
66 { 0x32, KEY_REWIND }, /* backward << */
67 { 0x34, KEY_FASTFORWARD }, /* forward >> */
68 { 0x35, KEY_PLAY },
69 { 0x36, KEY_STOP },
70 { 0x37, KEY_RECORD }, /* recording */
71 { 0x38, KEY_YELLOW }, /* yellow key */
72 { 0x3b, KEY_SELECT }, /* top right button */
73 { 0x3c, KEY_ZOOM }, /* full */
74 { 0x3d, KEY_POWER }, /* system power (green button) */
75};
76
77static struct rc_keymap hauppauge_new_map = {
78 .map = {
79 .scan = hauppauge_new,
80 .size = ARRAY_SIZE(hauppauge_new),
81 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
82 .name = RC_MAP_HAUPPAUGE_NEW,
83 }
84};
85
86static int __init init_rc_map_hauppauge_new(void)
87{
88 return ir_register_map(&hauppauge_new_map);
89}
90
91static void __exit exit_rc_map_hauppauge_new(void)
92{
93 ir_unregister_map(&hauppauge_new_map);
94}
95
96module_init(init_rc_map_hauppauge_new)
97module_exit(exit_rc_map_hauppauge_new)
98
99MODULE_LICENSE("GPL");
100MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-imon-mce.c b/drivers/media/rc/keymaps/rc-imon-mce.c
new file mode 100644
index 000000000000..e49f350e3a0d
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-imon-mce.c
@@ -0,0 +1,142 @@
1/* rc5-imon-mce.c - Keytable for Windows Media Center RC-6 remotes for use
2 * with the SoundGraph iMON/Antec Veris hardware IR decoder
3 *
4 * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <media/rc-map.h>
13
14/* mce-mode imon mce remote key table */
15static struct ir_scancode imon_mce[] = {
16 /* keys sorted mostly by frequency of use to optimize lookups */
17 { 0x800ff415, KEY_REWIND },
18 { 0x800ff414, KEY_FASTFORWARD },
19 { 0x800ff41b, KEY_PREVIOUS },
20 { 0x800ff41a, KEY_NEXT },
21
22 { 0x800ff416, KEY_PLAY },
23 { 0x800ff418, KEY_PAUSE },
24 { 0x800ff419, KEY_STOP },
25 { 0x800ff417, KEY_RECORD },
26
27 { 0x02000052, KEY_UP },
28 { 0x02000051, KEY_DOWN },
29 { 0x02000050, KEY_LEFT },
30 { 0x0200004f, KEY_RIGHT },
31
32 { 0x800ff41e, KEY_UP },
33 { 0x800ff41f, KEY_DOWN },
34 { 0x800ff420, KEY_LEFT },
35 { 0x800ff421, KEY_RIGHT },
36
37 /* 0x800ff40b also KEY_NUMERIC_POUND on some receivers */
38 { 0x800ff40b, KEY_ENTER },
39 { 0x02000028, KEY_ENTER },
40/* the OK and Enter buttons decode to the same value on some remotes
41 { 0x02000028, KEY_OK }, */
42 { 0x800ff422, KEY_OK },
43 { 0x0200002a, KEY_EXIT },
44 { 0x800ff423, KEY_EXIT },
45 { 0x02000029, KEY_DELETE },
46 /* 0x800ff40a also KEY_NUMERIC_STAR on some receivers */
47 { 0x800ff40a, KEY_DELETE },
48
49 { 0x800ff40e, KEY_MUTE },
50 { 0x800ff410, KEY_VOLUMEUP },
51 { 0x800ff411, KEY_VOLUMEDOWN },
52 { 0x800ff412, KEY_CHANNELUP },
53 { 0x800ff413, KEY_CHANNELDOWN },
54
55 { 0x0200001e, KEY_NUMERIC_1 },
56 { 0x0200001f, KEY_NUMERIC_2 },
57 { 0x02000020, KEY_NUMERIC_3 },
58 { 0x02000021, KEY_NUMERIC_4 },
59 { 0x02000022, KEY_NUMERIC_5 },
60 { 0x02000023, KEY_NUMERIC_6 },
61 { 0x02000024, KEY_NUMERIC_7 },
62 { 0x02000025, KEY_NUMERIC_8 },
63 { 0x02000026, KEY_NUMERIC_9 },
64 { 0x02000027, KEY_NUMERIC_0 },
65
66 { 0x800ff401, KEY_NUMERIC_1 },
67 { 0x800ff402, KEY_NUMERIC_2 },
68 { 0x800ff403, KEY_NUMERIC_3 },
69 { 0x800ff404, KEY_NUMERIC_4 },
70 { 0x800ff405, KEY_NUMERIC_5 },
71 { 0x800ff406, KEY_NUMERIC_6 },
72 { 0x800ff407, KEY_NUMERIC_7 },
73 { 0x800ff408, KEY_NUMERIC_8 },
74 { 0x800ff409, KEY_NUMERIC_9 },
75 { 0x800ff400, KEY_NUMERIC_0 },
76
77 { 0x02200025, KEY_NUMERIC_STAR },
78 { 0x02200020, KEY_NUMERIC_POUND },
79 /* 0x800ff41d also KEY_BLUE on some receivers */
80 { 0x800ff41d, KEY_NUMERIC_STAR },
81 /* 0x800ff41c also KEY_PREVIOUS on some receivers */
82 { 0x800ff41c, KEY_NUMERIC_POUND },
83
84 { 0x800ff446, KEY_TV },
85 { 0x800ff447, KEY_AUDIO }, /* My Music */
86 { 0x800ff448, KEY_PVR }, /* RecordedTV */
87 { 0x800ff449, KEY_CAMERA },
88 { 0x800ff44a, KEY_VIDEO },
89 /* 0x800ff424 also KEY_MENU on some receivers */
90 { 0x800ff424, KEY_DVD },
91 /* 0x800ff425 also KEY_GREEN on some receivers */
92 { 0x800ff425, KEY_TUNER }, /* LiveTV */
93 { 0x800ff450, KEY_RADIO },
94
95 { 0x800ff44c, KEY_LANGUAGE },
96 { 0x800ff427, KEY_ZOOM }, /* Aspect */
97
98 { 0x800ff45b, KEY_RED },
99 { 0x800ff45c, KEY_GREEN },
100 { 0x800ff45d, KEY_YELLOW },
101 { 0x800ff45e, KEY_BLUE },
102
103 { 0x800ff466, KEY_RED },
104 /* { 0x800ff425, KEY_GREEN }, */
105 { 0x800ff468, KEY_YELLOW },
106 /* { 0x800ff41d, KEY_BLUE }, */
107
108 { 0x800ff40f, KEY_INFO },
109 { 0x800ff426, KEY_EPG }, /* Guide */
110 { 0x800ff45a, KEY_SUBTITLE }, /* Caption/Teletext */
111 { 0x800ff44d, KEY_TITLE },
112
113 { 0x800ff40c, KEY_POWER },
114 { 0x800ff40d, KEY_PROG1 }, /* Windows MCE button */
115
116};
117
118static struct rc_keymap imon_mce_map = {
119 .map = {
120 .scan = imon_mce,
121 .size = ARRAY_SIZE(imon_mce),
122 /* its RC6, but w/a hardware decoder */
123 .ir_type = IR_TYPE_RC6,
124 .name = RC_MAP_IMON_MCE,
125 }
126};
127
128static int __init init_rc_map_imon_mce(void)
129{
130 return ir_register_map(&imon_mce_map);
131}
132
133static void __exit exit_rc_map_imon_mce(void)
134{
135 ir_unregister_map(&imon_mce_map);
136}
137
138module_init(init_rc_map_imon_mce)
139module_exit(exit_rc_map_imon_mce)
140
141MODULE_LICENSE("GPL");
142MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-imon-pad.c b/drivers/media/rc/keymaps/rc-imon-pad.c
new file mode 100644
index 000000000000..bc4db72f02e6
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-imon-pad.c
@@ -0,0 +1,156 @@
1/* rc5-imon-pad.c - Keytable for SoundGraph iMON PAD and Antec Veris
2 * RM-200 Remote Control
3 *
4 * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <media/rc-map.h>
13
14/*
15 * standard imon remote key table, which isn't really entirely
16 * "standard", as different receivers decode the same key on the
17 * same remote to different hex codes, and the silkscreened names
18 * vary a bit between the SoundGraph and Antec remotes... ugh.
19 */
20static struct ir_scancode imon_pad[] = {
21 /* keys sorted mostly by frequency of use to optimize lookups */
22 { 0x2a8195b7, KEY_REWIND },
23 { 0x298315b7, KEY_REWIND },
24 { 0x2b8115b7, KEY_FASTFORWARD },
25 { 0x2b8315b7, KEY_FASTFORWARD },
26 { 0x2b9115b7, KEY_PREVIOUS },
27 { 0x298195b7, KEY_NEXT },
28
29 { 0x2a8115b7, KEY_PLAY },
30 { 0x2a8315b7, KEY_PLAY },
31 { 0x2a9115b7, KEY_PAUSE },
32 { 0x2b9715b7, KEY_STOP },
33 { 0x298115b7, KEY_RECORD },
34
35 { 0x01008000, KEY_UP },
36 { 0x01007f00, KEY_DOWN },
37 { 0x01000080, KEY_LEFT },
38 { 0x0100007f, KEY_RIGHT },
39
40 { 0x2aa515b7, KEY_UP },
41 { 0x289515b7, KEY_DOWN },
42 { 0x29a515b7, KEY_LEFT },
43 { 0x2ba515b7, KEY_RIGHT },
44
45 { 0x0200002c, KEY_SPACE }, /* Select/Space */
46 { 0x2a9315b7, KEY_SPACE }, /* Select/Space */
47 { 0x02000028, KEY_ENTER },
48 { 0x28a195b7, KEY_ENTER },
49 { 0x288195b7, KEY_EXIT },
50 { 0x02000029, KEY_ESC },
51 { 0x2bb715b7, KEY_ESC },
52 { 0x0200002a, KEY_BACKSPACE },
53 { 0x28a115b7, KEY_BACKSPACE },
54
55 { 0x2b9595b7, KEY_MUTE },
56 { 0x28a395b7, KEY_VOLUMEUP },
57 { 0x28a595b7, KEY_VOLUMEDOWN },
58 { 0x289395b7, KEY_CHANNELUP },
59 { 0x288795b7, KEY_CHANNELDOWN },
60
61 { 0x0200001e, KEY_NUMERIC_1 },
62 { 0x0200001f, KEY_NUMERIC_2 },
63 { 0x02000020, KEY_NUMERIC_3 },
64 { 0x02000021, KEY_NUMERIC_4 },
65 { 0x02000022, KEY_NUMERIC_5 },
66 { 0x02000023, KEY_NUMERIC_6 },
67 { 0x02000024, KEY_NUMERIC_7 },
68 { 0x02000025, KEY_NUMERIC_8 },
69 { 0x02000026, KEY_NUMERIC_9 },
70 { 0x02000027, KEY_NUMERIC_0 },
71
72 { 0x28b595b7, KEY_NUMERIC_1 },
73 { 0x2bb195b7, KEY_NUMERIC_2 },
74 { 0x28b195b7, KEY_NUMERIC_3 },
75 { 0x2a8595b7, KEY_NUMERIC_4 },
76 { 0x299595b7, KEY_NUMERIC_5 },
77 { 0x2aa595b7, KEY_NUMERIC_6 },
78 { 0x2b9395b7, KEY_NUMERIC_7 },
79 { 0x2a8515b7, KEY_NUMERIC_8 },
80 { 0x2aa115b7, KEY_NUMERIC_9 },
81 { 0x2ba595b7, KEY_NUMERIC_0 },
82
83 { 0x02200025, KEY_NUMERIC_STAR },
84 { 0x28b515b7, KEY_NUMERIC_STAR },
85 { 0x02200020, KEY_NUMERIC_POUND },
86 { 0x29a115b7, KEY_NUMERIC_POUND },
87
88 { 0x2b8515b7, KEY_VIDEO },
89 { 0x299195b7, KEY_AUDIO },
90 { 0x2ba115b7, KEY_CAMERA },
91 { 0x28a515b7, KEY_TV },
92 { 0x29a395b7, KEY_DVD },
93 { 0x29a295b7, KEY_DVD },
94
95 /* the Menu key between DVD and Subtitle on the RM-200... */
96 { 0x2ba385b7, KEY_MENU },
97 { 0x2ba395b7, KEY_MENU },
98
99 { 0x288515b7, KEY_BOOKMARKS },
100 { 0x2ab715b7, KEY_MEDIA }, /* Thumbnail */
101 { 0x298595b7, KEY_SUBTITLE },
102 { 0x2b8595b7, KEY_LANGUAGE },
103
104 { 0x29a595b7, KEY_ZOOM },
105 { 0x2aa395b7, KEY_SCREEN }, /* FullScreen */
106
107 { 0x299115b7, KEY_KEYBOARD },
108 { 0x299135b7, KEY_KEYBOARD },
109
110 { 0x01010000, BTN_LEFT },
111 { 0x01020000, BTN_RIGHT },
112 { 0x01010080, BTN_LEFT },
113 { 0x01020080, BTN_RIGHT },
114 { 0x688301b7, BTN_LEFT },
115 { 0x688481b7, BTN_RIGHT },
116
117 { 0x2a9395b7, KEY_CYCLEWINDOWS }, /* TaskSwitcher */
118 { 0x2b8395b7, KEY_TIME }, /* Timer */
119
120 { 0x289115b7, KEY_POWER },
121 { 0x29b195b7, KEY_EJECTCD }, /* the one next to play */
122 { 0x299395b7, KEY_EJECTCLOSECD }, /* eject (by TaskSw) */
123
124 { 0x02800000, KEY_CONTEXT_MENU }, /* Left Menu */
125 { 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/
126 { 0x02000065, KEY_COMPOSE }, /* RightMenu */
127 { 0x28b715b7, KEY_COMPOSE }, /* RightMenu */
128 { 0x2ab195b7, KEY_PROG1 }, /* Go or MultiMon */
129 { 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */
130};
131
132static struct rc_keymap imon_pad_map = {
133 .map = {
134 .scan = imon_pad,
135 .size = ARRAY_SIZE(imon_pad),
136 /* actual protocol details unknown, hardware decoder */
137 .ir_type = IR_TYPE_OTHER,
138 .name = RC_MAP_IMON_PAD,
139 }
140};
141
142static int __init init_rc_map_imon_pad(void)
143{
144 return ir_register_map(&imon_pad_map);
145}
146
147static void __exit exit_rc_map_imon_pad(void)
148{
149 ir_unregister_map(&imon_pad_map);
150}
151
152module_init(init_rc_map_imon_pad)
153module_exit(exit_rc_map_imon_pad)
154
155MODULE_LICENSE("GPL");
156MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-iodata-bctv7e.c b/drivers/media/rc/keymaps/rc-iodata-bctv7e.c
new file mode 100644
index 000000000000..ef6600259fc0
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-iodata-bctv7e.c
@@ -0,0 +1,88 @@
1/* iodata-bctv7e.h - Keytable for iodata_bctv7e Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* IO-DATA BCTV7E Remote */
16
17static struct ir_scancode iodata_bctv7e[] = {
18 { 0x40, KEY_TV },
19 { 0x20, KEY_RADIO }, /* FM */
20 { 0x60, KEY_EPG },
21 { 0x00, KEY_POWER },
22
23 /* Keys 0 to 9 */
24 { 0x44, KEY_0 }, /* 10 */
25 { 0x50, KEY_1 },
26 { 0x30, KEY_2 },
27 { 0x70, KEY_3 },
28 { 0x48, KEY_4 },
29 { 0x28, KEY_5 },
30 { 0x68, KEY_6 },
31 { 0x58, KEY_7 },
32 { 0x38, KEY_8 },
33 { 0x78, KEY_9 },
34
35 { 0x10, KEY_L }, /* Live */
36 { 0x08, KEY_TIME }, /* Time Shift */
37
38 { 0x18, KEY_PLAYPAUSE }, /* Play */
39
40 { 0x24, KEY_ENTER }, /* 11 */
41 { 0x64, KEY_ESC }, /* 12 */
42 { 0x04, KEY_M }, /* Multi */
43
44 { 0x54, KEY_VIDEO },
45 { 0x34, KEY_CHANNELUP },
46 { 0x74, KEY_VOLUMEUP },
47 { 0x14, KEY_MUTE },
48
49 { 0x4c, KEY_VCR }, /* SVIDEO */
50 { 0x2c, KEY_CHANNELDOWN },
51 { 0x6c, KEY_VOLUMEDOWN },
52 { 0x0c, KEY_ZOOM },
53
54 { 0x5c, KEY_PAUSE },
55 { 0x3c, KEY_RED }, /* || (red) */
56 { 0x7c, KEY_RECORD }, /* recording */
57 { 0x1c, KEY_STOP },
58
59 { 0x41, KEY_REWIND }, /* backward << */
60 { 0x21, KEY_PLAY },
61 { 0x61, KEY_FASTFORWARD }, /* forward >> */
62 { 0x01, KEY_NEXT }, /* skip >| */
63};
64
65static struct rc_keymap iodata_bctv7e_map = {
66 .map = {
67 .scan = iodata_bctv7e,
68 .size = ARRAY_SIZE(iodata_bctv7e),
69 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
70 .name = RC_MAP_IODATA_BCTV7E,
71 }
72};
73
74static int __init init_rc_map_iodata_bctv7e(void)
75{
76 return ir_register_map(&iodata_bctv7e_map);
77}
78
79static void __exit exit_rc_map_iodata_bctv7e(void)
80{
81 ir_unregister_map(&iodata_bctv7e_map);
82}
83
84module_init(init_rc_map_iodata_bctv7e)
85module_exit(exit_rc_map_iodata_bctv7e)
86
87MODULE_LICENSE("GPL");
88MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-kaiomy.c b/drivers/media/rc/keymaps/rc-kaiomy.c
new file mode 100644
index 000000000000..4c7883ba0f15
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-kaiomy.c
@@ -0,0 +1,87 @@
1/* kaiomy.h - Keytable for kaiomy Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Kaiomy TVnPC U2
16 Mauro Carvalho Chehab <mchehab@infradead.org>
17 */
18
19static struct ir_scancode kaiomy[] = {
20 { 0x43, KEY_POWER2},
21 { 0x01, KEY_LIST},
22 { 0x0b, KEY_ZOOM},
23 { 0x03, KEY_POWER},
24
25 { 0x04, KEY_1},
26 { 0x08, KEY_2},
27 { 0x02, KEY_3},
28
29 { 0x0f, KEY_4},
30 { 0x05, KEY_5},
31 { 0x06, KEY_6},
32
33 { 0x0c, KEY_7},
34 { 0x0d, KEY_8},
35 { 0x0a, KEY_9},
36
37 { 0x11, KEY_0},
38
39 { 0x09, KEY_CHANNELUP},
40 { 0x07, KEY_CHANNELDOWN},
41
42 { 0x0e, KEY_VOLUMEUP},
43 { 0x13, KEY_VOLUMEDOWN},
44
45 { 0x10, KEY_HOME},
46 { 0x12, KEY_ENTER},
47
48 { 0x14, KEY_RECORD},
49 { 0x15, KEY_STOP},
50 { 0x16, KEY_PLAY},
51 { 0x17, KEY_MUTE},
52
53 { 0x18, KEY_UP},
54 { 0x19, KEY_DOWN},
55 { 0x1a, KEY_LEFT},
56 { 0x1b, KEY_RIGHT},
57
58 { 0x1c, KEY_RED},
59 { 0x1d, KEY_GREEN},
60 { 0x1e, KEY_YELLOW},
61 { 0x1f, KEY_BLUE},
62};
63
64static struct rc_keymap kaiomy_map = {
65 .map = {
66 .scan = kaiomy,
67 .size = ARRAY_SIZE(kaiomy),
68 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
69 .name = RC_MAP_KAIOMY,
70 }
71};
72
73static int __init init_rc_map_kaiomy(void)
74{
75 return ir_register_map(&kaiomy_map);
76}
77
78static void __exit exit_rc_map_kaiomy(void)
79{
80 ir_unregister_map(&kaiomy_map);
81}
82
83module_init(init_rc_map_kaiomy)
84module_exit(exit_rc_map_kaiomy)
85
86MODULE_LICENSE("GPL");
87MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-kworld-315u.c b/drivers/media/rc/keymaps/rc-kworld-315u.c
new file mode 100644
index 000000000000..618c817374e6
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-kworld-315u.c
@@ -0,0 +1,83 @@
1/* kworld-315u.h - Keytable for kworld_315u Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Kworld 315U
16 */
17
18static struct ir_scancode kworld_315u[] = {
19 { 0x6143, KEY_POWER },
20 { 0x6101, KEY_TUNER }, /* source */
21 { 0x610b, KEY_ZOOM },
22 { 0x6103, KEY_POWER2 }, /* shutdown */
23
24 { 0x6104, KEY_1 },
25 { 0x6108, KEY_2 },
26 { 0x6102, KEY_3 },
27 { 0x6109, KEY_CHANNELUP },
28
29 { 0x610f, KEY_4 },
30 { 0x6105, KEY_5 },
31 { 0x6106, KEY_6 },
32 { 0x6107, KEY_CHANNELDOWN },
33
34 { 0x610c, KEY_7 },
35 { 0x610d, KEY_8 },
36 { 0x610a, KEY_9 },
37 { 0x610e, KEY_VOLUMEUP },
38
39 { 0x6110, KEY_LAST },
40 { 0x6111, KEY_0 },
41 { 0x6112, KEY_ENTER },
42 { 0x6113, KEY_VOLUMEDOWN },
43
44 { 0x6114, KEY_RECORD },
45 { 0x6115, KEY_STOP },
46 { 0x6116, KEY_PLAY },
47 { 0x6117, KEY_MUTE },
48
49 { 0x6118, KEY_UP },
50 { 0x6119, KEY_DOWN },
51 { 0x611a, KEY_LEFT },
52 { 0x611b, KEY_RIGHT },
53
54 { 0x611c, KEY_RED },
55 { 0x611d, KEY_GREEN },
56 { 0x611e, KEY_YELLOW },
57 { 0x611f, KEY_BLUE },
58};
59
60static struct rc_keymap kworld_315u_map = {
61 .map = {
62 .scan = kworld_315u,
63 .size = ARRAY_SIZE(kworld_315u),
64 .ir_type = IR_TYPE_NEC,
65 .name = RC_MAP_KWORLD_315U,
66 }
67};
68
69static int __init init_rc_map_kworld_315u(void)
70{
71 return ir_register_map(&kworld_315u_map);
72}
73
74static void __exit exit_rc_map_kworld_315u(void)
75{
76 ir_unregister_map(&kworld_315u_map);
77}
78
79module_init(init_rc_map_kworld_315u)
80module_exit(exit_rc_map_kworld_315u)
81
82MODULE_LICENSE("GPL");
83MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c
new file mode 100644
index 000000000000..366732f1f7b7
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c
@@ -0,0 +1,99 @@
1/* kworld-plus-tv-analog.h - Keytable for kworld_plus_tv_analog Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Kworld Plus TV Analog Lite PCI IR
16 Mauro Carvalho Chehab <mchehab@infradead.org>
17 */
18
19static struct ir_scancode kworld_plus_tv_analog[] = {
20 { 0x0c, KEY_PROG1 }, /* Kworld key */
21 { 0x16, KEY_CLOSECD }, /* -> ) */
22 { 0x1d, KEY_POWER2 },
23
24 { 0x00, KEY_1 },
25 { 0x01, KEY_2 },
26 { 0x02, KEY_3 }, /* Two keys have the same code: 3 and left */
27 { 0x03, KEY_4 }, /* Two keys have the same code: 3 and right */
28 { 0x04, KEY_5 },
29 { 0x05, KEY_6 },
30 { 0x06, KEY_7 },
31 { 0x07, KEY_8 },
32 { 0x08, KEY_9 },
33 { 0x0a, KEY_0 },
34
35 { 0x09, KEY_AGAIN },
36 { 0x14, KEY_MUTE },
37
38 { 0x20, KEY_UP },
39 { 0x21, KEY_DOWN },
40 { 0x0b, KEY_ENTER },
41
42 { 0x10, KEY_CHANNELUP },
43 { 0x11, KEY_CHANNELDOWN },
44
45 /* Couldn't map key left/key right since those
46 conflict with '3' and '4' scancodes
47 I dunno what the original driver does
48 */
49
50 { 0x13, KEY_VOLUMEUP },
51 { 0x12, KEY_VOLUMEDOWN },
52
53 /* The lower part of the IR
54 There are several duplicated keycodes there.
55 Most of them conflict with digits.
56 Add mappings just to the unused scancodes.
57 Somehow, the original driver has a way to know,
58 but this doesn't seem to be on some GPIO.
59 Also, it is not related to the time between keyup
60 and keydown.
61 */
62 { 0x19, KEY_TIME}, /* Timeshift */
63 { 0x1a, KEY_STOP},
64 { 0x1b, KEY_RECORD},
65
66 { 0x22, KEY_TEXT},
67
68 { 0x15, KEY_AUDIO}, /* ((*)) */
69 { 0x0f, KEY_ZOOM},
70 { 0x1c, KEY_CAMERA}, /* snapshot */
71
72 { 0x18, KEY_RED}, /* B */
73 { 0x23, KEY_GREEN}, /* C */
74};
75
76static struct rc_keymap kworld_plus_tv_analog_map = {
77 .map = {
78 .scan = kworld_plus_tv_analog,
79 .size = ARRAY_SIZE(kworld_plus_tv_analog),
80 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
81 .name = RC_MAP_KWORLD_PLUS_TV_ANALOG,
82 }
83};
84
85static int __init init_rc_map_kworld_plus_tv_analog(void)
86{
87 return ir_register_map(&kworld_plus_tv_analog_map);
88}
89
90static void __exit exit_rc_map_kworld_plus_tv_analog(void)
91{
92 ir_unregister_map(&kworld_plus_tv_analog_map);
93}
94
95module_init(init_rc_map_kworld_plus_tv_analog)
96module_exit(exit_rc_map_kworld_plus_tv_analog)
97
98MODULE_LICENSE("GPL");
99MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c b/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c
new file mode 100644
index 000000000000..7521315fd876
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c
@@ -0,0 +1,99 @@
1/*
2 * LeadTek Y04G0051 remote controller keytable
3 *
4 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <media/rc-map.h>
22
23static struct ir_scancode leadtek_y04g0051[] = {
24 { 0x0300, KEY_POWER2 },
25 { 0x0303, KEY_SCREEN },
26 { 0x0304, KEY_RIGHT },
27 { 0x0305, KEY_1 },
28 { 0x0306, KEY_2 },
29 { 0x0307, KEY_3 },
30 { 0x0308, KEY_LEFT },
31 { 0x0309, KEY_4 },
32 { 0x030a, KEY_5 },
33 { 0x030b, KEY_6 },
34 { 0x030c, KEY_UP },
35 { 0x030d, KEY_7 },
36 { 0x030e, KEY_8 },
37 { 0x030f, KEY_9 },
38 { 0x0310, KEY_DOWN },
39 { 0x0311, KEY_AGAIN },
40 { 0x0312, KEY_0 },
41 { 0x0313, KEY_OK }, /* 1st ok */
42 { 0x0314, KEY_MUTE },
43 { 0x0316, KEY_OK }, /* 2nd ok */
44 { 0x031e, KEY_VIDEO }, /* 2nd video */
45 { 0x031b, KEY_AUDIO },
46 { 0x031f, KEY_TEXT },
47 { 0x0340, KEY_SLEEP },
48 { 0x0341, KEY_DOT },
49 { 0x0342, KEY_REWIND },
50 { 0x0343, KEY_PLAY },
51 { 0x0344, KEY_FASTFORWARD },
52 { 0x0345, KEY_TIME },
53 { 0x0346, KEY_STOP }, /* 2nd stop */
54 { 0x0347, KEY_RECORD },
55 { 0x0348, KEY_CAMERA },
56 { 0x0349, KEY_ESC },
57 { 0x034a, KEY_NEW },
58 { 0x034b, KEY_RED },
59 { 0x034c, KEY_GREEN },
60 { 0x034d, KEY_YELLOW },
61 { 0x034e, KEY_BLUE },
62 { 0x034f, KEY_MENU },
63 { 0x0350, KEY_STOP }, /* 1st stop */
64 { 0x0351, KEY_CHANNEL },
65 { 0x0352, KEY_VIDEO }, /* 1st video */
66 { 0x0353, KEY_EPG },
67 { 0x0354, KEY_PREVIOUS },
68 { 0x0355, KEY_NEXT },
69 { 0x0356, KEY_TV },
70 { 0x035a, KEY_VOLUMEDOWN },
71 { 0x035b, KEY_CHANNELUP },
72 { 0x035e, KEY_VOLUMEUP },
73 { 0x035f, KEY_CHANNELDOWN },
74};
75
76static struct rc_keymap leadtek_y04g0051_map = {
77 .map = {
78 .scan = leadtek_y04g0051,
79 .size = ARRAY_SIZE(leadtek_y04g0051),
80 .ir_type = IR_TYPE_NEC,
81 .name = RC_MAP_LEADTEK_Y04G0051,
82 }
83};
84
85static int __init init_rc_map_leadtek_y04g0051(void)
86{
87 return ir_register_map(&leadtek_y04g0051_map);
88}
89
90static void __exit exit_rc_map_leadtek_y04g0051(void)
91{
92 ir_unregister_map(&leadtek_y04g0051_map);
93}
94
95module_init(init_rc_map_leadtek_y04g0051)
96module_exit(exit_rc_map_leadtek_y04g0051)
97
98MODULE_LICENSE("GPL");
99MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff --git a/drivers/media/rc/keymaps/rc-lirc.c b/drivers/media/rc/keymaps/rc-lirc.c
new file mode 100644
index 000000000000..43fcf9035082
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-lirc.c
@@ -0,0 +1,41 @@
1/* rc-lirc.c - Empty dummy keytable, for use when its preferred to pass
2 * all raw IR data to the lirc userspace decoder.
3 *
4 * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <media/ir-core.h>
13
14static struct ir_scancode lirc[] = {
15 { },
16};
17
18static struct rc_keymap lirc_map = {
19 .map = {
20 .scan = lirc,
21 .size = ARRAY_SIZE(lirc),
22 .ir_type = IR_TYPE_LIRC,
23 .name = RC_MAP_LIRC,
24 }
25};
26
27static int __init init_rc_map_lirc(void)
28{
29 return ir_register_map(&lirc_map);
30}
31
32static void __exit exit_rc_map_lirc(void)
33{
34 ir_unregister_map(&lirc_map);
35}
36
37module_init(init_rc_map_lirc)
38module_exit(exit_rc_map_lirc)
39
40MODULE_LICENSE("GPL");
41MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-lme2510.c b/drivers/media/rc/keymaps/rc-lme2510.c
new file mode 100644
index 000000000000..40dcf0b4e21a
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-lme2510.c
@@ -0,0 +1,68 @@
1/* LME2510 remote control
2 *
3 *
4 * Copyright (C) 2010 Malcolm Priestley (tvboxspy@gmail.com)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <media/rc-map.h>
13
14
15static struct ir_scancode lme2510_rc[] = {
16 { 0xba45, KEY_0 },
17 { 0xa05f, KEY_1 },
18 { 0xaf50, KEY_2 },
19 { 0xa25d, KEY_3 },
20 { 0xbe41, KEY_4 },
21 { 0xf50a, KEY_5 },
22 { 0xbd42, KEY_6 },
23 { 0xb847, KEY_7 },
24 { 0xb649, KEY_8 },
25 { 0xfa05, KEY_9 },
26 { 0xbc43, KEY_POWER },
27 { 0xb946, KEY_SUBTITLE },
28 { 0xf906, KEY_PAUSE },
29 { 0xfc03, KEY_MEDIA_REPEAT},
30 { 0xfd02, KEY_PAUSE },
31 { 0xa15e, KEY_VOLUMEUP },
32 { 0xa35c, KEY_VOLUMEDOWN },
33 { 0xf609, KEY_CHANNELUP },
34 { 0xe51a, KEY_CHANNELDOWN },
35 { 0xe11e, KEY_PLAY },
36 { 0xe41b, KEY_ZOOM },
37 { 0xa659, KEY_MUTE },
38 { 0xa55a, KEY_TV },
39 { 0xe718, KEY_RECORD },
40 { 0xf807, KEY_EPG },
41 { 0xfe01, KEY_STOP },
42
43};
44
45static struct rc_keymap lme2510_map = {
46 .map = {
47 .scan = lme2510_rc,
48 .size = ARRAY_SIZE(lme2510_rc),
49 .ir_type = IR_TYPE_UNKNOWN,
50 .name = RC_MAP_LME2510,
51 }
52};
53
54static int __init init_rc_lme2510_map(void)
55{
56 return ir_register_map(&lme2510_map);
57}
58
59static void __exit exit_rc_lme2510_map(void)
60{
61 ir_unregister_map(&lme2510_map);
62}
63
64module_init(init_rc_lme2510_map)
65module_exit(exit_rc_lme2510_map)
66
67MODULE_LICENSE("GPL");
68MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
diff --git a/drivers/media/rc/keymaps/rc-manli.c b/drivers/media/rc/keymaps/rc-manli.c
new file mode 100644
index 000000000000..0f590b3d01c0
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-manli.c
@@ -0,0 +1,134 @@
1/* manli.h - Keytable for manli Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Michael Tokarev <mjt@tls.msk.ru>
16 keytable is used by MANLI MTV00[0x0c] and BeholdTV 40[13] at
17 least, and probably other cards too.
18 The "ascii-art picture" below (in comments, first row
19 is the keycode in hex, and subsequent row(s) shows
20 the button labels (several variants when appropriate)
21 helps to descide which keycodes to assign to the buttons.
22 */
23
24static struct ir_scancode manli[] = {
25
26 /* 0x1c 0x12 *
27 * FUNCTION POWER *
28 * FM (|) *
29 * */
30 { 0x1c, KEY_RADIO }, /*XXX*/
31 { 0x12, KEY_POWER },
32
33 /* 0x01 0x02 0x03 *
34 * 1 2 3 *
35 * *
36 * 0x04 0x05 0x06 *
37 * 4 5 6 *
38 * *
39 * 0x07 0x08 0x09 *
40 * 7 8 9 *
41 * */
42 { 0x01, KEY_1 },
43 { 0x02, KEY_2 },
44 { 0x03, KEY_3 },
45 { 0x04, KEY_4 },
46 { 0x05, KEY_5 },
47 { 0x06, KEY_6 },
48 { 0x07, KEY_7 },
49 { 0x08, KEY_8 },
50 { 0x09, KEY_9 },
51
52 /* 0x0a 0x00 0x17 *
53 * RECALL 0 +100 *
54 * PLUS *
55 * */
56 { 0x0a, KEY_AGAIN }, /*XXX KEY_REWIND? */
57 { 0x00, KEY_0 },
58 { 0x17, KEY_DIGITS }, /*XXX*/
59
60 /* 0x14 0x10 *
61 * MENU INFO *
62 * OSD */
63 { 0x14, KEY_MENU },
64 { 0x10, KEY_INFO },
65
66 /* 0x0b *
67 * Up *
68 * *
69 * 0x18 0x16 0x0c *
70 * Left Ok Right *
71 * *
72 * 0x015 *
73 * Down *
74 * */
75 { 0x0b, KEY_UP },
76 { 0x18, KEY_LEFT },
77 { 0x16, KEY_OK }, /*XXX KEY_SELECT? KEY_ENTER? */
78 { 0x0c, KEY_RIGHT },
79 { 0x15, KEY_DOWN },
80
81 /* 0x11 0x0d *
82 * TV/AV MODE *
83 * SOURCE STEREO *
84 * */
85 { 0x11, KEY_TV }, /*XXX*/
86 { 0x0d, KEY_MODE }, /*XXX there's no KEY_STEREO */
87
88 /* 0x0f 0x1b 0x1a *
89 * AUDIO Vol+ Chan+ *
90 * TIMESHIFT??? *
91 * *
92 * 0x0e 0x1f 0x1e *
93 * SLEEP Vol- Chan- *
94 * */
95 { 0x0f, KEY_AUDIO },
96 { 0x1b, KEY_VOLUMEUP },
97 { 0x1a, KEY_CHANNELUP },
98 { 0x0e, KEY_TIME },
99 { 0x1f, KEY_VOLUMEDOWN },
100 { 0x1e, KEY_CHANNELDOWN },
101
102 /* 0x13 0x19 *
103 * MUTE SNAPSHOT*
104 * */
105 { 0x13, KEY_MUTE },
106 { 0x19, KEY_CAMERA },
107
108 /* 0x1d unused ? */
109};
110
111static struct rc_keymap manli_map = {
112 .map = {
113 .scan = manli,
114 .size = ARRAY_SIZE(manli),
115 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
116 .name = RC_MAP_MANLI,
117 }
118};
119
120static int __init init_rc_map_manli(void)
121{
122 return ir_register_map(&manli_map);
123}
124
125static void __exit exit_rc_map_manli(void)
126{
127 ir_unregister_map(&manli_map);
128}
129
130module_init(init_rc_map_manli)
131module_exit(exit_rc_map_manli)
132
133MODULE_LICENSE("GPL");
134MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-msi-digivox-ii.c b/drivers/media/rc/keymaps/rc-msi-digivox-ii.c
new file mode 100644
index 000000000000..67237fbf9e4b
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-msi-digivox-ii.c
@@ -0,0 +1,67 @@
1/*
2 * MSI DIGIVOX mini II remote controller keytable
3 *
4 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <media/rc-map.h>
22
23static struct ir_scancode msi_digivox_ii[] = {
24 { 0x0002, KEY_2 },
25 { 0x0003, KEY_UP }, /* up */
26 { 0x0004, KEY_3 },
27 { 0x0005, KEY_CHANNELDOWN },
28 { 0x0008, KEY_5 },
29 { 0x0009, KEY_0 },
30 { 0x000b, KEY_8 },
31 { 0x000d, KEY_DOWN }, /* down */
32 { 0x0010, KEY_9 },
33 { 0x0011, KEY_7 },
34 { 0x0014, KEY_VOLUMEUP },
35 { 0x0015, KEY_CHANNELUP },
36 { 0x0016, KEY_OK },
37 { 0x0017, KEY_POWER2 },
38 { 0x001a, KEY_1 },
39 { 0x001c, KEY_4 },
40 { 0x001d, KEY_6 },
41 { 0x001f, KEY_VOLUMEDOWN },
42};
43
44static struct rc_keymap msi_digivox_ii_map = {
45 .map = {
46 .scan = msi_digivox_ii,
47 .size = ARRAY_SIZE(msi_digivox_ii),
48 .ir_type = IR_TYPE_NEC,
49 .name = RC_MAP_MSI_DIGIVOX_II,
50 }
51};
52
53static int __init init_rc_map_msi_digivox_ii(void)
54{
55 return ir_register_map(&msi_digivox_ii_map);
56}
57
58static void __exit exit_rc_map_msi_digivox_ii(void)
59{
60 ir_unregister_map(&msi_digivox_ii_map);
61}
62
63module_init(init_rc_map_msi_digivox_ii)
64module_exit(exit_rc_map_msi_digivox_ii)
65
66MODULE_LICENSE("GPL");
67MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff --git a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c
new file mode 100644
index 000000000000..882056e52ef9
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c
@@ -0,0 +1,85 @@
1/*
2 * MSI DIGIVOX mini III remote controller keytable
3 *
4 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <media/rc-map.h>
22
23/* MSI DIGIVOX mini III */
24/* Uses NEC extended 0x61d6. */
25/* This remote seems to be same as rc-kworld-315u.c. Anyhow, add new remote
26 since rc-kworld-315u.c lacks NEC extended address byte. */
27static struct ir_scancode msi_digivox_iii[] = {
28 { 0x61d601, KEY_VIDEO }, /* Source */
29 { 0x61d602, KEY_3 },
30 { 0x61d603, KEY_POWER }, /* ShutDown */
31 { 0x61d604, KEY_1 },
32 { 0x61d605, KEY_5 },
33 { 0x61d606, KEY_6 },
34 { 0x61d607, KEY_CHANNELDOWN }, /* CH- */
35 { 0x61d608, KEY_2 },
36 { 0x61d609, KEY_CHANNELUP }, /* CH+ */
37 { 0x61d60a, KEY_9 },
38 { 0x61d60b, KEY_ZOOM }, /* Zoom */
39 { 0x61d60c, KEY_7 },
40 { 0x61d60d, KEY_8 },
41 { 0x61d60e, KEY_VOLUMEUP }, /* Vol+ */
42 { 0x61d60f, KEY_4 },
43 { 0x61d610, KEY_ESC }, /* [back up arrow] */
44 { 0x61d611, KEY_0 },
45 { 0x61d612, KEY_OK }, /* [enter arrow] */
46 { 0x61d613, KEY_VOLUMEDOWN }, /* Vol- */
47 { 0x61d614, KEY_RECORD }, /* Rec */
48 { 0x61d615, KEY_STOP }, /* Stop */
49 { 0x61d616, KEY_PLAY }, /* Play */
50 { 0x61d617, KEY_MUTE }, /* Mute */
51 { 0x61d618, KEY_UP },
52 { 0x61d619, KEY_DOWN },
53 { 0x61d61a, KEY_LEFT },
54 { 0x61d61b, KEY_RIGHT },
55 { 0x61d61c, KEY_RED },
56 { 0x61d61d, KEY_GREEN },
57 { 0x61d61e, KEY_YELLOW },
58 { 0x61d61f, KEY_BLUE },
59 { 0x61d643, KEY_POWER2 }, /* [red power button] */
60};
61
62static struct rc_keymap msi_digivox_iii_map = {
63 .map = {
64 .scan = msi_digivox_iii,
65 .size = ARRAY_SIZE(msi_digivox_iii),
66 .ir_type = IR_TYPE_NEC,
67 .name = RC_MAP_MSI_DIGIVOX_III,
68 }
69};
70
71static int __init init_rc_map_msi_digivox_iii(void)
72{
73 return ir_register_map(&msi_digivox_iii_map);
74}
75
76static void __exit exit_rc_map_msi_digivox_iii(void)
77{
78 ir_unregister_map(&msi_digivox_iii_map);
79}
80
81module_init(init_rc_map_msi_digivox_iii)
82module_exit(exit_rc_map_msi_digivox_iii)
83
84MODULE_LICENSE("GPL");
85MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c
new file mode 100644
index 000000000000..eb8e42c18ff9
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c
@@ -0,0 +1,123 @@
1/* msi-tvanywhere-plus.h - Keytable for msi_tvanywhere_plus Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/*
16 Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card
17 is marked "KS003". The controller is I2C at address 0x30, but does not seem
18 to respond to probes until a read is performed from a valid device.
19 I don't know why...
20
21 Note: This remote may be of similar or identical design to the
22 Pixelview remote (?). The raw codes and duplicate button codes
23 appear to be the same.
24
25 Henry Wong <henry@stuffedcow.net>
26 Some changes to formatting and keycodes by Mark Schultz <n9xmj@yahoo.com>
27*/
28
29static struct ir_scancode msi_tvanywhere_plus[] = {
30
31/* ---- Remote Button Layout ----
32
33 POWER SOURCE SCAN MUTE
34 TV/FM 1 2 3
35 |> 4 5 6
36 <| 7 8 9
37 ^^UP 0 + RECALL
38 vvDN RECORD STOP PLAY
39
40 MINIMIZE ZOOM
41
42 CH+
43 VOL- VOL+
44 CH-
45
46 SNAPSHOT MTS
47
48 << FUNC >> RESET
49*/
50
51 { 0x01, KEY_1 }, /* 1 */
52 { 0x0b, KEY_2 }, /* 2 */
53 { 0x1b, KEY_3 }, /* 3 */
54 { 0x05, KEY_4 }, /* 4 */
55 { 0x09, KEY_5 }, /* 5 */
56 { 0x15, KEY_6 }, /* 6 */
57 { 0x06, KEY_7 }, /* 7 */
58 { 0x0a, KEY_8 }, /* 8 */
59 { 0x12, KEY_9 }, /* 9 */
60 { 0x02, KEY_0 }, /* 0 */
61 { 0x10, KEY_KPPLUS }, /* + */
62 { 0x13, KEY_AGAIN }, /* Recall */
63
64 { 0x1e, KEY_POWER }, /* Power */
65 { 0x07, KEY_TUNER }, /* Source */
66 { 0x1c, KEY_SEARCH }, /* Scan */
67 { 0x18, KEY_MUTE }, /* Mute */
68
69 { 0x03, KEY_RADIO }, /* TV/FM */
70 /* The next four keys are duplicates that appear to send the
71 same IR code as Ch+, Ch-, >>, and << . The raw code assigned
72 to them is the actual code + 0x20 - they will never be
73 detected as such unless some way is discovered to distinguish
74 these buttons from those that have the same code. */
75 { 0x3f, KEY_RIGHT }, /* |> and Ch+ */
76 { 0x37, KEY_LEFT }, /* <| and Ch- */
77 { 0x2c, KEY_UP }, /* ^^Up and >> */
78 { 0x24, KEY_DOWN }, /* vvDn and << */
79
80 { 0x00, KEY_RECORD }, /* Record */
81 { 0x08, KEY_STOP }, /* Stop */
82 { 0x11, KEY_PLAY }, /* Play */
83
84 { 0x0f, KEY_CLOSE }, /* Minimize */
85 { 0x19, KEY_ZOOM }, /* Zoom */
86 { 0x1a, KEY_CAMERA }, /* Snapshot */
87 { 0x0d, KEY_LANGUAGE }, /* MTS */
88
89 { 0x14, KEY_VOLUMEDOWN }, /* Vol- */
90 { 0x16, KEY_VOLUMEUP }, /* Vol+ */
91 { 0x17, KEY_CHANNELDOWN }, /* Ch- */
92 { 0x1f, KEY_CHANNELUP }, /* Ch+ */
93
94 { 0x04, KEY_REWIND }, /* << */
95 { 0x0e, KEY_MENU }, /* Function */
96 { 0x0c, KEY_FASTFORWARD }, /* >> */
97 { 0x1d, KEY_RESTART }, /* Reset */
98};
99
100static struct rc_keymap msi_tvanywhere_plus_map = {
101 .map = {
102 .scan = msi_tvanywhere_plus,
103 .size = ARRAY_SIZE(msi_tvanywhere_plus),
104 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
105 .name = RC_MAP_MSI_TVANYWHERE_PLUS,
106 }
107};
108
109static int __init init_rc_map_msi_tvanywhere_plus(void)
110{
111 return ir_register_map(&msi_tvanywhere_plus_map);
112}
113
114static void __exit exit_rc_map_msi_tvanywhere_plus(void)
115{
116 ir_unregister_map(&msi_tvanywhere_plus_map);
117}
118
119module_init(init_rc_map_msi_tvanywhere_plus)
120module_exit(exit_rc_map_msi_tvanywhere_plus)
121
122MODULE_LICENSE("GPL");
123MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere.c
new file mode 100644
index 000000000000..ef411854f067
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere.c
@@ -0,0 +1,69 @@
1/* msi-tvanywhere.h - Keytable for msi_tvanywhere Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* MSI TV@nywhere MASTER remote */
16
17static struct ir_scancode msi_tvanywhere[] = {
18 /* Keys 0 to 9 */
19 { 0x00, KEY_0 },
20 { 0x01, KEY_1 },
21 { 0x02, KEY_2 },
22 { 0x03, KEY_3 },
23 { 0x04, KEY_4 },
24 { 0x05, KEY_5 },
25 { 0x06, KEY_6 },
26 { 0x07, KEY_7 },
27 { 0x08, KEY_8 },
28 { 0x09, KEY_9 },
29
30 { 0x0c, KEY_MUTE },
31 { 0x0f, KEY_SCREEN }, /* Full Screen */
32 { 0x10, KEY_FN }, /* Funtion */
33 { 0x11, KEY_TIME }, /* Time shift */
34 { 0x12, KEY_POWER },
35 { 0x13, KEY_MEDIA }, /* MTS */
36 { 0x14, KEY_SLOW },
37 { 0x16, KEY_REWIND }, /* backward << */
38 { 0x17, KEY_ENTER }, /* Return */
39 { 0x18, KEY_FASTFORWARD }, /* forward >> */
40 { 0x1a, KEY_CHANNELUP },
41 { 0x1b, KEY_VOLUMEUP },
42 { 0x1e, KEY_CHANNELDOWN },
43 { 0x1f, KEY_VOLUMEDOWN },
44};
45
46static struct rc_keymap msi_tvanywhere_map = {
47 .map = {
48 .scan = msi_tvanywhere,
49 .size = ARRAY_SIZE(msi_tvanywhere),
50 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
51 .name = RC_MAP_MSI_TVANYWHERE,
52 }
53};
54
55static int __init init_rc_map_msi_tvanywhere(void)
56{
57 return ir_register_map(&msi_tvanywhere_map);
58}
59
60static void __exit exit_rc_map_msi_tvanywhere(void)
61{
62 ir_unregister_map(&msi_tvanywhere_map);
63}
64
65module_init(init_rc_map_msi_tvanywhere)
66module_exit(exit_rc_map_msi_tvanywhere)
67
68MODULE_LICENSE("GPL");
69MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-nebula.c b/drivers/media/rc/keymaps/rc-nebula.c
new file mode 100644
index 000000000000..ccc50eb402ec
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-nebula.c
@@ -0,0 +1,96 @@
1/* nebula.h - Keytable for nebula Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode nebula[] = {
16 { 0x00, KEY_0 },
17 { 0x01, KEY_1 },
18 { 0x02, KEY_2 },
19 { 0x03, KEY_3 },
20 { 0x04, KEY_4 },
21 { 0x05, KEY_5 },
22 { 0x06, KEY_6 },
23 { 0x07, KEY_7 },
24 { 0x08, KEY_8 },
25 { 0x09, KEY_9 },
26 { 0x0a, KEY_TV },
27 { 0x0b, KEY_AUX },
28 { 0x0c, KEY_DVD },
29 { 0x0d, KEY_POWER },
30 { 0x0e, KEY_MHP }, /* labelled 'Picture' */
31 { 0x0f, KEY_AUDIO },
32 { 0x10, KEY_INFO },
33 { 0x11, KEY_F13 }, /* 16:9 */
34 { 0x12, KEY_F14 }, /* 14:9 */
35 { 0x13, KEY_EPG },
36 { 0x14, KEY_EXIT },
37 { 0x15, KEY_MENU },
38 { 0x16, KEY_UP },
39 { 0x17, KEY_DOWN },
40 { 0x18, KEY_LEFT },
41 { 0x19, KEY_RIGHT },
42 { 0x1a, KEY_ENTER },
43 { 0x1b, KEY_CHANNELUP },
44 { 0x1c, KEY_CHANNELDOWN },
45 { 0x1d, KEY_VOLUMEUP },
46 { 0x1e, KEY_VOLUMEDOWN },
47 { 0x1f, KEY_RED },
48 { 0x20, KEY_GREEN },
49 { 0x21, KEY_YELLOW },
50 { 0x22, KEY_BLUE },
51 { 0x23, KEY_SUBTITLE },
52 { 0x24, KEY_F15 }, /* AD */
53 { 0x25, KEY_TEXT },
54 { 0x26, KEY_MUTE },
55 { 0x27, KEY_REWIND },
56 { 0x28, KEY_STOP },
57 { 0x29, KEY_PLAY },
58 { 0x2a, KEY_FASTFORWARD },
59 { 0x2b, KEY_F16 }, /* chapter */
60 { 0x2c, KEY_PAUSE },
61 { 0x2d, KEY_PLAY },
62 { 0x2e, KEY_RECORD },
63 { 0x2f, KEY_F17 }, /* picture in picture */
64 { 0x30, KEY_KPPLUS }, /* zoom in */
65 { 0x31, KEY_KPMINUS }, /* zoom out */
66 { 0x32, KEY_F18 }, /* capture */
67 { 0x33, KEY_F19 }, /* web */
68 { 0x34, KEY_EMAIL },
69 { 0x35, KEY_PHONE },
70 { 0x36, KEY_PC },
71};
72
73static struct rc_keymap nebula_map = {
74 .map = {
75 .scan = nebula,
76 .size = ARRAY_SIZE(nebula),
77 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
78 .name = RC_MAP_NEBULA,
79 }
80};
81
82static int __init init_rc_map_nebula(void)
83{
84 return ir_register_map(&nebula_map);
85}
86
87static void __exit exit_rc_map_nebula(void)
88{
89 ir_unregister_map(&nebula_map);
90}
91
92module_init(init_rc_map_nebula)
93module_exit(exit_rc_map_nebula)
94
95MODULE_LICENSE("GPL");
96MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c b/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c
new file mode 100644
index 000000000000..e1b54d20db60
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c
@@ -0,0 +1,105 @@
1/* nec-terratec-cinergy-xs.h - Keytable for nec_terratec_cinergy_xs Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Terratec Cinergy Hybrid T USB XS FM
16 Mauro Carvalho Chehab <mchehab@redhat.com>
17 */
18
19static struct ir_scancode nec_terratec_cinergy_xs[] = {
20 { 0x1441, KEY_HOME},
21 { 0x1401, KEY_POWER2},
22
23 { 0x1442, KEY_MENU}, /* DVD menu */
24 { 0x1443, KEY_SUBTITLE},
25 { 0x1444, KEY_TEXT}, /* Teletext */
26 { 0x1445, KEY_DELETE},
27
28 { 0x1402, KEY_1},
29 { 0x1403, KEY_2},
30 { 0x1404, KEY_3},
31 { 0x1405, KEY_4},
32 { 0x1406, KEY_5},
33 { 0x1407, KEY_6},
34 { 0x1408, KEY_7},
35 { 0x1409, KEY_8},
36 { 0x140a, KEY_9},
37 { 0x140c, KEY_0},
38
39 { 0x140b, KEY_TUNER}, /* AV */
40 { 0x140d, KEY_MODE}, /* A.B */
41
42 { 0x1446, KEY_TV},
43 { 0x1447, KEY_DVD},
44 { 0x1449, KEY_VIDEO},
45 { 0x144a, KEY_RADIO}, /* Music */
46 { 0x144b, KEY_CAMERA}, /* PIC */
47
48 { 0x1410, KEY_UP},
49 { 0x1411, KEY_LEFT},
50 { 0x1412, KEY_OK},
51 { 0x1413, KEY_RIGHT},
52 { 0x1414, KEY_DOWN},
53
54 { 0x140f, KEY_EPG},
55 { 0x1416, KEY_INFO},
56 { 0x144d, KEY_BACKSPACE},
57
58 { 0x141c, KEY_VOLUMEUP},
59 { 0x141e, KEY_VOLUMEDOWN},
60
61 { 0x144c, KEY_PLAY},
62 { 0x141d, KEY_MUTE},
63
64 { 0x141b, KEY_CHANNELUP},
65 { 0x141f, KEY_CHANNELDOWN},
66
67 { 0x1417, KEY_RED},
68 { 0x1418, KEY_GREEN},
69 { 0x1419, KEY_YELLOW},
70 { 0x141a, KEY_BLUE},
71
72 { 0x1458, KEY_RECORD},
73 { 0x1448, KEY_STOP},
74 { 0x1440, KEY_PAUSE},
75
76 { 0x1454, KEY_LAST},
77 { 0x144e, KEY_REWIND},
78 { 0x144f, KEY_FASTFORWARD},
79 { 0x145c, KEY_NEXT},
80};
81
82static struct rc_keymap nec_terratec_cinergy_xs_map = {
83 .map = {
84 .scan = nec_terratec_cinergy_xs,
85 .size = ARRAY_SIZE(nec_terratec_cinergy_xs),
86 .ir_type = IR_TYPE_NEC,
87 .name = RC_MAP_NEC_TERRATEC_CINERGY_XS,
88 }
89};
90
91static int __init init_rc_map_nec_terratec_cinergy_xs(void)
92{
93 return ir_register_map(&nec_terratec_cinergy_xs_map);
94}
95
96static void __exit exit_rc_map_nec_terratec_cinergy_xs(void)
97{
98 ir_unregister_map(&nec_terratec_cinergy_xs_map);
99}
100
101module_init(init_rc_map_nec_terratec_cinergy_xs)
102module_exit(exit_rc_map_nec_terratec_cinergy_xs)
103
104MODULE_LICENSE("GPL");
105MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-norwood.c b/drivers/media/rc/keymaps/rc-norwood.c
new file mode 100644
index 000000000000..e5849a6b3f05
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-norwood.c
@@ -0,0 +1,85 @@
1/* norwood.h - Keytable for norwood Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Norwood Micro (non-Pro) TV Tuner
16 By Peter Naulls <peter@chocky.org>
17 Key comments are the functions given in the manual */
18
19static struct ir_scancode norwood[] = {
20 /* Keys 0 to 9 */
21 { 0x20, KEY_0 },
22 { 0x21, KEY_1 },
23 { 0x22, KEY_2 },
24 { 0x23, KEY_3 },
25 { 0x24, KEY_4 },
26 { 0x25, KEY_5 },
27 { 0x26, KEY_6 },
28 { 0x27, KEY_7 },
29 { 0x28, KEY_8 },
30 { 0x29, KEY_9 },
31
32 { 0x78, KEY_TUNER }, /* Video Source */
33 { 0x2c, KEY_EXIT }, /* Open/Close software */
34 { 0x2a, KEY_SELECT }, /* 2 Digit Select */
35 { 0x69, KEY_AGAIN }, /* Recall */
36
37 { 0x32, KEY_BRIGHTNESSUP }, /* Brightness increase */
38 { 0x33, KEY_BRIGHTNESSDOWN }, /* Brightness decrease */
39 { 0x6b, KEY_KPPLUS }, /* (not named >>>>>) */
40 { 0x6c, KEY_KPMINUS }, /* (not named <<<<<) */
41
42 { 0x2d, KEY_MUTE }, /* Mute */
43 { 0x30, KEY_VOLUMEUP }, /* Volume up */
44 { 0x31, KEY_VOLUMEDOWN }, /* Volume down */
45 { 0x60, KEY_CHANNELUP }, /* Channel up */
46 { 0x61, KEY_CHANNELDOWN }, /* Channel down */
47
48 { 0x3f, KEY_RECORD }, /* Record */
49 { 0x37, KEY_PLAY }, /* Play */
50 { 0x36, KEY_PAUSE }, /* Pause */
51 { 0x2b, KEY_STOP }, /* Stop */
52 { 0x67, KEY_FASTFORWARD }, /* Foward */
53 { 0x66, KEY_REWIND }, /* Rewind */
54 { 0x3e, KEY_SEARCH }, /* Auto Scan */
55 { 0x2e, KEY_CAMERA }, /* Capture Video */
56 { 0x6d, KEY_MENU }, /* Show/Hide Control */
57 { 0x2f, KEY_ZOOM }, /* Full Screen */
58 { 0x34, KEY_RADIO }, /* FM */
59 { 0x65, KEY_POWER }, /* Computer power */
60};
61
62static struct rc_keymap norwood_map = {
63 .map = {
64 .scan = norwood,
65 .size = ARRAY_SIZE(norwood),
66 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
67 .name = RC_MAP_NORWOOD,
68 }
69};
70
71static int __init init_rc_map_norwood(void)
72{
73 return ir_register_map(&norwood_map);
74}
75
76static void __exit exit_rc_map_norwood(void)
77{
78 ir_unregister_map(&norwood_map);
79}
80
81module_init(init_rc_map_norwood)
82module_exit(exit_rc_map_norwood)
83
84MODULE_LICENSE("GPL");
85MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-npgtech.c b/drivers/media/rc/keymaps/rc-npgtech.c
new file mode 100644
index 000000000000..b9ece1e90296
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-npgtech.c
@@ -0,0 +1,80 @@
1/* npgtech.h - Keytable for npgtech Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode npgtech[] = {
16 { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */
17 { 0x2a, KEY_FRONT },
18
19 { 0x3e, KEY_1 },
20 { 0x02, KEY_2 },
21 { 0x06, KEY_3 },
22 { 0x0a, KEY_4 },
23 { 0x0e, KEY_5 },
24 { 0x12, KEY_6 },
25 { 0x16, KEY_7 },
26 { 0x1a, KEY_8 },
27 { 0x1e, KEY_9 },
28 { 0x3a, KEY_0 },
29 { 0x22, KEY_NUMLOCK }, /* -/-- */
30 { 0x20, KEY_REFRESH },
31
32 { 0x03, KEY_BRIGHTNESSDOWN },
33 { 0x28, KEY_AUDIO },
34 { 0x3c, KEY_CHANNELUP },
35 { 0x3f, KEY_VOLUMEDOWN },
36 { 0x2e, KEY_MUTE },
37 { 0x3b, KEY_VOLUMEUP },
38 { 0x00, KEY_CHANNELDOWN },
39 { 0x07, KEY_BRIGHTNESSUP },
40 { 0x2c, KEY_TEXT },
41
42 { 0x37, KEY_RECORD },
43 { 0x17, KEY_PLAY },
44 { 0x13, KEY_PAUSE },
45 { 0x26, KEY_STOP },
46 { 0x18, KEY_FASTFORWARD },
47 { 0x14, KEY_REWIND },
48 { 0x33, KEY_ZOOM },
49 { 0x32, KEY_KEYBOARD },
50 { 0x30, KEY_GOTO }, /* Pointing arrow */
51 { 0x36, KEY_MACRO }, /* Maximize/Minimize (yellow) */
52 { 0x0b, KEY_RADIO },
53 { 0x10, KEY_POWER },
54
55};
56
57static struct rc_keymap npgtech_map = {
58 .map = {
59 .scan = npgtech,
60 .size = ARRAY_SIZE(npgtech),
61 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
62 .name = RC_MAP_NPGTECH,
63 }
64};
65
66static int __init init_rc_map_npgtech(void)
67{
68 return ir_register_map(&npgtech_map);
69}
70
71static void __exit exit_rc_map_npgtech(void)
72{
73 ir_unregister_map(&npgtech_map);
74}
75
76module_init(init_rc_map_npgtech)
77module_exit(exit_rc_map_npgtech)
78
79MODULE_LICENSE("GPL");
80MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-pctv-sedna.c b/drivers/media/rc/keymaps/rc-pctv-sedna.c
new file mode 100644
index 000000000000..4129bb44a25b
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pctv-sedna.c
@@ -0,0 +1,80 @@
1/* pctv-sedna.h - Keytable for pctv_sedna Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Mapping for the 28 key remote control as seen at
16 http://www.sednacomputer.com/photo/cardbus-tv.jpg
17 Pavel Mihaylov <bin@bash.info>
18 Also for the remote bundled with Kozumi KTV-01C card */
19
20static struct ir_scancode pctv_sedna[] = {
21 { 0x00, KEY_0 },
22 { 0x01, KEY_1 },
23 { 0x02, KEY_2 },
24 { 0x03, KEY_3 },
25 { 0x04, KEY_4 },
26 { 0x05, KEY_5 },
27 { 0x06, KEY_6 },
28 { 0x07, KEY_7 },
29 { 0x08, KEY_8 },
30 { 0x09, KEY_9 },
31
32 { 0x0a, KEY_AGAIN }, /* Recall */
33 { 0x0b, KEY_CHANNELUP },
34 { 0x0c, KEY_VOLUMEUP },
35 { 0x0d, KEY_MODE }, /* Stereo */
36 { 0x0e, KEY_STOP },
37 { 0x0f, KEY_PREVIOUSSONG },
38 { 0x10, KEY_ZOOM },
39 { 0x11, KEY_TUNER }, /* Source */
40 { 0x12, KEY_POWER },
41 { 0x13, KEY_MUTE },
42 { 0x15, KEY_CHANNELDOWN },
43 { 0x18, KEY_VOLUMEDOWN },
44 { 0x19, KEY_CAMERA }, /* Snapshot */
45 { 0x1a, KEY_NEXTSONG },
46 { 0x1b, KEY_TIME }, /* Time Shift */
47 { 0x1c, KEY_RADIO }, /* FM Radio */
48 { 0x1d, KEY_RECORD },
49 { 0x1e, KEY_PAUSE },
50 /* additional codes for Kozumi's remote */
51 { 0x14, KEY_INFO }, /* OSD */
52 { 0x16, KEY_OK }, /* OK */
53 { 0x17, KEY_DIGITS }, /* Plus */
54 { 0x1f, KEY_PLAY }, /* Play */
55};
56
57static struct rc_keymap pctv_sedna_map = {
58 .map = {
59 .scan = pctv_sedna,
60 .size = ARRAY_SIZE(pctv_sedna),
61 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
62 .name = RC_MAP_PCTV_SEDNA,
63 }
64};
65
66static int __init init_rc_map_pctv_sedna(void)
67{
68 return ir_register_map(&pctv_sedna_map);
69}
70
71static void __exit exit_rc_map_pctv_sedna(void)
72{
73 ir_unregister_map(&pctv_sedna_map);
74}
75
76module_init(init_rc_map_pctv_sedna)
77module_exit(exit_rc_map_pctv_sedna)
78
79MODULE_LICENSE("GPL");
80MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-pinnacle-color.c b/drivers/media/rc/keymaps/rc-pinnacle-color.c
new file mode 100644
index 000000000000..326e023ce126
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pinnacle-color.c
@@ -0,0 +1,94 @@
1/* pinnacle-color.h - Keytable for pinnacle_color Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode pinnacle_color[] = {
16 { 0x59, KEY_MUTE },
17 { 0x4a, KEY_POWER },
18
19 { 0x18, KEY_TEXT },
20 { 0x26, KEY_TV },
21 { 0x3d, KEY_PRINT },
22
23 { 0x48, KEY_RED },
24 { 0x04, KEY_GREEN },
25 { 0x11, KEY_YELLOW },
26 { 0x00, KEY_BLUE },
27
28 { 0x2d, KEY_VOLUMEUP },
29 { 0x1e, KEY_VOLUMEDOWN },
30
31 { 0x49, KEY_MENU },
32
33 { 0x16, KEY_CHANNELUP },
34 { 0x17, KEY_CHANNELDOWN },
35
36 { 0x20, KEY_UP },
37 { 0x21, KEY_DOWN },
38 { 0x22, KEY_LEFT },
39 { 0x23, KEY_RIGHT },
40 { 0x0d, KEY_SELECT },
41
42 { 0x08, KEY_BACK },
43 { 0x07, KEY_REFRESH },
44
45 { 0x2f, KEY_ZOOM },
46 { 0x29, KEY_RECORD },
47
48 { 0x4b, KEY_PAUSE },
49 { 0x4d, KEY_REWIND },
50 { 0x2e, KEY_PLAY },
51 { 0x4e, KEY_FORWARD },
52 { 0x53, KEY_PREVIOUS },
53 { 0x4c, KEY_STOP },
54 { 0x54, KEY_NEXT },
55
56 { 0x69, KEY_0 },
57 { 0x6a, KEY_1 },
58 { 0x6b, KEY_2 },
59 { 0x6c, KEY_3 },
60 { 0x6d, KEY_4 },
61 { 0x6e, KEY_5 },
62 { 0x6f, KEY_6 },
63 { 0x70, KEY_7 },
64 { 0x71, KEY_8 },
65 { 0x72, KEY_9 },
66
67 { 0x74, KEY_CHANNEL },
68 { 0x0a, KEY_BACKSPACE },
69};
70
71static struct rc_keymap pinnacle_color_map = {
72 .map = {
73 .scan = pinnacle_color,
74 .size = ARRAY_SIZE(pinnacle_color),
75 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
76 .name = RC_MAP_PINNACLE_COLOR,
77 }
78};
79
80static int __init init_rc_map_pinnacle_color(void)
81{
82 return ir_register_map(&pinnacle_color_map);
83}
84
85static void __exit exit_rc_map_pinnacle_color(void)
86{
87 ir_unregister_map(&pinnacle_color_map);
88}
89
90module_init(init_rc_map_pinnacle_color)
91module_exit(exit_rc_map_pinnacle_color)
92
93MODULE_LICENSE("GPL");
94MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-pinnacle-grey.c b/drivers/media/rc/keymaps/rc-pinnacle-grey.c
new file mode 100644
index 000000000000..14cb772515c6
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pinnacle-grey.c
@@ -0,0 +1,89 @@
1/* pinnacle-grey.h - Keytable for pinnacle_grey Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode pinnacle_grey[] = {
16 { 0x3a, KEY_0 },
17 { 0x31, KEY_1 },
18 { 0x32, KEY_2 },
19 { 0x33, KEY_3 },
20 { 0x34, KEY_4 },
21 { 0x35, KEY_5 },
22 { 0x36, KEY_6 },
23 { 0x37, KEY_7 },
24 { 0x38, KEY_8 },
25 { 0x39, KEY_9 },
26
27 { 0x2f, KEY_POWER },
28
29 { 0x2e, KEY_P },
30 { 0x1f, KEY_L },
31 { 0x2b, KEY_I },
32
33 { 0x2d, KEY_SCREEN },
34 { 0x1e, KEY_ZOOM },
35 { 0x1b, KEY_VOLUMEUP },
36 { 0x0f, KEY_VOLUMEDOWN },
37 { 0x17, KEY_CHANNELUP },
38 { 0x1c, KEY_CHANNELDOWN },
39 { 0x25, KEY_INFO },
40
41 { 0x3c, KEY_MUTE },
42
43 { 0x3d, KEY_LEFT },
44 { 0x3b, KEY_RIGHT },
45
46 { 0x3f, KEY_UP },
47 { 0x3e, KEY_DOWN },
48 { 0x1a, KEY_ENTER },
49
50 { 0x1d, KEY_MENU },
51 { 0x19, KEY_AGAIN },
52 { 0x16, KEY_PREVIOUSSONG },
53 { 0x13, KEY_NEXTSONG },
54 { 0x15, KEY_PAUSE },
55 { 0x0e, KEY_REWIND },
56 { 0x0d, KEY_PLAY },
57 { 0x0b, KEY_STOP },
58 { 0x07, KEY_FORWARD },
59 { 0x27, KEY_RECORD },
60 { 0x26, KEY_TUNER },
61 { 0x29, KEY_TEXT },
62 { 0x2a, KEY_MEDIA },
63 { 0x18, KEY_EPG },
64};
65
66static struct rc_keymap pinnacle_grey_map = {
67 .map = {
68 .scan = pinnacle_grey,
69 .size = ARRAY_SIZE(pinnacle_grey),
70 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
71 .name = RC_MAP_PINNACLE_GREY,
72 }
73};
74
75static int __init init_rc_map_pinnacle_grey(void)
76{
77 return ir_register_map(&pinnacle_grey_map);
78}
79
80static void __exit exit_rc_map_pinnacle_grey(void)
81{
82 ir_unregister_map(&pinnacle_grey_map);
83}
84
85module_init(init_rc_map_pinnacle_grey)
86module_exit(exit_rc_map_pinnacle_grey)
87
88MODULE_LICENSE("GPL");
89MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c
new file mode 100644
index 000000000000..835bf4ef8de7
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c
@@ -0,0 +1,73 @@
1/* pinnacle-pctv-hd.h - Keytable for pinnacle_pctv_hd Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Pinnacle PCTV HD 800i mini remote */
16
17static struct ir_scancode pinnacle_pctv_hd[] = {
18
19 { 0x0f, KEY_1 },
20 { 0x15, KEY_2 },
21 { 0x10, KEY_3 },
22 { 0x18, KEY_4 },
23 { 0x1b, KEY_5 },
24 { 0x1e, KEY_6 },
25 { 0x11, KEY_7 },
26 { 0x21, KEY_8 },
27 { 0x12, KEY_9 },
28 { 0x27, KEY_0 },
29
30 { 0x24, KEY_ZOOM },
31 { 0x2a, KEY_SUBTITLE },
32
33 { 0x00, KEY_MUTE },
34 { 0x01, KEY_ENTER }, /* Pinnacle Logo */
35 { 0x39, KEY_POWER },
36
37 { 0x03, KEY_VOLUMEUP },
38 { 0x09, KEY_VOLUMEDOWN },
39 { 0x06, KEY_CHANNELUP },
40 { 0x0c, KEY_CHANNELDOWN },
41
42 { 0x2d, KEY_REWIND },
43 { 0x30, KEY_PLAYPAUSE },
44 { 0x33, KEY_FASTFORWARD },
45 { 0x3c, KEY_STOP },
46 { 0x36, KEY_RECORD },
47 { 0x3f, KEY_EPG }, /* Labeled "?" */
48};
49
50static struct rc_keymap pinnacle_pctv_hd_map = {
51 .map = {
52 .scan = pinnacle_pctv_hd,
53 .size = ARRAY_SIZE(pinnacle_pctv_hd),
54 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
55 .name = RC_MAP_PINNACLE_PCTV_HD,
56 }
57};
58
59static int __init init_rc_map_pinnacle_pctv_hd(void)
60{
61 return ir_register_map(&pinnacle_pctv_hd_map);
62}
63
64static void __exit exit_rc_map_pinnacle_pctv_hd(void)
65{
66 ir_unregister_map(&pinnacle_pctv_hd_map);
67}
68
69module_init(init_rc_map_pinnacle_pctv_hd)
70module_exit(exit_rc_map_pinnacle_pctv_hd)
71
72MODULE_LICENSE("GPL");
73MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-pixelview-mk12.c b/drivers/media/rc/keymaps/rc-pixelview-mk12.c
new file mode 100644
index 000000000000..5a735d569a8b
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pixelview-mk12.c
@@ -0,0 +1,83 @@
1/* rc-pixelview-mk12.h - Keytable for pixelview Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/*
16 * Keytable for MK-F12 IR remote provided together with Pixelview
17 * Ultra Pro Remote Controller. Uses NEC extended format.
18 */
19static struct ir_scancode pixelview_mk12[] = {
20 { 0x866b03, KEY_TUNER }, /* Timeshift */
21 { 0x866b1e, KEY_POWER2 }, /* power */
22
23 { 0x866b01, KEY_1 },
24 { 0x866b0b, KEY_2 },
25 { 0x866b1b, KEY_3 },
26 { 0x866b05, KEY_4 },
27 { 0x866b09, KEY_5 },
28 { 0x866b15, KEY_6 },
29 { 0x866b06, KEY_7 },
30 { 0x866b0a, KEY_8 },
31 { 0x866b12, KEY_9 },
32 { 0x866b02, KEY_0 },
33
34 { 0x866b13, KEY_AGAIN }, /* loop */
35 { 0x866b10, KEY_DIGITS }, /* +100 */
36
37 { 0x866b00, KEY_MEDIA }, /* source */
38 { 0x866b18, KEY_MUTE }, /* mute */
39 { 0x866b19, KEY_CAMERA }, /* snapshot */
40 { 0x866b1a, KEY_SEARCH }, /* scan */
41
42 { 0x866b16, KEY_CHANNELUP }, /* chn + */
43 { 0x866b14, KEY_CHANNELDOWN }, /* chn - */
44 { 0x866b1f, KEY_VOLUMEUP }, /* vol + */
45 { 0x866b17, KEY_VOLUMEDOWN }, /* vol - */
46 { 0x866b1c, KEY_ZOOM }, /* zoom */
47
48 { 0x866b04, KEY_REWIND },
49 { 0x866b0e, KEY_RECORD },
50 { 0x866b0c, KEY_FORWARD },
51
52 { 0x866b1d, KEY_STOP },
53 { 0x866b08, KEY_PLAY },
54 { 0x866b0f, KEY_PAUSE },
55
56 { 0x866b0d, KEY_TV },
57 { 0x866b07, KEY_RADIO }, /* FM */
58};
59
60static struct rc_keymap pixelview_map = {
61 .map = {
62 .scan = pixelview_mk12,
63 .size = ARRAY_SIZE(pixelview_mk12),
64 .ir_type = IR_TYPE_NEC,
65 .name = RC_MAP_PIXELVIEW_MK12,
66 }
67};
68
69static int __init init_rc_map_pixelview(void)
70{
71 return ir_register_map(&pixelview_map);
72}
73
74static void __exit exit_rc_map_pixelview(void)
75{
76 ir_unregister_map(&pixelview_map);
77}
78
79module_init(init_rc_map_pixelview)
80module_exit(exit_rc_map_pixelview)
81
82MODULE_LICENSE("GPL");
83MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-pixelview-new.c b/drivers/media/rc/keymaps/rc-pixelview-new.c
new file mode 100644
index 000000000000..7bbbbf5735e6
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pixelview-new.c
@@ -0,0 +1,83 @@
1/* pixelview-new.h - Keytable for pixelview_new Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/*
16 Mauro Carvalho Chehab <mchehab@infradead.org>
17 present on PV MPEG 8000GT
18 */
19
20static struct ir_scancode pixelview_new[] = {
21 { 0x3c, KEY_TIME }, /* Timeshift */
22 { 0x12, KEY_POWER },
23
24 { 0x3d, KEY_1 },
25 { 0x38, KEY_2 },
26 { 0x18, KEY_3 },
27 { 0x35, KEY_4 },
28 { 0x39, KEY_5 },
29 { 0x15, KEY_6 },
30 { 0x36, KEY_7 },
31 { 0x3a, KEY_8 },
32 { 0x1e, KEY_9 },
33 { 0x3e, KEY_0 },
34
35 { 0x1c, KEY_AGAIN }, /* LOOP */
36 { 0x3f, KEY_MEDIA }, /* Source */
37 { 0x1f, KEY_LAST }, /* +100 */
38 { 0x1b, KEY_MUTE },
39
40 { 0x17, KEY_CHANNELDOWN },
41 { 0x16, KEY_CHANNELUP },
42 { 0x10, KEY_VOLUMEUP },
43 { 0x14, KEY_VOLUMEDOWN },
44 { 0x13, KEY_ZOOM },
45
46 { 0x19, KEY_CAMERA }, /* SNAPSHOT */
47 { 0x1a, KEY_SEARCH }, /* scan */
48
49 { 0x37, KEY_REWIND }, /* << */
50 { 0x32, KEY_RECORD }, /* o (red) */
51 { 0x33, KEY_FORWARD }, /* >> */
52 { 0x11, KEY_STOP }, /* square */
53 { 0x3b, KEY_PLAY }, /* > */
54 { 0x30, KEY_PLAYPAUSE }, /* || */
55
56 { 0x31, KEY_TV },
57 { 0x34, KEY_RADIO },
58};
59
60static struct rc_keymap pixelview_new_map = {
61 .map = {
62 .scan = pixelview_new,
63 .size = ARRAY_SIZE(pixelview_new),
64 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
65 .name = RC_MAP_PIXELVIEW_NEW,
66 }
67};
68
69static int __init init_rc_map_pixelview_new(void)
70{
71 return ir_register_map(&pixelview_new_map);
72}
73
74static void __exit exit_rc_map_pixelview_new(void)
75{
76 ir_unregister_map(&pixelview_new_map);
77}
78
79module_init(init_rc_map_pixelview_new)
80module_exit(exit_rc_map_pixelview_new)
81
82MODULE_LICENSE("GPL");
83MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-pixelview.c b/drivers/media/rc/keymaps/rc-pixelview.c
new file mode 100644
index 000000000000..82ff12e182a0
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pixelview.c
@@ -0,0 +1,82 @@
1/* pixelview.h - Keytable for pixelview Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode pixelview[] = {
16
17 { 0x1e, KEY_POWER }, /* power */
18 { 0x07, KEY_MEDIA }, /* source */
19 { 0x1c, KEY_SEARCH }, /* scan */
20
21
22 { 0x03, KEY_TUNER }, /* TV/FM */
23
24 { 0x00, KEY_RECORD },
25 { 0x08, KEY_STOP },
26 { 0x11, KEY_PLAY },
27
28 { 0x1a, KEY_PLAYPAUSE }, /* freeze */
29 { 0x19, KEY_ZOOM }, /* zoom */
30 { 0x0f, KEY_TEXT }, /* min */
31
32 { 0x01, KEY_1 },
33 { 0x0b, KEY_2 },
34 { 0x1b, KEY_3 },
35 { 0x05, KEY_4 },
36 { 0x09, KEY_5 },
37 { 0x15, KEY_6 },
38 { 0x06, KEY_7 },
39 { 0x0a, KEY_8 },
40 { 0x12, KEY_9 },
41 { 0x02, KEY_0 },
42 { 0x10, KEY_LAST }, /* +100 */
43 { 0x13, KEY_LIST }, /* recall */
44
45 { 0x1f, KEY_CHANNELUP }, /* chn down */
46 { 0x17, KEY_CHANNELDOWN }, /* chn up */
47 { 0x16, KEY_VOLUMEUP }, /* vol down */
48 { 0x14, KEY_VOLUMEDOWN }, /* vol up */
49
50 { 0x04, KEY_KPMINUS }, /* <<< */
51 { 0x0e, KEY_SETUP }, /* function */
52 { 0x0c, KEY_KPPLUS }, /* >>> */
53
54 { 0x0d, KEY_GOTO }, /* mts */
55 { 0x1d, KEY_REFRESH }, /* reset */
56 { 0x18, KEY_MUTE }, /* mute/unmute */
57};
58
59static struct rc_keymap pixelview_map = {
60 .map = {
61 .scan = pixelview,
62 .size = ARRAY_SIZE(pixelview),
63 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
64 .name = RC_MAP_PIXELVIEW,
65 }
66};
67
68static int __init init_rc_map_pixelview(void)
69{
70 return ir_register_map(&pixelview_map);
71}
72
73static void __exit exit_rc_map_pixelview(void)
74{
75 ir_unregister_map(&pixelview_map);
76}
77
78module_init(init_rc_map_pixelview)
79module_exit(exit_rc_map_pixelview)
80
81MODULE_LICENSE("GPL");
82MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-powercolor-real-angel.c b/drivers/media/rc/keymaps/rc-powercolor-real-angel.c
new file mode 100644
index 000000000000..7cef8190a224
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-powercolor-real-angel.c
@@ -0,0 +1,81 @@
1/* powercolor-real-angel.h - Keytable for powercolor_real_angel Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/*
16 * Remote control for Powercolor Real Angel 330
17 * Daniel Fraga <fragabr@gmail.com>
18 */
19
20static struct ir_scancode powercolor_real_angel[] = {
21 { 0x38, KEY_SWITCHVIDEOMODE }, /* switch inputs */
22 { 0x0c, KEY_MEDIA }, /* Turn ON/OFF App */
23 { 0x00, KEY_0 },
24 { 0x01, KEY_1 },
25 { 0x02, KEY_2 },
26 { 0x03, KEY_3 },
27 { 0x04, KEY_4 },
28 { 0x05, KEY_5 },
29 { 0x06, KEY_6 },
30 { 0x07, KEY_7 },
31 { 0x08, KEY_8 },
32 { 0x09, KEY_9 },
33 { 0x0a, KEY_DIGITS }, /* single, double, tripple digit */
34 { 0x29, KEY_PREVIOUS }, /* previous channel */
35 { 0x12, KEY_BRIGHTNESSUP },
36 { 0x13, KEY_BRIGHTNESSDOWN },
37 { 0x2b, KEY_MODE }, /* stereo/mono */
38 { 0x2c, KEY_TEXT }, /* teletext */
39 { 0x20, KEY_CHANNELUP }, /* channel up */
40 { 0x21, KEY_CHANNELDOWN }, /* channel down */
41 { 0x10, KEY_VOLUMEUP }, /* volume up */
42 { 0x11, KEY_VOLUMEDOWN }, /* volume down */
43 { 0x0d, KEY_MUTE },
44 { 0x1f, KEY_RECORD },
45 { 0x17, KEY_PLAY },
46 { 0x16, KEY_PAUSE },
47 { 0x0b, KEY_STOP },
48 { 0x27, KEY_FASTFORWARD },
49 { 0x26, KEY_REWIND },
50 { 0x1e, KEY_SEARCH }, /* autoscan */
51 { 0x0e, KEY_CAMERA }, /* snapshot */
52 { 0x2d, KEY_SETUP },
53 { 0x0f, KEY_SCREEN }, /* full screen */
54 { 0x14, KEY_RADIO }, /* FM radio */
55 { 0x25, KEY_POWER }, /* power */
56};
57
58static struct rc_keymap powercolor_real_angel_map = {
59 .map = {
60 .scan = powercolor_real_angel,
61 .size = ARRAY_SIZE(powercolor_real_angel),
62 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
63 .name = RC_MAP_POWERCOLOR_REAL_ANGEL,
64 }
65};
66
67static int __init init_rc_map_powercolor_real_angel(void)
68{
69 return ir_register_map(&powercolor_real_angel_map);
70}
71
72static void __exit exit_rc_map_powercolor_real_angel(void)
73{
74 ir_unregister_map(&powercolor_real_angel_map);
75}
76
77module_init(init_rc_map_powercolor_real_angel)
78module_exit(exit_rc_map_powercolor_real_angel)
79
80MODULE_LICENSE("GPL");
81MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-proteus-2309.c b/drivers/media/rc/keymaps/rc-proteus-2309.c
new file mode 100644
index 000000000000..22e92d39dee5
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-proteus-2309.c
@@ -0,0 +1,69 @@
1/* proteus-2309.h - Keytable for proteus_2309 Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Michal Majchrowicz <mmajchrowicz@gmail.com> */
16
17static struct ir_scancode proteus_2309[] = {
18 /* numeric */
19 { 0x00, KEY_0 },
20 { 0x01, KEY_1 },
21 { 0x02, KEY_2 },
22 { 0x03, KEY_3 },
23 { 0x04, KEY_4 },
24 { 0x05, KEY_5 },
25 { 0x06, KEY_6 },
26 { 0x07, KEY_7 },
27 { 0x08, KEY_8 },
28 { 0x09, KEY_9 },
29
30 { 0x5c, KEY_POWER }, /* power */
31 { 0x20, KEY_ZOOM }, /* full screen */
32 { 0x0f, KEY_BACKSPACE }, /* recall */
33 { 0x1b, KEY_ENTER }, /* mute */
34 { 0x41, KEY_RECORD }, /* record */
35 { 0x43, KEY_STOP }, /* stop */
36 { 0x16, KEY_S },
37 { 0x1a, KEY_POWER2 }, /* off */
38 { 0x2e, KEY_RED },
39 { 0x1f, KEY_CHANNELDOWN }, /* channel - */
40 { 0x1c, KEY_CHANNELUP }, /* channel + */
41 { 0x10, KEY_VOLUMEDOWN }, /* volume - */
42 { 0x1e, KEY_VOLUMEUP }, /* volume + */
43 { 0x14, KEY_F1 },
44};
45
46static struct rc_keymap proteus_2309_map = {
47 .map = {
48 .scan = proteus_2309,
49 .size = ARRAY_SIZE(proteus_2309),
50 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
51 .name = RC_MAP_PROTEUS_2309,
52 }
53};
54
55static int __init init_rc_map_proteus_2309(void)
56{
57 return ir_register_map(&proteus_2309_map);
58}
59
60static void __exit exit_rc_map_proteus_2309(void)
61{
62 ir_unregister_map(&proteus_2309_map);
63}
64
65module_init(init_rc_map_proteus_2309)
66module_exit(exit_rc_map_proteus_2309)
67
68MODULE_LICENSE("GPL");
69MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-purpletv.c b/drivers/media/rc/keymaps/rc-purpletv.c
new file mode 100644
index 000000000000..4e20fc2269f7
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-purpletv.c
@@ -0,0 +1,81 @@
1/* purpletv.h - Keytable for purpletv Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode purpletv[] = {
16 { 0x03, KEY_POWER },
17 { 0x6f, KEY_MUTE },
18 { 0x10, KEY_BACKSPACE }, /* Recall */
19
20 { 0x11, KEY_0 },
21 { 0x04, KEY_1 },
22 { 0x05, KEY_2 },
23 { 0x06, KEY_3 },
24 { 0x08, KEY_4 },
25 { 0x09, KEY_5 },
26 { 0x0a, KEY_6 },
27 { 0x0c, KEY_7 },
28 { 0x0d, KEY_8 },
29 { 0x0e, KEY_9 },
30 { 0x12, KEY_DOT }, /* 100+ */
31
32 { 0x07, KEY_VOLUMEUP },
33 { 0x0b, KEY_VOLUMEDOWN },
34 { 0x1a, KEY_KPPLUS },
35 { 0x18, KEY_KPMINUS },
36 { 0x15, KEY_UP },
37 { 0x1d, KEY_DOWN },
38 { 0x0f, KEY_CHANNELUP },
39 { 0x13, KEY_CHANNELDOWN },
40 { 0x48, KEY_ZOOM },
41
42 { 0x1b, KEY_VIDEO }, /* Video source */
43 { 0x1f, KEY_CAMERA }, /* Snapshot */
44 { 0x49, KEY_LANGUAGE }, /* MTS Select */
45 { 0x19, KEY_SEARCH }, /* Auto Scan */
46
47 { 0x4b, KEY_RECORD },
48 { 0x46, KEY_PLAY },
49 { 0x45, KEY_PAUSE }, /* Pause */
50 { 0x44, KEY_STOP },
51 { 0x43, KEY_TIME }, /* Time Shift */
52 { 0x17, KEY_CHANNEL }, /* SURF CH */
53 { 0x40, KEY_FORWARD }, /* Forward ? */
54 { 0x42, KEY_REWIND }, /* Backward ? */
55
56};
57
58static struct rc_keymap purpletv_map = {
59 .map = {
60 .scan = purpletv,
61 .size = ARRAY_SIZE(purpletv),
62 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
63 .name = RC_MAP_PURPLETV,
64 }
65};
66
67static int __init init_rc_map_purpletv(void)
68{
69 return ir_register_map(&purpletv_map);
70}
71
72static void __exit exit_rc_map_purpletv(void)
73{
74 ir_unregister_map(&purpletv_map);
75}
76
77module_init(init_rc_map_purpletv)
78module_exit(exit_rc_map_purpletv)
79
80MODULE_LICENSE("GPL");
81MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-pv951.c b/drivers/media/rc/keymaps/rc-pv951.c
new file mode 100644
index 000000000000..36679e706cf3
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pv951.c
@@ -0,0 +1,78 @@
1/* pv951.h - Keytable for pv951 Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Mark Phalan <phalanm@o2.ie> */
16
17static struct ir_scancode pv951[] = {
18 { 0x00, KEY_0 },
19 { 0x01, KEY_1 },
20 { 0x02, KEY_2 },
21 { 0x03, KEY_3 },
22 { 0x04, KEY_4 },
23 { 0x05, KEY_5 },
24 { 0x06, KEY_6 },
25 { 0x07, KEY_7 },
26 { 0x08, KEY_8 },
27 { 0x09, KEY_9 },
28
29 { 0x12, KEY_POWER },
30 { 0x10, KEY_MUTE },
31 { 0x1f, KEY_VOLUMEDOWN },
32 { 0x1b, KEY_VOLUMEUP },
33 { 0x1a, KEY_CHANNELUP },
34 { 0x1e, KEY_CHANNELDOWN },
35 { 0x0e, KEY_PAGEUP },
36 { 0x1d, KEY_PAGEDOWN },
37 { 0x13, KEY_SOUND },
38
39 { 0x18, KEY_KPPLUSMINUS }, /* CH +/- */
40 { 0x16, KEY_SUBTITLE }, /* CC */
41 { 0x0d, KEY_TEXT }, /* TTX */
42 { 0x0b, KEY_TV }, /* AIR/CBL */
43 { 0x11, KEY_PC }, /* PC/TV */
44 { 0x17, KEY_OK }, /* CH RTN */
45 { 0x19, KEY_MODE }, /* FUNC */
46 { 0x0c, KEY_SEARCH }, /* AUTOSCAN */
47
48 /* Not sure what to do with these ones! */
49 { 0x0f, KEY_SELECT }, /* SOURCE */
50 { 0x0a, KEY_KPPLUS }, /* +100 */
51 { 0x14, KEY_EQUAL }, /* SYNC */
52 { 0x1c, KEY_MEDIA }, /* PC/TV */
53};
54
55static struct rc_keymap pv951_map = {
56 .map = {
57 .scan = pv951,
58 .size = ARRAY_SIZE(pv951),
59 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
60 .name = RC_MAP_PV951,
61 }
62};
63
64static int __init init_rc_map_pv951(void)
65{
66 return ir_register_map(&pv951_map);
67}
68
69static void __exit exit_rc_map_pv951(void)
70{
71 ir_unregister_map(&pv951_map);
72}
73
74module_init(init_rc_map_pv951)
75module_exit(exit_rc_map_pv951)
76
77MODULE_LICENSE("GPL");
78MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c
new file mode 100644
index 000000000000..cc6b8f548747
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c
@@ -0,0 +1,103 @@
1/* rc5-hauppauge-new.h - Keytable for rc5_hauppauge_new Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/*
16 * Hauppauge:the newer, gray remotes (seems there are multiple
17 * slightly different versions), shipped with cx88+ivtv cards.
18 *
19 * This table contains the complete RC5 code, instead of just the data part
20 */
21
22static struct ir_scancode rc5_hauppauge_new[] = {
23 /* Keys 0 to 9 */
24 { 0x1e00, KEY_0 },
25 { 0x1e01, KEY_1 },
26 { 0x1e02, KEY_2 },
27 { 0x1e03, KEY_3 },
28 { 0x1e04, KEY_4 },
29 { 0x1e05, KEY_5 },
30 { 0x1e06, KEY_6 },
31 { 0x1e07, KEY_7 },
32 { 0x1e08, KEY_8 },
33 { 0x1e09, KEY_9 },
34
35 { 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */
36 { 0x1e0b, KEY_RED }, /* red button */
37 { 0x1e0c, KEY_RADIO },
38 { 0x1e0d, KEY_MENU },
39 { 0x1e0e, KEY_SUBTITLE }, /* also the # key */
40 { 0x1e0f, KEY_MUTE },
41 { 0x1e10, KEY_VOLUMEUP },
42 { 0x1e11, KEY_VOLUMEDOWN },
43 { 0x1e12, KEY_PREVIOUS }, /* previous channel */
44 { 0x1e14, KEY_UP },
45 { 0x1e15, KEY_DOWN },
46 { 0x1e16, KEY_LEFT },
47 { 0x1e17, KEY_RIGHT },
48 { 0x1e18, KEY_VIDEO }, /* Videos */
49 { 0x1e19, KEY_AUDIO }, /* Music */
50 /* 0x1e1a: Pictures - presume this means
51 "Multimedia Home Platform" -
52 no "PICTURES" key in input.h
53 */
54 { 0x1e1a, KEY_MHP },
55
56 { 0x1e1b, KEY_EPG }, /* Guide */
57 { 0x1e1c, KEY_TV },
58 { 0x1e1e, KEY_NEXTSONG }, /* skip >| */
59 { 0x1e1f, KEY_EXIT }, /* back/exit */
60 { 0x1e20, KEY_CHANNELUP }, /* channel / program + */
61 { 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */
62 { 0x1e22, KEY_CHANNEL }, /* source (old black remote) */
63 { 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */
64 { 0x1e25, KEY_ENTER }, /* OK */
65 { 0x1e26, KEY_SLEEP }, /* minimize (old black remote) */
66 { 0x1e29, KEY_BLUE }, /* blue key */
67 { 0x1e2e, KEY_GREEN }, /* green button */
68 { 0x1e30, KEY_PAUSE }, /* pause */
69 { 0x1e32, KEY_REWIND }, /* backward << */
70 { 0x1e34, KEY_FASTFORWARD }, /* forward >> */
71 { 0x1e35, KEY_PLAY },
72 { 0x1e36, KEY_STOP },
73 { 0x1e37, KEY_RECORD }, /* recording */
74 { 0x1e38, KEY_YELLOW }, /* yellow key */
75 { 0x1e3b, KEY_SELECT }, /* top right button */
76 { 0x1e3c, KEY_ZOOM }, /* full */
77 { 0x1e3d, KEY_POWER }, /* system power (green button) */
78};
79
80static struct rc_keymap rc5_hauppauge_new_map = {
81 .map = {
82 .scan = rc5_hauppauge_new,
83 .size = ARRAY_SIZE(rc5_hauppauge_new),
84 .ir_type = IR_TYPE_RC5,
85 .name = RC_MAP_RC5_HAUPPAUGE_NEW,
86 }
87};
88
89static int __init init_rc_map_rc5_hauppauge_new(void)
90{
91 return ir_register_map(&rc5_hauppauge_new_map);
92}
93
94static void __exit exit_rc_map_rc5_hauppauge_new(void)
95{
96 ir_unregister_map(&rc5_hauppauge_new_map);
97}
98
99module_init(init_rc_map_rc5_hauppauge_new)
100module_exit(exit_rc_map_rc5_hauppauge_new)
101
102MODULE_LICENSE("GPL");
103MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-rc5-tv.c b/drivers/media/rc/keymaps/rc-rc5-tv.c
new file mode 100644
index 000000000000..73cce2f8ddfb
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-rc5-tv.c
@@ -0,0 +1,81 @@
1/* rc5-tv.h - Keytable for rc5_tv Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* generic RC5 keytable */
16/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */
17/* used by old (black) Hauppauge remotes */
18
19static struct ir_scancode rc5_tv[] = {
20 /* Keys 0 to 9 */
21 { 0x00, KEY_0 },
22 { 0x01, KEY_1 },
23 { 0x02, KEY_2 },
24 { 0x03, KEY_3 },
25 { 0x04, KEY_4 },
26 { 0x05, KEY_5 },
27 { 0x06, KEY_6 },
28 { 0x07, KEY_7 },
29 { 0x08, KEY_8 },
30 { 0x09, KEY_9 },
31
32 { 0x0b, KEY_CHANNEL }, /* channel / program (japan: 11) */
33 { 0x0c, KEY_POWER }, /* standby */
34 { 0x0d, KEY_MUTE }, /* mute / demute */
35 { 0x0f, KEY_TV }, /* display */
36 { 0x10, KEY_VOLUMEUP },
37 { 0x11, KEY_VOLUMEDOWN },
38 { 0x12, KEY_BRIGHTNESSUP },
39 { 0x13, KEY_BRIGHTNESSDOWN },
40 { 0x1e, KEY_SEARCH }, /* search + */
41 { 0x20, KEY_CHANNELUP }, /* channel / program + */
42 { 0x21, KEY_CHANNELDOWN }, /* channel / program - */
43 { 0x22, KEY_CHANNEL }, /* alt / channel */
44 { 0x23, KEY_LANGUAGE }, /* 1st / 2nd language */
45 { 0x26, KEY_SLEEP }, /* sleeptimer */
46 { 0x2e, KEY_MENU }, /* 2nd controls (USA: menu) */
47 { 0x30, KEY_PAUSE },
48 { 0x32, KEY_REWIND },
49 { 0x33, KEY_GOTO },
50 { 0x35, KEY_PLAY },
51 { 0x36, KEY_STOP },
52 { 0x37, KEY_RECORD }, /* recording */
53 { 0x3c, KEY_TEXT }, /* teletext submode (Japan: 12) */
54 { 0x3d, KEY_SUSPEND }, /* system standby */
55
56};
57
58static struct rc_keymap rc5_tv_map = {
59 .map = {
60 .scan = rc5_tv,
61 .size = ARRAY_SIZE(rc5_tv),
62 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
63 .name = RC_MAP_RC5_TV,
64 }
65};
66
67static int __init init_rc_map_rc5_tv(void)
68{
69 return ir_register_map(&rc5_tv_map);
70}
71
72static void __exit exit_rc_map_rc5_tv(void)
73{
74 ir_unregister_map(&rc5_tv_map);
75}
76
77module_init(init_rc_map_rc5_tv)
78module_exit(exit_rc_map_rc5_tv)
79
80MODULE_LICENSE("GPL");
81MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c
new file mode 100644
index 000000000000..6da955dfef48
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-rc6-mce.c
@@ -0,0 +1,113 @@
1/* rc-rc6-mce.c - Keytable for Windows Media Center RC-6 remotes for use
2 * with the Media Center Edition eHome Infrared Transceiver.
3 *
4 * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <media/rc-map.h>
13
14static struct ir_scancode rc6_mce[] = {
15
16 { 0x800f0400, KEY_NUMERIC_0 },
17 { 0x800f0401, KEY_NUMERIC_1 },
18 { 0x800f0402, KEY_NUMERIC_2 },
19 { 0x800f0403, KEY_NUMERIC_3 },
20 { 0x800f0404, KEY_NUMERIC_4 },
21 { 0x800f0405, KEY_NUMERIC_5 },
22 { 0x800f0406, KEY_NUMERIC_6 },
23 { 0x800f0407, KEY_NUMERIC_7 },
24 { 0x800f0408, KEY_NUMERIC_8 },
25 { 0x800f0409, KEY_NUMERIC_9 },
26
27 { 0x800f040a, KEY_DELETE },
28 { 0x800f040b, KEY_ENTER },
29 { 0x800f040c, KEY_POWER }, /* PC Power */
30 { 0x800f040d, KEY_PROG1 }, /* Windows MCE button */
31 { 0x800f040e, KEY_MUTE },
32 { 0x800f040f, KEY_INFO },
33
34 { 0x800f0410, KEY_VOLUMEUP },
35 { 0x800f0411, KEY_VOLUMEDOWN },
36 { 0x800f0412, KEY_CHANNELUP },
37 { 0x800f0413, KEY_CHANNELDOWN },
38
39 { 0x800f0414, KEY_FASTFORWARD },
40 { 0x800f0415, KEY_REWIND },
41 { 0x800f0416, KEY_PLAY },
42 { 0x800f0417, KEY_RECORD },
43 { 0x800f0418, KEY_PAUSE },
44 { 0x800f046e, KEY_PLAYPAUSE },
45 { 0x800f0419, KEY_STOP },
46 { 0x800f041a, KEY_NEXT },
47 { 0x800f041b, KEY_PREVIOUS },
48 { 0x800f041c, KEY_NUMERIC_POUND },
49 { 0x800f041d, KEY_NUMERIC_STAR },
50
51 { 0x800f041e, KEY_UP },
52 { 0x800f041f, KEY_DOWN },
53 { 0x800f0420, KEY_LEFT },
54 { 0x800f0421, KEY_RIGHT },
55
56 { 0x800f0422, KEY_OK },
57 { 0x800f0423, KEY_EXIT },
58 { 0x800f0424, KEY_DVD },
59 { 0x800f0425, KEY_TUNER }, /* LiveTV */
60 { 0x800f0426, KEY_EPG }, /* Guide */
61 { 0x800f0427, KEY_ZOOM }, /* Aspect */
62
63 { 0x800f043a, KEY_BRIGHTNESSUP },
64
65 { 0x800f0446, KEY_TV },
66 { 0x800f0447, KEY_AUDIO }, /* My Music */
67 { 0x800f0448, KEY_PVR }, /* RecordedTV */
68 { 0x800f0449, KEY_CAMERA },
69 { 0x800f044a, KEY_VIDEO },
70 { 0x800f044c, KEY_LANGUAGE },
71 { 0x800f044d, KEY_TITLE },
72 { 0x800f044e, KEY_PRINT }, /* Print - HP OEM version of remote */
73
74 { 0x800f0450, KEY_RADIO },
75
76 { 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */
77 { 0x800f045b, KEY_RED },
78 { 0x800f045c, KEY_GREEN },
79 { 0x800f045d, KEY_YELLOW },
80 { 0x800f045e, KEY_BLUE },
81
82 { 0x800f0465, KEY_POWER2 }, /* TV Power */
83 { 0x800f046e, KEY_PLAYPAUSE },
84 { 0x800f046f, KEY_MEDIA }, /* Start media application (NEW) */
85
86 { 0x800f0480, KEY_BRIGHTNESSDOWN },
87 { 0x800f0481, KEY_PLAYPAUSE },
88};
89
90static struct rc_keymap rc6_mce_map = {
91 .map = {
92 .scan = rc6_mce,
93 .size = ARRAY_SIZE(rc6_mce),
94 .ir_type = IR_TYPE_RC6,
95 .name = RC_MAP_RC6_MCE,
96 }
97};
98
99static int __init init_rc_map_rc6_mce(void)
100{
101 return ir_register_map(&rc6_mce_map);
102}
103
104static void __exit exit_rc_map_rc6_mce(void)
105{
106 ir_unregister_map(&rc6_mce_map);
107}
108
109module_init(init_rc_map_rc6_mce)
110module_exit(exit_rc_map_rc6_mce)
111
112MODULE_LICENSE("GPL");
113MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c
new file mode 100644
index 000000000000..ab1a6d2baf72
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c
@@ -0,0 +1,78 @@
1/* real-audio-220-32-keys.h - Keytable for real_audio_220_32_keys Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Zogis Real Audio 220 - 32 keys IR */
16
17static struct ir_scancode real_audio_220_32_keys[] = {
18 { 0x1c, KEY_RADIO},
19 { 0x12, KEY_POWER2},
20
21 { 0x01, KEY_1},
22 { 0x02, KEY_2},
23 { 0x03, KEY_3},
24 { 0x04, KEY_4},
25 { 0x05, KEY_5},
26 { 0x06, KEY_6},
27 { 0x07, KEY_7},
28 { 0x08, KEY_8},
29 { 0x09, KEY_9},
30 { 0x00, KEY_0},
31
32 { 0x0c, KEY_VOLUMEUP},
33 { 0x18, KEY_VOLUMEDOWN},
34 { 0x0b, KEY_CHANNELUP},
35 { 0x15, KEY_CHANNELDOWN},
36 { 0x16, KEY_ENTER},
37
38 { 0x11, KEY_LIST}, /* Source */
39 { 0x0d, KEY_AUDIO}, /* stereo */
40
41 { 0x0f, KEY_PREVIOUS}, /* Prev */
42 { 0x1b, KEY_TIME}, /* Timeshift */
43 { 0x1a, KEY_NEXT}, /* Next */
44
45 { 0x0e, KEY_STOP},
46 { 0x1f, KEY_PLAY},
47 { 0x1e, KEY_PLAYPAUSE}, /* Pause */
48
49 { 0x1d, KEY_RECORD},
50 { 0x13, KEY_MUTE},
51 { 0x19, KEY_CAMERA}, /* Snapshot */
52
53};
54
55static struct rc_keymap real_audio_220_32_keys_map = {
56 .map = {
57 .scan = real_audio_220_32_keys,
58 .size = ARRAY_SIZE(real_audio_220_32_keys),
59 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
60 .name = RC_MAP_REAL_AUDIO_220_32_KEYS,
61 }
62};
63
64static int __init init_rc_map_real_audio_220_32_keys(void)
65{
66 return ir_register_map(&real_audio_220_32_keys_map);
67}
68
69static void __exit exit_rc_map_real_audio_220_32_keys(void)
70{
71 ir_unregister_map(&real_audio_220_32_keys_map);
72}
73
74module_init(init_rc_map_real_audio_220_32_keys)
75module_exit(exit_rc_map_real_audio_220_32_keys)
76
77MODULE_LICENSE("GPL");
78MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-streamzap.c b/drivers/media/rc/keymaps/rc-streamzap.c
new file mode 100644
index 000000000000..df32013a321c
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-streamzap.c
@@ -0,0 +1,82 @@
1/* rc-streamzap.c - Keytable for Streamzap PC Remote, for use
2 * with the Streamzap PC Remote IR Receiver.
3 *
4 * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <media/rc-map.h>
13
14static struct ir_scancode streamzap[] = {
15/*
16 * The Streamzap remote is almost, but not quite, RC-5, as it has an extra
17 * bit in it, which throws the in-kernel RC-5 decoder for a loop. Currently,
18 * an additional RC-5-sz decoder is being deployed to support it, but it
19 * may be possible to merge it back with the standard RC-5 decoder.
20 */
21 { 0x28c0, KEY_NUMERIC_0 },
22 { 0x28c1, KEY_NUMERIC_1 },
23 { 0x28c2, KEY_NUMERIC_2 },
24 { 0x28c3, KEY_NUMERIC_3 },
25 { 0x28c4, KEY_NUMERIC_4 },
26 { 0x28c5, KEY_NUMERIC_5 },
27 { 0x28c6, KEY_NUMERIC_6 },
28 { 0x28c7, KEY_NUMERIC_7 },
29 { 0x28c8, KEY_NUMERIC_8 },
30 { 0x28c9, KEY_NUMERIC_9 },
31 { 0x28ca, KEY_POWER },
32 { 0x28cb, KEY_MUTE },
33 { 0x28cc, KEY_CHANNELUP },
34 { 0x28cd, KEY_VOLUMEUP },
35 { 0x28ce, KEY_CHANNELDOWN },
36 { 0x28cf, KEY_VOLUMEDOWN },
37 { 0x28d0, KEY_UP },
38 { 0x28d1, KEY_LEFT },
39 { 0x28d2, KEY_OK },
40 { 0x28d3, KEY_RIGHT },
41 { 0x28d4, KEY_DOWN },
42 { 0x28d5, KEY_MENU },
43 { 0x28d6, KEY_EXIT },
44 { 0x28d7, KEY_PLAY },
45 { 0x28d8, KEY_PAUSE },
46 { 0x28d9, KEY_STOP },
47 { 0x28da, KEY_BACK },
48 { 0x28db, KEY_FORWARD },
49 { 0x28dc, KEY_RECORD },
50 { 0x28dd, KEY_REWIND },
51 { 0x28de, KEY_FASTFORWARD },
52 { 0x28e0, KEY_RED },
53 { 0x28e1, KEY_GREEN },
54 { 0x28e2, KEY_YELLOW },
55 { 0x28e3, KEY_BLUE },
56
57};
58
59static struct rc_keymap streamzap_map = {
60 .map = {
61 .scan = streamzap,
62 .size = ARRAY_SIZE(streamzap),
63 .ir_type = IR_TYPE_RC5_SZ,
64 .name = RC_MAP_STREAMZAP,
65 }
66};
67
68static int __init init_rc_map_streamzap(void)
69{
70 return ir_register_map(&streamzap_map);
71}
72
73static void __exit exit_rc_map_streamzap(void)
74{
75 ir_unregister_map(&streamzap_map);
76}
77
78module_init(init_rc_map_streamzap)
79module_exit(exit_rc_map_streamzap)
80
81MODULE_LICENSE("GPL");
82MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-tbs-nec.c b/drivers/media/rc/keymaps/rc-tbs-nec.c
new file mode 100644
index 000000000000..3309631e6f80
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-tbs-nec.c
@@ -0,0 +1,73 @@
1/* tbs-nec.h - Keytable for tbs_nec Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode tbs_nec[] = {
16 { 0x04, KEY_POWER2}, /*power*/
17 { 0x14, KEY_MUTE}, /*mute*/
18 { 0x07, KEY_1},
19 { 0x06, KEY_2},
20 { 0x05, KEY_3},
21 { 0x0b, KEY_4},
22 { 0x0a, KEY_5},
23 { 0x09, KEY_6},
24 { 0x0f, KEY_7},
25 { 0x0e, KEY_8},
26 { 0x0d, KEY_9},
27 { 0x12, KEY_0},
28 { 0x16, KEY_CHANNELUP}, /*ch+*/
29 { 0x11, KEY_CHANNELDOWN},/*ch-*/
30 { 0x13, KEY_VOLUMEUP}, /*vol+*/
31 { 0x0c, KEY_VOLUMEDOWN},/*vol-*/
32 { 0x03, KEY_RECORD}, /*rec*/
33 { 0x18, KEY_PAUSE}, /*pause*/
34 { 0x19, KEY_OK}, /*ok*/
35 { 0x1a, KEY_CAMERA}, /* snapshot */
36 { 0x01, KEY_UP},
37 { 0x10, KEY_LEFT},
38 { 0x02, KEY_RIGHT},
39 { 0x08, KEY_DOWN},
40 { 0x15, KEY_FAVORITES},
41 { 0x17, KEY_SUBTITLE},
42 { 0x1d, KEY_ZOOM},
43 { 0x1f, KEY_EXIT},
44 { 0x1e, KEY_MENU},
45 { 0x1c, KEY_EPG},
46 { 0x00, KEY_PREVIOUS},
47 { 0x1b, KEY_MODE},
48};
49
50static struct rc_keymap tbs_nec_map = {
51 .map = {
52 .scan = tbs_nec,
53 .size = ARRAY_SIZE(tbs_nec),
54 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
55 .name = RC_MAP_TBS_NEC,
56 }
57};
58
59static int __init init_rc_map_tbs_nec(void)
60{
61 return ir_register_map(&tbs_nec_map);
62}
63
64static void __exit exit_rc_map_tbs_nec(void)
65{
66 ir_unregister_map(&tbs_nec_map);
67}
68
69module_init(init_rc_map_tbs_nec)
70module_exit(exit_rc_map_tbs_nec)
71
72MODULE_LICENSE("GPL");
73MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c b/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c
new file mode 100644
index 000000000000..5326a0b444c1
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c
@@ -0,0 +1,92 @@
1/* terratec-cinergy-xs.h - Keytable for terratec_cinergy_xs Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Terratec Cinergy Hybrid T USB XS
16 Devin Heitmueller <dheitmueller@linuxtv.org>
17 */
18
19static struct ir_scancode terratec_cinergy_xs[] = {
20 { 0x41, KEY_HOME},
21 { 0x01, KEY_POWER},
22 { 0x42, KEY_MENU},
23 { 0x02, KEY_1},
24 { 0x03, KEY_2},
25 { 0x04, KEY_3},
26 { 0x43, KEY_SUBTITLE},
27 { 0x05, KEY_4},
28 { 0x06, KEY_5},
29 { 0x07, KEY_6},
30 { 0x44, KEY_TEXT},
31 { 0x08, KEY_7},
32 { 0x09, KEY_8},
33 { 0x0a, KEY_9},
34 { 0x45, KEY_DELETE},
35 { 0x0b, KEY_TUNER},
36 { 0x0c, KEY_0},
37 { 0x0d, KEY_MODE},
38 { 0x46, KEY_TV},
39 { 0x47, KEY_DVD},
40 { 0x49, KEY_VIDEO},
41 { 0x4b, KEY_AUX},
42 { 0x10, KEY_UP},
43 { 0x11, KEY_LEFT},
44 { 0x12, KEY_OK},
45 { 0x13, KEY_RIGHT},
46 { 0x14, KEY_DOWN},
47 { 0x0f, KEY_EPG},
48 { 0x16, KEY_INFO},
49 { 0x4d, KEY_BACKSPACE},
50 { 0x1c, KEY_VOLUMEUP},
51 { 0x4c, KEY_PLAY},
52 { 0x1b, KEY_CHANNELUP},
53 { 0x1e, KEY_VOLUMEDOWN},
54 { 0x1d, KEY_MUTE},
55 { 0x1f, KEY_CHANNELDOWN},
56 { 0x17, KEY_RED},
57 { 0x18, KEY_GREEN},
58 { 0x19, KEY_YELLOW},
59 { 0x1a, KEY_BLUE},
60 { 0x58, KEY_RECORD},
61 { 0x48, KEY_STOP},
62 { 0x40, KEY_PAUSE},
63 { 0x54, KEY_LAST},
64 { 0x4e, KEY_REWIND},
65 { 0x4f, KEY_FASTFORWARD},
66 { 0x5c, KEY_NEXT},
67};
68
69static struct rc_keymap terratec_cinergy_xs_map = {
70 .map = {
71 .scan = terratec_cinergy_xs,
72 .size = ARRAY_SIZE(terratec_cinergy_xs),
73 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
74 .name = RC_MAP_TERRATEC_CINERGY_XS,
75 }
76};
77
78static int __init init_rc_map_terratec_cinergy_xs(void)
79{
80 return ir_register_map(&terratec_cinergy_xs_map);
81}
82
83static void __exit exit_rc_map_terratec_cinergy_xs(void)
84{
85 ir_unregister_map(&terratec_cinergy_xs_map);
86}
87
88module_init(init_rc_map_terratec_cinergy_xs)
89module_exit(exit_rc_map_terratec_cinergy_xs)
90
91MODULE_LICENSE("GPL");
92MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-terratec-slim.c b/drivers/media/rc/keymaps/rc-terratec-slim.c
new file mode 100644
index 000000000000..10dee4c1deff
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-terratec-slim.c
@@ -0,0 +1,79 @@
1/*
2 * TerraTec remote controller keytable
3 *
4 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <media/rc-map.h>
22
23/* TerraTec slim remote, 7 rows, 4 columns. */
24/* Uses NEC extended 0x02bd. */
25static struct ir_scancode terratec_slim[] = {
26 { 0x02bd00, KEY_1 },
27 { 0x02bd01, KEY_2 },
28 { 0x02bd02, KEY_3 },
29 { 0x02bd03, KEY_4 },
30 { 0x02bd04, KEY_5 },
31 { 0x02bd05, KEY_6 },
32 { 0x02bd06, KEY_7 },
33 { 0x02bd07, KEY_8 },
34 { 0x02bd08, KEY_9 },
35 { 0x02bd09, KEY_0 },
36 { 0x02bd0a, KEY_MUTE },
37 { 0x02bd0b, KEY_NEW }, /* symbol: PIP */
38 { 0x02bd0e, KEY_VOLUMEDOWN },
39 { 0x02bd0f, KEY_PLAYPAUSE },
40 { 0x02bd10, KEY_RIGHT },
41 { 0x02bd11, KEY_LEFT },
42 { 0x02bd12, KEY_UP },
43 { 0x02bd13, KEY_DOWN },
44 { 0x02bd15, KEY_OK },
45 { 0x02bd16, KEY_STOP },
46 { 0x02bd17, KEY_CAMERA }, /* snapshot */
47 { 0x02bd18, KEY_CHANNELUP },
48 { 0x02bd19, KEY_RECORD },
49 { 0x02bd1a, KEY_CHANNELDOWN },
50 { 0x02bd1c, KEY_ESC },
51 { 0x02bd1f, KEY_VOLUMEUP },
52 { 0x02bd44, KEY_EPG },
53 { 0x02bd45, KEY_POWER2 }, /* [red power button] */
54};
55
56static struct rc_keymap terratec_slim_map = {
57 .map = {
58 .scan = terratec_slim,
59 .size = ARRAY_SIZE(terratec_slim),
60 .ir_type = IR_TYPE_NEC,
61 .name = RC_MAP_TERRATEC_SLIM,
62 }
63};
64
65static int __init init_rc_map_terratec_slim(void)
66{
67 return ir_register_map(&terratec_slim_map);
68}
69
70static void __exit exit_rc_map_terratec_slim(void)
71{
72 ir_unregister_map(&terratec_slim_map);
73}
74
75module_init(init_rc_map_terratec_slim)
76module_exit(exit_rc_map_terratec_slim)
77
78MODULE_LICENSE("GPL");
79MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff --git a/drivers/media/rc/keymaps/rc-tevii-nec.c b/drivers/media/rc/keymaps/rc-tevii-nec.c
new file mode 100644
index 000000000000..e30d411c07bb
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-tevii-nec.c
@@ -0,0 +1,88 @@
1/* tevii-nec.h - Keytable for tevii_nec Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode tevii_nec[] = {
16 { 0x0a, KEY_POWER2},
17 { 0x0c, KEY_MUTE},
18 { 0x11, KEY_1},
19 { 0x12, KEY_2},
20 { 0x13, KEY_3},
21 { 0x14, KEY_4},
22 { 0x15, KEY_5},
23 { 0x16, KEY_6},
24 { 0x17, KEY_7},
25 { 0x18, KEY_8},
26 { 0x19, KEY_9},
27 { 0x10, KEY_0},
28 { 0x1c, KEY_MENU},
29 { 0x0f, KEY_VOLUMEDOWN},
30 { 0x1a, KEY_LAST},
31 { 0x0e, KEY_OPEN},
32 { 0x04, KEY_RECORD},
33 { 0x09, KEY_VOLUMEUP},
34 { 0x08, KEY_CHANNELUP},
35 { 0x07, KEY_PVR},
36 { 0x0b, KEY_TIME},
37 { 0x02, KEY_RIGHT},
38 { 0x03, KEY_LEFT},
39 { 0x00, KEY_UP},
40 { 0x1f, KEY_OK},
41 { 0x01, KEY_DOWN},
42 { 0x05, KEY_TUNER},
43 { 0x06, KEY_CHANNELDOWN},
44 { 0x40, KEY_PLAYPAUSE},
45 { 0x1e, KEY_REWIND},
46 { 0x1b, KEY_FAVORITES},
47 { 0x1d, KEY_BACK},
48 { 0x4d, KEY_FASTFORWARD},
49 { 0x44, KEY_EPG},
50 { 0x4c, KEY_INFO},
51 { 0x41, KEY_AB},
52 { 0x43, KEY_AUDIO},
53 { 0x45, KEY_SUBTITLE},
54 { 0x4a, KEY_LIST},
55 { 0x46, KEY_F1},
56 { 0x47, KEY_F2},
57 { 0x5e, KEY_F3},
58 { 0x5c, KEY_F4},
59 { 0x52, KEY_F5},
60 { 0x5a, KEY_F6},
61 { 0x56, KEY_MODE},
62 { 0x58, KEY_SWITCHVIDEOMODE},
63};
64
65static struct rc_keymap tevii_nec_map = {
66 .map = {
67 .scan = tevii_nec,
68 .size = ARRAY_SIZE(tevii_nec),
69 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
70 .name = RC_MAP_TEVII_NEC,
71 }
72};
73
74static int __init init_rc_map_tevii_nec(void)
75{
76 return ir_register_map(&tevii_nec_map);
77}
78
79static void __exit exit_rc_map_tevii_nec(void)
80{
81 ir_unregister_map(&tevii_nec_map);
82}
83
84module_init(init_rc_map_tevii_nec)
85module_exit(exit_rc_map_tevii_nec)
86
87MODULE_LICENSE("GPL");
88MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-total-media-in-hand.c b/drivers/media/rc/keymaps/rc-total-media-in-hand.c
new file mode 100644
index 000000000000..fd1985763781
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-total-media-in-hand.c
@@ -0,0 +1,85 @@
1/*
2 * Total Media In Hand remote controller keytable
3 *
4 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <media/rc-map.h>
22
23/* Uses NEC extended 0x02bd */
24static struct ir_scancode total_media_in_hand[] = {
25 { 0x02bd00, KEY_1 },
26 { 0x02bd01, KEY_2 },
27 { 0x02bd02, KEY_3 },
28 { 0x02bd03, KEY_4 },
29 { 0x02bd04, KEY_5 },
30 { 0x02bd05, KEY_6 },
31 { 0x02bd06, KEY_7 },
32 { 0x02bd07, KEY_8 },
33 { 0x02bd08, KEY_9 },
34 { 0x02bd09, KEY_0 },
35 { 0x02bd0a, KEY_MUTE },
36 { 0x02bd0b, KEY_CYCLEWINDOWS }, /* yellow, [min / max] */
37 { 0x02bd0c, KEY_VIDEO }, /* TV / AV */
38 { 0x02bd0e, KEY_VOLUMEDOWN },
39 { 0x02bd0f, KEY_TIME }, /* TimeShift */
40 { 0x02bd10, KEY_RIGHT }, /* right arrow */
41 { 0x02bd11, KEY_LEFT }, /* left arrow */
42 { 0x02bd12, KEY_UP }, /* up arrow */
43 { 0x02bd13, KEY_DOWN }, /* down arrow */
44 { 0x02bd14, KEY_POWER2 }, /* [red] */
45 { 0x02bd15, KEY_OK }, /* OK */
46 { 0x02bd16, KEY_STOP },
47 { 0x02bd17, KEY_CAMERA }, /* Snapshot */
48 { 0x02bd18, KEY_CHANNELUP },
49 { 0x02bd19, KEY_RECORD },
50 { 0x02bd1a, KEY_CHANNELDOWN },
51 { 0x02bd1c, KEY_ESC }, /* Esc */
52 { 0x02bd1e, KEY_PLAY },
53 { 0x02bd1f, KEY_VOLUMEUP },
54 { 0x02bd40, KEY_PAUSE },
55 { 0x02bd41, KEY_FASTFORWARD }, /* FF >> */
56 { 0x02bd42, KEY_REWIND }, /* FR << */
57 { 0x02bd43, KEY_ZOOM }, /* [window + mouse pointer] */
58 { 0x02bd44, KEY_SHUFFLE }, /* Shuffle */
59 { 0x02bd45, KEY_INFO }, /* [red (I)] */
60};
61
62static struct rc_keymap total_media_in_hand_map = {
63 .map = {
64 .scan = total_media_in_hand,
65 .size = ARRAY_SIZE(total_media_in_hand),
66 .ir_type = IR_TYPE_NEC,
67 .name = RC_MAP_TOTAL_MEDIA_IN_HAND,
68 }
69};
70
71static int __init init_rc_map_total_media_in_hand(void)
72{
73 return ir_register_map(&total_media_in_hand_map);
74}
75
76static void __exit exit_rc_map_total_media_in_hand(void)
77{
78 ir_unregister_map(&total_media_in_hand_map);
79}
80
81module_init(init_rc_map_total_media_in_hand)
82module_exit(exit_rc_map_total_media_in_hand)
83
84MODULE_LICENSE("GPL");
85MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff --git a/drivers/media/rc/keymaps/rc-trekstor.c b/drivers/media/rc/keymaps/rc-trekstor.c
new file mode 100644
index 000000000000..91092caca452
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-trekstor.c
@@ -0,0 +1,80 @@
1/*
2 * TrekStor remote controller keytable
3 *
4 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <media/rc-map.h>
22
23/* TrekStor DVB-T USB Stick remote controller. */
24/* Imported from af9015.h.
25 Initial keytable was from Marc Schneider <macke@macke.org> */
26static struct ir_scancode trekstor[] = {
27 { 0x0084, KEY_0 },
28 { 0x0085, KEY_MUTE }, /* Mute */
29 { 0x0086, KEY_HOMEPAGE }, /* Home */
30 { 0x0087, KEY_UP }, /* Up */
31 { 0x0088, KEY_OK }, /* OK */
32 { 0x0089, KEY_RIGHT }, /* Right */
33 { 0x008a, KEY_FASTFORWARD }, /* Fast forward */
34 { 0x008b, KEY_VOLUMEUP }, /* Volume + */
35 { 0x008c, KEY_DOWN }, /* Down */
36 { 0x008d, KEY_PLAY }, /* Play/Pause */
37 { 0x008e, KEY_STOP }, /* Stop */
38 { 0x008f, KEY_EPG }, /* Info/EPG */
39 { 0x0090, KEY_7 },
40 { 0x0091, KEY_4 },
41 { 0x0092, KEY_1 },
42 { 0x0093, KEY_CHANNELDOWN }, /* Channel - */
43 { 0x0094, KEY_8 },
44 { 0x0095, KEY_5 },
45 { 0x0096, KEY_2 },
46 { 0x0097, KEY_CHANNELUP }, /* Channel + */
47 { 0x0098, KEY_9 },
48 { 0x0099, KEY_6 },
49 { 0x009a, KEY_3 },
50 { 0x009b, KEY_VOLUMEDOWN }, /* Volume - */
51 { 0x009c, KEY_TV }, /* TV */
52 { 0x009d, KEY_RECORD }, /* Record */
53 { 0x009e, KEY_REWIND }, /* Rewind */
54 { 0x009f, KEY_LEFT }, /* Left */
55};
56
57static struct rc_keymap trekstor_map = {
58 .map = {
59 .scan = trekstor,
60 .size = ARRAY_SIZE(trekstor),
61 .ir_type = IR_TYPE_NEC,
62 .name = RC_MAP_TREKSTOR,
63 }
64};
65
66static int __init init_rc_map_trekstor(void)
67{
68 return ir_register_map(&trekstor_map);
69}
70
71static void __exit exit_rc_map_trekstor(void)
72{
73 ir_unregister_map(&trekstor_map);
74}
75
76module_init(init_rc_map_trekstor)
77module_exit(exit_rc_map_trekstor)
78
79MODULE_LICENSE("GPL");
80MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff --git a/drivers/media/rc/keymaps/rc-tt-1500.c b/drivers/media/rc/keymaps/rc-tt-1500.c
new file mode 100644
index 000000000000..bc88de011d5d
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-tt-1500.c
@@ -0,0 +1,82 @@
1/* tt-1500.h - Keytable for tt_1500 Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* for the Technotrend 1500 bundled remotes (grey and black): */
16
17static struct ir_scancode tt_1500[] = {
18 { 0x01, KEY_POWER },
19 { 0x02, KEY_SHUFFLE }, /* ? double-arrow key */
20 { 0x03, KEY_1 },
21 { 0x04, KEY_2 },
22 { 0x05, KEY_3 },
23 { 0x06, KEY_4 },
24 { 0x07, KEY_5 },
25 { 0x08, KEY_6 },
26 { 0x09, KEY_7 },
27 { 0x0a, KEY_8 },
28 { 0x0b, KEY_9 },
29 { 0x0c, KEY_0 },
30 { 0x0d, KEY_UP },
31 { 0x0e, KEY_LEFT },
32 { 0x0f, KEY_OK },
33 { 0x10, KEY_RIGHT },
34 { 0x11, KEY_DOWN },
35 { 0x12, KEY_INFO },
36 { 0x13, KEY_EXIT },
37 { 0x14, KEY_RED },
38 { 0x15, KEY_GREEN },
39 { 0x16, KEY_YELLOW },
40 { 0x17, KEY_BLUE },
41 { 0x18, KEY_MUTE },
42 { 0x19, KEY_TEXT },
43 { 0x1a, KEY_MODE }, /* ? TV/Radio */
44 { 0x21, KEY_OPTION },
45 { 0x22, KEY_EPG },
46 { 0x23, KEY_CHANNELUP },
47 { 0x24, KEY_CHANNELDOWN },
48 { 0x25, KEY_VOLUMEUP },
49 { 0x26, KEY_VOLUMEDOWN },
50 { 0x27, KEY_SETUP },
51 { 0x3a, KEY_RECORD }, /* these keys are only in the black remote */
52 { 0x3b, KEY_PLAY },
53 { 0x3c, KEY_STOP },
54 { 0x3d, KEY_REWIND },
55 { 0x3e, KEY_PAUSE },
56 { 0x3f, KEY_FORWARD },
57};
58
59static struct rc_keymap tt_1500_map = {
60 .map = {
61 .scan = tt_1500,
62 .size = ARRAY_SIZE(tt_1500),
63 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
64 .name = RC_MAP_TT_1500,
65 }
66};
67
68static int __init init_rc_map_tt_1500(void)
69{
70 return ir_register_map(&tt_1500_map);
71}
72
73static void __exit exit_rc_map_tt_1500(void)
74{
75 ir_unregister_map(&tt_1500_map);
76}
77
78module_init(init_rc_map_tt_1500)
79module_exit(exit_rc_map_tt_1500)
80
81MODULE_LICENSE("GPL");
82MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-twinhan1027.c b/drivers/media/rc/keymaps/rc-twinhan1027.c
new file mode 100644
index 000000000000..0b5d356c2d84
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-twinhan1027.c
@@ -0,0 +1,87 @@
1#include <media/rc-map.h>
2
3static struct ir_scancode twinhan_vp1027[] = {
4 { 0x16, KEY_POWER2 },
5 { 0x17, KEY_FAVORITES },
6 { 0x0f, KEY_TEXT },
7 { 0x48, KEY_INFO},
8 { 0x1c, KEY_EPG },
9 { 0x04, KEY_LIST },
10
11 { 0x03, KEY_1 },
12 { 0x01, KEY_2 },
13 { 0x06, KEY_3 },
14 { 0x09, KEY_4 },
15 { 0x1d, KEY_5 },
16 { 0x1f, KEY_6 },
17 { 0x0d, KEY_7 },
18 { 0x19, KEY_8 },
19 { 0x1b, KEY_9 },
20 { 0x15, KEY_0 },
21
22 { 0x0c, KEY_CANCEL },
23 { 0x4a, KEY_CLEAR },
24 { 0x13, KEY_BACKSPACE },
25 { 0x00, KEY_TAB },
26
27 { 0x4b, KEY_UP },
28 { 0x51, KEY_DOWN },
29 { 0x4e, KEY_LEFT },
30 { 0x52, KEY_RIGHT },
31 { 0x4f, KEY_ENTER },
32
33 { 0x1e, KEY_VOLUMEUP },
34 { 0x0a, KEY_VOLUMEDOWN },
35 { 0x02, KEY_CHANNELDOWN },
36 { 0x05, KEY_CHANNELUP },
37 { 0x11, KEY_RECORD },
38
39 { 0x14, KEY_PLAY },
40 { 0x4c, KEY_PAUSE },
41 { 0x1a, KEY_STOP },
42 { 0x40, KEY_REWIND },
43 { 0x12, KEY_FASTFORWARD },
44 { 0x41, KEY_PREVIOUSSONG },
45 { 0x42, KEY_NEXTSONG },
46 { 0x54, KEY_SAVE },
47 { 0x50, KEY_LANGUAGE },
48 { 0x47, KEY_MEDIA },
49 { 0x4d, KEY_SCREEN },
50 { 0x43, KEY_SUBTITLE },
51 { 0x10, KEY_MUTE },
52 { 0x49, KEY_AUDIO },
53 { 0x07, KEY_SLEEP },
54 { 0x08, KEY_VIDEO },
55 { 0x0e, KEY_AGAIN },
56 { 0x45, KEY_EQUAL },
57 { 0x46, KEY_MINUS },
58 { 0x18, KEY_RED },
59 { 0x53, KEY_GREEN },
60 { 0x5e, KEY_YELLOW },
61 { 0x5f, KEY_BLUE },
62};
63
64static struct rc_keymap twinhan_vp1027_map = {
65 .map = {
66 .scan = twinhan_vp1027,
67 .size = ARRAY_SIZE(twinhan_vp1027),
68 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
69 .name = RC_MAP_TWINHAN_VP1027_DVBS,
70 }
71};
72
73static int __init init_rc_map_twinhan_vp1027(void)
74{
75 return ir_register_map(&twinhan_vp1027_map);
76}
77
78static void __exit exit_rc_map_twinhan_vp1027(void)
79{
80 ir_unregister_map(&twinhan_vp1027_map);
81}
82
83module_init(init_rc_map_twinhan_vp1027)
84module_exit(exit_rc_map_twinhan_vp1027)
85
86MODULE_LICENSE("GPL");
87MODULE_AUTHOR("Sergey Ivanov <123kash@gmail.com>");
diff --git a/drivers/media/rc/keymaps/rc-videomate-s350.c b/drivers/media/rc/keymaps/rc-videomate-s350.c
new file mode 100644
index 000000000000..4df7fcd1d2fc
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-videomate-s350.c
@@ -0,0 +1,85 @@
1/* videomate-s350.h - Keytable for videomate_s350 Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode videomate_s350[] = {
16 { 0x00, KEY_TV},
17 { 0x01, KEY_DVD},
18 { 0x04, KEY_RECORD},
19 { 0x05, KEY_VIDEO}, /* TV/Video */
20 { 0x07, KEY_STOP},
21 { 0x08, KEY_PLAYPAUSE},
22 { 0x0a, KEY_REWIND},
23 { 0x0f, KEY_FASTFORWARD},
24 { 0x10, KEY_CHANNELUP},
25 { 0x12, KEY_VOLUMEUP},
26 { 0x13, KEY_CHANNELDOWN},
27 { 0x14, KEY_MUTE},
28 { 0x15, KEY_VOLUMEDOWN},
29 { 0x16, KEY_1},
30 { 0x17, KEY_2},
31 { 0x18, KEY_3},
32 { 0x19, KEY_4},
33 { 0x1a, KEY_5},
34 { 0x1b, KEY_6},
35 { 0x1c, KEY_7},
36 { 0x1d, KEY_8},
37 { 0x1e, KEY_9},
38 { 0x1f, KEY_0},
39 { 0x21, KEY_SLEEP},
40 { 0x24, KEY_ZOOM},
41 { 0x25, KEY_LAST}, /* Recall */
42 { 0x26, KEY_SUBTITLE}, /* CC */
43 { 0x27, KEY_LANGUAGE}, /* MTS */
44 { 0x29, KEY_CHANNEL}, /* SURF */
45 { 0x2b, KEY_A},
46 { 0x2c, KEY_B},
47 { 0x2f, KEY_CAMERA}, /* Snapshot */
48 { 0x23, KEY_RADIO},
49 { 0x02, KEY_PREVIOUSSONG},
50 { 0x06, KEY_NEXTSONG},
51 { 0x03, KEY_EPG},
52 { 0x09, KEY_SETUP},
53 { 0x22, KEY_BACKSPACE},
54 { 0x0c, KEY_UP},
55 { 0x0e, KEY_DOWN},
56 { 0x0b, KEY_LEFT},
57 { 0x0d, KEY_RIGHT},
58 { 0x11, KEY_ENTER},
59 { 0x20, KEY_TEXT},
60};
61
62static struct rc_keymap videomate_s350_map = {
63 .map = {
64 .scan = videomate_s350,
65 .size = ARRAY_SIZE(videomate_s350),
66 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
67 .name = RC_MAP_VIDEOMATE_S350,
68 }
69};
70
71static int __init init_rc_map_videomate_s350(void)
72{
73 return ir_register_map(&videomate_s350_map);
74}
75
76static void __exit exit_rc_map_videomate_s350(void)
77{
78 ir_unregister_map(&videomate_s350_map);
79}
80
81module_init(init_rc_map_videomate_s350)
82module_exit(exit_rc_map_videomate_s350)
83
84MODULE_LICENSE("GPL");
85MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c b/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c
new file mode 100644
index 000000000000..776b0a638d87
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c
@@ -0,0 +1,87 @@
1/* videomate-tv-pvr.h - Keytable for videomate_tv_pvr Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15static struct ir_scancode videomate_tv_pvr[] = {
16 { 0x14, KEY_MUTE },
17 { 0x24, KEY_ZOOM },
18
19 { 0x01, KEY_DVD },
20 { 0x23, KEY_RADIO },
21 { 0x00, KEY_TV },
22
23 { 0x0a, KEY_REWIND },
24 { 0x08, KEY_PLAYPAUSE },
25 { 0x0f, KEY_FORWARD },
26
27 { 0x02, KEY_PREVIOUS },
28 { 0x07, KEY_STOP },
29 { 0x06, KEY_NEXT },
30
31 { 0x0c, KEY_UP },
32 { 0x0e, KEY_DOWN },
33 { 0x0b, KEY_LEFT },
34 { 0x0d, KEY_RIGHT },
35 { 0x11, KEY_OK },
36
37 { 0x03, KEY_MENU },
38 { 0x09, KEY_SETUP },
39 { 0x05, KEY_VIDEO },
40 { 0x22, KEY_CHANNEL },
41
42 { 0x12, KEY_VOLUMEUP },
43 { 0x15, KEY_VOLUMEDOWN },
44 { 0x10, KEY_CHANNELUP },
45 { 0x13, KEY_CHANNELDOWN },
46
47 { 0x04, KEY_RECORD },
48
49 { 0x16, KEY_1 },
50 { 0x17, KEY_2 },
51 { 0x18, KEY_3 },
52 { 0x19, KEY_4 },
53 { 0x1a, KEY_5 },
54 { 0x1b, KEY_6 },
55 { 0x1c, KEY_7 },
56 { 0x1d, KEY_8 },
57 { 0x1e, KEY_9 },
58 { 0x1f, KEY_0 },
59
60 { 0x20, KEY_LANGUAGE },
61 { 0x21, KEY_SLEEP },
62};
63
64static struct rc_keymap videomate_tv_pvr_map = {
65 .map = {
66 .scan = videomate_tv_pvr,
67 .size = ARRAY_SIZE(videomate_tv_pvr),
68 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
69 .name = RC_MAP_VIDEOMATE_TV_PVR,
70 }
71};
72
73static int __init init_rc_map_videomate_tv_pvr(void)
74{
75 return ir_register_map(&videomate_tv_pvr_map);
76}
77
78static void __exit exit_rc_map_videomate_tv_pvr(void)
79{
80 ir_unregister_map(&videomate_tv_pvr_map);
81}
82
83module_init(init_rc_map_videomate_tv_pvr)
84module_exit(exit_rc_map_videomate_tv_pvr)
85
86MODULE_LICENSE("GPL");
87MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c b/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c
new file mode 100644
index 000000000000..9d2d550aaa90
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c
@@ -0,0 +1,82 @@
1/* winfast-usbii-deluxe.h - Keytable for winfast_usbii_deluxe Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Leadtek Winfast TV USB II Deluxe remote
16 Magnus Alm <magnus.alm@gmail.com>
17 */
18
19static struct ir_scancode winfast_usbii_deluxe[] = {
20 { 0x62, KEY_0},
21 { 0x75, KEY_1},
22 { 0x76, KEY_2},
23 { 0x77, KEY_3},
24 { 0x79, KEY_4},
25 { 0x7a, KEY_5},
26 { 0x7b, KEY_6},
27 { 0x7d, KEY_7},
28 { 0x7e, KEY_8},
29 { 0x7f, KEY_9},
30
31 { 0x38, KEY_CAMERA}, /* SNAPSHOT */
32 { 0x37, KEY_RECORD}, /* RECORD */
33 { 0x35, KEY_TIME}, /* TIMESHIFT */
34
35 { 0x74, KEY_VOLUMEUP}, /* VOLUMEUP */
36 { 0x78, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */
37 { 0x64, KEY_MUTE}, /* MUTE */
38
39 { 0x21, KEY_CHANNEL}, /* SURF */
40 { 0x7c, KEY_CHANNELUP}, /* CHANNELUP */
41 { 0x60, KEY_CHANNELDOWN}, /* CHANNELDOWN */
42 { 0x61, KEY_LAST}, /* LAST CHANNEL (RECALL) */
43
44 { 0x72, KEY_VIDEO}, /* INPUT MODES (TV/FM) */
45
46 { 0x70, KEY_POWER2}, /* TV ON/OFF */
47
48 { 0x39, KEY_CYCLEWINDOWS}, /* MINIMIZE (BOSS) */
49 { 0x3a, KEY_NEW}, /* PIP */
50 { 0x73, KEY_ZOOM}, /* FULLSECREEN */
51
52 { 0x66, KEY_INFO}, /* OSD (DISPLAY) */
53
54 { 0x31, KEY_DOT}, /* '.' */
55 { 0x63, KEY_ENTER}, /* ENTER */
56
57};
58
59static struct rc_keymap winfast_usbii_deluxe_map = {
60 .map = {
61 .scan = winfast_usbii_deluxe,
62 .size = ARRAY_SIZE(winfast_usbii_deluxe),
63 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
64 .name = RC_MAP_WINFAST_USBII_DELUXE,
65 }
66};
67
68static int __init init_rc_map_winfast_usbii_deluxe(void)
69{
70 return ir_register_map(&winfast_usbii_deluxe_map);
71}
72
73static void __exit exit_rc_map_winfast_usbii_deluxe(void)
74{
75 ir_unregister_map(&winfast_usbii_deluxe_map);
76}
77
78module_init(init_rc_map_winfast_usbii_deluxe)
79module_exit(exit_rc_map_winfast_usbii_deluxe)
80
81MODULE_LICENSE("GPL");
82MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-winfast.c b/drivers/media/rc/keymaps/rc-winfast.c
new file mode 100644
index 000000000000..0e90a3bd9499
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-winfast.c
@@ -0,0 +1,102 @@
1/* winfast.h - Keytable for winfast Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */
16
17static struct ir_scancode winfast[] = {
18 /* Keys 0 to 9 */
19 { 0x12, KEY_0 },
20 { 0x05, KEY_1 },
21 { 0x06, KEY_2 },
22 { 0x07, KEY_3 },
23 { 0x09, KEY_4 },
24 { 0x0a, KEY_5 },
25 { 0x0b, KEY_6 },
26 { 0x0d, KEY_7 },
27 { 0x0e, KEY_8 },
28 { 0x0f, KEY_9 },
29
30 { 0x00, KEY_POWER },
31 { 0x1b, KEY_AUDIO }, /* Audio Source */
32 { 0x02, KEY_TUNER }, /* TV/FM, not on Y0400052 */
33 { 0x1e, KEY_VIDEO }, /* Video Source */
34 { 0x16, KEY_INFO }, /* Display information */
35 { 0x04, KEY_VOLUMEUP },
36 { 0x08, KEY_VOLUMEDOWN },
37 { 0x0c, KEY_CHANNELUP },
38 { 0x10, KEY_CHANNELDOWN },
39 { 0x03, KEY_ZOOM }, /* fullscreen */
40 { 0x1f, KEY_TEXT }, /* closed caption/teletext */
41 { 0x20, KEY_SLEEP },
42 { 0x29, KEY_CLEAR }, /* boss key */
43 { 0x14, KEY_MUTE },
44 { 0x2b, KEY_RED },
45 { 0x2c, KEY_GREEN },
46 { 0x2d, KEY_YELLOW },
47 { 0x2e, KEY_BLUE },
48 { 0x18, KEY_KPPLUS }, /* fine tune + , not on Y040052 */
49 { 0x19, KEY_KPMINUS }, /* fine tune - , not on Y040052 */
50 { 0x2a, KEY_MEDIA }, /* PIP (Picture in picture */
51 { 0x21, KEY_DOT },
52 { 0x13, KEY_ENTER },
53 { 0x11, KEY_LAST }, /* Recall (last channel */
54 { 0x22, KEY_PREVIOUS },
55 { 0x23, KEY_PLAYPAUSE },
56 { 0x24, KEY_NEXT },
57 { 0x25, KEY_TIME }, /* Time Shifting */
58 { 0x26, KEY_STOP },
59 { 0x27, KEY_RECORD },
60 { 0x28, KEY_SAVE }, /* Screenshot */
61 { 0x2f, KEY_MENU },
62 { 0x30, KEY_CANCEL },
63 { 0x31, KEY_CHANNEL }, /* Channel Surf */
64 { 0x32, KEY_SUBTITLE },
65 { 0x33, KEY_LANGUAGE },
66 { 0x34, KEY_REWIND },
67 { 0x35, KEY_FASTFORWARD },
68 { 0x36, KEY_TV },
69 { 0x37, KEY_RADIO }, /* FM */
70 { 0x38, KEY_DVD },
71
72 { 0x1a, KEY_MODE}, /* change to MCE mode on Y04G0051 */
73 { 0x3e, KEY_F21 }, /* MCE +VOL, on Y04G0033 */
74 { 0x3a, KEY_F22 }, /* MCE -VOL, on Y04G0033 */
75 { 0x3b, KEY_F23 }, /* MCE +CH, on Y04G0033 */
76 { 0x3f, KEY_F24 } /* MCE -CH, on Y04G0033 */
77};
78
79static struct rc_keymap winfast_map = {
80 .map = {
81 .scan = winfast,
82 .size = ARRAY_SIZE(winfast),
83 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
84 .name = RC_MAP_WINFAST,
85 }
86};
87
88static int __init init_rc_map_winfast(void)
89{
90 return ir_register_map(&winfast_map);
91}
92
93static void __exit exit_rc_map_winfast(void)
94{
95 ir_unregister_map(&winfast_map);
96}
97
98module_init(init_rc_map_winfast)
99module_exit(exit_rc_map_winfast)
100
101MODULE_LICENSE("GPL");
102MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
new file mode 100644
index 000000000000..756656e17bdd
--- /dev/null
+++ b/drivers/media/rc/lirc_dev.c
@@ -0,0 +1,814 @@
1/*
2 * LIRC base driver
3 *
4 * by Artur Lipowski <alipowski@interia.pl>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/sched.h>
25#include <linux/errno.h>
26#include <linux/ioctl.h>
27#include <linux/fs.h>
28#include <linux/poll.h>
29#include <linux/completion.h>
30#include <linux/mutex.h>
31#include <linux/wait.h>
32#include <linux/unistd.h>
33#include <linux/kthread.h>
34#include <linux/bitops.h>
35#include <linux/device.h>
36#include <linux/cdev.h>
37
38#include <media/lirc.h>
39#include <media/lirc_dev.h>
40
41static int debug;
42
43#define IRCTL_DEV_NAME "BaseRemoteCtl"
44#define NOPLUG -1
45#define LOGHEAD "lirc_dev (%s[%d]): "
46
47static dev_t lirc_base_dev;
48
49struct irctl {
50 struct lirc_driver d;
51 int attached;
52 int open;
53
54 struct mutex irctl_lock;
55 struct lirc_buffer *buf;
56 unsigned int chunk_size;
57
58 struct task_struct *task;
59 long jiffies_to_wait;
60};
61
62static DEFINE_MUTEX(lirc_dev_lock);
63
64static struct irctl *irctls[MAX_IRCTL_DEVICES];
65static struct cdev cdevs[MAX_IRCTL_DEVICES];
66
67/* Only used for sysfs but defined to void otherwise */
68static struct class *lirc_class;
69
70/* helper function
71 * initializes the irctl structure
72 */
73static void lirc_irctl_init(struct irctl *ir)
74{
75 mutex_init(&ir->irctl_lock);
76 ir->d.minor = NOPLUG;
77}
78
79static void lirc_irctl_cleanup(struct irctl *ir)
80{
81 dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
82
83 device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
84
85 if (ir->buf != ir->d.rbuf) {
86 lirc_buffer_free(ir->buf);
87 kfree(ir->buf);
88 }
89 ir->buf = NULL;
90}
91
92/* helper function
93 * reads key codes from driver and puts them into buffer
94 * returns 0 on success
95 */
96static int lirc_add_to_buf(struct irctl *ir)
97{
98 if (ir->d.add_to_buf) {
99 int res = -ENODATA;
100 int got_data = 0;
101
102 /*
103 * service the device as long as it is returning
104 * data and we have space
105 */
106get_data:
107 res = ir->d.add_to_buf(ir->d.data, ir->buf);
108 if (res == 0) {
109 got_data++;
110 goto get_data;
111 }
112
113 if (res == -ENODEV)
114 kthread_stop(ir->task);
115
116 return got_data ? 0 : res;
117 }
118
119 return 0;
120}
121
122/* main function of the polling thread
123 */
124static int lirc_thread(void *irctl)
125{
126 struct irctl *ir = irctl;
127
128 dev_dbg(ir->d.dev, LOGHEAD "poll thread started\n",
129 ir->d.name, ir->d.minor);
130
131 do {
132 if (ir->open) {
133 if (ir->jiffies_to_wait) {
134 set_current_state(TASK_INTERRUPTIBLE);
135 schedule_timeout(ir->jiffies_to_wait);
136 }
137 if (kthread_should_stop())
138 break;
139 if (!lirc_add_to_buf(ir))
140 wake_up_interruptible(&ir->buf->wait_poll);
141 } else {
142 set_current_state(TASK_INTERRUPTIBLE);
143 schedule();
144 }
145 } while (!kthread_should_stop());
146
147 dev_dbg(ir->d.dev, LOGHEAD "poll thread ended\n",
148 ir->d.name, ir->d.minor);
149
150 return 0;
151}
152
153
154static struct file_operations lirc_dev_fops = {
155 .owner = THIS_MODULE,
156 .read = lirc_dev_fop_read,
157 .write = lirc_dev_fop_write,
158 .poll = lirc_dev_fop_poll,
159 .unlocked_ioctl = lirc_dev_fop_ioctl,
160#ifdef CONFIG_COMPAT
161 .compat_ioctl = lirc_dev_fop_ioctl,
162#endif
163 .open = lirc_dev_fop_open,
164 .release = lirc_dev_fop_close,
165 .llseek = noop_llseek,
166};
167
168static int lirc_cdev_add(struct irctl *ir)
169{
170 int retval;
171 struct lirc_driver *d = &ir->d;
172 struct cdev *cdev = &cdevs[d->minor];
173
174 if (d->fops) {
175 cdev_init(cdev, d->fops);
176 cdev->owner = d->owner;
177 } else {
178 cdev_init(cdev, &lirc_dev_fops);
179 cdev->owner = THIS_MODULE;
180 }
181 kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
182
183 retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
184 if (retval)
185 kobject_put(&cdev->kobj);
186
187 return retval;
188}
189
190int lirc_register_driver(struct lirc_driver *d)
191{
192 struct irctl *ir;
193 int minor;
194 int bytes_in_key;
195 unsigned int chunk_size;
196 unsigned int buffer_size;
197 int err;
198
199 if (!d) {
200 printk(KERN_ERR "lirc_dev: lirc_register_driver: "
201 "driver pointer must be not NULL!\n");
202 err = -EBADRQC;
203 goto out;
204 }
205
206 if (!d->dev) {
207 printk(KERN_ERR "%s: dev pointer not filled in!\n", __func__);
208 err = -EINVAL;
209 goto out;
210 }
211
212 if (MAX_IRCTL_DEVICES <= d->minor) {
213 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
214 "\"minor\" must be between 0 and %d (%d)!\n",
215 MAX_IRCTL_DEVICES-1, d->minor);
216 err = -EBADRQC;
217 goto out;
218 }
219
220 if (1 > d->code_length || (BUFLEN * 8) < d->code_length) {
221 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
222 "code length in bits for minor (%d) "
223 "must be less than %d!\n",
224 d->minor, BUFLEN * 8);
225 err = -EBADRQC;
226 goto out;
227 }
228
229 dev_dbg(d->dev, "lirc_dev: lirc_register_driver: sample_rate: %d\n",
230 d->sample_rate);
231 if (d->sample_rate) {
232 if (2 > d->sample_rate || HZ < d->sample_rate) {
233 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
234 "sample_rate must be between 2 and %d!\n", HZ);
235 err = -EBADRQC;
236 goto out;
237 }
238 if (!d->add_to_buf) {
239 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
240 "add_to_buf cannot be NULL when "
241 "sample_rate is set\n");
242 err = -EBADRQC;
243 goto out;
244 }
245 } else if (!(d->fops && d->fops->read) && !d->rbuf) {
246 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
247 "fops->read and rbuf cannot all be NULL!\n");
248 err = -EBADRQC;
249 goto out;
250 } else if (!d->rbuf) {
251 if (!(d->fops && d->fops->read && d->fops->poll &&
252 d->fops->unlocked_ioctl)) {
253 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
254 "neither read, poll nor unlocked_ioctl can be NULL!\n");
255 err = -EBADRQC;
256 goto out;
257 }
258 }
259
260 mutex_lock(&lirc_dev_lock);
261
262 minor = d->minor;
263
264 if (minor < 0) {
265 /* find first free slot for driver */
266 for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++)
267 if (!irctls[minor])
268 break;
269 if (MAX_IRCTL_DEVICES == minor) {
270 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
271 "no free slots for drivers!\n");
272 err = -ENOMEM;
273 goto out_lock;
274 }
275 } else if (irctls[minor]) {
276 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
277 "minor (%d) just registered!\n", minor);
278 err = -EBUSY;
279 goto out_lock;
280 }
281
282 ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
283 if (!ir) {
284 err = -ENOMEM;
285 goto out_lock;
286 }
287 lirc_irctl_init(ir);
288 irctls[minor] = ir;
289 d->minor = minor;
290
291 if (d->sample_rate) {
292 ir->jiffies_to_wait = HZ / d->sample_rate;
293 } else {
294 /* it means - wait for external event in task queue */
295 ir->jiffies_to_wait = 0;
296 }
297
298 /* some safety check 8-) */
299 d->name[sizeof(d->name)-1] = '\0';
300
301 bytes_in_key = BITS_TO_LONGS(d->code_length) +
302 (d->code_length % 8 ? 1 : 0);
303 buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key;
304 chunk_size = d->chunk_size ? d->chunk_size : bytes_in_key;
305
306 if (d->rbuf) {
307 ir->buf = d->rbuf;
308 } else {
309 ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
310 if (!ir->buf) {
311 err = -ENOMEM;
312 goto out_lock;
313 }
314 err = lirc_buffer_init(ir->buf, chunk_size, buffer_size);
315 if (err) {
316 kfree(ir->buf);
317 goto out_lock;
318 }
319 }
320 ir->chunk_size = ir->buf->chunk_size;
321
322 if (d->features == 0)
323 d->features = LIRC_CAN_REC_LIRCCODE;
324
325 ir->d = *d;
326
327 device_create(lirc_class, ir->d.dev,
328 MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL,
329 "lirc%u", ir->d.minor);
330
331 if (d->sample_rate) {
332 /* try to fire up polling thread */
333 ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev");
334 if (IS_ERR(ir->task)) {
335 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
336 "cannot run poll thread for minor = %d\n",
337 d->minor);
338 err = -ECHILD;
339 goto out_sysfs;
340 }
341 }
342
343 err = lirc_cdev_add(ir);
344 if (err)
345 goto out_sysfs;
346
347 ir->attached = 1;
348 mutex_unlock(&lirc_dev_lock);
349
350 dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
351 ir->d.name, ir->d.minor);
352 return minor;
353
354out_sysfs:
355 device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
356out_lock:
357 mutex_unlock(&lirc_dev_lock);
358out:
359 return err;
360}
361EXPORT_SYMBOL(lirc_register_driver);
362
363int lirc_unregister_driver(int minor)
364{
365 struct irctl *ir;
366 struct cdev *cdev;
367
368 if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
369 printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between "
370 "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1);
371 return -EBADRQC;
372 }
373
374 ir = irctls[minor];
375 if (!ir) {
376 printk(KERN_ERR "lirc_dev: %s: failed to get irctl struct "
377 "for minor %d!\n", __func__, minor);
378 return -ENOENT;
379 }
380
381 cdev = &cdevs[minor];
382
383 mutex_lock(&lirc_dev_lock);
384
385 if (ir->d.minor != minor) {
386 printk(KERN_ERR "lirc_dev: %s: minor (%d) device not "
387 "registered!\n", __func__, minor);
388 mutex_unlock(&lirc_dev_lock);
389 return -ENOENT;
390 }
391
392 /* end up polling thread */
393 if (ir->task)
394 kthread_stop(ir->task);
395
396 dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
397 ir->d.name, ir->d.minor);
398
399 ir->attached = 0;
400 if (ir->open) {
401 dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
402 ir->d.name, ir->d.minor);
403 wake_up_interruptible(&ir->buf->wait_poll);
404 mutex_lock(&ir->irctl_lock);
405 ir->d.set_use_dec(ir->d.data);
406 module_put(cdev->owner);
407 mutex_unlock(&ir->irctl_lock);
408 } else {
409 lirc_irctl_cleanup(ir);
410 cdev_del(cdev);
411 kfree(ir);
412 irctls[minor] = NULL;
413 }
414
415 mutex_unlock(&lirc_dev_lock);
416
417 return 0;
418}
419EXPORT_SYMBOL(lirc_unregister_driver);
420
421int lirc_dev_fop_open(struct inode *inode, struct file *file)
422{
423 struct irctl *ir;
424 struct cdev *cdev;
425 int retval = 0;
426
427 if (iminor(inode) >= MAX_IRCTL_DEVICES) {
428 printk(KERN_WARNING "lirc_dev [%d]: open result = -ENODEV\n",
429 iminor(inode));
430 return -ENODEV;
431 }
432
433 if (mutex_lock_interruptible(&lirc_dev_lock))
434 return -ERESTARTSYS;
435
436 ir = irctls[iminor(inode)];
437 if (!ir) {
438 retval = -ENODEV;
439 goto error;
440 }
441
442 dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
443
444 if (ir->d.minor == NOPLUG) {
445 retval = -ENODEV;
446 goto error;
447 }
448
449 if (ir->open) {
450 retval = -EBUSY;
451 goto error;
452 }
453
454 cdev = &cdevs[iminor(inode)];
455 if (try_module_get(cdev->owner)) {
456 ir->open++;
457 retval = ir->d.set_use_inc(ir->d.data);
458
459 if (retval) {
460 module_put(cdev->owner);
461 ir->open--;
462 } else {
463 lirc_buffer_clear(ir->buf);
464 }
465 if (ir->task)
466 wake_up_process(ir->task);
467 }
468
469error:
470 if (ir)
471 dev_dbg(ir->d.dev, LOGHEAD "open result = %d\n",
472 ir->d.name, ir->d.minor, retval);
473
474 mutex_unlock(&lirc_dev_lock);
475
476 nonseekable_open(inode, file);
477
478 return retval;
479}
480EXPORT_SYMBOL(lirc_dev_fop_open);
481
482int lirc_dev_fop_close(struct inode *inode, struct file *file)
483{
484 struct irctl *ir = irctls[iminor(inode)];
485 struct cdev *cdev = &cdevs[iminor(inode)];
486
487 if (!ir) {
488 printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
489 return -EINVAL;
490 }
491
492 dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
493
494 WARN_ON(mutex_lock_killable(&lirc_dev_lock));
495
496 ir->open--;
497 if (ir->attached) {
498 ir->d.set_use_dec(ir->d.data);
499 module_put(cdev->owner);
500 } else {
501 lirc_irctl_cleanup(ir);
502 cdev_del(cdev);
503 irctls[ir->d.minor] = NULL;
504 kfree(ir);
505 }
506
507 mutex_unlock(&lirc_dev_lock);
508
509 return 0;
510}
511EXPORT_SYMBOL(lirc_dev_fop_close);
512
513unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
514{
515 struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
516 unsigned int ret;
517
518 if (!ir) {
519 printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
520 return POLLERR;
521 }
522
523 dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
524
525 if (!ir->attached)
526 return POLLERR;
527
528 poll_wait(file, &ir->buf->wait_poll, wait);
529
530 if (ir->buf)
531 if (lirc_buffer_empty(ir->buf))
532 ret = 0;
533 else
534 ret = POLLIN | POLLRDNORM;
535 else
536 ret = POLLERR;
537
538 dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
539 ir->d.name, ir->d.minor, ret);
540
541 return ret;
542}
543EXPORT_SYMBOL(lirc_dev_fop_poll);
544
545long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
546{
547 __u32 mode;
548 int result = 0;
549 struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
550
551 if (!ir) {
552 printk(KERN_ERR "lirc_dev: %s: no irctl found!\n", __func__);
553 return -ENODEV;
554 }
555
556 dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
557 ir->d.name, ir->d.minor, cmd);
558
559 if (ir->d.minor == NOPLUG || !ir->attached) {
560 dev_dbg(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
561 ir->d.name, ir->d.minor);
562 return -ENODEV;
563 }
564
565 mutex_lock(&ir->irctl_lock);
566
567 switch (cmd) {
568 case LIRC_GET_FEATURES:
569 result = put_user(ir->d.features, (__u32 *)arg);
570 break;
571 case LIRC_GET_REC_MODE:
572 if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
573 result = -ENOSYS;
574 break;
575 }
576
577 result = put_user(LIRC_REC2MODE
578 (ir->d.features & LIRC_CAN_REC_MASK),
579 (__u32 *)arg);
580 break;
581 case LIRC_SET_REC_MODE:
582 if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
583 result = -ENOSYS;
584 break;
585 }
586
587 result = get_user(mode, (__u32 *)arg);
588 if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
589 result = -EINVAL;
590 /*
591 * FIXME: We should actually set the mode somehow but
592 * for now, lirc_serial doesn't support mode changing either
593 */
594 break;
595 case LIRC_GET_LENGTH:
596 result = put_user(ir->d.code_length, (__u32 *)arg);
597 break;
598 case LIRC_GET_MIN_TIMEOUT:
599 if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
600 ir->d.min_timeout == 0) {
601 result = -ENOSYS;
602 break;
603 }
604
605 result = put_user(ir->d.min_timeout, (__u32 *)arg);
606 break;
607 case LIRC_GET_MAX_TIMEOUT:
608 if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
609 ir->d.max_timeout == 0) {
610 result = -ENOSYS;
611 break;
612 }
613
614 result = put_user(ir->d.max_timeout, (__u32 *)arg);
615 break;
616 default:
617 result = -EINVAL;
618 }
619
620 dev_dbg(ir->d.dev, LOGHEAD "ioctl result = %d\n",
621 ir->d.name, ir->d.minor, result);
622
623 mutex_unlock(&ir->irctl_lock);
624
625 return result;
626}
627EXPORT_SYMBOL(lirc_dev_fop_ioctl);
628
629ssize_t lirc_dev_fop_read(struct file *file,
630 char *buffer,
631 size_t length,
632 loff_t *ppos)
633{
634 struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
635 unsigned char *buf;
636 int ret = 0, written = 0;
637 DECLARE_WAITQUEUE(wait, current);
638
639 if (!ir) {
640 printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
641 return -ENODEV;
642 }
643
644 dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
645
646 buf = kzalloc(ir->chunk_size, GFP_KERNEL);
647 if (!buf)
648 return -ENOMEM;
649
650 if (mutex_lock_interruptible(&ir->irctl_lock)) {
651 ret = -ERESTARTSYS;
652 goto out_unlocked;
653 }
654 if (!ir->attached) {
655 ret = -ENODEV;
656 goto out_locked;
657 }
658
659 if (length % ir->chunk_size) {
660 ret = -EINVAL;
661 goto out_locked;
662 }
663
664 /*
665 * we add ourselves to the task queue before buffer check
666 * to avoid losing scan code (in case when queue is awaken somewhere
667 * between while condition checking and scheduling)
668 */
669 add_wait_queue(&ir->buf->wait_poll, &wait);
670 set_current_state(TASK_INTERRUPTIBLE);
671
672 /*
673 * while we didn't provide 'length' bytes, device is opened in blocking
674 * mode and 'copy_to_user' is happy, wait for data.
675 */
676 while (written < length && ret == 0) {
677 if (lirc_buffer_empty(ir->buf)) {
678 /* According to the read(2) man page, 'written' can be
679 * returned as less than 'length', instead of blocking
680 * again, returning -EWOULDBLOCK, or returning
681 * -ERESTARTSYS */
682 if (written)
683 break;
684 if (file->f_flags & O_NONBLOCK) {
685 ret = -EWOULDBLOCK;
686 break;
687 }
688 if (signal_pending(current)) {
689 ret = -ERESTARTSYS;
690 break;
691 }
692
693 mutex_unlock(&ir->irctl_lock);
694 schedule();
695 set_current_state(TASK_INTERRUPTIBLE);
696
697 if (mutex_lock_interruptible(&ir->irctl_lock)) {
698 ret = -ERESTARTSYS;
699 remove_wait_queue(&ir->buf->wait_poll, &wait);
700 set_current_state(TASK_RUNNING);
701 goto out_unlocked;
702 }
703
704 if (!ir->attached) {
705 ret = -ENODEV;
706 break;
707 }
708 } else {
709 lirc_buffer_read(ir->buf, buf);
710 ret = copy_to_user((void *)buffer+written, buf,
711 ir->buf->chunk_size);
712 if (!ret)
713 written += ir->buf->chunk_size;
714 else
715 ret = -EFAULT;
716 }
717 }
718
719 remove_wait_queue(&ir->buf->wait_poll, &wait);
720 set_current_state(TASK_RUNNING);
721
722out_locked:
723 mutex_unlock(&ir->irctl_lock);
724
725out_unlocked:
726 kfree(buf);
727 dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
728 ir->d.name, ir->d.minor, ret ? "<fail>" : "<ok>", ret);
729
730 return ret ? ret : written;
731}
732EXPORT_SYMBOL(lirc_dev_fop_read);
733
734void *lirc_get_pdata(struct file *file)
735{
736 void *data = NULL;
737
738 if (file && file->f_dentry && file->f_dentry->d_inode &&
739 file->f_dentry->d_inode->i_rdev) {
740 struct irctl *ir;
741 ir = irctls[iminor(file->f_dentry->d_inode)];
742 data = ir->d.data;
743 }
744
745 return data;
746}
747EXPORT_SYMBOL(lirc_get_pdata);
748
749
750ssize_t lirc_dev_fop_write(struct file *file, const char *buffer,
751 size_t length, loff_t *ppos)
752{
753 struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
754
755 if (!ir) {
756 printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
757 return -ENODEV;
758 }
759
760 dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor);
761
762 if (!ir->attached)
763 return -ENODEV;
764
765 return -EINVAL;
766}
767EXPORT_SYMBOL(lirc_dev_fop_write);
768
769
770static int __init lirc_dev_init(void)
771{
772 int retval;
773
774 lirc_class = class_create(THIS_MODULE, "lirc");
775 if (IS_ERR(lirc_class)) {
776 retval = PTR_ERR(lirc_class);
777 printk(KERN_ERR "lirc_dev: class_create failed\n");
778 goto error;
779 }
780
781 retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES,
782 IRCTL_DEV_NAME);
783 if (retval) {
784 class_destroy(lirc_class);
785 printk(KERN_ERR "lirc_dev: alloc_chrdev_region failed\n");
786 goto error;
787 }
788
789
790 printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, "
791 "major %d \n", MAJOR(lirc_base_dev));
792
793error:
794 return retval;
795}
796
797
798
799static void __exit lirc_dev_exit(void)
800{
801 class_destroy(lirc_class);
802 unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES);
803 printk(KERN_INFO "lirc_dev: module unloaded\n");
804}
805
806module_init(lirc_dev_init);
807module_exit(lirc_dev_exit);
808
809MODULE_DESCRIPTION("LIRC base driver module");
810MODULE_AUTHOR("Artur Lipowski");
811MODULE_LICENSE("GPL");
812
813module_param(debug, bool, S_IRUGO | S_IWUSR);
814MODULE_PARM_DESC(debug, "Enable debugging messages");
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
new file mode 100644
index 000000000000..392ca24132da
--- /dev/null
+++ b/drivers/media/rc/mceusb.c
@@ -0,0 +1,1333 @@
1/*
2 * Driver for USB Windows Media Center Ed. eHome Infrared Transceivers
3 *
4 * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
5 *
6 * Based on the original lirc_mceusb and lirc_mceusb2 drivers, by Dan
7 * Conti, Martin Blatter and Daniel Melander, the latter of which was
8 * in turn also based on the lirc_atiusb driver by Paul Miller. The
9 * two mce drivers were merged into one by Jarod Wilson, with transmit
10 * support for the 1st-gen device added primarily by Patrick Calhoun,
11 * with a bit of tweaks by Jarod. Debugging improvements and proper
12 * support for what appears to be 3rd-gen hardware added by Jarod.
13 * Initial port from lirc driver to ir-core drivery by Jarod, based
14 * partially on a port to an earlier proposed IR infrastructure by
15 * Jon Smirl, which included enhancements and simplifications to the
16 * incoming IR buffer parsing routines.
17 *
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 *
33 */
34
35#include <linux/device.h>
36#include <linux/module.h>
37#include <linux/slab.h>
38#include <linux/input.h>
39#include <linux/usb.h>
40#include <linux/usb/input.h>
41#include <media/ir-core.h>
42
43#define DRIVER_VERSION "1.91"
44#define DRIVER_AUTHOR "Jarod Wilson <jarod@wilsonet.com>"
45#define DRIVER_DESC "Windows Media Center Ed. eHome Infrared Transceiver " \
46 "device driver"
47#define DRIVER_NAME "mceusb"
48
49#define USB_BUFLEN 32 /* USB reception buffer length */
50#define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */
51#define MCE_G1_INIT_MSGS 40 /* Init messages on gen1 hw to throw out */
52#define MS_TO_NS(msec) ((msec) * 1000)
53
54/* MCE constants */
55#define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */
56#define MCE_TIME_UNIT 50 /* Approx 50us resolution */
57#define MCE_CODE_LENGTH 5 /* Normal length of packet (with header) */
58#define MCE_PACKET_SIZE 4 /* Normal length of packet (without header) */
59#define MCE_IRDATA_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */
60#define MCE_IRDATA_TRAILER 0x80 /* End of IR data */
61#define MCE_TX_HEADER_LENGTH 3 /* # of bytes in the initializing tx header */
62#define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */
63#define MCE_DEFAULT_TX_MASK 0x03 /* Vals: TX1=0x01, TX2=0x02, ALL=0x03 */
64#define MCE_PULSE_BIT 0x80 /* Pulse bit, MSB set == PULSE else SPACE */
65#define MCE_PULSE_MASK 0x7f /* Pulse mask */
66#define MCE_MAX_PULSE_LENGTH 0x7f /* Longest transmittable pulse symbol */
67
68#define MCE_HW_CMD_HEADER 0xff /* MCE hardware command header */
69#define MCE_COMMAND_HEADER 0x9f /* MCE command header */
70#define MCE_COMMAND_MASK 0xe0 /* Mask out command bits */
71#define MCE_COMMAND_NULL 0x00 /* These show up various places... */
72/* if buf[i] & MCE_COMMAND_MASK == 0x80 and buf[i] != MCE_COMMAND_HEADER,
73 * then we're looking at a raw IR data sample */
74#define MCE_COMMAND_IRDATA 0x80
75#define MCE_PACKET_LENGTH_MASK 0x1f /* Packet length mask */
76
77/* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */
78#define MCE_CMD_SIG_END 0x01 /* End of signal */
79#define MCE_CMD_PING 0x03 /* Ping device */
80#define MCE_CMD_UNKNOWN 0x04 /* Unknown */
81#define MCE_CMD_UNKNOWN2 0x05 /* Unknown */
82#define MCE_CMD_S_CARRIER 0x06 /* Set TX carrier frequency */
83#define MCE_CMD_G_CARRIER 0x07 /* Get TX carrier frequency */
84#define MCE_CMD_S_TXMASK 0x08 /* Set TX port bitmask */
85#define MCE_CMD_UNKNOWN3 0x09 /* Unknown */
86#define MCE_CMD_UNKNOWN4 0x0a /* Unknown */
87#define MCE_CMD_G_REVISION 0x0b /* Get hw/sw revision */
88#define MCE_CMD_S_TIMEOUT 0x0c /* Set RX timeout value */
89#define MCE_CMD_G_TIMEOUT 0x0d /* Get RX timeout value */
90#define MCE_CMD_UNKNOWN5 0x0e /* Unknown */
91#define MCE_CMD_UNKNOWN6 0x0f /* Unknown */
92#define MCE_CMD_G_RXPORTSTS 0x11 /* Get RX port status */
93#define MCE_CMD_G_TXMASK 0x13 /* Set TX port bitmask */
94#define MCE_CMD_S_RXSENSOR 0x14 /* Set RX sensor (std/learning) */
95#define MCE_CMD_G_RXSENSOR 0x15 /* Get RX sensor (std/learning) */
96#define MCE_RSP_PULSE_COUNT 0x15 /* RX pulse count (only if learning) */
97#define MCE_CMD_TX_PORTS 0x16 /* Get number of TX ports */
98#define MCE_CMD_G_WAKESRC 0x17 /* Get wake source */
99#define MCE_CMD_UNKNOWN7 0x18 /* Unknown */
100#define MCE_CMD_UNKNOWN8 0x19 /* Unknown */
101#define MCE_CMD_UNKNOWN9 0x1b /* Unknown */
102#define MCE_CMD_DEVICE_RESET 0xaa /* Reset the hardware */
103#define MCE_RSP_CMD_INVALID 0xfe /* Invalid command issued */
104
105
106/* module parameters */
107#ifdef CONFIG_USB_DEBUG
108static int debug = 1;
109#else
110static int debug;
111#endif
112
113/* general constants */
114#define SEND_FLAG_IN_PROGRESS 1
115#define SEND_FLAG_COMPLETE 2
116#define RECV_FLAG_IN_PROGRESS 3
117#define RECV_FLAG_COMPLETE 4
118
119#define MCEUSB_RX 1
120#define MCEUSB_TX 2
121
122#define VENDOR_PHILIPS 0x0471
123#define VENDOR_SMK 0x0609
124#define VENDOR_TATUNG 0x1460
125#define VENDOR_GATEWAY 0x107b
126#define VENDOR_SHUTTLE 0x1308
127#define VENDOR_SHUTTLE2 0x051c
128#define VENDOR_MITSUMI 0x03ee
129#define VENDOR_TOPSEED 0x1784
130#define VENDOR_RICAVISION 0x179d
131#define VENDOR_ITRON 0x195d
132#define VENDOR_FIC 0x1509
133#define VENDOR_LG 0x043e
134#define VENDOR_MICROSOFT 0x045e
135#define VENDOR_FORMOSA 0x147a
136#define VENDOR_FINTEK 0x1934
137#define VENDOR_PINNACLE 0x2304
138#define VENDOR_ECS 0x1019
139#define VENDOR_WISTRON 0x0fb8
140#define VENDOR_COMPRO 0x185b
141#define VENDOR_NORTHSTAR 0x04eb
142#define VENDOR_REALTEK 0x0bda
143#define VENDOR_TIVO 0x105a
144#define VENDOR_CONEXANT 0x0572
145
146enum mceusb_model_type {
147 MCE_GEN2 = 0, /* Most boards */
148 MCE_GEN1,
149 MCE_GEN3,
150 MCE_GEN2_TX_INV,
151 POLARIS_EVK,
152 CX_HYBRID_TV,
153};
154
155struct mceusb_model {
156 u32 mce_gen1:1;
157 u32 mce_gen2:1;
158 u32 mce_gen3:1;
159 u32 tx_mask_normal:1;
160 u32 is_polaris:1;
161 u32 no_tx:1;
162
163 const char *rc_map; /* Allow specify a per-board map */
164 const char *name; /* per-board name */
165};
166
167static const struct mceusb_model mceusb_model[] = {
168 [MCE_GEN1] = {
169 .mce_gen1 = 1,
170 .tx_mask_normal = 1,
171 },
172 [MCE_GEN2] = {
173 .mce_gen2 = 1,
174 },
175 [MCE_GEN2_TX_INV] = {
176 .mce_gen2 = 1,
177 .tx_mask_normal = 1,
178 },
179 [MCE_GEN3] = {
180 .mce_gen3 = 1,
181 .tx_mask_normal = 1,
182 },
183 [POLARIS_EVK] = {
184 .is_polaris = 1,
185 /*
186 * In fact, the EVK is shipped without
187 * remotes, but we should have something handy,
188 * to allow testing it
189 */
190 .rc_map = RC_MAP_RC5_HAUPPAUGE_NEW,
191 .name = "Conexant Hybrid TV (cx231xx) MCE IR",
192 },
193 [CX_HYBRID_TV] = {
194 .is_polaris = 1,
195 .no_tx = 1, /* tx isn't wired up at all */
196 .name = "Conexant Hybrid TV (cx231xx) MCE IR",
197 },
198};
199
200static struct usb_device_id mceusb_dev_table[] = {
201 /* Original Microsoft MCE IR Transceiver (often HP-branded) */
202 { USB_DEVICE(VENDOR_MICROSOFT, 0x006d),
203 .driver_info = MCE_GEN1 },
204 /* Philips Infrared Transceiver - Sahara branded */
205 { USB_DEVICE(VENDOR_PHILIPS, 0x0608) },
206 /* Philips Infrared Transceiver - HP branded */
207 { USB_DEVICE(VENDOR_PHILIPS, 0x060c),
208 .driver_info = MCE_GEN2_TX_INV },
209 /* Philips SRM5100 */
210 { USB_DEVICE(VENDOR_PHILIPS, 0x060d) },
211 /* Philips Infrared Transceiver - Omaura */
212 { USB_DEVICE(VENDOR_PHILIPS, 0x060f) },
213 /* Philips Infrared Transceiver - Spinel plus */
214 { USB_DEVICE(VENDOR_PHILIPS, 0x0613) },
215 /* Philips eHome Infrared Transceiver */
216 { USB_DEVICE(VENDOR_PHILIPS, 0x0815) },
217 /* Philips/Spinel plus IR transceiver for ASUS */
218 { USB_DEVICE(VENDOR_PHILIPS, 0x206c) },
219 /* Philips/Spinel plus IR transceiver for ASUS */
220 { USB_DEVICE(VENDOR_PHILIPS, 0x2088) },
221 /* Realtek MCE IR Receiver */
222 { USB_DEVICE(VENDOR_REALTEK, 0x0161) },
223 /* SMK/Toshiba G83C0004D410 */
224 { USB_DEVICE(VENDOR_SMK, 0x031d),
225 .driver_info = MCE_GEN2_TX_INV },
226 /* SMK eHome Infrared Transceiver (Sony VAIO) */
227 { USB_DEVICE(VENDOR_SMK, 0x0322),
228 .driver_info = MCE_GEN2_TX_INV },
229 /* bundled with Hauppauge PVR-150 */
230 { USB_DEVICE(VENDOR_SMK, 0x0334),
231 .driver_info = MCE_GEN2_TX_INV },
232 /* SMK eHome Infrared Transceiver */
233 { USB_DEVICE(VENDOR_SMK, 0x0338) },
234 /* Tatung eHome Infrared Transceiver */
235 { USB_DEVICE(VENDOR_TATUNG, 0x9150) },
236 /* Shuttle eHome Infrared Transceiver */
237 { USB_DEVICE(VENDOR_SHUTTLE, 0xc001) },
238 /* Shuttle eHome Infrared Transceiver */
239 { USB_DEVICE(VENDOR_SHUTTLE2, 0xc001) },
240 /* Gateway eHome Infrared Transceiver */
241 { USB_DEVICE(VENDOR_GATEWAY, 0x3009) },
242 /* Mitsumi */
243 { USB_DEVICE(VENDOR_MITSUMI, 0x2501) },
244 /* Topseed eHome Infrared Transceiver */
245 { USB_DEVICE(VENDOR_TOPSEED, 0x0001),
246 .driver_info = MCE_GEN2_TX_INV },
247 /* Topseed HP eHome Infrared Transceiver */
248 { USB_DEVICE(VENDOR_TOPSEED, 0x0006),
249 .driver_info = MCE_GEN2_TX_INV },
250 /* Topseed eHome Infrared Transceiver */
251 { USB_DEVICE(VENDOR_TOPSEED, 0x0007),
252 .driver_info = MCE_GEN2_TX_INV },
253 /* Topseed eHome Infrared Transceiver */
254 { USB_DEVICE(VENDOR_TOPSEED, 0x0008),
255 .driver_info = MCE_GEN3 },
256 /* Topseed eHome Infrared Transceiver */
257 { USB_DEVICE(VENDOR_TOPSEED, 0x000a),
258 .driver_info = MCE_GEN2_TX_INV },
259 /* Topseed eHome Infrared Transceiver */
260 { USB_DEVICE(VENDOR_TOPSEED, 0x0011),
261 .driver_info = MCE_GEN2_TX_INV },
262 /* Ricavision internal Infrared Transceiver */
263 { USB_DEVICE(VENDOR_RICAVISION, 0x0010) },
264 /* Itron ione Libra Q-11 */
265 { USB_DEVICE(VENDOR_ITRON, 0x7002) },
266 /* FIC eHome Infrared Transceiver */
267 { USB_DEVICE(VENDOR_FIC, 0x9242) },
268 /* LG eHome Infrared Transceiver */
269 { USB_DEVICE(VENDOR_LG, 0x9803) },
270 /* Microsoft MCE Infrared Transceiver */
271 { USB_DEVICE(VENDOR_MICROSOFT, 0x00a0) },
272 /* Formosa eHome Infrared Transceiver */
273 { USB_DEVICE(VENDOR_FORMOSA, 0xe015) },
274 /* Formosa21 / eHome Infrared Receiver */
275 { USB_DEVICE(VENDOR_FORMOSA, 0xe016) },
276 /* Formosa aim / Trust MCE Infrared Receiver */
277 { USB_DEVICE(VENDOR_FORMOSA, 0xe017) },
278 /* Formosa Industrial Computing / Beanbag Emulation Device */
279 { USB_DEVICE(VENDOR_FORMOSA, 0xe018) },
280 /* Formosa21 / eHome Infrared Receiver */
281 { USB_DEVICE(VENDOR_FORMOSA, 0xe03a) },
282 /* Formosa Industrial Computing AIM IR605/A */
283 { USB_DEVICE(VENDOR_FORMOSA, 0xe03c) },
284 /* Formosa Industrial Computing */
285 { USB_DEVICE(VENDOR_FORMOSA, 0xe03e) },
286 /* Fintek eHome Infrared Transceiver (HP branded) */
287 { USB_DEVICE(VENDOR_FINTEK, 0x5168) },
288 /* Fintek eHome Infrared Transceiver */
289 { USB_DEVICE(VENDOR_FINTEK, 0x0602) },
290 /* Fintek eHome Infrared Transceiver (in the AOpen MP45) */
291 { USB_DEVICE(VENDOR_FINTEK, 0x0702) },
292 /* Pinnacle Remote Kit */
293 { USB_DEVICE(VENDOR_PINNACLE, 0x0225),
294 .driver_info = MCE_GEN3 },
295 /* Elitegroup Computer Systems IR */
296 { USB_DEVICE(VENDOR_ECS, 0x0f38) },
297 /* Wistron Corp. eHome Infrared Receiver */
298 { USB_DEVICE(VENDOR_WISTRON, 0x0002) },
299 /* Compro K100 */
300 { USB_DEVICE(VENDOR_COMPRO, 0x3020) },
301 /* Compro K100 v2 */
302 { USB_DEVICE(VENDOR_COMPRO, 0x3082) },
303 /* Northstar Systems, Inc. eHome Infrared Transceiver */
304 { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) },
305 /* TiVo PC IR Receiver */
306 { USB_DEVICE(VENDOR_TIVO, 0x2000) },
307 /* Conexant Hybrid TV "Shelby" Polaris SDK */
308 { USB_DEVICE(VENDOR_CONEXANT, 0x58a1),
309 .driver_info = POLARIS_EVK },
310 /* Conexant Hybrid TV RDU253S Polaris */
311 { USB_DEVICE(VENDOR_CONEXANT, 0x58a5),
312 .driver_info = CX_HYBRID_TV },
313 /* Terminating entry */
314 { }
315};
316
317/* data structure for each usb transceiver */
318struct mceusb_dev {
319 /* ir-core bits */
320 struct ir_dev_props *props;
321
322 /* optional features we can enable */
323 bool carrier_report_enabled;
324 bool learning_enabled;
325
326 /* core device bits */
327 struct device *dev;
328 struct input_dev *idev;
329
330 /* usb */
331 struct usb_device *usbdev;
332 struct urb *urb_in;
333 struct usb_endpoint_descriptor *usb_ep_in;
334 struct usb_endpoint_descriptor *usb_ep_out;
335
336 /* buffers and dma */
337 unsigned char *buf_in;
338 unsigned int len_in;
339 dma_addr_t dma_in;
340 dma_addr_t dma_out;
341
342 enum {
343 CMD_HEADER = 0,
344 SUBCMD,
345 CMD_DATA,
346 PARSE_IRDATA,
347 } parser_state;
348
349 u8 cmd, rem; /* Remaining IR data bytes in packet */
350
351 struct {
352 u32 connected:1;
353 u32 tx_mask_normal:1;
354 u32 microsoft_gen1:1;
355 u32 no_tx:1;
356 } flags;
357
358 /* transmit support */
359 int send_flags;
360 u32 carrier;
361 unsigned char tx_mask;
362
363 char name[128];
364 char phys[64];
365 enum mceusb_model_type model;
366};
367
368/*
369 * MCE Device Command Strings
370 * Device command responses vary from device to device...
371 * - DEVICE_RESET resets the hardware to its default state
372 * - GET_REVISION fetches the hardware/software revision, common
373 * replies are ff 0b 45 ff 1b 08 and ff 0b 50 ff 1b 42
374 * - GET_CARRIER_FREQ gets the carrier mode and frequency of the
375 * device, with replies in the form of 9f 06 MM FF, where MM is 0-3,
376 * meaning clk of 10000000, 2500000, 625000 or 156250, and FF is
377 * ((clk / frequency) - 1)
378 * - GET_RX_TIMEOUT fetches the receiver timeout in units of 50us,
379 * response in the form of 9f 0c msb lsb
380 * - GET_TX_BITMASK fetches the transmitter bitmask, replies in
381 * the form of 9f 08 bm, where bm is the bitmask
382 * - GET_RX_SENSOR fetches the RX sensor setting -- long-range
383 * general use one or short-range learning one, in the form of
384 * 9f 14 ss, where ss is either 01 for long-range or 02 for short
385 * - SET_CARRIER_FREQ sets a new carrier mode and frequency
386 * - SET_TX_BITMASK sets the transmitter bitmask
387 * - SET_RX_TIMEOUT sets the receiver timeout
388 * - SET_RX_SENSOR sets which receiver sensor to use
389 */
390static char DEVICE_RESET[] = {MCE_COMMAND_NULL, MCE_HW_CMD_HEADER,
391 MCE_CMD_DEVICE_RESET};
392static char GET_REVISION[] = {MCE_HW_CMD_HEADER, MCE_CMD_G_REVISION};
393static char GET_UNKNOWN[] = {MCE_HW_CMD_HEADER, MCE_CMD_UNKNOWN7};
394static char GET_UNKNOWN2[] = {MCE_COMMAND_HEADER, MCE_CMD_UNKNOWN2};
395static char GET_CARRIER_FREQ[] = {MCE_COMMAND_HEADER, MCE_CMD_G_CARRIER};
396static char GET_RX_TIMEOUT[] = {MCE_COMMAND_HEADER, MCE_CMD_G_TIMEOUT};
397static char GET_TX_BITMASK[] = {MCE_COMMAND_HEADER, MCE_CMD_G_TXMASK};
398static char GET_RX_SENSOR[] = {MCE_COMMAND_HEADER, MCE_CMD_G_RXSENSOR};
399/* sub in desired values in lower byte or bytes for full command */
400/* FIXME: make use of these for transmit.
401static char SET_CARRIER_FREQ[] = {MCE_COMMAND_HEADER,
402 MCE_CMD_S_CARRIER, 0x00, 0x00};
403static char SET_TX_BITMASK[] = {MCE_COMMAND_HEADER, MCE_CMD_S_TXMASK, 0x00};
404static char SET_RX_TIMEOUT[] = {MCE_COMMAND_HEADER,
405 MCE_CMD_S_TIMEOUT, 0x00, 0x00};
406static char SET_RX_SENSOR[] = {MCE_COMMAND_HEADER,
407 MCE_CMD_S_RXSENSOR, 0x00};
408*/
409
410static int mceusb_cmdsize(u8 cmd, u8 subcmd)
411{
412 int datasize = 0;
413
414 switch (cmd) {
415 case MCE_COMMAND_NULL:
416 if (subcmd == MCE_HW_CMD_HEADER)
417 datasize = 1;
418 break;
419 case MCE_HW_CMD_HEADER:
420 switch (subcmd) {
421 case MCE_CMD_G_REVISION:
422 datasize = 2;
423 break;
424 }
425 case MCE_COMMAND_HEADER:
426 switch (subcmd) {
427 case MCE_CMD_UNKNOWN:
428 case MCE_CMD_S_CARRIER:
429 case MCE_CMD_S_TIMEOUT:
430 case MCE_RSP_PULSE_COUNT:
431 datasize = 2;
432 break;
433 case MCE_CMD_SIG_END:
434 case MCE_CMD_S_TXMASK:
435 case MCE_CMD_S_RXSENSOR:
436 datasize = 1;
437 break;
438 }
439 }
440 return datasize;
441}
442
443static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
444 int offset, int len, bool out)
445{
446 char codes[USB_BUFLEN * 3 + 1];
447 char inout[9];
448 u8 cmd, subcmd, data1, data2;
449 struct device *dev = ir->dev;
450 int i, start, skip = 0;
451
452 if (!debug)
453 return;
454
455 /* skip meaningless 0xb1 0x60 header bytes on orig receiver */
456 if (ir->flags.microsoft_gen1 && !out && !offset)
457 skip = 2;
458
459 if (len <= skip)
460 return;
461
462 for (i = 0; i < len && i < USB_BUFLEN; i++)
463 snprintf(codes + i * 3, 4, "%02x ", buf[i + offset] & 0xff);
464
465 dev_info(dev, "%sx data: %s(length=%d)\n",
466 (out ? "t" : "r"), codes, len);
467
468 if (out)
469 strcpy(inout, "Request\0");
470 else
471 strcpy(inout, "Got\0");
472
473 start = offset + skip;
474 cmd = buf[start] & 0xff;
475 subcmd = buf[start + 1] & 0xff;
476 data1 = buf[start + 2] & 0xff;
477 data2 = buf[start + 3] & 0xff;
478
479 switch (cmd) {
480 case MCE_COMMAND_NULL:
481 if ((subcmd == MCE_HW_CMD_HEADER) &&
482 (data1 == MCE_CMD_DEVICE_RESET))
483 dev_info(dev, "Device reset requested\n");
484 else
485 dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
486 cmd, subcmd);
487 break;
488 case MCE_HW_CMD_HEADER:
489 switch (subcmd) {
490 case MCE_CMD_G_REVISION:
491 if (len == 2)
492 dev_info(dev, "Get hw/sw rev?\n");
493 else
494 dev_info(dev, "hw/sw rev 0x%02x 0x%02x "
495 "0x%02x 0x%02x\n", data1, data2,
496 buf[start + 4], buf[start + 5]);
497 break;
498 case MCE_CMD_DEVICE_RESET:
499 dev_info(dev, "Device reset requested\n");
500 break;
501 case MCE_RSP_CMD_INVALID:
502 dev_info(dev, "Previous command not supported\n");
503 break;
504 case MCE_CMD_UNKNOWN7:
505 case MCE_CMD_UNKNOWN9:
506 default:
507 dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
508 cmd, subcmd);
509 break;
510 }
511 break;
512 case MCE_COMMAND_HEADER:
513 switch (subcmd) {
514 case MCE_CMD_SIG_END:
515 dev_info(dev, "End of signal\n");
516 break;
517 case MCE_CMD_PING:
518 dev_info(dev, "Ping\n");
519 break;
520 case MCE_CMD_UNKNOWN:
521 dev_info(dev, "Resp to 9f 05 of 0x%02x 0x%02x\n",
522 data1, data2);
523 break;
524 case MCE_CMD_S_CARRIER:
525 dev_info(dev, "%s carrier mode and freq of "
526 "0x%02x 0x%02x\n", inout, data1, data2);
527 break;
528 case MCE_CMD_G_CARRIER:
529 dev_info(dev, "Get carrier mode and freq\n");
530 break;
531 case MCE_CMD_S_TXMASK:
532 dev_info(dev, "%s transmit blaster mask of 0x%02x\n",
533 inout, data1);
534 break;
535 case MCE_CMD_S_TIMEOUT:
536 /* value is in units of 50us, so x*50/100 or x/2 ms */
537 dev_info(dev, "%s receive timeout of %d ms\n",
538 inout, ((data1 << 8) | data2) / 2);
539 break;
540 case MCE_CMD_G_TIMEOUT:
541 dev_info(dev, "Get receive timeout\n");
542 break;
543 case MCE_CMD_G_TXMASK:
544 dev_info(dev, "Get transmit blaster mask\n");
545 break;
546 case MCE_CMD_S_RXSENSOR:
547 dev_info(dev, "%s %s-range receive sensor in use\n",
548 inout, data1 == 0x02 ? "short" : "long");
549 break;
550 case MCE_CMD_G_RXSENSOR:
551 /* aka MCE_RSP_PULSE_COUNT */
552 if (out)
553 dev_info(dev, "Get receive sensor\n");
554 else if (ir->learning_enabled)
555 dev_info(dev, "RX pulse count: %d\n",
556 ((data1 << 8) | data2));
557 break;
558 case MCE_RSP_CMD_INVALID:
559 dev_info(dev, "Error! Hardware is likely wedged...\n");
560 break;
561 case MCE_CMD_UNKNOWN2:
562 case MCE_CMD_UNKNOWN3:
563 case MCE_CMD_UNKNOWN5:
564 default:
565 dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
566 cmd, subcmd);
567 break;
568 }
569 break;
570 default:
571 break;
572 }
573
574 if (cmd == MCE_IRDATA_TRAILER)
575 dev_info(dev, "End of raw IR data\n");
576 else if ((cmd != MCE_COMMAND_HEADER) &&
577 ((cmd & MCE_COMMAND_MASK) == MCE_COMMAND_IRDATA))
578 dev_info(dev, "Raw IR data, %d pulse/space samples\n", ir->rem);
579}
580
581static void mce_async_callback(struct urb *urb, struct pt_regs *regs)
582{
583 struct mceusb_dev *ir;
584 int len;
585
586 if (!urb)
587 return;
588
589 ir = urb->context;
590 if (ir) {
591 len = urb->actual_length;
592
593 dev_dbg(ir->dev, "callback called (status=%d len=%d)\n",
594 urb->status, len);
595
596 mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true);
597 }
598
599}
600
601/* request incoming or send outgoing usb packet - used to initialize remote */
602static void mce_request_packet(struct mceusb_dev *ir,
603 struct usb_endpoint_descriptor *ep,
604 unsigned char *data, int size, int urb_type)
605{
606 int res;
607 struct urb *async_urb;
608 struct device *dev = ir->dev;
609 unsigned char *async_buf;
610
611 if (urb_type == MCEUSB_TX) {
612 async_urb = usb_alloc_urb(0, GFP_KERNEL);
613 if (unlikely(!async_urb)) {
614 dev_err(dev, "Error, couldn't allocate urb!\n");
615 return;
616 }
617
618 async_buf = kzalloc(size, GFP_KERNEL);
619 if (!async_buf) {
620 dev_err(dev, "Error, couldn't allocate buf!\n");
621 usb_free_urb(async_urb);
622 return;
623 }
624
625 /* outbound data */
626 usb_fill_int_urb(async_urb, ir->usbdev,
627 usb_sndintpipe(ir->usbdev, ep->bEndpointAddress),
628 async_buf, size, (usb_complete_t)mce_async_callback,
629 ir, ep->bInterval);
630 memcpy(async_buf, data, size);
631
632 } else if (urb_type == MCEUSB_RX) {
633 /* standard request */
634 async_urb = ir->urb_in;
635 ir->send_flags = RECV_FLAG_IN_PROGRESS;
636
637 } else {
638 dev_err(dev, "Error! Unknown urb type %d\n", urb_type);
639 return;
640 }
641
642 dev_dbg(dev, "receive request called (size=%#x)\n", size);
643
644 async_urb->transfer_buffer_length = size;
645 async_urb->dev = ir->usbdev;
646
647 res = usb_submit_urb(async_urb, GFP_ATOMIC);
648 if (res) {
649 dev_dbg(dev, "receive request FAILED! (res=%d)\n", res);
650 return;
651 }
652 dev_dbg(dev, "receive request complete (res=%d)\n", res);
653}
654
655static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
656{
657 mce_request_packet(ir, ir->usb_ep_out, data, size, MCEUSB_TX);
658}
659
660static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size)
661{
662 mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_RX);
663}
664
665/* Send data out the IR blaster port(s) */
666static int mceusb_tx_ir(void *priv, int *txbuf, u32 n)
667{
668 struct mceusb_dev *ir = priv;
669 int i, ret = 0;
670 int count, cmdcount = 0;
671 unsigned char *cmdbuf; /* MCE command buffer */
672 long signal_duration = 0; /* Singnal length in us */
673 struct timeval start_time, end_time;
674
675 do_gettimeofday(&start_time);
676
677 count = n / sizeof(int);
678
679 cmdbuf = kzalloc(sizeof(int) * MCE_CMDBUF_SIZE, GFP_KERNEL);
680 if (!cmdbuf)
681 return -ENOMEM;
682
683 /* MCE tx init header */
684 cmdbuf[cmdcount++] = MCE_COMMAND_HEADER;
685 cmdbuf[cmdcount++] = MCE_CMD_S_TXMASK;
686 cmdbuf[cmdcount++] = ir->tx_mask;
687
688 /* Generate mce packet data */
689 for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) {
690 signal_duration += txbuf[i];
691 txbuf[i] = txbuf[i] / MCE_TIME_UNIT;
692
693 do { /* loop to support long pulses/spaces > 127*50us=6.35ms */
694
695 /* Insert mce packet header every 4th entry */
696 if ((cmdcount < MCE_CMDBUF_SIZE) &&
697 (cmdcount - MCE_TX_HEADER_LENGTH) %
698 MCE_CODE_LENGTH == 0)
699 cmdbuf[cmdcount++] = MCE_IRDATA_HEADER;
700
701 /* Insert mce packet data */
702 if (cmdcount < MCE_CMDBUF_SIZE)
703 cmdbuf[cmdcount++] =
704 (txbuf[i] < MCE_PULSE_BIT ?
705 txbuf[i] : MCE_MAX_PULSE_LENGTH) |
706 (i & 1 ? 0x00 : MCE_PULSE_BIT);
707 else {
708 ret = -EINVAL;
709 goto out;
710 }
711
712 } while ((txbuf[i] > MCE_MAX_PULSE_LENGTH) &&
713 (txbuf[i] -= MCE_MAX_PULSE_LENGTH));
714 }
715
716 /* Fix packet length in last header */
717 cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] =
718 MCE_COMMAND_IRDATA + (cmdcount - MCE_TX_HEADER_LENGTH) %
719 MCE_CODE_LENGTH - 1;
720
721 /* Check if we have room for the empty packet at the end */
722 if (cmdcount >= MCE_CMDBUF_SIZE) {
723 ret = -EINVAL;
724 goto out;
725 }
726
727 /* All mce commands end with an empty packet (0x80) */
728 cmdbuf[cmdcount++] = MCE_IRDATA_TRAILER;
729
730 /* Transmit the command to the mce device */
731 mce_async_out(ir, cmdbuf, cmdcount);
732
733 /*
734 * The lircd gap calculation expects the write function to
735 * wait the time it takes for the ircommand to be sent before
736 * it returns.
737 */
738 do_gettimeofday(&end_time);
739 signal_duration -= (end_time.tv_usec - start_time.tv_usec) +
740 (end_time.tv_sec - start_time.tv_sec) * 1000000;
741
742 /* delay with the closest number of ticks */
743 set_current_state(TASK_INTERRUPTIBLE);
744 schedule_timeout(usecs_to_jiffies(signal_duration));
745
746out:
747 kfree(cmdbuf);
748 return ret ? ret : n;
749}
750
751/* Sets active IR outputs -- mce devices typically have two */
752static int mceusb_set_tx_mask(void *priv, u32 mask)
753{
754 struct mceusb_dev *ir = priv;
755
756 if (ir->flags.tx_mask_normal)
757 ir->tx_mask = mask;
758 else
759 ir->tx_mask = (mask != MCE_DEFAULT_TX_MASK ?
760 mask ^ MCE_DEFAULT_TX_MASK : mask) << 1;
761
762 return 0;
763}
764
765/* Sets the send carrier frequency and mode */
766static int mceusb_set_tx_carrier(void *priv, u32 carrier)
767{
768 struct mceusb_dev *ir = priv;
769 int clk = 10000000;
770 int prescaler = 0, divisor = 0;
771 unsigned char cmdbuf[4] = { MCE_COMMAND_HEADER,
772 MCE_CMD_S_CARRIER, 0x00, 0x00 };
773
774 /* Carrier has changed */
775 if (ir->carrier != carrier) {
776
777 if (carrier == 0) {
778 ir->carrier = carrier;
779 cmdbuf[2] = MCE_CMD_SIG_END;
780 cmdbuf[3] = MCE_IRDATA_TRAILER;
781 dev_dbg(ir->dev, "%s: disabling carrier "
782 "modulation\n", __func__);
783 mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
784 return carrier;
785 }
786
787 for (prescaler = 0; prescaler < 4; ++prescaler) {
788 divisor = (clk >> (2 * prescaler)) / carrier;
789 if (divisor <= 0xff) {
790 ir->carrier = carrier;
791 cmdbuf[2] = prescaler;
792 cmdbuf[3] = divisor;
793 dev_dbg(ir->dev, "%s: requesting %u HZ "
794 "carrier\n", __func__, carrier);
795
796 /* Transmit new carrier to mce device */
797 mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
798 return carrier;
799 }
800 }
801
802 return -EINVAL;
803
804 }
805
806 return carrier;
807}
808
809/*
810 * We don't do anything but print debug spew for many of the command bits
811 * we receive from the hardware, but some of them are useful information
812 * we want to store so that we can use them.
813 */
814static void mceusb_handle_command(struct mceusb_dev *ir, int index)
815{
816 u8 hi = ir->buf_in[index + 1] & 0xff;
817 u8 lo = ir->buf_in[index + 2] & 0xff;
818
819 switch (ir->buf_in[index]) {
820 /* 2-byte return value commands */
821 case MCE_CMD_S_TIMEOUT:
822 ir->props->timeout = MS_TO_NS((hi << 8 | lo) / 2);
823 break;
824
825 /* 1-byte return value commands */
826 case MCE_CMD_S_TXMASK:
827 ir->tx_mask = hi;
828 break;
829 case MCE_CMD_S_RXSENSOR:
830 ir->learning_enabled = (hi == 0x02);
831 break;
832 default:
833 break;
834 }
835}
836
837static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
838{
839 DEFINE_IR_RAW_EVENT(rawir);
840 int i = 0;
841
842 /* skip meaningless 0xb1 0x60 header bytes on orig receiver */
843 if (ir->flags.microsoft_gen1)
844 i = 2;
845
846 /* if there's no data, just return now */
847 if (buf_len <= i)
848 return;
849
850 for (; i < buf_len; i++) {
851 switch (ir->parser_state) {
852 case SUBCMD:
853 ir->rem = mceusb_cmdsize(ir->cmd, ir->buf_in[i]);
854 mceusb_dev_printdata(ir, ir->buf_in, i - 1,
855 ir->rem + 2, false);
856 mceusb_handle_command(ir, i);
857 ir->parser_state = CMD_DATA;
858 break;
859 case PARSE_IRDATA:
860 ir->rem--;
861 rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);
862 rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
863 * MS_TO_NS(MCE_TIME_UNIT);
864
865 dev_dbg(ir->dev, "Storing %s with duration %d\n",
866 rawir.pulse ? "pulse" : "space",
867 rawir.duration);
868
869 ir_raw_event_store_with_filter(ir->idev, &rawir);
870 break;
871 case CMD_DATA:
872 ir->rem--;
873 break;
874 case CMD_HEADER:
875 /* decode mce packets of the form (84),AA,BB,CC,DD */
876 /* IR data packets can span USB messages - rem */
877 ir->cmd = ir->buf_in[i];
878 if ((ir->cmd == MCE_COMMAND_HEADER) ||
879 ((ir->cmd & MCE_COMMAND_MASK) !=
880 MCE_COMMAND_IRDATA)) {
881 ir->parser_state = SUBCMD;
882 continue;
883 }
884 ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK);
885 mceusb_dev_printdata(ir, ir->buf_in,
886 i, ir->rem + 1, false);
887 if (ir->rem)
888 ir->parser_state = PARSE_IRDATA;
889 break;
890 }
891
892 if (ir->parser_state != CMD_HEADER && !ir->rem)
893 ir->parser_state = CMD_HEADER;
894 }
895 dev_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n");
896 ir_raw_event_handle(ir->idev);
897}
898
899static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
900{
901 struct mceusb_dev *ir;
902 int buf_len;
903
904 if (!urb)
905 return;
906
907 ir = urb->context;
908 if (!ir) {
909 usb_unlink_urb(urb);
910 return;
911 }
912
913 buf_len = urb->actual_length;
914
915 if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
916 ir->send_flags = SEND_FLAG_COMPLETE;
917 dev_dbg(ir->dev, "setup answer received %d bytes\n",
918 buf_len);
919 }
920
921 switch (urb->status) {
922 /* success */
923 case 0:
924 mceusb_process_ir_data(ir, buf_len);
925 break;
926
927 case -ECONNRESET:
928 case -ENOENT:
929 case -ESHUTDOWN:
930 usb_unlink_urb(urb);
931 return;
932
933 case -EPIPE:
934 default:
935 dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status);
936 break;
937 }
938
939 usb_submit_urb(urb, GFP_ATOMIC);
940}
941
942static void mceusb_gen1_init(struct mceusb_dev *ir)
943{
944 int ret;
945 int maxp = ir->len_in;
946 struct device *dev = ir->dev;
947 char *data;
948
949 data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL);
950 if (!data) {
951 dev_err(dev, "%s: memory allocation failed!\n", __func__);
952 return;
953 }
954
955 /*
956 * This is a strange one. Windows issues a set address to the device
957 * on the receive control pipe and expect a certain value pair back
958 */
959 ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
960 USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,
961 data, USB_CTRL_MSG_SZ, HZ * 3);
962 dev_dbg(dev, "%s - ret = %d\n", __func__, ret);
963 dev_dbg(dev, "%s - data[0] = %d, data[1] = %d\n",
964 __func__, data[0], data[1]);
965
966 /* set feature: bit rate 38400 bps */
967 ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
968 USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
969 0xc04e, 0x0000, NULL, 0, HZ * 3);
970
971 dev_dbg(dev, "%s - ret = %d\n", __func__, ret);
972
973 /* bRequest 4: set char length to 8 bits */
974 ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
975 4, USB_TYPE_VENDOR,
976 0x0808, 0x0000, NULL, 0, HZ * 3);
977 dev_dbg(dev, "%s - retB = %d\n", __func__, ret);
978
979 /* bRequest 2: set handshaking to use DTR/DSR */
980 ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
981 2, USB_TYPE_VENDOR,
982 0x0000, 0x0100, NULL, 0, HZ * 3);
983 dev_dbg(dev, "%s - retC = %d\n", __func__, ret);
984
985 /* device reset */
986 mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
987 mce_sync_in(ir, NULL, maxp);
988
989 /* get hw/sw revision? */
990 mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
991 mce_sync_in(ir, NULL, maxp);
992
993 kfree(data);
994};
995
996static void mceusb_gen2_init(struct mceusb_dev *ir)
997{
998 int maxp = ir->len_in;
999
1000 /* device reset */
1001 mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
1002 mce_sync_in(ir, NULL, maxp);
1003
1004 /* get hw/sw revision? */
1005 mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
1006 mce_sync_in(ir, NULL, maxp);
1007
1008 /* unknown what the next two actually return... */
1009 mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN));
1010 mce_sync_in(ir, NULL, maxp);
1011 mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2));
1012 mce_sync_in(ir, NULL, maxp);
1013}
1014
1015static void mceusb_get_parameters(struct mceusb_dev *ir)
1016{
1017 int maxp = ir->len_in;
1018
1019 /* get the carrier and frequency */
1020 mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ));
1021 mce_sync_in(ir, NULL, maxp);
1022
1023 if (!ir->flags.no_tx) {
1024 /* get the transmitter bitmask */
1025 mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK));
1026 mce_sync_in(ir, NULL, maxp);
1027 }
1028
1029 /* get receiver timeout value */
1030 mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT));
1031 mce_sync_in(ir, NULL, maxp);
1032
1033 /* get receiver sensor setting */
1034 mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR));
1035 mce_sync_in(ir, NULL, maxp);
1036}
1037
1038static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
1039{
1040 struct input_dev *idev;
1041 struct ir_dev_props *props;
1042 struct device *dev = ir->dev;
1043 const char *rc_map = RC_MAP_RC6_MCE;
1044 const char *name = "Media Center Ed. eHome Infrared Remote Transceiver";
1045 int ret = -ENODEV;
1046
1047 idev = input_allocate_device();
1048 if (!idev) {
1049 dev_err(dev, "remote input dev allocation failed\n");
1050 goto idev_alloc_failed;
1051 }
1052
1053 ret = -ENOMEM;
1054 props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
1055 if (!props) {
1056 dev_err(dev, "remote ir dev props allocation failed\n");
1057 goto props_alloc_failed;
1058 }
1059
1060 if (mceusb_model[ir->model].name)
1061 name = mceusb_model[ir->model].name;
1062
1063 snprintf(ir->name, sizeof(ir->name), "%s (%04x:%04x)",
1064 name,
1065 le16_to_cpu(ir->usbdev->descriptor.idVendor),
1066 le16_to_cpu(ir->usbdev->descriptor.idProduct));
1067
1068 idev->name = ir->name;
1069 usb_make_path(ir->usbdev, ir->phys, sizeof(ir->phys));
1070 strlcat(ir->phys, "/input0", sizeof(ir->phys));
1071 idev->phys = ir->phys;
1072
1073 props->priv = ir;
1074 props->driver_type = RC_DRIVER_IR_RAW;
1075 props->allowed_protos = IR_TYPE_ALL;
1076 props->timeout = MS_TO_NS(1000);
1077 if (!ir->flags.no_tx) {
1078 props->s_tx_mask = mceusb_set_tx_mask;
1079 props->s_tx_carrier = mceusb_set_tx_carrier;
1080 props->tx_ir = mceusb_tx_ir;
1081 }
1082
1083 ir->props = props;
1084
1085 usb_to_input_id(ir->usbdev, &idev->id);
1086 idev->dev.parent = ir->dev;
1087
1088 if (mceusb_model[ir->model].rc_map)
1089 rc_map = mceusb_model[ir->model].rc_map;
1090
1091 ret = ir_input_register(idev, rc_map, props, DRIVER_NAME);
1092 if (ret < 0) {
1093 dev_err(dev, "remote input device register failed\n");
1094 goto irdev_failed;
1095 }
1096
1097 return idev;
1098
1099irdev_failed:
1100 kfree(props);
1101props_alloc_failed:
1102 input_free_device(idev);
1103idev_alloc_failed:
1104 return NULL;
1105}
1106
1107static int __devinit mceusb_dev_probe(struct usb_interface *intf,
1108 const struct usb_device_id *id)
1109{
1110 struct usb_device *dev = interface_to_usbdev(intf);
1111 struct usb_host_interface *idesc;
1112 struct usb_endpoint_descriptor *ep = NULL;
1113 struct usb_endpoint_descriptor *ep_in = NULL;
1114 struct usb_endpoint_descriptor *ep_out = NULL;
1115 struct mceusb_dev *ir = NULL;
1116 int pipe, maxp, i;
1117 char buf[63], name[128] = "";
1118 enum mceusb_model_type model = id->driver_info;
1119 bool is_gen3;
1120 bool is_microsoft_gen1;
1121 bool tx_mask_normal;
1122 bool is_polaris;
1123
1124 dev_dbg(&intf->dev, "%s called\n", __func__);
1125
1126 idesc = intf->cur_altsetting;
1127
1128 is_gen3 = mceusb_model[model].mce_gen3;
1129 is_microsoft_gen1 = mceusb_model[model].mce_gen1;
1130 tx_mask_normal = mceusb_model[model].tx_mask_normal;
1131 is_polaris = mceusb_model[model].is_polaris;
1132
1133 if (is_polaris) {
1134 /* Interface 0 is IR */
1135 if (idesc->desc.bInterfaceNumber)
1136 return -ENODEV;
1137 }
1138
1139 /* step through the endpoints to find first bulk in and out endpoint */
1140 for (i = 0; i < idesc->desc.bNumEndpoints; ++i) {
1141 ep = &idesc->endpoint[i].desc;
1142
1143 if ((ep_in == NULL)
1144 && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
1145 == USB_DIR_IN)
1146 && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1147 == USB_ENDPOINT_XFER_BULK)
1148 || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1149 == USB_ENDPOINT_XFER_INT))) {
1150
1151 ep_in = ep;
1152 ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;
1153 ep_in->bInterval = 1;
1154 dev_dbg(&intf->dev, "acceptable inbound endpoint "
1155 "found\n");
1156 }
1157
1158 if ((ep_out == NULL)
1159 && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
1160 == USB_DIR_OUT)
1161 && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1162 == USB_ENDPOINT_XFER_BULK)
1163 || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1164 == USB_ENDPOINT_XFER_INT))) {
1165
1166 ep_out = ep;
1167 ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;
1168 ep_out->bInterval = 1;
1169 dev_dbg(&intf->dev, "acceptable outbound endpoint "
1170 "found\n");
1171 }
1172 }
1173 if (ep_in == NULL) {
1174 dev_dbg(&intf->dev, "inbound and/or endpoint not found\n");
1175 return -ENODEV;
1176 }
1177
1178 pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress);
1179 maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
1180
1181 ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL);
1182 if (!ir)
1183 goto mem_alloc_fail;
1184
1185 ir->buf_in = usb_alloc_coherent(dev, maxp, GFP_ATOMIC, &ir->dma_in);
1186 if (!ir->buf_in)
1187 goto buf_in_alloc_fail;
1188
1189 ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
1190 if (!ir->urb_in)
1191 goto urb_in_alloc_fail;
1192
1193 ir->usbdev = dev;
1194 ir->dev = &intf->dev;
1195 ir->len_in = maxp;
1196 ir->flags.microsoft_gen1 = is_microsoft_gen1;
1197 ir->flags.tx_mask_normal = tx_mask_normal;
1198 ir->flags.no_tx = mceusb_model[model].no_tx;
1199 ir->model = model;
1200
1201 /* Saving usb interface data for use by the transmitter routine */
1202 ir->usb_ep_in = ep_in;
1203 ir->usb_ep_out = ep_out;
1204
1205 if (dev->descriptor.iManufacturer
1206 && usb_string(dev, dev->descriptor.iManufacturer,
1207 buf, sizeof(buf)) > 0)
1208 strlcpy(name, buf, sizeof(name));
1209 if (dev->descriptor.iProduct
1210 && usb_string(dev, dev->descriptor.iProduct,
1211 buf, sizeof(buf)) > 0)
1212 snprintf(name + strlen(name), sizeof(name) - strlen(name),
1213 " %s", buf);
1214
1215 ir->idev = mceusb_init_input_dev(ir);
1216 if (!ir->idev)
1217 goto input_dev_fail;
1218
1219 /* flush buffers on the device */
1220 mce_sync_in(ir, NULL, maxp);
1221 mce_sync_in(ir, NULL, maxp);
1222
1223 /* wire up inbound data handler */
1224 usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in,
1225 maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval);
1226 ir->urb_in->transfer_dma = ir->dma_in;
1227 ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1228
1229 /* initialize device */
1230 if (ir->flags.microsoft_gen1)
1231 mceusb_gen1_init(ir);
1232 else if (!is_gen3)
1233 mceusb_gen2_init(ir);
1234
1235 mceusb_get_parameters(ir);
1236
1237 if (!ir->flags.no_tx)
1238 mceusb_set_tx_mask(ir, MCE_DEFAULT_TX_MASK);
1239
1240 usb_set_intfdata(intf, ir);
1241
1242 dev_info(&intf->dev, "Registered %s on usb%d:%d\n", name,
1243 dev->bus->busnum, dev->devnum);
1244
1245 return 0;
1246
1247 /* Error-handling path */
1248input_dev_fail:
1249 usb_free_urb(ir->urb_in);
1250urb_in_alloc_fail:
1251 usb_free_coherent(dev, maxp, ir->buf_in, ir->dma_in);
1252buf_in_alloc_fail:
1253 kfree(ir);
1254mem_alloc_fail:
1255 dev_err(&intf->dev, "%s: device setup failed!\n", __func__);
1256
1257 return -ENOMEM;
1258}
1259
1260
1261static void __devexit mceusb_dev_disconnect(struct usb_interface *intf)
1262{
1263 struct usb_device *dev = interface_to_usbdev(intf);
1264 struct mceusb_dev *ir = usb_get_intfdata(intf);
1265
1266 usb_set_intfdata(intf, NULL);
1267
1268 if (!ir)
1269 return;
1270
1271 ir->usbdev = NULL;
1272 ir_input_unregister(ir->idev);
1273 usb_kill_urb(ir->urb_in);
1274 usb_free_urb(ir->urb_in);
1275 usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in);
1276
1277 kfree(ir);
1278}
1279
1280static int mceusb_dev_suspend(struct usb_interface *intf, pm_message_t message)
1281{
1282 struct mceusb_dev *ir = usb_get_intfdata(intf);
1283 dev_info(ir->dev, "suspend\n");
1284 usb_kill_urb(ir->urb_in);
1285 return 0;
1286}
1287
1288static int mceusb_dev_resume(struct usb_interface *intf)
1289{
1290 struct mceusb_dev *ir = usb_get_intfdata(intf);
1291 dev_info(ir->dev, "resume\n");
1292 if (usb_submit_urb(ir->urb_in, GFP_ATOMIC))
1293 return -EIO;
1294 return 0;
1295}
1296
1297static struct usb_driver mceusb_dev_driver = {
1298 .name = DRIVER_NAME,
1299 .probe = mceusb_dev_probe,
1300 .disconnect = mceusb_dev_disconnect,
1301 .suspend = mceusb_dev_suspend,
1302 .resume = mceusb_dev_resume,
1303 .reset_resume = mceusb_dev_resume,
1304 .id_table = mceusb_dev_table
1305};
1306
1307static int __init mceusb_dev_init(void)
1308{
1309 int ret;
1310
1311 ret = usb_register(&mceusb_dev_driver);
1312 if (ret < 0)
1313 printk(KERN_ERR DRIVER_NAME
1314 ": usb register failed, result = %d\n", ret);
1315
1316 return ret;
1317}
1318
1319static void __exit mceusb_dev_exit(void)
1320{
1321 usb_deregister(&mceusb_dev_driver);
1322}
1323
1324module_init(mceusb_dev_init);
1325module_exit(mceusb_dev_exit);
1326
1327MODULE_DESCRIPTION(DRIVER_DESC);
1328MODULE_AUTHOR(DRIVER_AUTHOR);
1329MODULE_LICENSE("GPL");
1330MODULE_DEVICE_TABLE(usb, mceusb_dev_table);
1331
1332module_param(debug, bool, S_IRUGO | S_IWUSR);
1333MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
new file mode 100644
index 000000000000..acc729c79cec
--- /dev/null
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -0,0 +1,1252 @@
1/*
2 * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR
3 *
4 * Copyright (C) 2010 Jarod Wilson <jarod@redhat.com>
5 * Copyright (C) 2009 Nuvoton PS Team
6 *
7 * Special thanks to Nuvoton for providing hardware, spec sheets and
8 * sample code upon which portions of this driver are based. Indirect
9 * thanks also to Maxim Levitsky, whose ene_ir driver this driver is
10 * modeled after.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25 * USA
26 */
27
28#include <linux/kernel.h>
29#include <linux/module.h>
30#include <linux/pnp.h>
31#include <linux/io.h>
32#include <linux/interrupt.h>
33#include <linux/sched.h>
34#include <linux/slab.h>
35#include <linux/input.h>
36#include <media/ir-core.h>
37#include <linux/pci_ids.h>
38
39#include "nuvoton-cir.h"
40
41static char *chip_id = "w836x7hg";
42
43/* write val to config reg */
44static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg)
45{
46 outb(reg, nvt->cr_efir);
47 outb(val, nvt->cr_efdr);
48}
49
50/* read val from config reg */
51static inline u8 nvt_cr_read(struct nvt_dev *nvt, u8 reg)
52{
53 outb(reg, nvt->cr_efir);
54 return inb(nvt->cr_efdr);
55}
56
57/* update config register bit without changing other bits */
58static inline void nvt_set_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg)
59{
60 u8 tmp = nvt_cr_read(nvt, reg) | val;
61 nvt_cr_write(nvt, tmp, reg);
62}
63
64/* clear config register bit without changing other bits */
65static inline void nvt_clear_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg)
66{
67 u8 tmp = nvt_cr_read(nvt, reg) & ~val;
68 nvt_cr_write(nvt, tmp, reg);
69}
70
71/* enter extended function mode */
72static inline void nvt_efm_enable(struct nvt_dev *nvt)
73{
74 /* Enabling Extended Function Mode explicitly requires writing 2x */
75 outb(EFER_EFM_ENABLE, nvt->cr_efir);
76 outb(EFER_EFM_ENABLE, nvt->cr_efir);
77}
78
79/* exit extended function mode */
80static inline void nvt_efm_disable(struct nvt_dev *nvt)
81{
82 outb(EFER_EFM_DISABLE, nvt->cr_efir);
83}
84
85/*
86 * When you want to address a specific logical device, write its logical
87 * device number to CR_LOGICAL_DEV_SEL, then enable/disable by writing
88 * 0x1/0x0 respectively to CR_LOGICAL_DEV_EN.
89 */
90static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev)
91{
92 outb(CR_LOGICAL_DEV_SEL, nvt->cr_efir);
93 outb(ldev, nvt->cr_efdr);
94}
95
96/* write val to cir config register */
97static inline void nvt_cir_reg_write(struct nvt_dev *nvt, u8 val, u8 offset)
98{
99 outb(val, nvt->cir_addr + offset);
100}
101
102/* read val from cir config register */
103static u8 nvt_cir_reg_read(struct nvt_dev *nvt, u8 offset)
104{
105 u8 val;
106
107 val = inb(nvt->cir_addr + offset);
108
109 return val;
110}
111
112/* write val to cir wake register */
113static inline void nvt_cir_wake_reg_write(struct nvt_dev *nvt,
114 u8 val, u8 offset)
115{
116 outb(val, nvt->cir_wake_addr + offset);
117}
118
119/* read val from cir wake config register */
120static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset)
121{
122 u8 val;
123
124 val = inb(nvt->cir_wake_addr + offset);
125
126 return val;
127}
128
129#define pr_reg(text, ...) \
130 printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__)
131
132/* dump current cir register contents */
133static void cir_dump_regs(struct nvt_dev *nvt)
134{
135 nvt_efm_enable(nvt);
136 nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
137
138 pr_reg("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME);
139 pr_reg(" * CR CIR ACTIVE : 0x%x\n",
140 nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
141 pr_reg(" * CR CIR BASE ADDR: 0x%x\n",
142 (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
143 nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO));
144 pr_reg(" * CR CIR IRQ NUM: 0x%x\n",
145 nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
146
147 nvt_efm_disable(nvt);
148
149 pr_reg("%s: Dump CIR registers:\n", NVT_DRIVER_NAME);
150 pr_reg(" * IRCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON));
151 pr_reg(" * IRSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS));
152 pr_reg(" * IREN: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN));
153 pr_reg(" * RXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT));
154 pr_reg(" * CP: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CP));
155 pr_reg(" * CC: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CC));
156 pr_reg(" * SLCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH));
157 pr_reg(" * SLCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL));
158 pr_reg(" * FIFOCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON));
159 pr_reg(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS));
160 pr_reg(" * SRXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO));
161 pr_reg(" * TXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT));
162 pr_reg(" * STXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO));
163 pr_reg(" * FCCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH));
164 pr_reg(" * FCCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL));
165 pr_reg(" * IRFSM: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM));
166}
167
168/* dump current cir wake register contents */
169static void cir_wake_dump_regs(struct nvt_dev *nvt)
170{
171 u8 i, fifo_len;
172
173 nvt_efm_enable(nvt);
174 nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
175
176 pr_reg("%s: Dump CIR WAKE logical device registers:\n",
177 NVT_DRIVER_NAME);
178 pr_reg(" * CR CIR WAKE ACTIVE : 0x%x\n",
179 nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
180 pr_reg(" * CR CIR WAKE BASE ADDR: 0x%x\n",
181 (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
182 nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO));
183 pr_reg(" * CR CIR WAKE IRQ NUM: 0x%x\n",
184 nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
185
186 nvt_efm_disable(nvt);
187
188 pr_reg("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME);
189 pr_reg(" * IRCON: 0x%x\n",
190 nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON));
191 pr_reg(" * IRSTS: 0x%x\n",
192 nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS));
193 pr_reg(" * IREN: 0x%x\n",
194 nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN));
195 pr_reg(" * FIFO CMP DEEP: 0x%x\n",
196 nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP));
197 pr_reg(" * FIFO CMP TOL: 0x%x\n",
198 nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL));
199 pr_reg(" * FIFO COUNT: 0x%x\n",
200 nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT));
201 pr_reg(" * SLCH: 0x%x\n",
202 nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH));
203 pr_reg(" * SLCL: 0x%x\n",
204 nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL));
205 pr_reg(" * FIFOCON: 0x%x\n",
206 nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON));
207 pr_reg(" * SRXFSTS: 0x%x\n",
208 nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS));
209 pr_reg(" * SAMPLE RX FIFO: 0x%x\n",
210 nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO));
211 pr_reg(" * WR FIFO DATA: 0x%x\n",
212 nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA));
213 pr_reg(" * RD FIFO ONLY: 0x%x\n",
214 nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
215 pr_reg(" * RD FIFO ONLY IDX: 0x%x\n",
216 nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX));
217 pr_reg(" * FIFO IGNORE: 0x%x\n",
218 nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE));
219 pr_reg(" * IRFSM: 0x%x\n",
220 nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM));
221
222 fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT);
223 pr_reg("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len);
224 pr_reg("* Contents = ");
225 for (i = 0; i < fifo_len; i++)
226 printk(KERN_CONT "%02x ",
227 nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
228 printk(KERN_CONT "\n");
229}
230
231/* detect hardware features */
232static int nvt_hw_detect(struct nvt_dev *nvt)
233{
234 unsigned long flags;
235 u8 chip_major, chip_minor;
236 int ret = 0;
237
238 nvt_efm_enable(nvt);
239
240 /* Check if we're wired for the alternate EFER setup */
241 chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI);
242 if (chip_major == 0xff) {
243 nvt->cr_efir = CR_EFIR2;
244 nvt->cr_efdr = CR_EFDR2;
245 nvt_efm_enable(nvt);
246 chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI);
247 }
248
249 chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO);
250 nvt_dbg("%s: chip id: 0x%02x 0x%02x", chip_id, chip_major, chip_minor);
251
252 if (chip_major != CHIP_ID_HIGH &&
253 (chip_minor != CHIP_ID_LOW || chip_minor != CHIP_ID_LOW2))
254 ret = -ENODEV;
255
256 nvt_efm_disable(nvt);
257
258 spin_lock_irqsave(&nvt->nvt_lock, flags);
259 nvt->chip_major = chip_major;
260 nvt->chip_minor = chip_minor;
261 spin_unlock_irqrestore(&nvt->nvt_lock, flags);
262
263 return ret;
264}
265
266static void nvt_cir_ldev_init(struct nvt_dev *nvt)
267{
268 u8 val;
269
270 /* output pin selection (Pin95=CIRRX, Pin96=CIRTX1, WB enabled */
271 val = nvt_cr_read(nvt, CR_OUTPUT_PIN_SEL);
272 val &= OUTPUT_PIN_SEL_MASK;
273 val |= (OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB);
274 nvt_cr_write(nvt, val, CR_OUTPUT_PIN_SEL);
275
276 /* Select CIR logical device and enable */
277 nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
278 nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
279
280 nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI);
281 nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO);
282
283 nvt_cr_write(nvt, nvt->cir_irq, CR_CIR_IRQ_RSRC);
284
285 nvt_dbg("CIR initialized, base io port address: 0x%lx, irq: %d",
286 nvt->cir_addr, nvt->cir_irq);
287}
288
289static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt)
290{
291 /* Select ACPI logical device, enable it and CIR Wake */
292 nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI);
293 nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
294
295 /* Enable CIR Wake via PSOUT# (Pin60) */
296 nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE);
297
298 /* enable cir interrupt of mouse/keyboard IRQ event */
299 nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS);
300
301 /* enable pme interrupt of cir wakeup event */
302 nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2);
303
304 /* Select CIR Wake logical device and enable */
305 nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
306 nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
307
308 nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI);
309 nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO);
310
311 nvt_cr_write(nvt, nvt->cir_wake_irq, CR_CIR_IRQ_RSRC);
312
313 nvt_dbg("CIR Wake initialized, base io port address: 0x%lx, irq: %d",
314 nvt->cir_wake_addr, nvt->cir_wake_irq);
315}
316
317/* clear out the hardware's cir rx fifo */
318static void nvt_clear_cir_fifo(struct nvt_dev *nvt)
319{
320 u8 val;
321
322 val = nvt_cir_reg_read(nvt, CIR_FIFOCON);
323 nvt_cir_reg_write(nvt, val | CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON);
324}
325
326/* clear out the hardware's cir wake rx fifo */
327static void nvt_clear_cir_wake_fifo(struct nvt_dev *nvt)
328{
329 u8 val;
330
331 val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON);
332 nvt_cir_wake_reg_write(nvt, val | CIR_WAKE_FIFOCON_RXFIFOCLR,
333 CIR_WAKE_FIFOCON);
334}
335
336/* clear out the hardware's cir tx fifo */
337static void nvt_clear_tx_fifo(struct nvt_dev *nvt)
338{
339 u8 val;
340
341 val = nvt_cir_reg_read(nvt, CIR_FIFOCON);
342 nvt_cir_reg_write(nvt, val | CIR_FIFOCON_TXFIFOCLR, CIR_FIFOCON);
343}
344
345/* enable RX Trigger Level Reach and Packet End interrupts */
346static void nvt_set_cir_iren(struct nvt_dev *nvt)
347{
348 u8 iren;
349
350 iren = CIR_IREN_RTR | CIR_IREN_PE;
351 nvt_cir_reg_write(nvt, iren, CIR_IREN);
352}
353
354static void nvt_cir_regs_init(struct nvt_dev *nvt)
355{
356 /* set sample limit count (PE interrupt raised when reached) */
357 nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_SLCH);
358 nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_SLCL);
359
360 /* set fifo irq trigger levels */
361 nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV |
362 CIR_FIFOCON_RX_TRIGGER_LEV, CIR_FIFOCON);
363
364 /*
365 * Enable TX and RX, specify carrier on = low, off = high, and set
366 * sample period (currently 50us)
367 */
368 nvt_cir_reg_write(nvt,
369 CIR_IRCON_TXEN | CIR_IRCON_RXEN |
370 CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
371 CIR_IRCON);
372
373 /* clear hardware rx and tx fifos */
374 nvt_clear_cir_fifo(nvt);
375 nvt_clear_tx_fifo(nvt);
376
377 /* clear any and all stray interrupts */
378 nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
379
380 /* and finally, enable interrupts */
381 nvt_set_cir_iren(nvt);
382}
383
384static void nvt_cir_wake_regs_init(struct nvt_dev *nvt)
385{
386 /* set number of bytes needed for wake key comparison (default 67) */
387 nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFO_LEN, CIR_WAKE_FIFO_CMP_DEEP);
388
389 /* set tolerance/variance allowed per byte during wake compare */
390 nvt_cir_wake_reg_write(nvt, CIR_WAKE_CMP_TOLERANCE,
391 CIR_WAKE_FIFO_CMP_TOL);
392
393 /* set sample limit count (PE interrupt raised when reached) */
394 nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_WAKE_SLCH);
395 nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_WAKE_SLCL);
396
397 /* set cir wake fifo rx trigger level (currently 67) */
398 nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFOCON_RX_TRIGGER_LEV,
399 CIR_WAKE_FIFOCON);
400
401 /*
402 * Enable TX and RX, specific carrier on = low, off = high, and set
403 * sample period (currently 50us)
404 */
405 nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN |
406 CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV |
407 CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL,
408 CIR_WAKE_IRCON);
409
410 /* clear cir wake rx fifo */
411 nvt_clear_cir_wake_fifo(nvt);
412
413 /* clear any and all stray interrupts */
414 nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
415}
416
417static void nvt_enable_wake(struct nvt_dev *nvt)
418{
419 nvt_efm_enable(nvt);
420
421 nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI);
422 nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE);
423 nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS);
424 nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2);
425
426 nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
427 nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
428
429 nvt_efm_disable(nvt);
430
431 nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN |
432 CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV |
433 CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL,
434 CIR_WAKE_IRCON);
435 nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
436 nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
437}
438
439/* rx carrier detect only works in learning mode, must be called w/nvt_lock */
440static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt)
441{
442 u32 count, carrier, duration = 0;
443 int i;
444
445 count = nvt_cir_reg_read(nvt, CIR_FCCL) |
446 nvt_cir_reg_read(nvt, CIR_FCCH) << 8;
447
448 for (i = 0; i < nvt->pkts; i++) {
449 if (nvt->buf[i] & BUF_PULSE_BIT)
450 duration += nvt->buf[i] & BUF_LEN_MASK;
451 }
452
453 duration *= SAMPLE_PERIOD;
454
455 if (!count || !duration) {
456 nvt_pr(KERN_NOTICE, "Unable to determine carrier! (c:%u, d:%u)",
457 count, duration);
458 return 0;
459 }
460
461 carrier = (count * 1000000) / duration;
462
463 if ((carrier > MAX_CARRIER) || (carrier < MIN_CARRIER))
464 nvt_dbg("WTF? Carrier frequency out of range!");
465
466 nvt_dbg("Carrier frequency: %u (count %u, duration %u)",
467 carrier, count, duration);
468
469 return carrier;
470}
471
472/*
473 * set carrier frequency
474 *
475 * set carrier on 2 registers: CP & CC
476 * always set CP as 0x81
477 * set CC by SPEC, CC = 3MHz/carrier - 1
478 */
479static int nvt_set_tx_carrier(void *data, u32 carrier)
480{
481 struct nvt_dev *nvt = data;
482 u16 val;
483
484 nvt_cir_reg_write(nvt, 1, CIR_CP);
485 val = 3000000 / (carrier) - 1;
486 nvt_cir_reg_write(nvt, val & 0xff, CIR_CC);
487
488 nvt_dbg("cp: 0x%x cc: 0x%x\n",
489 nvt_cir_reg_read(nvt, CIR_CP), nvt_cir_reg_read(nvt, CIR_CC));
490
491 return 0;
492}
493
494/*
495 * nvt_tx_ir
496 *
497 * 1) clean TX fifo first (handled by AP)
498 * 2) copy data from user space
499 * 3) disable RX interrupts, enable TX interrupts: TTR & TFU
500 * 4) send 9 packets to TX FIFO to open TTR
501 * in interrupt_handler:
502 * 5) send all data out
503 * go back to write():
504 * 6) disable TX interrupts, re-enable RX interupts
505 *
506 * The key problem of this function is user space data may larger than
507 * driver's data buf length. So nvt_tx_ir() will only copy TX_BUF_LEN data to
508 * buf, and keep current copied data buf num in cur_buf_num. But driver's buf
509 * number may larger than TXFCONT (0xff). So in interrupt_handler, it has to
510 * set TXFCONT as 0xff, until buf_count less than 0xff.
511 */
512static int nvt_tx_ir(void *priv, int *txbuf, u32 n)
513{
514 struct nvt_dev *nvt = priv;
515 unsigned long flags;
516 size_t cur_count;
517 unsigned int i;
518 u8 iren;
519 int ret;
520
521 spin_lock_irqsave(&nvt->tx.lock, flags);
522
523 if (n >= TX_BUF_LEN) {
524 nvt->tx.buf_count = cur_count = TX_BUF_LEN;
525 ret = TX_BUF_LEN;
526 } else {
527 nvt->tx.buf_count = cur_count = n;
528 ret = n;
529 }
530
531 memcpy(nvt->tx.buf, txbuf, nvt->tx.buf_count);
532
533 nvt->tx.cur_buf_num = 0;
534
535 /* save currently enabled interrupts */
536 iren = nvt_cir_reg_read(nvt, CIR_IREN);
537
538 /* now disable all interrupts, save TFU & TTR */
539 nvt_cir_reg_write(nvt, CIR_IREN_TFU | CIR_IREN_TTR, CIR_IREN);
540
541 nvt->tx.tx_state = ST_TX_REPLY;
542
543 nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV_8 |
544 CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON);
545
546 /* trigger TTR interrupt by writing out ones, (yes, it's ugly) */
547 for (i = 0; i < 9; i++)
548 nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO);
549
550 spin_unlock_irqrestore(&nvt->tx.lock, flags);
551
552 wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST);
553
554 spin_lock_irqsave(&nvt->tx.lock, flags);
555 nvt->tx.tx_state = ST_TX_NONE;
556 spin_unlock_irqrestore(&nvt->tx.lock, flags);
557
558 /* restore enabled interrupts to prior state */
559 nvt_cir_reg_write(nvt, iren, CIR_IREN);
560
561 return ret;
562}
563
564/* dump contents of the last rx buffer we got from the hw rx fifo */
565static void nvt_dump_rx_buf(struct nvt_dev *nvt)
566{
567 int i;
568
569 printk(KERN_DEBUG "%s (len %d): ", __func__, nvt->pkts);
570 for (i = 0; (i < nvt->pkts) && (i < RX_BUF_LEN); i++)
571 printk(KERN_CONT "0x%02x ", nvt->buf[i]);
572 printk(KERN_CONT "\n");
573}
574
575/*
576 * Process raw data in rx driver buffer, store it in raw IR event kfifo,
577 * trigger decode when appropriate.
578 *
579 * We get IR data samples one byte at a time. If the msb is set, its a pulse,
580 * otherwise its a space. The lower 7 bits are the count of SAMPLE_PERIOD
581 * (default 50us) intervals for that pulse/space. A discrete signal is
582 * followed by a series of 0x7f packets, then either 0x7<something> or 0x80
583 * to signal more IR coming (repeats) or end of IR, respectively. We store
584 * sample data in the raw event kfifo until we see 0x7<something> (except f)
585 * or 0x80, at which time, we trigger a decode operation.
586 */
587static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
588{
589 DEFINE_IR_RAW_EVENT(rawir);
590 unsigned int count;
591 u32 carrier;
592 u8 sample;
593 int i;
594
595 nvt_dbg_verbose("%s firing", __func__);
596
597 if (debug)
598 nvt_dump_rx_buf(nvt);
599
600 if (nvt->carrier_detect_enabled)
601 carrier = nvt_rx_carrier_detect(nvt);
602
603 count = nvt->pkts;
604 nvt_dbg_verbose("Processing buffer of len %d", count);
605
606 init_ir_raw_event(&rawir);
607
608 for (i = 0; i < count; i++) {
609 nvt->pkts--;
610 sample = nvt->buf[i];
611
612 rawir.pulse = ((sample & BUF_PULSE_BIT) != 0);
613 rawir.duration = (sample & BUF_LEN_MASK)
614 * SAMPLE_PERIOD * 1000;
615
616 if ((sample & BUF_LEN_MASK) == BUF_LEN_MASK) {
617 if (nvt->rawir.pulse == rawir.pulse)
618 nvt->rawir.duration += rawir.duration;
619 else {
620 nvt->rawir.duration = rawir.duration;
621 nvt->rawir.pulse = rawir.pulse;
622 }
623 continue;
624 }
625
626 rawir.duration += nvt->rawir.duration;
627
628 init_ir_raw_event(&nvt->rawir);
629 nvt->rawir.duration = 0;
630 nvt->rawir.pulse = rawir.pulse;
631
632 if (sample == BUF_PULSE_BIT)
633 rawir.pulse = false;
634
635 if (rawir.duration) {
636 nvt_dbg("Storing %s with duration %d",
637 rawir.pulse ? "pulse" : "space",
638 rawir.duration);
639
640 ir_raw_event_store(nvt->rdev, &rawir);
641 }
642
643 /*
644 * BUF_PULSE_BIT indicates end of IR data, BUF_REPEAT_BYTE
645 * indicates end of IR signal, but new data incoming. In both
646 * cases, it means we're ready to call ir_raw_event_handle
647 */
648 if ((sample == BUF_PULSE_BIT) && nvt->pkts) {
649 nvt_dbg("Calling ir_raw_event_handle (signal end)\n");
650 ir_raw_event_handle(nvt->rdev);
651 }
652 }
653
654 nvt_dbg("Calling ir_raw_event_handle (buffer empty)\n");
655 ir_raw_event_handle(nvt->rdev);
656
657 if (nvt->pkts) {
658 nvt_dbg("Odd, pkts should be 0 now... (its %u)", nvt->pkts);
659 nvt->pkts = 0;
660 }
661
662 nvt_dbg_verbose("%s done", __func__);
663}
664
665static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt)
666{
667 nvt_pr(KERN_WARNING, "RX FIFO overrun detected, flushing data!");
668
669 nvt->pkts = 0;
670 nvt_clear_cir_fifo(nvt);
671 ir_raw_event_reset(nvt->rdev);
672}
673
674/* copy data from hardware rx fifo into driver buffer */
675static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
676{
677 unsigned long flags;
678 u8 fifocount, val;
679 unsigned int b_idx;
680 bool overrun = false;
681 int i;
682
683 /* Get count of how many bytes to read from RX FIFO */
684 fifocount = nvt_cir_reg_read(nvt, CIR_RXFCONT);
685 /* if we get 0xff, probably means the logical dev is disabled */
686 if (fifocount == 0xff)
687 return;
688 /* watch out for a fifo overrun condition */
689 else if (fifocount > RX_BUF_LEN) {
690 overrun = true;
691 fifocount = RX_BUF_LEN;
692 }
693
694 nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount);
695
696 spin_lock_irqsave(&nvt->nvt_lock, flags);
697
698 b_idx = nvt->pkts;
699
700 /* This should never happen, but lets check anyway... */
701 if (b_idx + fifocount > RX_BUF_LEN) {
702 nvt_process_rx_ir_data(nvt);
703 b_idx = 0;
704 }
705
706 /* Read fifocount bytes from CIR Sample RX FIFO register */
707 for (i = 0; i < fifocount; i++) {
708 val = nvt_cir_reg_read(nvt, CIR_SRXFIFO);
709 nvt->buf[b_idx + i] = val;
710 }
711
712 nvt->pkts += fifocount;
713 nvt_dbg("%s: pkts now %d", __func__, nvt->pkts);
714
715 nvt_process_rx_ir_data(nvt);
716
717 if (overrun)
718 nvt_handle_rx_fifo_overrun(nvt);
719
720 spin_unlock_irqrestore(&nvt->nvt_lock, flags);
721}
722
723static void nvt_cir_log_irqs(u8 status, u8 iren)
724{
725 nvt_pr(KERN_INFO, "IRQ 0x%02x (IREN 0x%02x) :%s%s%s%s%s%s%s%s%s",
726 status, iren,
727 status & CIR_IRSTS_RDR ? " RDR" : "",
728 status & CIR_IRSTS_RTR ? " RTR" : "",
729 status & CIR_IRSTS_PE ? " PE" : "",
730 status & CIR_IRSTS_RFO ? " RFO" : "",
731 status & CIR_IRSTS_TE ? " TE" : "",
732 status & CIR_IRSTS_TTR ? " TTR" : "",
733 status & CIR_IRSTS_TFU ? " TFU" : "",
734 status & CIR_IRSTS_GH ? " GH" : "",
735 status & ~(CIR_IRSTS_RDR | CIR_IRSTS_RTR | CIR_IRSTS_PE |
736 CIR_IRSTS_RFO | CIR_IRSTS_TE | CIR_IRSTS_TTR |
737 CIR_IRSTS_TFU | CIR_IRSTS_GH) ? " ?" : "");
738}
739
740static bool nvt_cir_tx_inactive(struct nvt_dev *nvt)
741{
742 unsigned long flags;
743 bool tx_inactive;
744 u8 tx_state;
745
746 spin_lock_irqsave(&nvt->tx.lock, flags);
747 tx_state = nvt->tx.tx_state;
748 spin_unlock_irqrestore(&nvt->tx.lock, flags);
749
750 tx_inactive = (tx_state == ST_TX_NONE);
751
752 return tx_inactive;
753}
754
755/* interrupt service routine for incoming and outgoing CIR data */
756static irqreturn_t nvt_cir_isr(int irq, void *data)
757{
758 struct nvt_dev *nvt = data;
759 u8 status, iren, cur_state;
760 unsigned long flags;
761
762 nvt_dbg_verbose("%s firing", __func__);
763
764 nvt_efm_enable(nvt);
765 nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
766 nvt_efm_disable(nvt);
767
768 /*
769 * Get IR Status register contents. Write 1 to ack/clear
770 *
771 * bit: reg name - description
772 * 7: CIR_IRSTS_RDR - RX Data Ready
773 * 6: CIR_IRSTS_RTR - RX FIFO Trigger Level Reach
774 * 5: CIR_IRSTS_PE - Packet End
775 * 4: CIR_IRSTS_RFO - RX FIFO Overrun (RDR will also be set)
776 * 3: CIR_IRSTS_TE - TX FIFO Empty
777 * 2: CIR_IRSTS_TTR - TX FIFO Trigger Level Reach
778 * 1: CIR_IRSTS_TFU - TX FIFO Underrun
779 * 0: CIR_IRSTS_GH - Min Length Detected
780 */
781 status = nvt_cir_reg_read(nvt, CIR_IRSTS);
782 if (!status) {
783 nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__);
784 nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
785 return IRQ_RETVAL(IRQ_NONE);
786 }
787
788 /* ack/clear all irq flags we've got */
789 nvt_cir_reg_write(nvt, status, CIR_IRSTS);
790 nvt_cir_reg_write(nvt, 0, CIR_IRSTS);
791
792 /* Interrupt may be shared with CIR Wake, bail if CIR not enabled */
793 iren = nvt_cir_reg_read(nvt, CIR_IREN);
794 if (!iren) {
795 nvt_dbg_verbose("%s exiting, CIR not enabled", __func__);
796 return IRQ_RETVAL(IRQ_NONE);
797 }
798
799 if (debug)
800 nvt_cir_log_irqs(status, iren);
801
802 if (status & CIR_IRSTS_RTR) {
803 /* FIXME: add code for study/learn mode */
804 /* We only do rx if not tx'ing */
805 if (nvt_cir_tx_inactive(nvt))
806 nvt_get_rx_ir_data(nvt);
807 }
808
809 if (status & CIR_IRSTS_PE) {
810 if (nvt_cir_tx_inactive(nvt))
811 nvt_get_rx_ir_data(nvt);
812
813 spin_lock_irqsave(&nvt->nvt_lock, flags);
814
815 cur_state = nvt->study_state;
816
817 spin_unlock_irqrestore(&nvt->nvt_lock, flags);
818
819 if (cur_state == ST_STUDY_NONE)
820 nvt_clear_cir_fifo(nvt);
821 }
822
823 if (status & CIR_IRSTS_TE)
824 nvt_clear_tx_fifo(nvt);
825
826 if (status & CIR_IRSTS_TTR) {
827 unsigned int pos, count;
828 u8 tmp;
829
830 spin_lock_irqsave(&nvt->tx.lock, flags);
831
832 pos = nvt->tx.cur_buf_num;
833 count = nvt->tx.buf_count;
834
835 /* Write data into the hardware tx fifo while pos < count */
836 if (pos < count) {
837 nvt_cir_reg_write(nvt, nvt->tx.buf[pos], CIR_STXFIFO);
838 nvt->tx.cur_buf_num++;
839 /* Disable TX FIFO Trigger Level Reach (TTR) interrupt */
840 } else {
841 tmp = nvt_cir_reg_read(nvt, CIR_IREN);
842 nvt_cir_reg_write(nvt, tmp & ~CIR_IREN_TTR, CIR_IREN);
843 }
844
845 spin_unlock_irqrestore(&nvt->tx.lock, flags);
846
847 }
848
849 if (status & CIR_IRSTS_TFU) {
850 spin_lock_irqsave(&nvt->tx.lock, flags);
851 if (nvt->tx.tx_state == ST_TX_REPLY) {
852 nvt->tx.tx_state = ST_TX_REQUEST;
853 wake_up(&nvt->tx.queue);
854 }
855 spin_unlock_irqrestore(&nvt->tx.lock, flags);
856 }
857
858 nvt_dbg_verbose("%s done", __func__);
859 return IRQ_RETVAL(IRQ_HANDLED);
860}
861
862/* Interrupt service routine for CIR Wake */
863static irqreturn_t nvt_cir_wake_isr(int irq, void *data)
864{
865 u8 status, iren, val;
866 struct nvt_dev *nvt = data;
867 unsigned long flags;
868
869 nvt_dbg_wake("%s firing", __func__);
870
871 status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS);
872 if (!status)
873 return IRQ_RETVAL(IRQ_NONE);
874
875 if (status & CIR_WAKE_IRSTS_IR_PENDING)
876 nvt_clear_cir_wake_fifo(nvt);
877
878 nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS);
879 nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS);
880
881 /* Interrupt may be shared with CIR, bail if Wake not enabled */
882 iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN);
883 if (!iren) {
884 nvt_dbg_wake("%s exiting, wake not enabled", __func__);
885 return IRQ_RETVAL(IRQ_HANDLED);
886 }
887
888 if ((status & CIR_WAKE_IRSTS_PE) &&
889 (nvt->wake_state == ST_WAKE_START)) {
890 while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) {
891 val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY);
892 nvt_dbg("setting wake up key: 0x%x", val);
893 }
894
895 nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
896 spin_lock_irqsave(&nvt->nvt_lock, flags);
897 nvt->wake_state = ST_WAKE_FINISH;
898 spin_unlock_irqrestore(&nvt->nvt_lock, flags);
899 }
900
901 nvt_dbg_wake("%s done", __func__);
902 return IRQ_RETVAL(IRQ_HANDLED);
903}
904
905static void nvt_enable_cir(struct nvt_dev *nvt)
906{
907 /* set function enable flags */
908 nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN |
909 CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
910 CIR_IRCON);
911
912 nvt_efm_enable(nvt);
913
914 /* enable the CIR logical device */
915 nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
916 nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
917
918 nvt_efm_disable(nvt);
919
920 /* clear all pending interrupts */
921 nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
922
923 /* enable interrupts */
924 nvt_set_cir_iren(nvt);
925}
926
927static void nvt_disable_cir(struct nvt_dev *nvt)
928{
929 /* disable CIR interrupts */
930 nvt_cir_reg_write(nvt, 0, CIR_IREN);
931
932 /* clear any and all pending interrupts */
933 nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
934
935 /* clear all function enable flags */
936 nvt_cir_reg_write(nvt, 0, CIR_IRCON);
937
938 /* clear hardware rx and tx fifos */
939 nvt_clear_cir_fifo(nvt);
940 nvt_clear_tx_fifo(nvt);
941
942 nvt_efm_enable(nvt);
943
944 /* disable the CIR logical device */
945 nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
946 nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN);
947
948 nvt_efm_disable(nvt);
949}
950
951static int nvt_open(void *data)
952{
953 struct nvt_dev *nvt = (struct nvt_dev *)data;
954 unsigned long flags;
955
956 spin_lock_irqsave(&nvt->nvt_lock, flags);
957 nvt->in_use = true;
958 nvt_enable_cir(nvt);
959 spin_unlock_irqrestore(&nvt->nvt_lock, flags);
960
961 return 0;
962}
963
964static void nvt_close(void *data)
965{
966 struct nvt_dev *nvt = (struct nvt_dev *)data;
967 unsigned long flags;
968
969 spin_lock_irqsave(&nvt->nvt_lock, flags);
970 nvt->in_use = false;
971 nvt_disable_cir(nvt);
972 spin_unlock_irqrestore(&nvt->nvt_lock, flags);
973}
974
975/* Allocate memory, probe hardware, and initialize everything */
976static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
977{
978 struct nvt_dev *nvt = NULL;
979 struct input_dev *rdev = NULL;
980 struct ir_dev_props *props = NULL;
981 int ret = -ENOMEM;
982
983 nvt = kzalloc(sizeof(struct nvt_dev), GFP_KERNEL);
984 if (!nvt)
985 return ret;
986
987 props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
988 if (!props)
989 goto failure;
990
991 /* input device for IR remote (and tx) */
992 rdev = input_allocate_device();
993 if (!rdev)
994 goto failure;
995
996 ret = -ENODEV;
997 /* validate pnp resources */
998 if (!pnp_port_valid(pdev, 0) ||
999 pnp_port_len(pdev, 0) < CIR_IOREG_LENGTH) {
1000 dev_err(&pdev->dev, "IR PNP Port not valid!\n");
1001 goto failure;
1002 }
1003
1004 if (!pnp_irq_valid(pdev, 0)) {
1005 dev_err(&pdev->dev, "PNP IRQ not valid!\n");
1006 goto failure;
1007 }
1008
1009 if (!pnp_port_valid(pdev, 1) ||
1010 pnp_port_len(pdev, 1) < CIR_IOREG_LENGTH) {
1011 dev_err(&pdev->dev, "Wake PNP Port not valid!\n");
1012 goto failure;
1013 }
1014
1015 nvt->cir_addr = pnp_port_start(pdev, 0);
1016 nvt->cir_irq = pnp_irq(pdev, 0);
1017
1018 nvt->cir_wake_addr = pnp_port_start(pdev, 1);
1019 /* irq is always shared between cir and cir wake */
1020 nvt->cir_wake_irq = nvt->cir_irq;
1021
1022 nvt->cr_efir = CR_EFIR;
1023 nvt->cr_efdr = CR_EFDR;
1024
1025 spin_lock_init(&nvt->nvt_lock);
1026 spin_lock_init(&nvt->tx.lock);
1027 init_ir_raw_event(&nvt->rawir);
1028
1029 ret = -EBUSY;
1030 /* now claim resources */
1031 if (!request_region(nvt->cir_addr,
1032 CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
1033 goto failure;
1034
1035 if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED,
1036 NVT_DRIVER_NAME, (void *)nvt))
1037 goto failure;
1038
1039 if (!request_region(nvt->cir_wake_addr,
1040 CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
1041 goto failure;
1042
1043 if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED,
1044 NVT_DRIVER_NAME, (void *)nvt))
1045 goto failure;
1046
1047 pnp_set_drvdata(pdev, nvt);
1048 nvt->pdev = pdev;
1049
1050 init_waitqueue_head(&nvt->tx.queue);
1051
1052 ret = nvt_hw_detect(nvt);
1053 if (ret)
1054 goto failure;
1055
1056 /* Initialize CIR & CIR Wake Logical Devices */
1057 nvt_efm_enable(nvt);
1058 nvt_cir_ldev_init(nvt);
1059 nvt_cir_wake_ldev_init(nvt);
1060 nvt_efm_disable(nvt);
1061
1062 /* Initialize CIR & CIR Wake Config Registers */
1063 nvt_cir_regs_init(nvt);
1064 nvt_cir_wake_regs_init(nvt);
1065
1066 /* Set up ir-core props */
1067 props->priv = nvt;
1068 props->driver_type = RC_DRIVER_IR_RAW;
1069 props->allowed_protos = IR_TYPE_ALL;
1070 props->open = nvt_open;
1071 props->close = nvt_close;
1072#if 0
1073 props->min_timeout = XYZ;
1074 props->max_timeout = XYZ;
1075 props->timeout = XYZ;
1076 /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */
1077 props->rx_resolution = XYZ;
1078
1079 /* tx bits */
1080 props->tx_resolution = XYZ;
1081#endif
1082 props->tx_ir = nvt_tx_ir;
1083 props->s_tx_carrier = nvt_set_tx_carrier;
1084
1085 rdev->name = "Nuvoton w836x7hg Infrared Remote Transceiver";
1086 rdev->id.bustype = BUS_HOST;
1087 rdev->id.vendor = PCI_VENDOR_ID_WINBOND2;
1088 rdev->id.product = nvt->chip_major;
1089 rdev->id.version = nvt->chip_minor;
1090
1091 nvt->props = props;
1092 nvt->rdev = rdev;
1093
1094 device_set_wakeup_capable(&pdev->dev, 1);
1095 device_set_wakeup_enable(&pdev->dev, 1);
1096
1097 ret = ir_input_register(rdev, RC_MAP_RC6_MCE, props, NVT_DRIVER_NAME);
1098 if (ret)
1099 goto failure;
1100
1101 nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n");
1102 if (debug) {
1103 cir_dump_regs(nvt);
1104 cir_wake_dump_regs(nvt);
1105 }
1106
1107 return 0;
1108
1109failure:
1110 if (nvt->cir_irq)
1111 free_irq(nvt->cir_irq, nvt);
1112 if (nvt->cir_addr)
1113 release_region(nvt->cir_addr, CIR_IOREG_LENGTH);
1114
1115 if (nvt->cir_wake_irq)
1116 free_irq(nvt->cir_wake_irq, nvt);
1117 if (nvt->cir_wake_addr)
1118 release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH);
1119
1120 input_free_device(rdev);
1121 kfree(props);
1122 kfree(nvt);
1123
1124 return ret;
1125}
1126
1127static void __devexit nvt_remove(struct pnp_dev *pdev)
1128{
1129 struct nvt_dev *nvt = pnp_get_drvdata(pdev);
1130 unsigned long flags;
1131
1132 spin_lock_irqsave(&nvt->nvt_lock, flags);
1133 /* disable CIR */
1134 nvt_cir_reg_write(nvt, 0, CIR_IREN);
1135 nvt_disable_cir(nvt);
1136 /* enable CIR Wake (for IR power-on) */
1137 nvt_enable_wake(nvt);
1138 spin_unlock_irqrestore(&nvt->nvt_lock, flags);
1139
1140 /* free resources */
1141 free_irq(nvt->cir_irq, nvt);
1142 free_irq(nvt->cir_wake_irq, nvt);
1143 release_region(nvt->cir_addr, CIR_IOREG_LENGTH);
1144 release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH);
1145
1146 ir_input_unregister(nvt->rdev);
1147
1148 kfree(nvt->props);
1149 kfree(nvt);
1150}
1151
1152static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state)
1153{
1154 struct nvt_dev *nvt = pnp_get_drvdata(pdev);
1155 unsigned long flags;
1156
1157 nvt_dbg("%s called", __func__);
1158
1159 /* zero out misc state tracking */
1160 spin_lock_irqsave(&nvt->nvt_lock, flags);
1161 nvt->study_state = ST_STUDY_NONE;
1162 nvt->wake_state = ST_WAKE_NONE;
1163 spin_unlock_irqrestore(&nvt->nvt_lock, flags);
1164
1165 spin_lock_irqsave(&nvt->tx.lock, flags);
1166 nvt->tx.tx_state = ST_TX_NONE;
1167 spin_unlock_irqrestore(&nvt->tx.lock, flags);
1168
1169 /* disable all CIR interrupts */
1170 nvt_cir_reg_write(nvt, 0, CIR_IREN);
1171
1172 nvt_efm_enable(nvt);
1173
1174 /* disable cir logical dev */
1175 nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
1176 nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN);
1177
1178 nvt_efm_disable(nvt);
1179
1180 /* make sure wake is enabled */
1181 nvt_enable_wake(nvt);
1182
1183 return 0;
1184}
1185
1186static int nvt_resume(struct pnp_dev *pdev)
1187{
1188 int ret = 0;
1189 struct nvt_dev *nvt = pnp_get_drvdata(pdev);
1190
1191 nvt_dbg("%s called", __func__);
1192
1193 /* open interrupt */
1194 nvt_set_cir_iren(nvt);
1195
1196 /* Enable CIR logical device */
1197 nvt_efm_enable(nvt);
1198 nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
1199 nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
1200
1201 nvt_efm_disable(nvt);
1202
1203 nvt_cir_regs_init(nvt);
1204 nvt_cir_wake_regs_init(nvt);
1205
1206 return ret;
1207}
1208
1209static void nvt_shutdown(struct pnp_dev *pdev)
1210{
1211 struct nvt_dev *nvt = pnp_get_drvdata(pdev);
1212 nvt_enable_wake(nvt);
1213}
1214
1215static const struct pnp_device_id nvt_ids[] = {
1216 { "WEC0530", 0 }, /* CIR */
1217 { "NTN0530", 0 }, /* CIR for new chip's pnp id*/
1218 { "", 0 },
1219};
1220
1221static struct pnp_driver nvt_driver = {
1222 .name = NVT_DRIVER_NAME,
1223 .id_table = nvt_ids,
1224 .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
1225 .probe = nvt_probe,
1226 .remove = __devexit_p(nvt_remove),
1227 .suspend = nvt_suspend,
1228 .resume = nvt_resume,
1229 .shutdown = nvt_shutdown,
1230};
1231
1232int nvt_init(void)
1233{
1234 return pnp_register_driver(&nvt_driver);
1235}
1236
1237void nvt_exit(void)
1238{
1239 pnp_unregister_driver(&nvt_driver);
1240}
1241
1242module_param(debug, int, S_IRUGO | S_IWUSR);
1243MODULE_PARM_DESC(debug, "Enable debugging output");
1244
1245MODULE_DEVICE_TABLE(pnp, nvt_ids);
1246MODULE_DESCRIPTION("Nuvoton W83667HG-A & W83677HG-I CIR driver");
1247
1248MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
1249MODULE_LICENSE("GPL");
1250
1251module_init(nvt_init);
1252module_exit(nvt_exit);
diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h
new file mode 100644
index 000000000000..62dc53017c8e
--- /dev/null
+++ b/drivers/media/rc/nuvoton-cir.h
@@ -0,0 +1,408 @@
1/*
2 * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR
3 *
4 * Copyright (C) 2010 Jarod Wilson <jarod@redhat.com>
5 * Copyright (C) 2009 Nuvoton PS Team
6 *
7 * Special thanks to Nuvoton for providing hardware, spec sheets and
8 * sample code upon which portions of this driver are based. Indirect
9 * thanks also to Maxim Levitsky, whose ene_ir driver this driver is
10 * modeled after.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25 * USA
26 */
27
28#include <linux/spinlock.h>
29#include <linux/ioctl.h>
30
31/* platform driver name to register */
32#define NVT_DRIVER_NAME "nuvoton-cir"
33
34/* debugging module parameter */
35static int debug;
36
37
38#define nvt_pr(level, text, ...) \
39 printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__)
40
41#define nvt_dbg(text, ...) \
42 if (debug) \
43 printk(KERN_DEBUG \
44 KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
45
46#define nvt_dbg_verbose(text, ...) \
47 if (debug > 1) \
48 printk(KERN_DEBUG \
49 KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
50
51#define nvt_dbg_wake(text, ...) \
52 if (debug > 2) \
53 printk(KERN_DEBUG \
54 KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
55
56
57/*
58 * Original lirc driver said min value of 76, and recommended value of 256
59 * for the buffer length, but then used 2048. Never mind that the size of the
60 * RX FIFO is 32 bytes... So I'm using 32 for RX and 256 for TX atm, but I'm
61 * not sure if maybe that TX value is off by a factor of 8 (bits vs. bytes),
62 * and I don't have TX-capable hardware to test/debug on...
63 */
64#define TX_BUF_LEN 256
65#define RX_BUF_LEN 32
66
67struct nvt_dev {
68 struct pnp_dev *pdev;
69 struct input_dev *rdev;
70 struct ir_dev_props *props;
71 struct ir_raw_event rawir;
72
73 spinlock_t nvt_lock;
74 bool in_use;
75
76 /* for rx */
77 u8 buf[RX_BUF_LEN];
78 unsigned int pkts;
79
80 struct {
81 spinlock_t lock;
82 u8 buf[TX_BUF_LEN];
83 unsigned int buf_count;
84 unsigned int cur_buf_num;
85 wait_queue_head_t queue;
86 u8 tx_state;
87 } tx;
88
89 /* EFER Config register index/data pair */
90 u8 cr_efir;
91 u8 cr_efdr;
92
93 /* hardware I/O settings */
94 unsigned long cir_addr;
95 unsigned long cir_wake_addr;
96 int cir_irq;
97 int cir_wake_irq;
98
99 /* hardware id */
100 u8 chip_major;
101 u8 chip_minor;
102
103 /* hardware features */
104 bool hw_learning_capable;
105 bool hw_tx_capable;
106
107 /* rx settings */
108 bool learning_enabled;
109 bool carrier_detect_enabled;
110
111 /* track cir wake state */
112 u8 wake_state;
113 /* for study */
114 u8 study_state;
115 /* carrier period = 1 / frequency */
116 u32 carrier;
117};
118
119/* study states */
120#define ST_STUDY_NONE 0x0
121#define ST_STUDY_START 0x1
122#define ST_STUDY_CARRIER 0x2
123#define ST_STUDY_ALL_RECV 0x4
124
125/* wake states */
126#define ST_WAKE_NONE 0x0
127#define ST_WAKE_START 0x1
128#define ST_WAKE_FINISH 0x2
129
130/* receive states */
131#define ST_RX_WAIT_7F 0x1
132#define ST_RX_WAIT_HEAD 0x2
133#define ST_RX_WAIT_SILENT_END 0x4
134
135/* send states */
136#define ST_TX_NONE 0x0
137#define ST_TX_REQUEST 0x2
138#define ST_TX_REPLY 0x4
139
140/* buffer packet constants */
141#define BUF_PULSE_BIT 0x80
142#define BUF_LEN_MASK 0x7f
143#define BUF_REPEAT_BYTE 0x70
144#define BUF_REPEAT_MASK 0xf0
145
146/* CIR settings */
147
148/* total length of CIR and CIR WAKE */
149#define CIR_IOREG_LENGTH 0x0f
150
151/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */
152#define CIR_RX_LIMIT_COUNT 0x7d0
153
154/* CIR Regs */
155#define CIR_IRCON 0x00
156#define CIR_IRSTS 0x01
157#define CIR_IREN 0x02
158#define CIR_RXFCONT 0x03
159#define CIR_CP 0x04
160#define CIR_CC 0x05
161#define CIR_SLCH 0x06
162#define CIR_SLCL 0x07
163#define CIR_FIFOCON 0x08
164#define CIR_IRFIFOSTS 0x09
165#define CIR_SRXFIFO 0x0a
166#define CIR_TXFCONT 0x0b
167#define CIR_STXFIFO 0x0c
168#define CIR_FCCH 0x0d
169#define CIR_FCCL 0x0e
170#define CIR_IRFSM 0x0f
171
172/* CIR IRCON settings */
173#define CIR_IRCON_RECV 0x80
174#define CIR_IRCON_WIREN 0x40
175#define CIR_IRCON_TXEN 0x20
176#define CIR_IRCON_RXEN 0x10
177#define CIR_IRCON_WRXINV 0x08
178#define CIR_IRCON_RXINV 0x04
179
180#define CIR_IRCON_SAMPLE_PERIOD_SEL_1 0x00
181#define CIR_IRCON_SAMPLE_PERIOD_SEL_25 0x01
182#define CIR_IRCON_SAMPLE_PERIOD_SEL_50 0x02
183#define CIR_IRCON_SAMPLE_PERIOD_SEL_100 0x03
184
185/* FIXME: make this a runtime option */
186/* select sample period as 50us */
187#define CIR_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50
188
189/* CIR IRSTS settings */
190#define CIR_IRSTS_RDR 0x80
191#define CIR_IRSTS_RTR 0x40
192#define CIR_IRSTS_PE 0x20
193#define CIR_IRSTS_RFO 0x10
194#define CIR_IRSTS_TE 0x08
195#define CIR_IRSTS_TTR 0x04
196#define CIR_IRSTS_TFU 0x02
197#define CIR_IRSTS_GH 0x01
198
199/* CIR IREN settings */
200#define CIR_IREN_RDR 0x80
201#define CIR_IREN_RTR 0x40
202#define CIR_IREN_PE 0x20
203#define CIR_IREN_RFO 0x10
204#define CIR_IREN_TE 0x08
205#define CIR_IREN_TTR 0x04
206#define CIR_IREN_TFU 0x02
207#define CIR_IREN_GH 0x01
208
209/* CIR FIFOCON settings */
210#define CIR_FIFOCON_TXFIFOCLR 0x80
211
212#define CIR_FIFOCON_TX_TRIGGER_LEV_31 0x00
213#define CIR_FIFOCON_TX_TRIGGER_LEV_24 0x10
214#define CIR_FIFOCON_TX_TRIGGER_LEV_16 0x20
215#define CIR_FIFOCON_TX_TRIGGER_LEV_8 0x30
216
217/* FIXME: make this a runtime option */
218/* select TX trigger level as 16 */
219#define CIR_FIFOCON_TX_TRIGGER_LEV CIR_FIFOCON_TX_TRIGGER_LEV_16
220
221#define CIR_FIFOCON_RXFIFOCLR 0x08
222
223#define CIR_FIFOCON_RX_TRIGGER_LEV_1 0x00
224#define CIR_FIFOCON_RX_TRIGGER_LEV_8 0x01
225#define CIR_FIFOCON_RX_TRIGGER_LEV_16 0x02
226#define CIR_FIFOCON_RX_TRIGGER_LEV_24 0x03
227
228/* FIXME: make this a runtime option */
229/* select RX trigger level as 24 */
230#define CIR_FIFOCON_RX_TRIGGER_LEV CIR_FIFOCON_RX_TRIGGER_LEV_24
231
232/* CIR IRFIFOSTS settings */
233#define CIR_IRFIFOSTS_IR_PENDING 0x80
234#define CIR_IRFIFOSTS_RX_GS 0x40
235#define CIR_IRFIFOSTS_RX_FTA 0x20
236#define CIR_IRFIFOSTS_RX_EMPTY 0x10
237#define CIR_IRFIFOSTS_RX_FULL 0x08
238#define CIR_IRFIFOSTS_TX_FTA 0x04
239#define CIR_IRFIFOSTS_TX_EMPTY 0x02
240#define CIR_IRFIFOSTS_TX_FULL 0x01
241
242
243/* CIR WAKE UP Regs */
244#define CIR_WAKE_IRCON 0x00
245#define CIR_WAKE_IRSTS 0x01
246#define CIR_WAKE_IREN 0x02
247#define CIR_WAKE_FIFO_CMP_DEEP 0x03
248#define CIR_WAKE_FIFO_CMP_TOL 0x04
249#define CIR_WAKE_FIFO_COUNT 0x05
250#define CIR_WAKE_SLCH 0x06
251#define CIR_WAKE_SLCL 0x07
252#define CIR_WAKE_FIFOCON 0x08
253#define CIR_WAKE_SRXFSTS 0x09
254#define CIR_WAKE_SAMPLE_RX_FIFO 0x0a
255#define CIR_WAKE_WR_FIFO_DATA 0x0b
256#define CIR_WAKE_RD_FIFO_ONLY 0x0c
257#define CIR_WAKE_RD_FIFO_ONLY_IDX 0x0d
258#define CIR_WAKE_FIFO_IGNORE 0x0e
259#define CIR_WAKE_IRFSM 0x0f
260
261/* CIR WAKE UP IRCON settings */
262#define CIR_WAKE_IRCON_DEC_RST 0x80
263#define CIR_WAKE_IRCON_MODE1 0x40
264#define CIR_WAKE_IRCON_MODE0 0x20
265#define CIR_WAKE_IRCON_RXEN 0x10
266#define CIR_WAKE_IRCON_R 0x08
267#define CIR_WAKE_IRCON_RXINV 0x04
268
269/* FIXME/jarod: make this a runtime option */
270/* select a same sample period like cir register */
271#define CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50
272
273/* CIR WAKE IRSTS Bits */
274#define CIR_WAKE_IRSTS_RDR 0x80
275#define CIR_WAKE_IRSTS_RTR 0x40
276#define CIR_WAKE_IRSTS_PE 0x20
277#define CIR_WAKE_IRSTS_RFO 0x10
278#define CIR_WAKE_IRSTS_GH 0x08
279#define CIR_WAKE_IRSTS_IR_PENDING 0x01
280
281/* CIR WAKE UP IREN Bits */
282#define CIR_WAKE_IREN_RDR 0x80
283#define CIR_WAKE_IREN_RTR 0x40
284#define CIR_WAKE_IREN_PE 0x20
285#define CIR_WAKE_IREN_RFO 0x10
286#define CIR_WAKE_IREN_TE 0x08
287#define CIR_WAKE_IREN_TTR 0x04
288#define CIR_WAKE_IREN_TFU 0x02
289#define CIR_WAKE_IREN_GH 0x01
290
291/* CIR WAKE FIFOCON settings */
292#define CIR_WAKE_FIFOCON_RXFIFOCLR 0x08
293
294#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67 0x00
295#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_66 0x01
296#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_65 0x02
297#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_64 0x03
298
299/* FIXME: make this a runtime option */
300/* select WAKE UP RX trigger level as 67 */
301#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67
302
303/* CIR WAKE SRXFSTS settings */
304#define CIR_WAKE_IRFIFOSTS_RX_GS 0x80
305#define CIR_WAKE_IRFIFOSTS_RX_FTA 0x40
306#define CIR_WAKE_IRFIFOSTS_RX_EMPTY 0x20
307#define CIR_WAKE_IRFIFOSTS_RX_FULL 0x10
308
309/* CIR Wake FIFO buffer is 67 bytes long */
310#define CIR_WAKE_FIFO_LEN 67
311/* CIR Wake byte comparison tolerance */
312#define CIR_WAKE_CMP_TOLERANCE 5
313
314/*
315 * Extended Function Enable Registers:
316 * Extended Function Index Register
317 * Extended Function Data Register
318 */
319#define CR_EFIR 0x2e
320#define CR_EFDR 0x2f
321
322/* Possible alternate EFER values, depends on how the chip is wired */
323#define CR_EFIR2 0x4e
324#define CR_EFDR2 0x4f
325
326/* Extended Function Mode enable/disable magic values */
327#define EFER_EFM_ENABLE 0x87
328#define EFER_EFM_DISABLE 0xaa
329
330/* Chip IDs found in CR_CHIP_ID_{HI,LO} */
331#define CHIP_ID_HIGH 0xb4
332#define CHIP_ID_LOW 0x72
333#define CHIP_ID_LOW2 0x73
334
335/* Config regs we need to care about */
336#define CR_SOFTWARE_RESET 0x02
337#define CR_LOGICAL_DEV_SEL 0x07
338#define CR_CHIP_ID_HI 0x20
339#define CR_CHIP_ID_LO 0x21
340#define CR_DEV_POWER_DOWN 0x22 /* bit 2 is CIR power, default power on */
341#define CR_OUTPUT_PIN_SEL 0x27
342#define CR_LOGICAL_DEV_EN 0x30 /* valid for all logical devices */
343/* next three regs valid for both the CIR and CIR_WAKE logical devices */
344#define CR_CIR_BASE_ADDR_HI 0x60
345#define CR_CIR_BASE_ADDR_LO 0x61
346#define CR_CIR_IRQ_RSRC 0x70
347/* next three regs valid only for ACPI logical dev */
348#define CR_ACPI_CIR_WAKE 0xe0
349#define CR_ACPI_IRQ_EVENTS 0xf6
350#define CR_ACPI_IRQ_EVENTS2 0xf7
351
352/* Logical devices that we need to care about */
353#define LOGICAL_DEV_LPT 0x01
354#define LOGICAL_DEV_CIR 0x06
355#define LOGICAL_DEV_ACPI 0x0a
356#define LOGICAL_DEV_CIR_WAKE 0x0e
357
358#define LOGICAL_DEV_DISABLE 0x00
359#define LOGICAL_DEV_ENABLE 0x01
360
361#define CIR_WAKE_ENABLE_BIT 0x08
362#define CIR_INTR_MOUSE_IRQ_BIT 0x80
363#define PME_INTR_CIR_PASS_BIT 0x08
364
365#define OUTPUT_PIN_SEL_MASK 0xbc
366#define OUTPUT_ENABLE_CIR 0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */
367#define OUTPUT_ENABLE_CIRWB 0x40 /* enable wide-band sensor */
368
369/* MCE CIR signal length, related on sample period */
370
371/* MCE CIR controller signal length: about 43ms
372 * 43ms / 50us (sample period) * 0.85 (inaccuracy)
373 */
374#define CONTROLLER_BUF_LEN_MIN 830
375
376/* MCE CIR keyboard signal length: about 26ms
377 * 26ms / 50us (sample period) * 0.85 (inaccuracy)
378 */
379#define KEYBOARD_BUF_LEN_MAX 650
380#define KEYBOARD_BUF_LEN_MIN 610
381
382/* MCE CIR mouse signal length: about 24ms
383 * 24ms / 50us (sample period) * 0.85 (inaccuracy)
384 */
385#define MOUSE_BUF_LEN_MIN 565
386
387#define CIR_SAMPLE_PERIOD 50
388#define CIR_SAMPLE_LOW_INACCURACY 0.85
389
390/* MAX silence time that driver will sent to lirc */
391#define MAX_SILENCE_TIME 60000
392
393#if CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_100
394#define SAMPLE_PERIOD 100
395
396#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_50
397#define SAMPLE_PERIOD 50
398
399#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_25
400#define SAMPLE_PERIOD 25
401
402#else
403#define SAMPLE_PERIOD 1
404#endif
405
406/* as VISTA MCE definition, valid carrier value */
407#define MAX_CARRIER 60000
408#define MIN_CARRIER 30000
diff --git a/drivers/media/rc/rc-map.c b/drivers/media/rc/rc-map.c
new file mode 100644
index 000000000000..689143f2fff0
--- /dev/null
+++ b/drivers/media/rc/rc-map.c
@@ -0,0 +1,107 @@
1/* ir-raw-event.c - handle IR Pulse/Space event
2 *
3 * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <media/ir-core.h>
16#include <linux/spinlock.h>
17#include <linux/delay.h>
18
19/* Used to handle IR raw handler extensions */
20static LIST_HEAD(rc_map_list);
21static DEFINE_SPINLOCK(rc_map_lock);
22
23static struct rc_keymap *seek_rc_map(const char *name)
24{
25 struct rc_keymap *map = NULL;
26
27 spin_lock(&rc_map_lock);
28 list_for_each_entry(map, &rc_map_list, list) {
29 if (!strcmp(name, map->map.name)) {
30 spin_unlock(&rc_map_lock);
31 return map;
32 }
33 }
34 spin_unlock(&rc_map_lock);
35
36 return NULL;
37}
38
39struct ir_scancode_table *get_rc_map(const char *name)
40{
41
42 struct rc_keymap *map;
43
44 map = seek_rc_map(name);
45#ifdef MODULE
46 if (!map) {
47 int rc = request_module(name);
48 if (rc < 0) {
49 printk(KERN_ERR "Couldn't load IR keymap %s\n", name);
50 return NULL;
51 }
52 msleep(20); /* Give some time for IR to register */
53
54 map = seek_rc_map(name);
55 }
56#endif
57 if (!map) {
58 printk(KERN_ERR "IR keymap %s not found\n", name);
59 return NULL;
60 }
61
62 printk(KERN_INFO "Registered IR keymap %s\n", map->map.name);
63
64 return &map->map;
65}
66EXPORT_SYMBOL_GPL(get_rc_map);
67
68int ir_register_map(struct rc_keymap *map)
69{
70 spin_lock(&rc_map_lock);
71 list_add_tail(&map->list, &rc_map_list);
72 spin_unlock(&rc_map_lock);
73 return 0;
74}
75EXPORT_SYMBOL_GPL(ir_register_map);
76
77void ir_unregister_map(struct rc_keymap *map)
78{
79 spin_lock(&rc_map_lock);
80 list_del(&map->list);
81 spin_unlock(&rc_map_lock);
82}
83EXPORT_SYMBOL_GPL(ir_unregister_map);
84
85
86static struct ir_scancode empty[] = {
87 { 0x2a, KEY_COFFEE },
88};
89
90static struct rc_keymap empty_map = {
91 .map = {
92 .scan = empty,
93 .size = ARRAY_SIZE(empty),
94 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
95 .name = RC_MAP_EMPTY,
96 }
97};
98
99int ir_rcmap_init(void)
100{
101 return ir_register_map(&empty_map);
102}
103
104void ir_rcmap_cleanup(void)
105{
106 ir_unregister_map(&empty_map);
107}
diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
new file mode 100644
index 000000000000..3a20aef67d08
--- /dev/null
+++ b/drivers/media/rc/streamzap.c
@@ -0,0 +1,572 @@
1/*
2 * Streamzap Remote Control driver
3 *
4 * Copyright (c) 2005 Christoph Bartelmus <lirc@bartelmus.de>
5 * Copyright (c) 2010 Jarod Wilson <jarod@wilsonet.com>
6 *
7 * This driver was based on the work of Greg Wickham and Adrian
8 * Dewhurst. It was substantially rewritten to support correct signal
9 * gaps and now maintains a delay buffer, which is used to present
10 * consistent timing behaviour to user space applications. Without the
11 * delay buffer an ugly hack would be required in lircd, which can
12 * cause sluggish signal decoding in certain situations.
13 *
14 * Ported to in-kernel ir-core interface by Jarod Wilson
15 *
16 * This driver is based on the USB skeleton driver packaged with the
17 * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com)
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 */
33
34#include <linux/device.h>
35#include <linux/module.h>
36#include <linux/slab.h>
37#include <linux/input.h>
38#include <linux/usb.h>
39#include <linux/usb/input.h>
40#include <media/ir-core.h>
41
42#define DRIVER_VERSION "1.61"
43#define DRIVER_NAME "streamzap"
44#define DRIVER_DESC "Streamzap Remote Control driver"
45
46#ifdef CONFIG_USB_DEBUG
47static int debug = 1;
48#else
49static int debug;
50#endif
51
52#define USB_STREAMZAP_VENDOR_ID 0x0e9c
53#define USB_STREAMZAP_PRODUCT_ID 0x0000
54
55/* table of devices that work with this driver */
56static struct usb_device_id streamzap_table[] = {
57 /* Streamzap Remote Control */
58 { USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) },
59 /* Terminating entry */
60 { }
61};
62
63MODULE_DEVICE_TABLE(usb, streamzap_table);
64
65#define SZ_PULSE_MASK 0xf0
66#define SZ_SPACE_MASK 0x0f
67#define SZ_TIMEOUT 0xff
68#define SZ_RESOLUTION 256
69
70/* number of samples buffered */
71#define SZ_BUF_LEN 128
72
73/* from ir-rc5-sz-decoder.c */
74#ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE
75#define load_rc5_sz_decode() request_module("ir-rc5-sz-decoder")
76#else
77#define load_rc5_sz_decode() 0
78#endif
79
80enum StreamzapDecoderState {
81 PulseSpace,
82 FullPulse,
83 FullSpace,
84 IgnorePulse
85};
86
87/* structure to hold our device specific stuff */
88struct streamzap_ir {
89
90 /* ir-core */
91 struct ir_dev_props *props;
92
93 /* core device info */
94 struct device *dev;
95 struct input_dev *idev;
96
97 /* usb */
98 struct usb_device *usbdev;
99 struct usb_interface *interface;
100 struct usb_endpoint_descriptor *endpoint;
101 struct urb *urb_in;
102
103 /* buffer & dma */
104 unsigned char *buf_in;
105 dma_addr_t dma_in;
106 unsigned int buf_in_len;
107
108 /* track what state we're in */
109 enum StreamzapDecoderState decoder_state;
110 /* tracks whether we are currently receiving some signal */
111 bool idle;
112 /* sum of signal lengths received since signal start */
113 unsigned long sum;
114 /* start time of signal; necessary for gap tracking */
115 struct timeval signal_last;
116 struct timeval signal_start;
117 bool timeout_enabled;
118
119 char name[128];
120 char phys[64];
121};
122
123
124/* local function prototypes */
125static int streamzap_probe(struct usb_interface *interface,
126 const struct usb_device_id *id);
127static void streamzap_disconnect(struct usb_interface *interface);
128static void streamzap_callback(struct urb *urb);
129static int streamzap_suspend(struct usb_interface *intf, pm_message_t message);
130static int streamzap_resume(struct usb_interface *intf);
131
132/* usb specific object needed to register this driver with the usb subsystem */
133static struct usb_driver streamzap_driver = {
134 .name = DRIVER_NAME,
135 .probe = streamzap_probe,
136 .disconnect = streamzap_disconnect,
137 .suspend = streamzap_suspend,
138 .resume = streamzap_resume,
139 .id_table = streamzap_table,
140};
141
142static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
143{
144 dev_dbg(sz->dev, "Storing %s with duration %u us\n",
145 (rawir.pulse ? "pulse" : "space"), rawir.duration);
146 ir_raw_event_store_with_filter(sz->idev, &rawir);
147}
148
149static void sz_push_full_pulse(struct streamzap_ir *sz,
150 unsigned char value)
151{
152 DEFINE_IR_RAW_EVENT(rawir);
153
154 if (sz->idle) {
155 long deltv;
156
157 sz->signal_last = sz->signal_start;
158 do_gettimeofday(&sz->signal_start);
159
160 deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec;
161 rawir.pulse = false;
162 if (deltv > 15) {
163 /* really long time */
164 rawir.duration = IR_MAX_DURATION;
165 } else {
166 rawir.duration = (int)(deltv * 1000000 +
167 sz->signal_start.tv_usec -
168 sz->signal_last.tv_usec);
169 rawir.duration -= sz->sum;
170 rawir.duration *= 1000;
171 rawir.duration &= IR_MAX_DURATION;
172 }
173 sz_push(sz, rawir);
174
175 sz->idle = false;
176 sz->sum = 0;
177 }
178
179 rawir.pulse = true;
180 rawir.duration = ((int) value) * SZ_RESOLUTION;
181 rawir.duration += SZ_RESOLUTION / 2;
182 sz->sum += rawir.duration;
183 rawir.duration *= 1000;
184 rawir.duration &= IR_MAX_DURATION;
185 sz_push(sz, rawir);
186}
187
188static void sz_push_half_pulse(struct streamzap_ir *sz,
189 unsigned char value)
190{
191 sz_push_full_pulse(sz, (value & SZ_PULSE_MASK) >> 4);
192}
193
194static void sz_push_full_space(struct streamzap_ir *sz,
195 unsigned char value)
196{
197 DEFINE_IR_RAW_EVENT(rawir);
198
199 rawir.pulse = false;
200 rawir.duration = ((int) value) * SZ_RESOLUTION;
201 rawir.duration += SZ_RESOLUTION / 2;
202 sz->sum += rawir.duration;
203 rawir.duration *= 1000;
204 sz_push(sz, rawir);
205}
206
207static void sz_push_half_space(struct streamzap_ir *sz,
208 unsigned long value)
209{
210 sz_push_full_space(sz, value & SZ_SPACE_MASK);
211}
212
213/**
214 * streamzap_callback - usb IRQ handler callback
215 *
216 * This procedure is invoked on reception of data from
217 * the usb remote.
218 */
219static void streamzap_callback(struct urb *urb)
220{
221 struct streamzap_ir *sz;
222 unsigned int i;
223 int len;
224
225 if (!urb)
226 return;
227
228 sz = urb->context;
229 len = urb->actual_length;
230
231 switch (urb->status) {
232 case -ECONNRESET:
233 case -ENOENT:
234 case -ESHUTDOWN:
235 /*
236 * this urb is terminated, clean up.
237 * sz might already be invalid at this point
238 */
239 dev_err(sz->dev, "urb terminated, status: %d\n", urb->status);
240 return;
241 default:
242 break;
243 }
244
245 dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
246 for (i = 0; i < len; i++) {
247 dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n",
248 i, (unsigned char)sz->buf_in[i]);
249 switch (sz->decoder_state) {
250 case PulseSpace:
251 if ((sz->buf_in[i] & SZ_PULSE_MASK) ==
252 SZ_PULSE_MASK) {
253 sz->decoder_state = FullPulse;
254 continue;
255 } else if ((sz->buf_in[i] & SZ_SPACE_MASK)
256 == SZ_SPACE_MASK) {
257 sz_push_half_pulse(sz, sz->buf_in[i]);
258 sz->decoder_state = FullSpace;
259 continue;
260 } else {
261 sz_push_half_pulse(sz, sz->buf_in[i]);
262 sz_push_half_space(sz, sz->buf_in[i]);
263 }
264 break;
265 case FullPulse:
266 sz_push_full_pulse(sz, sz->buf_in[i]);
267 sz->decoder_state = IgnorePulse;
268 break;
269 case FullSpace:
270 if (sz->buf_in[i] == SZ_TIMEOUT) {
271 DEFINE_IR_RAW_EVENT(rawir);
272
273 rawir.pulse = false;
274 rawir.duration = sz->props->timeout;
275 sz->idle = true;
276 if (sz->timeout_enabled)
277 sz_push(sz, rawir);
278 ir_raw_event_handle(sz->idev);
279 } else {
280 sz_push_full_space(sz, sz->buf_in[i]);
281 }
282 sz->decoder_state = PulseSpace;
283 break;
284 case IgnorePulse:
285 if ((sz->buf_in[i] & SZ_SPACE_MASK) ==
286 SZ_SPACE_MASK) {
287 sz->decoder_state = FullSpace;
288 continue;
289 }
290 sz_push_half_space(sz, sz->buf_in[i]);
291 sz->decoder_state = PulseSpace;
292 break;
293 }
294 }
295
296 usb_submit_urb(urb, GFP_ATOMIC);
297
298 return;
299}
300
301static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz)
302{
303 struct input_dev *idev;
304 struct ir_dev_props *props;
305 struct device *dev = sz->dev;
306 int ret;
307
308 idev = input_allocate_device();
309 if (!idev) {
310 dev_err(dev, "remote input dev allocation failed\n");
311 goto idev_alloc_failed;
312 }
313
314 props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
315 if (!props) {
316 dev_err(dev, "remote ir dev props allocation failed\n");
317 goto props_alloc_failed;
318 }
319
320 snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared "
321 "Receiver (%04x:%04x)",
322 le16_to_cpu(sz->usbdev->descriptor.idVendor),
323 le16_to_cpu(sz->usbdev->descriptor.idProduct));
324
325 idev->name = sz->name;
326 usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys));
327 strlcat(sz->phys, "/input0", sizeof(sz->phys));
328 idev->phys = sz->phys;
329
330 props->priv = sz;
331 props->driver_type = RC_DRIVER_IR_RAW;
332 props->allowed_protos = IR_TYPE_ALL;
333
334 sz->props = props;
335
336 usb_to_input_id(sz->usbdev, &idev->id);
337 idev->dev.parent = sz->dev;
338
339 ret = ir_input_register(idev, RC_MAP_STREAMZAP, props, DRIVER_NAME);
340 if (ret < 0) {
341 dev_err(dev, "remote input device register failed\n");
342 goto irdev_failed;
343 }
344
345 return idev;
346
347irdev_failed:
348 kfree(props);
349props_alloc_failed:
350 input_free_device(idev);
351idev_alloc_failed:
352 return NULL;
353}
354
355/**
356 * streamzap_probe
357 *
358 * Called by usb-core to associated with a candidate device
359 * On any failure the return value is the ERROR
360 * On success return 0
361 */
362static int __devinit streamzap_probe(struct usb_interface *intf,
363 const struct usb_device_id *id)
364{
365 struct usb_device *usbdev = interface_to_usbdev(intf);
366 struct usb_host_interface *iface_host;
367 struct streamzap_ir *sz = NULL;
368 char buf[63], name[128] = "";
369 int retval = -ENOMEM;
370 int pipe, maxp;
371
372 /* Allocate space for device driver specific data */
373 sz = kzalloc(sizeof(struct streamzap_ir), GFP_KERNEL);
374 if (!sz)
375 return -ENOMEM;
376
377 sz->usbdev = usbdev;
378 sz->interface = intf;
379
380 /* Check to ensure endpoint information matches requirements */
381 iface_host = intf->cur_altsetting;
382
383 if (iface_host->desc.bNumEndpoints != 1) {
384 dev_err(&intf->dev, "%s: Unexpected desc.bNumEndpoints (%d)\n",
385 __func__, iface_host->desc.bNumEndpoints);
386 retval = -ENODEV;
387 goto free_sz;
388 }
389
390 sz->endpoint = &(iface_host->endpoint[0].desc);
391 if ((sz->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
392 != USB_DIR_IN) {
393 dev_err(&intf->dev, "%s: endpoint doesn't match input device "
394 "02%02x\n", __func__, sz->endpoint->bEndpointAddress);
395 retval = -ENODEV;
396 goto free_sz;
397 }
398
399 if ((sz->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
400 != USB_ENDPOINT_XFER_INT) {
401 dev_err(&intf->dev, "%s: endpoint attributes don't match xfer "
402 "02%02x\n", __func__, sz->endpoint->bmAttributes);
403 retval = -ENODEV;
404 goto free_sz;
405 }
406
407 pipe = usb_rcvintpipe(usbdev, sz->endpoint->bEndpointAddress);
408 maxp = usb_maxpacket(usbdev, pipe, usb_pipeout(pipe));
409
410 if (maxp == 0) {
411 dev_err(&intf->dev, "%s: endpoint Max Packet Size is 0!?!\n",
412 __func__);
413 retval = -ENODEV;
414 goto free_sz;
415 }
416
417 /* Allocate the USB buffer and IRQ URB */
418 sz->buf_in = usb_alloc_coherent(usbdev, maxp, GFP_ATOMIC, &sz->dma_in);
419 if (!sz->buf_in)
420 goto free_sz;
421
422 sz->urb_in = usb_alloc_urb(0, GFP_KERNEL);
423 if (!sz->urb_in)
424 goto free_buf_in;
425
426 sz->dev = &intf->dev;
427 sz->buf_in_len = maxp;
428
429 if (usbdev->descriptor.iManufacturer
430 && usb_string(usbdev, usbdev->descriptor.iManufacturer,
431 buf, sizeof(buf)) > 0)
432 strlcpy(name, buf, sizeof(name));
433
434 if (usbdev->descriptor.iProduct
435 && usb_string(usbdev, usbdev->descriptor.iProduct,
436 buf, sizeof(buf)) > 0)
437 snprintf(name + strlen(name), sizeof(name) - strlen(name),
438 " %s", buf);
439
440 sz->idev = streamzap_init_input_dev(sz);
441 if (!sz->idev)
442 goto input_dev_fail;
443
444 sz->idle = true;
445 sz->decoder_state = PulseSpace;
446 /* FIXME: don't yet have a way to set this */
447 sz->timeout_enabled = true;
448 sz->props->timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) &
449 IR_MAX_DURATION) | 0x03000000);
450 #if 0
451 /* not yet supported, depends on patches from maxim */
452 /* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */
453 sz->min_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000;
454 sz->max_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000;
455 #endif
456
457 do_gettimeofday(&sz->signal_start);
458
459 /* Complete final initialisations */
460 usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in,
461 maxp, (usb_complete_t)streamzap_callback,
462 sz, sz->endpoint->bInterval);
463 sz->urb_in->transfer_dma = sz->dma_in;
464 sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
465
466 usb_set_intfdata(intf, sz);
467
468 if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
469 dev_err(sz->dev, "urb submit failed\n");
470
471 dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
472 usbdev->bus->busnum, usbdev->devnum);
473
474 /* Load the streamzap not-quite-rc5 decoder too */
475 load_rc5_sz_decode();
476
477 return 0;
478
479input_dev_fail:
480 usb_free_urb(sz->urb_in);
481free_buf_in:
482 usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in);
483free_sz:
484 kfree(sz);
485
486 return retval;
487}
488
489/**
490 * streamzap_disconnect
491 *
492 * Called by the usb core when the device is removed from the system.
493 *
494 * This routine guarantees that the driver will not submit any more urbs
495 * by clearing dev->usbdev. It is also supposed to terminate any currently
496 * active urbs. Unfortunately, usb_bulk_msg(), used in streamzap_read(),
497 * does not provide any way to do this.
498 */
499static void streamzap_disconnect(struct usb_interface *interface)
500{
501 struct streamzap_ir *sz = usb_get_intfdata(interface);
502 struct usb_device *usbdev = interface_to_usbdev(interface);
503
504 usb_set_intfdata(interface, NULL);
505
506 if (!sz)
507 return;
508
509 sz->usbdev = NULL;
510 ir_input_unregister(sz->idev);
511 usb_kill_urb(sz->urb_in);
512 usb_free_urb(sz->urb_in);
513 usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in);
514
515 kfree(sz);
516}
517
518static int streamzap_suspend(struct usb_interface *intf, pm_message_t message)
519{
520 struct streamzap_ir *sz = usb_get_intfdata(intf);
521
522 usb_kill_urb(sz->urb_in);
523
524 return 0;
525}
526
527static int streamzap_resume(struct usb_interface *intf)
528{
529 struct streamzap_ir *sz = usb_get_intfdata(intf);
530
531 if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) {
532 dev_err(sz->dev, "Error sumbiting urb\n");
533 return -EIO;
534 }
535
536 return 0;
537}
538
539/**
540 * streamzap_init
541 */
542static int __init streamzap_init(void)
543{
544 int ret;
545
546 /* register this driver with the USB subsystem */
547 ret = usb_register(&streamzap_driver);
548 if (ret < 0)
549 printk(KERN_ERR DRIVER_NAME ": usb register failed, "
550 "result = %d\n", ret);
551
552 return ret;
553}
554
555/**
556 * streamzap_exit
557 */
558static void __exit streamzap_exit(void)
559{
560 usb_deregister(&streamzap_driver);
561}
562
563
564module_init(streamzap_init);
565module_exit(streamzap_exit);
566
567MODULE_AUTHOR("Jarod Wilson <jarod@wilsonet.com>");
568MODULE_DESCRIPTION(DRIVER_DESC);
569MODULE_LICENSE("GPL");
570
571module_param(debug, bool, S_IRUGO | S_IWUSR);
572MODULE_PARM_DESC(debug, "Enable debugging messages");